FileProvider.getUriForFile空指针异常求助:旧Android相机拍照修复
修复旧Android APP相机拍照功能时的FileProvider空指针问题
时隔10年重新回到Android开发,尝试修复一款旧APP的相机拍照功能,执行以下代码时:
public void photoIntent() { Log.d("MainActivity", "photoIntent"); Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); File photo = null; try { File outputDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); // context being the Activity pointer photo = new File(outputDir+"picture.jpg"); // place where to store camera taken picture //photo.delete(); } catch (Exception e) { Log.d("MainActivity", "Can't create file to take picture!"); } *Uri mImageUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID+".fileprovider", photo);* intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); // start camera intent this.startActivityForResult(intent, 1); }
在Uri mImageUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID+".fileprovider", photo);行出现空指针异常:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:583) at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:557) at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:399) at com.marzinp.mycelium.MainActivity.photoIntent(MainActivity.java:96) at com.marzinp.mycelium.MainActivity$1.onClick(MainActivity.java:69) at android.view.View.performClick(View.java:7892) at android.widget.TextView.performClick(TextView.java:16220) at android.view.View.performClickInternal(View.java:7869) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:30891) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8762) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
当前配置
Manifest文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.marzinp.mycelium" android:versionCode="112" android:versionName="1.1.2" > <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="33" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/lombric" android:label="@string/app_name" android:theme="@style/AppTheme" > <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.marzinp.mycelium.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/> </provider> <activity android:name="com.marzinp.mycelium.MainActivity" android:configChanges="orientation|screenSize" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
res/xml/provider_paths文件:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android" <external-path name="external_files" path="Pictures" /> </paths>
解决方案
匹配FileProvider的authorities参数:代码中使用的authorities是
BuildConfig.APPLICATION_ID+".fileprovider"(即com.marzinp.mycelium.fileprovider),但Manifest里配置的android:authorities是com.marzinp.mycelium.provider,二者不匹配。将Manifest中的android:authorities修改为com.marzinp.mycelium.fileprovider,或者将代码中的authorities参数改为com.marzinp.mycelium.provider,保证两边一致。修复provider_paths的XML语法错误:原文件中
<paths>标签未正确闭合,缺少末尾的>,正确的内容应为:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="Pictures" /> </paths>
- 处理photo为空的情况:代码中try块如果创建文件失败,
photo会为null,直接调用FileProvider.getUriForFile会导致崩溃。需要在调用前增加非空判断:
if (photo != null) { Uri mImageUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID+".fileprovider", photo); intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); this.startActivityForResult(intent, 1); } else { Log.e("MainActivity", "Failed to create photo file"); // 可在此处添加用户提示,比如Toast }
- 确认FileProvider依赖:由于使用的是
android.support.v4.content.FileProvider,需确保项目中已正确引入support-v4库;如果项目已迁移到AndroidX,建议替换为androidx.core.content.FileProvider,并同步修改Manifest中的android:name属性及meta-data中的name为androidx.core.content.FileProvider。
内容的提问来源于stack exchange,提问作者Pierre Marzin
相关产品推荐
相关产品推荐

