Android 12+应用启动相机偶发崩溃,无日志且调试器断开
Android 12+ 相机偶发崩溃问题排查与修复
一、先修正致命的权限检查逻辑错误
当前权限检查代码完全颠倒,导致你无法正确判断相机权限状态,这是引发权限误判的核心原因:
// 错误代码逻辑:判断未授权时,却打印"Permission granted" if (ContextCompat.checkSelfPermission(DocCollectionActivity.this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) { Log.e(TAG, "onCameraClickListener: Permission granted"); }
正确的权限处理方式
// 1. 检查相机权限 if (ContextCompat.checkSelfPermission(DocCollectionActivity.this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) { Log.e(TAG, "onCameraClickListener: 相机权限未授权"); // 发起权限申请 registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { launchCamera(); // 权限通过后启动相机 } else { // 处理权限拒绝逻辑,比如引导用户到设置页开启 } }).launch(Manifest.permission.CAMERA); } else { Log.d(TAG, "onCameraClickListener: 相机权限已授权"); launchCamera(); } // 2. 特殊权限 MANAGE_APP_ALL_FILES_ACCESS_PERMISSION 的单独处理 if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); }
二、适配Android 12+ 相机文件输出URI
直接传递自定义URI给MediaStore.EXTRA_OUTPUT,在Android 12+会因文件权限限制导致相机无法写入,进而引发偶发崩溃。改用FileProvider生成安全URI是标准解决方案:
1. 注册FileProvider(AndroidManifest.xml)
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
2. 创建文件路径配置(res/xml/file_paths.xml)
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="camera_photos" path="Pictures/" /> </paths>
3. 修改图片URI生成逻辑
public static Uri setImageUri(Context context) { // 用应用私有目录存储临时照片,避免权限问题 File photoDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); File photoFile = new File(photoDir, "temp_camera_photo_" + System.currentTimeMillis() + ".jpg"); return FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", photoFile); }
4. 启动相机时添加URI临时授权
private void launchCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri photoUri = GeneralFunctions.setImageUri(DActivity.this); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); // 给相机应用授予临时读写权限,避免写入失败 List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; grantUriPermission(packageName, photoUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); } startActivityForResult(intent, ConstantVariables.IMAGE_REQUEST_CODE); }
三、调试器断开&无日志问题排查
偶发崩溃且调试器断开,大概率是Native层崩溃,Java层Logcat不会输出相关日志,可通过以下方式排查:
- 打开Logcat的
No Filters过滤器,查看系统级崩溃日志(标记崩溃进程的DEBUG/ERROR日志); - 若设备已root,可读取
/data/tombstones目录下的崩溃 tombstone 文件,分析Native层崩溃原因; - 在build.gradle中开启Native调试开关:
android { buildTypes { debug { debuggable true jniDebuggable true } } }
内容的提问来源于stack exchange,提问作者komal Mane
相关产品推荐
相关产品推荐

