【问题标题】:Camera picture Uri null path相机图片Uri空路径
【发布时间】:2015-06-15 15:32:49
【问题描述】:

在我的应用中,我让用户有机会获取照片并将其设置为个人资料照片。有两种获取照片的方法,从图库中获取照片,以及直接用相机拍摄。

我已经编写了适用于booth 方法的代码,并且我已经在带有棒棒糖5.0 的Galaxy S5 上进行了测试。使用 KitKat 4.4.4 对其进行测试时,它正在抛出 NPE。但是只是在直接从相机拍摄照片时抛出这个NPE。

在展位案例中,这是我遵循的结构:

  1. 从 onActivityResult 调用数据中获取 Uri。
  2. 获取图片方向值(在某些情况下,纵向图像在图像视图中出现旋转)。
  3. 解码位图以缩小其尺寸以保持纵横比。
  4. 如果图像方向错误,请旋转图像。
  5. 将位图保存在应用内部数据中。

这是“从相机拍照”请求的代码:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case TAKE_PHOTO_REQUEST_FRAG:
            if (resultCode == getActivity().RESULT_OK && data != null) {

                Uri selectedImageUri = data.getData();
                Bitmap srcBmp = null;

                /*Get image orientation*/
                int orientation = getImageOrientation(getActivity(), selectedImageUri);
                Log.d("IMAGE_ORIENTATION", String.valueOf(orientation));

                /*Downsize bitmap mantaining aspect ratio*/
                srcBmp = decodeSampledBitmapFromUri(
                        selectedImageUri,
                        pic_view.getWidth(), pic_view.getHeight());

                /*Rotate image if needed*/
                if (orientation == 90) {
                    Matrix matrix = new Matrix();
                    matrix.postRotate(90);
                    srcBmp = Bitmap.createBitmap(srcBmp, 0, 0,
                            srcBmp.getWidth(), srcBmp.getHeight(), matrix,
                            true);
                }
                else if (orientation == 180) {
                    Matrix matrix = new Matrix();
                    matrix.postRotate(180);
                    srcBmp = Bitmap.createBitmap(srcBmp, 0, 0,
                            srcBmp.getWidth(), srcBmp.getHeight(), matrix,
                            true);
                }
                else if (orientation == 270) {
                    Matrix matrix = new Matrix();
                    matrix.postRotate(270);
                    srcBmp = Bitmap.createBitmap(srcBmp, 0, 0,
                            srcBmp.getWidth(), srcBmp.getHeight(), matrix,
                            true);
                }

                /*Save bitmap in internal memory*/
                ContextWrapper cw1 = new ContextWrapper(getActivity().getApplicationContext());
                File directory1 = cw1.getDir("profile", Context.MODE_PRIVATE);
                if (!directory1.exists()) {
                    directory1.mkdir();
                }
                File filepath1 = new File(directory1, "profile_pic.png");
                FileOutputStream fos1 = null;
                try {
                    fos1 = new FileOutputStream(filepath1);
                    srcBmp.compress(Bitmap.CompressFormat.JPEG, 90, fos1);
                    fos1.close();
                } catch (Exception e) {
                    Log.e("SAVE_FULL_IMAGE", e.getMessage(), e);
                }

                /*Show image in imageview*/
                pic_view.setImageBitmap(srcBmp);
            }
            break;
    }
}

-

/*Downsize the bitmap from uri*/
public Bitmap decodeSampledBitmapFromUri(Uri uri, int reqWidth, int reqHeight) {
    Bitmap bm = null;
    try{
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(uri), null, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bm = BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(uri), null, options);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        Toast.makeText(getActivity().getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
    }
    return bm;
}


public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }
    return inSampleSize;
}

-

/*Get image orientation first from Exif info*/
public int getImageOrientation(Context context, Uri photoUri) {
    int orientation = getOrientationFromExif(photoUri);
    if(orientation <= 0) {
        orientation = getOrientationFromMediaStore(context, photoUri);
    }
    return orientation;
}

private int getOrientationFromExif(Uri photoUri) {
    int orientation = -1;
    try {
        ExifInterface exif = new ExifInterface(photoUri.getPath());
        int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        switch (exifOrientation) {
            case ExifInterface.ORIENTATION_ROTATE_270:
                orientation = 270;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                orientation = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                orientation = 90;
                break;
            case ExifInterface.ORIENTATION_NORMAL:
                orientation = 0;
                break;
            default:
                break;
        }
    } catch (IOException e) {
        Log.e("EXIF_ORIENTATION", "Unable to get image exif orientation", e);
    }
    return orientation;
}

/* normal landscape: 0
 * normal portrait: 90
 * upside-down landscape: 180
 * upside-down portrait: 270
 * image not found: -1
 */
private static int getOrientationFromMediaStore(Context context, Uri photoUri) {
    String[] projection = {MediaStore.Images.ImageColumns.ORIENTATION};
    Cursor cursor = context.getContentResolver().query(photoUri, projection, null, null, null);

    try {
        if (cursor.moveToFirst()) {
            return cursor.getInt(0);
        } else {
            return -1;
        }
    } finally {
        cursor.close();
    }
}

它将 NPE 扔到我想从 exif 数据中获取图像方向的行中,正是我从 uri 中获取路径的位置:

ExifInterface exif = new ExifInterface(photoUri.getPath());

所以我知道它一定与路径有关。我已经阅读了几篇关于 kitkat 以不同格式返回路径的帖子。我尝试了不同的自定义 getPath() 方法,但在调用 Cursor 时总是抛出 NPE。

【问题讨论】:

    标签: android image


    【解决方案1】:

    所以我知道它一定是路径的东西。

    那是因为它不是文件系统路径。 A Uri is not a file,当您在其他地方正确处理时,您在这里没有这样做。

    您需要切换到可以处理InputStream 的EXIF 逻辑,例如this code culled from the AOSP Mms app

    【讨论】:

    • 所以,您的意思是对 Uri 使用 getPath() 并不是正确的做法。我正在查看您提供的代码,但我认为我的知识不足以完全理解它并知道如何在我的代码中使用它。如果您能指导我如何使用 Exif 逻辑处理 InputStream,我将不胜感激。
    猜你喜欢
    • 2011-10-19
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 2012-06-24
    • 2013-11-05
    • 2015-11-27
    相关资源
    最近更新 更多