【发布时间】:2015-06-15 15:32:49
【问题描述】:
在我的应用中,我让用户有机会获取照片并将其设置为个人资料照片。有两种获取照片的方法,从图库中获取照片,以及直接用相机拍摄。
我已经编写了适用于booth 方法的代码,并且我已经在带有棒棒糖5.0 的Galaxy S5 上进行了测试。使用 KitKat 4.4.4 对其进行测试时,它正在抛出 NPE。但是只是在直接从相机拍摄照片时抛出这个NPE。
在展位案例中,这是我遵循的结构:
- 从 onActivityResult 调用数据中获取 Uri。
- 获取图片方向值(在某些情况下,纵向图像在图像视图中出现旋转)。
- 解码位图以缩小其尺寸以保持纵横比。
- 如果图像方向错误,请旋转图像。
- 将位图保存在应用内部数据中。
这是“从相机拍照”请求的代码:
@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。
【问题讨论】: