Android使用FileProvider获取缓存文件Uri时出现NullPointerException
这个NPE问题我之前处理过几次,从你的错误栈和代码来看,核心是FileProvider无法正确读取配置元数据或者上下文引用失效,下面分点给你分析和解决步骤:
一、先看错误根源
错误栈里的关键信息:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.PackageItemInfo.loadXmlMetaData(...)' on a null object reference
这说明FileProvider在尝试读取<meta-data>配置时,找不到对应的配置项,或者传入的Context有问题。
二、具体修正步骤
1. 修复Activity初始化顺序和Context引用
你的onCreate方法里把super.onCreate(savedInstanceState)放在了后面,这会导致Activity上下文未完全初始化就被赋值使用,而且onPostExecute里用的是Activity的成员context,不如直接用AsyncTask里持有的mContext更安全:
修改onCreate:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 必须放在第一行 PACKAGE_NAME = getApplicationContext().getPackageName(); context = this; new MyTask(getFileFromIntent(getIntent()), context).execute(); }
修改onPostExecute里的Uri获取代码:
@Override protected void onPostExecute(File outputFile) { if (outputFile == null) { finish(); return; } // 先确认文件存在 if (!outputFile.exists() || !outputFile.isFile()) { Log.e(TAG, "输出文件不存在: " + outputFile.getAbsolutePath()); finish(); return; } Uri uri; try { // 使用AsyncTask里的mContext,避免Activity上下文失效 uri = FileProvider.getUriForFile(mContext, PACKAGE_NAME, outputFile); } catch (Exception e){ Log.e(TAG, "获取临时文件Uri失败: ", e); return; } // 后续使用Uri的代码 };
2. 验证FileProvider的Manifest配置
你的Manifest配置看起来基本正确,但要注意几个细节:
- authority必须和代码中的PACKAGE_NAME完全一致:如果你的应用实际包名不是
com.example.package,要同步修改android:authorities的值,建议直接用${applicationId}自动匹配包名:<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> - meta-data的name不能写错:如果你用的是support库的
android.support.v4.content.FileProvider,name必须是android.support.FILE_PROVIDER_PATHS,大小写和拼写都不能错。 - 确认file_paths.xml存在且无语法错误:你的xml内容是对的,但要确保它在
res/xml/目录下,xmlns属性正确,标签都闭合。
3. 避免support和AndroidX混淆
如果你的项目已经迁移到AndroidX,建议改用AndroidX版本的FileProvider,避免兼容性问题:
- 替换Manifest里的provider:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="androidx.core.content.FileProvider.PATH" android:resource="@xml/file_paths" /> </provider> - 代码里的
FileProvider也要换成androidx.core.content.FileProvider。
4. 后台线程操作的问题
你在doInBackground里调用了MediaStoreUtil.updateFile(MyActivity.this, outputFile);,MediaStore的操作应该在主线程执行,建议移到onPostExecute里,避免线程安全问题和内存泄漏。
三、总结
最可能导致这个NPE的原因是Context引用失效或者FileProvider的配置不匹配,按照上面的步骤逐一排查,应该能解决问题。
内容的提问来源于stack exchange,提问作者PCB

