【问题标题】:ImageView will not load via setImageURI when ran on Samsung Galaxy S4 Only仅在三星 Galaxy S4 上运行时,ImageView 不会通过 setImageURI 加载
【发布时间】:2015-04-29 00:04:33
【问题描述】:

我在三星 Galaxy S4(型号:GT-I9500)上运行一些基本代码时遇到了一个特定问题。

我正在通过相机或画廊实现图像选择器,但我一生都无法弄清楚为什么 ImageView 在调用时为空白 -

imageView.setImageURI(uri);

直到我在模拟器(然后是 Nexus 5)中运行完全相同的代码后,我才发现这是三星 S4 的问题。

完整的示例项目可以在Github & ready to run找到

我使用的代码取自SO post

OnCreate中:

btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("Choose Image Source");
            builder.setItems(new CharSequence[]{"Gallery", "Camera"},
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            switch (which) {
                                case 0:

                                    //Launching the gallery
                                    Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                                    startActivityForResult(i, GALLERY);

                                    break;

                                case 1:
                                    //Specify a camera intent
                                    Intent getCameraImage = new Intent("android.media.action.IMAGE_CAPTURE");

                                    File cameraFolder;

                                    //Check to see if there is an SD card mounted
                                    if (android.os.Environment.getExternalStorageState().equals
                                            (android.os.Environment.MEDIA_MOUNTED))
                                        cameraFolder = new File(android.os.Environment.getExternalStorageDirectory(),
                                                IMAGEFOLDER);
                                    else
                                        cameraFolder = MainActivity.this.getCacheDir();
                                    if (!cameraFolder.exists())
                                        cameraFolder.mkdirs();

                                    //Appending timestamp to "picture_"
                                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
                                    String timeStamp = dateFormat.format(new Date());
                                    String imageFileName = "picture_" + timeStamp + ".jpg";

                                    File photo = new File(Environment.getExternalStorageDirectory(),
                                            IMAGEFOLDER + imageFileName);
                                    getCameraImage.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));

                                    //Setting a global variable to be used in the OnActivityResult
                                    imageURI = Uri.fromFile(photo);

                                    startActivityForResult(getCameraImage, CAMERA);

                                    break;
                                default:
                                    break;
                            }
                        }
                    });

            builder.show();
        }
    });

OnActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == RESULT_OK) {


        switch (requestCode) {
            case GALLERY:
                Uri selectedImage = data.getData();
                imageView.setImageURI(selectedImage);

                break;
            case CAMERA:

                imageView.setImageURI(imageURI);
                break;
        }

    }

}

使用时也会发生 Picasso

 if (resultCode == RESULT_OK) {


        switch (requestCode) {
            case GALLERY:
                Uri selectedImage = data.getData();
                Picasso.with(context)
                        .load(selectedImage)
                        .into(imageView);

                break;
            case CAMERA:
                Picasso.with(context)
                        .load(imageURI)
                        .into(imageView);
                break;
        }

    }

使用位图工厂时也会发生

  try {
                    Bitmap bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(imageURI));
                    imageView.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

在运行 4.2.2 的三星 S4 上运行时的结果

在运行 Android 4.4.4 的 GenyMotion 2.4.0 上运行时的结果

有人知道为什么会这样吗?

【问题讨论】:

  • setImageURI() 很少是一个好主意,因为这会将图像加载到主应用程序线程上。
  • 从图库中加载图像时,更好的解决方案是什么?
  • 使用many image loading libraries 之一,它将在后台线程上加载图像并在准备好时将其应用于ImageView。或者,自己做,也许使用AsyncTask
  • 所以我尝试使用毕加索,但这也不起作用。它仍然加载一个空白的图像视图。我会将它添加到 github 存储库中。
  • 嗯,这有点奇怪。您从MediaStore 提取的所有图像都会发生这种情况,还是仅部分发生这种情况?

标签: android camera imageview gallery onactivityresult


【解决方案1】:

所以问题是图像位图太大,三星 S4 无法处理。

令人沮丧的是没有抛出错误 - 正确的解决方案如下:

switch (requestCode) {
            case GALLERY:
                Bitmap bitmap = createScaledBitmap(getImagePath(data, getApplicationContext()), imageView.getWidth(), imageView.getHeight());
                imageView.setImageBitmap(bitmap);
                break;
            case CAMERA:
                String path = imageURI.getPath();
                Bitmap bitmapCamera = createScaledBitmap(path, imageView.getWidth(), imageView.getHeight());
                imageView.setImageBitmap(bitmapCamera);
                break;
        }

辅助方法:

// Function to get image path from ImagePicker
public static String getImagePath(Intent data, Context context) {
    Uri selectedImage = data.getData();
    String[] filePathColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = context.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
    cursor.moveToFirst();
    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    String picturePath = cursor.getString(columnIndex);
    cursor.close();
    return picturePath;
}


public Bitmap createScaledBitmap(String pathName, int width, int height) {
    final BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathName, opt);
    opt.inSampleSize = calculateBmpSampleSize(opt, width, height);
    opt.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(pathName, opt);
}

public int calculateBmpSampleSize(BitmapFactory.Options opt, int width, int height) {
    final int outHeight = opt.outHeight;
    final int outWidth = opt.outWidth;
    int sampleSize = 1;
    if (outHeight > height || outWidth > width) {
        final int heightRatio = Math.round((float) outHeight / (float) height);
        final int widthRatio = Math.round((float) outWidth / (float) width);
        sampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return sampleSize;
}

【讨论】:

  • 我很高兴你的工作基本上正常了。但是,您的“从 ImagePicker 获取图像路径的功能”将无法可靠地工作,尤其是在较新的 Android 设备上。正如我似乎一直在说的那样,a Uri is not a file。此外,您不需要它。只需使用getContentResolver().openInputStream(),然后在BitmapFactory 上使用decodeStream()
【解决方案2】:

使用毕加索时,使用 fit() 或 resize()。它处理调整位图的大小。

【讨论】:

  • 谢谢,resize()fit() 在三星 Galaxy S4 中工作。
【解决方案3】:

他们是否有机会使用不同的应用程序? 4.4 引入了几个新的 URI 用于图像选择,因为它们可以是本地的、google plus 等。

试试这个:BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri))

它返回一个可以在图像视图中使用的位图

imgView.setImageBitmap(bitmap)

【讨论】:

  • 它们是完全相同的应用程序,从完全相同的 IDE/设置推送。我也尝试了上述方法,但没有成功,我将在项目中添加第三个活动,并在今天晚些时候添加更多屏幕截图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多