android - FileProvider崩溃-attempting to invoke XmlResourceParser on a null object reference
在android 6.0及以后版本写SD都需要在manifest里面配置一个provider声明。
常见的manifest配置如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.angel.example" <!--包名 -->
android:versionCode="118"
android:versionName="118" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<application
android:name="com.angel.example.AsdApplication"
android:allowBackup="true"
android:allowTaskReparenting="true"
android:theme="@style/AsdTheme" >
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.angel.example.fileProvider" <!--格式:报名+fileprovider-->
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" /> <!-- 声明的路径列表 -->
</provider>
...
</application>
</manifest>
对应的路径授权声明,也就是xml/filepaths(请记住这是一个xml,且可以配置多个路径
):
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/com.angel.example/" name="files_root" />
<external-path path="." name="external_storage_root" />
<!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
<external-path name="beta_external_path" path="Download/"/>
<!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
<external-path name="beta_external_files_path" path="Android/data/"/>
<external-path name="external_image_files_path" path="DCIM/"/>
</paths>
代码使用provider示例,也就是调用provider授权的路径进行操作:
public class MediaStoreUpdate {
public static void updateAndBroadcast(Context context, File file) {
Log.e("msg", "file path" + file.getAbsolutePath());
// 其次把文件插入到系统图库
try {
MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 最后通知图库更新
Uri contentUri;
//适配不同的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
contentUri = FileProvider.getUriForFile(context, "com.angel.example.fileprovider", file);
} else {
contentUri = Uri.parse("file://" + file.getAbsolutePath());
}
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, contentUri));
}
}
最后报了异常信息,信息如下:
java.lang.NullPointerException
Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:560)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:534)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:376)
通过代码跟中发现,在取出了一个未赋值的provider,然后试图用这个未赋值的provider去loader路径(也就是上面配的xml)报空指针。报错代码:
ProviderInfo info = context.getPackageManager().resolveContentProvider(authority, 128);
XmlResourceParser in = info.loadXmlMetaData(context.getPackageManager(), "android.support.FILE_PROVIDER_PATHS");//报空指针
代码分析:
- 1.根据authorities取出的provider为空,那么就是不存在provider,但是列表里面已经配置。
- 2.因为authorities在manifest已经配置了,但是一个是字符串,在代码中也是利用字符串,把两个值拿出来对发现:
1. contentUri = FileProvider.getUriForFile(context, "com.angel.example.fileprovider", file);
2. android:authorities="com.angel.example.fileProvider" <!--格式:报名+fileprovider-->
代码中的fileprovider是小写,而manifest中的fileProvider为大写,终于找出问题。
把其中一个改(这里全部改为小写)以后再运行,发现代码成功。
总结:authorities的配置和代码中的配置为一个字符串,名字必须一致且符合(包名+名字)的规则。
当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »