Android:使用Camera Intent时,应用程序在onActivityResult上崩溃

我正在使用相机意图捕捉我的应用程序中的图像。 在使用相机时,我的应用在Android 5.0.2上崩溃的问题。 我正在使用片段的意图。 下面是我的代码里面的片段:

照相方法

 private void takePhoto() { mHighQualityImageUri = Util.generateTimeStampPhotoFileUri(getActivity()); Log.d(UploadPicturesFragment.class.getSimpleName(), "URI: " + mHighQualityImageUri.toString()); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, mHighQualityImageUri); startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); } 

onActivityResult在我的片段

 public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK) { return; } if (requestCode == REQUEST_IMAGE_CAPTURE) { Log.d(UploadPicturesFragment.class.getSimpleName(), "IMAGE URI NOT NULL: " + (mHighQualityImageUri == null)); try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), mHighQualityImageUri); DroomUtil.beginCrop(mHighQualityImageUri, getActivity(), this, true, bitmap.getWidth(), bitmap.getHeight()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } 

日志跟踪

 12-29 10:28:03.491: E/AndroidRuntime(9780): java.lang.RuntimeException: Unable to resume activity {in.droom/in.droom.activity.MainActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=android:fragment:2, request=1, result=-1, data=null} to activity {in.droom/in.droom.activity.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3224) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3257) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2479) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.access$800(ActivityThread.java:144) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.os.Handler.dispatchMessage(Handler.java:102) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.os.Looper.loop(Looper.java:155) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.main(ActivityThread.java:5702) 12-29 10:28:03.491: E/AndroidRuntime(9780): at java.lang.reflect.Method.invoke(Native Method) 12-29 10:28:03.491: E/AndroidRuntime(9780): at java.lang.reflect.Method.invoke(Method.java:372) 12-29 10:28:03.491: E/AndroidRuntime(9780): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029) 12-29 10:28:03.491: E/AndroidRuntime(9780): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824) 12-29 10:28:03.491: E/AndroidRuntime(9780): Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=android:fragment:2, request=1, result=-1, data=null} to activity {in.droom/in.droom.activity.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.deliverResults(ActivityThread.java:3881) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3197) 12-29 10:28:03.491: E/AndroidRuntime(9780): ... 11 more 12-29 10:28:03.491: E/AndroidRuntime(9780): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.content.ContentResolver.openInputStream(ContentResolver.java:651) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:1019) 12-29 10:28:03.491: E/AndroidRuntime(9780): at in.droom.fragments.UploadPicturesFragment.onActivityResult(UploadPicturesFragment.java:395) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.Activity.dispatchActivityResult(Activity.java:6164) 12-29 10:28:03.491: E/AndroidRuntime(9780): at android.app.ActivityThread.deliverResults(ActivityThread.java:3877) 12-29 10:28:03.491: E/AndroidRuntime(9780): ... 12 more 

行号 395是:

 Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), mHighQualityImageUri); 

Solutions Collecting From Web of "Android:使用Camera Intent时,应用程序在onActivityResult上崩溃"

 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference 

这意味着mHighQualityImageUri很可能是null 。 如果你没有使用onSaveInstanceState()来保持这个Uri就会发生这种情况。 当您的应用程序处于后台并且相机应用程序处于前台时,您的进程完全可能会被终止。

按照以下步骤从相机拍照并显示在ImageView

1)启动相机意图

 Uri fileUri; String photoPath = ""; private void startingCameraIntent() { String fileName = System.currentTimeMillis()+".jpg"; ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, fileName); fileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); startActivityForResult(intent, YOUR_REQ_CODE); } 

2)callbackonActivityResult函数

 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { try { photoPath = getPath(fileUri); System.out.println("Image Path : " + photoPath); Bitmap b = decodeUri(fileUri); your_image_view.setImageBitmap(b); } catch(Exception e) { e.printStackTrace(); } } } 

