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

 具体原因:

为了提高私有目录的安全性,防止应用信息的泄漏,从 Android 7.0 开始,应用私有目录的访问权限被做限制。具体表现为,开发人员不能够再简单地通过 file:// URI 访问其他应用的私有目录文件或者让其他应用访问自己的私有目录文件。

备注:如果你对应用私有目录不太清楚的话,可以阅读我的这篇文章:了解 Android 应用的文件存储目录,掌握持久化数据的正确姿势。

同时,也是从 7.0 开始,Android SDK 中的 StrictMode 策略禁止开发人员在应用外部公开 file:// URI。具体表现为,当我们在应用中使用包含 file:// URI 的 Intent 离开自己的应用时,程序会发生故障。

开发中,如果我们在使用 file:// URI 时忽视了这两条规定,将导致用户在 7.0 及更高版本系统的设备中使用到相关功能时,出现 FileUriExposedException 异常,导致应用出现崩溃闪退问题。而这两个过程的替代解决方案便是使用 FileProvider。
 

解决方法:

第一步:在Androidmanifes.xml中注册一个FileProvider

在项目所在的AndroidManifest.xml里面注册一个provider:

            

第二步:在res/下面新建一个xml文件夹,添加共享目录就是上面注册的resource/的地址:

目录结构如下:

文件内容:

<?xml version="1.0" encoding="utf-8"?>            

需要注意的是 path的填写和前面的external-path / external-cache-path 嘻嘻相关,具体关系如下:

<?xml version="1.0" encoding="utf-8"?>                                                        

path路径填写错误则会爆出以下错误:

java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.icfun.game.cn/cache/upgrade_apk/icfun_new.apk        at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:738)

其实 cache-path-external 等价于 /storage/emulated/0/Android/data/com.icfun.game.cn/cache

例如:我只需要在path中写上upgrade_apk即可找到我的apk的文件路径了

第三步:代码中生成Content URI 使用:

                    Uri uri;                    File file = new File(Uri.parse(downloadFileUrl).getPath());                    if (file.exists()) {                        if ((Build.VERSION.SDK_INT >= 24)) {//判读版本是否在7.0以上                            uri = FileProvider.getUriForFile(context, "com.qushuru.fileprovide", file);                        } else {                            uri = Uri.parse(downloadFileUrl);                        }                        startInstall(context, uri);
private boolean startInstall(Context context, Uri uri) {        Intent intent = new Intent();        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.setAction(Intent.ACTION_VIEW);        if ((Build.VERSION.SDK_INT >= 24)) {//判读版本是否在7.0以上            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件        }        intent.setDataAndType(uri, "application/vnd.android.package-archive");        context.startActivity(intent);        return true;    }

 

更多相关文章

  1. android的文件操作
  2. Android如何在xml布局中使用自定义属性
  3. cocos2d-x android
  4. android 文件管理工具类
  5. Android(安卓)应用文件路径
  6. android 文件管理工具类
  7. Android流量统计代码
  8. Android往SD卡上存储文件
  9. Android的文件系统结构

随机推荐

  1. Android进阶——Android事件分发机制之di
  2. Android(安卓)Service生命周期及用法!
  3. Android(安卓)使用WiFi打印
  4. Android之个性化ListView实现
  5. Android系统架构基本模式解析
  6. 如何实现android EditText允许输入字母和
  7. Android(安卓)ROM分析(1):刷机原理及方法
  8. Android(安卓)日历开发教程[六]
  9. Android(安卓)Studio 出现 Gradle's depe
  10. Android多点触控