Camera Crashing求助:Android相机拍照后点OK键应用崩溃问题
Hey there, let's figure out why your app crashes when tapping "Ok" after taking a photo! You mentioned the image saves correctly to the target folder, so the issue is likely in how you handle the result after the camera returns. Here are some common fixes to try:
1. 检查Uri的FileProvider配置(Android 7.0+必看)
If you're targeting Android 7.0 or higher, using a plain file:// Uri will trigger a FileUriExposedException when the camera tries to return the result. This is a super common cause of crashes here.
- Fix steps:
- Add a FileProvider entry in your
AndroidManifest.xml:<application> ... <provider android:name="androidx.core.content.FileProvider" android:authorities="com.example.tauheed.cameraapplication.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application> - Create a
res/xml/file_paths.xmlfile to define the directory you're saving photos to:<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="my_images" path="Pictures" /> <!-- 或者根据你的存储目录调整,比如external-path对应外部根目录 --> </paths> - When launching the camera, generate the output Uri using
FileProvider.getUriForFile()instead ofUri.fromFile():private Uri photoUri; private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); // 你的创建图片文件方法 } catch (IOException ex) { // 处理文件创建失败的情况 } if (photoFile != null) { photoUri = FileProvider.getUriForFile(this, "com.example.tauheed.cameraapplication.fileprovider", photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } } }
- Add a FileProvider entry in your
2. 不要从返回的Intent获取data(当指定了EXTRA_OUTPUT时)
When you set MediaStore.EXTRA_OUTPUT to your custom Uri, the camera app won't return the image data in the Intent parameter of onActivityResult (it'll be null). If you're trying to call data.getData() here, that'll throw a NullPointerException.
- Fix:
In youronActivityResult(or Activity Result API callback), use the pre-savedphotoUrior the photo file path directly to load the image:@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { // 直接用你之前创建的photoFile或photoUri加载图片,不要用data.getData() Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath()); // 后续显示或处理图片的逻辑 } }
3. 验证权限配置(尤其是高版本Android)
Even though the image saves successfully, you might be missing the necessary permissions to read the image when returning to your app.
- For Android 12 and below: Ensure you've requested
WRITE_EXTERNAL_STORAGE(and granted it) dynamically. - For Android 13+: Request
READ_MEDIA_IMAGESinstead, since storage permissions were restructured. - Example permission check code:
private static final int REQUEST_PERMISSIONS = 100; private void checkPermissions() { String[] permissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { permissions = new String[]{Manifest.permission.READ_MEDIA_IMAGES}; } else { permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; } if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, permissions, REQUEST_PERMISSIONS); } else { dispatchTakePictureIntent(); // 权限已授予,启动相机 } }
4. 避免图片解码时的内存溢出
High-resolution photos can cause an OutOfMemoryError when you try to load them directly with BitmapFactory.decodeFile.
- Fix: Use
BitmapFactory.Optionsto sample the image down to a manageable size:
Then use this method to load your image:private Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); // 计算采样率 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(path, options); } private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }Bitmap bitmap = decodeSampledBitmapFromFile(photoFile.getAbsolutePath(), 1080, 1920); // 按需调整目标尺寸
5. 调试空指针或其他异常
If none of the above works, add log statements or use breakpoints to check which line is causing the crash. For example:
- Is
photoFilenull when you try to access its path? - Is
photoUrinull inonActivityResult? - Are you calling any methods on a null object (like
ImageView.setImageBitmap(null))?
内容的提问来源于stack exchange,提问作者shellac85