3)decodeUri函数

 private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException { BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(getContentResolver() .openInputStream(selectedImage), null, o); final int REQUIRED_SIZE = 72; int width_tmp = o.outWidth, height_tmp = o.outHeight; int scale = 1; while (true) { if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) { break; } width_tmp /= 2; height_tmp /= 2; scale *= 2; } BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver() .openInputStream(selectedImage), null, o2); return bitmap; } 

4)getPath的图像

 @SuppressWarnings("deprecation") private String getPath(Uri selectedImaeUri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(selectedImaeUri, projection, null, null, null); if (cursor != null) { cursor.moveToFirst(); int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); return cursor.getString(columnIndex); } return selectedImaeUri.getPath(); } 

最后在清单中定义权限

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

注意:如果您使用棉花糖(Android 6.0),则必须在使用相机应用程序之前设置权限检查。 您可以在运行时阅读Android 请求权限

首先检查onActivityResultdata是否为null ,方法是添加一个额外的代码,以防止应用程序崩溃 ,如下所示

 public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK && data !=null) { return; } } 

然后考虑本课讲解如何使用现有的相机应用程序拍摄照片。

有一个关于使用uses-feature标签 请求相机权限的完整参考, 获取缩略图 , 保存完整大小的照片 ,还有很多,这可能会非常有助于您完成您的任务…

  please check your path from mHighQualityImageUri because output path is not found, below code is modify please check it, it work and remember camera result is give in Main Activity class because You used Fragment so declare on activity Result in Main Activity (Fragment Activity) class. //on Fragment Class private void takePhoto() { /* mHighQualityImageUri = Util.generateTimeStampPhotoFileUri(getActivity()); Log.d(UploadPicturesFragment.class.getSimpleName(), "URI: " + mHighQualityImageUri.toString());*/ imageUri =Uri.fromFile(new File("/sdcard/")); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); context.startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); } //on Main Activity Class @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1) { /* Log.d(UploadPicturesFragment.class.getSimpleName(), "IMAGE URI NOT NULL: " + (mHighQualityImageUri == null));*/ try { /*if(imageUri==null){ Log.i("Bitmap", "Image URI Null"); }else { Log.i("Bitmap","Image URI is not Null"); }*/ Uri imageUri = Uri.fromFile(new File("/sdcard/")); Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),imageUri); // mHighQualityImageUri); if(bitmap !=null) { Log.i("Bitmap", "Bitmap not Null"); }else { Log.i("Bitmap","Bitmap is Null"); } // DroomUtil.beginCrop(mHighQualityImageUri, getActivity(), this, true, bitmap.getWidth(), // bitmap.getHeight()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } super.onActivityResult(requestCode, resultCode, data); } 

在Android上,我看到不同的设备在用相机和图库select图像时performance出不同的行为。 我发现更好的方法是:

  1. 在您的应用中创build一个内容提供者。
  2. 从您的内容提供商获取Uri并将其传递给相机意图。
  3. 相机将把拍摄的图像写入你的Uri。
  4. 使用context.getContentResolver()。openInputStream()读取它。

由于您拥有Uri,所以此方法使您的代码独立于返回的Uri。 此外,这也支持图片图像挑选太小的修改。

我发现你的相机也有设备方向问题。 这(不幸的是)需要在你的应用程序中进行处理,在后期处理步骤中获取图像。 下面还列出了它的代码。 大多数情况下,方向问题发生在三星设备上,相机只能以横向模式拍摄图像。

为图像创buildUri:

 string imageId = "IMG" + System.currentTimeMillis(); Uri attachmentUri = Uri.parse("content://"+ AttachmentContentProvider.AUTHORITY + "/images/" + imageId); // Store this as a member in your activity/fragment as mAttachmentUri 

注意 :使用共享首选项或使用onSaveInstanceState()的活动包坚持使用mAttachmentUri非常重要,否则在应用程序被mAttachmentUri时Uri可能会丢失。

获取相机意图:

 public static Intent getImageCaptureIntent(Context context, Uri outputFileUri) { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); return cameraIntent; } 

