Android 12中拍照或扫描二维码后应用崩溃问题求助
解决Android 12下拍照/扫描二维码后应用崩溃问题
问题说明
应用支持拍照和扫描二维码功能,在Android 12以外的所有版本运行正常,但在Android 12系统中执行拍照或扫码操作后会崩溃。
相关代码
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (cameraIntent.resolveActivity(getPackageManager()) != null) { java.io.File photoFile = null; try { photoFile = createImageFile(); } catch (java.io.IOException ex) { android.widget.Toast.makeText(this, "Error occure while creating image file", android.widget.Toast.LENGTH_LONG).show(); } if (photoFile != null) { cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.net.Uri.fromFile(photoFile)); startActivityForResult(cameraIntent, CAMERA_RESULT); } }
崩溃日志
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=3001, result=-1, data=Intent { (has extras) }} to activity {com.xxxxx/com.xxxx.xxxxx}: java.lang.NullPointerException: Attempt to read from field 'org.apache.cordova.PluginManager org.apache.cordova.CordovaWebView.pluginManager' on a null object reference in method 'void org.apache.cordova.CordovaActivity.onActivityResult(int, int, android.content.Intent)' android.app.ActivityThread.deliverResults(ActivityThread.java:5567) android.app.ActivityThread.performResumeActivity(ActivityThread.java:4953) android.app.ActivityThread.handleResumeActivity(ActivityThread.java:5017) android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:60) android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) android.app.ActivityThread$H.handleMessage(ActivityThread.java:2374) android.os.Handler.dispatchMessage(Handler.java:106) android.os.Looper.loopOnce(Looper.java:233) android.os.Looper.loop(Looper.java:344) android.app.ActivityThread.main(ActivityThread.java:8248) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)
原因分析
- File Uri权限问题:Android 7.0+已禁止直接使用
Uri.fromFile()传递文件路径,Android 12对此限制更严格,会导致相机应用无法访问文件,间接触发Activity生命周期异常。 - Cordova Activity回收问题:Android 12对后台Activity回收逻辑更严格,启动相机后原Cordova Activity可能被系统回收,恢复时
CordovaWebView或PluginManager为空,导致onActivityResult回调抛出空指针。
解决方案
1. 替换File Uri为FileProvider
- 在
AndroidManifest.xml中注册FileProvider:<application> <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> </application> - 在
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> - 修改代码中的Uri生成逻辑:
if (photoFile != null) { Uri photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(cameraIntent, CAMERA_RESULT); }
2. 修复Cordova onActivityResult空指针
- 重写CordovaActivity的
onActivityResult方法,增加空指针判断:@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (this.appView != null && this.appView.getPluginManager() != null) { super.onActivityResult(requestCode, resultCode, intent); } else { // 暂存结果,待Activity恢复后处理 if (resultCode == RESULT_OK && requestCode == CAMERA_RESULT) { SharedPreferences prefs = getSharedPreferences("CameraTemp", MODE_PRIVATE); prefs.edit().putString("temp_photo_path", photoFile.getAbsolutePath()).apply(); } } } - 在
onCreate中添加结果恢复逻辑:@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 检查暂存的拍照结果 SharedPreferences prefs = getSharedPreferences("CameraTemp", MODE_PRIVATE); String tempPhotoPath = prefs.getString("temp_photo_path", null); if (tempPhotoPath != null) { // 处理拍照结果(如显示图片、传递给业务逻辑) handleCapturedPhoto(tempPhotoPath); prefs.edit().remove("temp_photo_path").apply(); } }
3. 优化Activity生命周期配置
在AndroidManifest.xml中给目标Activity添加配置,减少系统回收概率:
<activity android:name=".YourCordovaActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" android:exported="true"> </activity>
内容的提问来源于stack exchange,提问作者suresh
相关产品推荐
相关产品推荐