阅读图片:

 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK) { return; } if (requestCode == REQUEST_IMAGE_CAPTURE) { try { Bitmap bitmap = decodeSampledBitmapFromResource(getActivity(), mAttachmentUri, Config.RGB_565); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public static Bitmap decodeSampledBitmapFromResource(Context context, Uri uri, Config config) { Bitmap bmp = null; InputStream is = null; if (uri != null) { try { is = context.getContentResolver().openInputStream(uri); boolean resize = true; // First decode with inJustDecodeBounds=true to check dimensions BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); mLogger.d("Image Original Width:" + options.outWidth + " Height:" + options.outHeight ); // close and open the stream again is.close(); is = context.getContentResolver().openInputStream(uri); int reqWidth = options.outWidth; int reqHeight = options.outHeight; // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; options.inPreferredConfig = config; bmp = BitmapFactory.decodeStream(is, null, options); if(bmp != null) { bmp = correctImageRotation(context, bmp, uri); } else { mLogger.e("BitmapFactory.decodeStream returned null bitmap , skip correctImageRotation"); } } catch (FileNotFoundException fnfex) { mLogger.e("FileNotFoundException : while decoding inline image bitmap: " + fnfex.getMessage()); } catch (IOException ioex) { mLogger.e("IOException : while decoding inline image bitmap: " + ioex.getMessage()); } catch (OutOfMemoryError e) { mLogger.e("OutOfMemoryError : in decodeSampledBitmapFromResource BitmapFactory.decodeStream . Skip loading Resource"); } finally { try { if (is != null) { is.close(); } } catch (IOException ioex2) { mLogger.e("IOException2 : while decoding inline image bitmap: " + ioex2.getMessage()); } } } return bmp; } // Seemed necessary on a lot of Samsung devices public static Bitmap correctImageRotation( Context context, Bitmap bitmap , Uri inputUri ) throws FileNotFoundException { int orientation = ExifInterface.ORIENTATION_UNDEFINED; try { String appfilesDir = context.getApplicationContext().getFilesDir().getAbsolutePath(); String attachmentDirPath = appfilesDir + ('/') + "images"); String fileName = ContentUris.parseId(uri) + ".jpg"; String absolutePath = attachmentDirPath + ('/') + fileName; ExifInterface exif = new ExifInterface(path); orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); } catch (IOException e) { } return rotateBitmap(bitmap, orientation); } /** * rotate bitmap code reference: * http://stackoverflow.com/questions/20478765/how-to-get-the-correct-orientation-of-the-image-selected-from-the-default-image */ private static Bitmap rotateBitmap(Bitmap bitmap, int orientation) { Matrix matrix = new Matrix(); switch (orientation) { case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: matrix.setScale(-1, 1); break; case ExifInterface.ORIENTATION_ROTATE_180: matrix.setRotate(180); break; case ExifInterface.ORIENTATION_FLIP_VERTICAL: matrix.setRotate(180); matrix.postScale(-1, 1); break; case ExifInterface.ORIENTATION_TRANSPOSE: matrix.setRotate(90); matrix.postScale(-1, 1); break; case ExifInterface.ORIENTATION_ROTATE_90: matrix.setRotate(90); break; case ExifInterface.ORIENTATION_TRANSVERSE: matrix.setRotate(-90); matrix.postScale(-1, 1); break; case ExifInterface.ORIENTATION_ROTATE_270: matrix.setRotate(-90); break; case ExifInterface.ORIENTATION_NORMAL: case ExifInterface.ORIENTATION_UNDEFINED: default: return bitmap; } try { Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); bitmap.recycle(); return bmRotated; } catch (OutOfMemoryError e) { mLogger.e("OutOfMemoryError occured while rotating the image"); return bitmap; } } 

内容提供商:

对于内容提供者的实现,你可以使用一个android的FileProvider或者像下面那样实现一个内容提供者。 此内容提供商将在您的应用程序容器中打开相机应用程序要写入的文件。

 public class AttachmentContentProvider extends ContentProvider { public static final String AUTHORITY = "com.yourcompany.yourapp.AttachmentContentProvider"; public static final int ENTITY_ATTACHMENT = 1; public static final int ENTITY_ATTACHMENT_ID = 2; private static final UriMatcher sUriMatcher; static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(AUTHORITY, "images", ENTITY_ATTACHMENT); sUriMatcher.addURI(AUTHORITY, "images"+"/#", ENTITY_ATTACHMENT_ID); } @Override public boolean onCreate() { return true; } @Override public int delete(Uri uri, String where, String[] whereArgs) { return 0; } @Override public String getType(Uri uri) { int match = sUriMatcher.match(uri); switch (match) { case ENTITY_ATTACHMENT: case ENTITY_ATTACHMENT_ID: return "image/jpeg"; default: return null; } } @Override public Uri insert(Uri uri, ContentValues initialValues) { return null; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { return 0; } public static File getAttachmentFile(String fileName) { String appfilesDir = context.getApplicationContext().getFilesDir().getAbsolutePath(); String attachmentDirPath = appfilesDir + ('/') + "images"); File newFile = new File(AttachmentHelper.getAttachmentsDir() + File.separator + fileName); newFile.getParentFile().mkdirs(); return newFile; } @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { long id = -1; try { id = ContentUris.parseId(uri); } catch (NumberFormatException e) { m_logger.e("Invalid id for Uri : " + uri ); } String filename = id + ".jpg"; // id will be IMG+current time millis File imageFile = getAttachmentFile(id); return (ParcelFileDescriptor.open(file, parseMode(mode))); } } 

总之,这个代码应该在大多数被testing的设备上工作,并且在需要的时候对从相机接收到的图像进行校正。

根据日志

 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference 

它清楚地表明你正在调用一个空对象的getScheme() 。 所以在处理之前,您需要检查空意图数据。

另外,从Android M开始,您需要向用户索取相机权限。 缺乏相机权限,应用程序将崩溃。

要了解如何使用新的权限架构,请查看: http : //developer.android.com/training/permissions/index.html

这是我经常在我的项目中做的,请看看。 希望能帮助到你!

片段类:

 btnCapturePicture.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { captureImage(); } }); btnSelectPicture.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectImage(); } }); ... private void captureImage() { mFileUri = Uri.fromFile(Utils.getOutputMediaFile(MEDIA_TYPE_IMAGE)); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri); startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE); } private void selectImage() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType(MIME_IMAGE_ALL); startActivityForResult(intent, SELECT_PHOTO_CODE); } ... @Override public void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { super.onActivityResult(requestCode, resultCode, imageReturnedIntent); switch (requestCode) { case SELECT_PHOTO_CODE: if (resultCode == Activity.RESULT_OK) { mFileUri = imageReturnedIntent.getData(); if (mFileUri != null) { mFilePath = Utils.getRealPathFromUri(mContext, mFileUri); mFilePath = mFilePath.replace("file://", ""); // do something such as display ImageView... } } break; case CAMERA_CAPTURE_IMAGE_REQUEST_CODE: if (resultCode == Activity.RESULT_OK) { if (mFileUri != null) { mFilePath = mFileUri.toString(); mFilePath = mFilePath.replace("file://", ""); // do something such as display ImageView... } } break; } // refresh phone's folder content if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); mediaScanIntent.setData(mFileUri); getActivity().sendBroadcast(mediaScanIntent); } else { getActivity().sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); } } 

工具类:

 //returning image, video public static File getOutputMediaFile(int type) { // External sdcard location File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "DCIM/Camera"); // Create the storage directory if it does not exist if (!mediaStorageDir.exists()) { if (!mediaStorageDir.mkdirs()) { return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); } else if (type == MEDIA_TYPE_VIDEO) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp + ".mp4"); } else { return null; } return mediaFile; } //For select picture public static String getRealPathFromUri(Context context, Uri contentUri) { Cursor cursor = null; try { String[] proj = {MediaStore.Images.Media.DATA}; cursor = context.getContentResolver().query(contentUri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } finally { if (cursor != null) { cursor.close(); } } }