最近刚刚把古老的项目targetSdk版本升级到26,升级之前是19(非常非常古老了)。那么升级后一些问题开始出现。

Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他无关应用。在应用权限设置的“特殊访问权限”中,加入了“安装其他应用”的设置,默认是关闭的。所以安装时需要授权用户去开启。

实现

1.清单文件权限声明

<uses-permissionandroid:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

  

2.点击安装判断是否有权限

    if (Build.VERSION.SDK_INT >= ) {
//来判断应用是否有权限安装apk
boolean installAllowed= getPackageManager().canRequestPackageInstalls();
//有权限
if (installAllowed) {
//安装apk
install(apkPath);
} else {
//无权限 申请权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, INSTALL_APK_REQUESTCODE);
}
} else {
install(apkPath);
}

权限申请回调

 @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case INSTALL_APK_REQUESTCODE:
//有注册权限且用户允许安装
if (grantResults.length > && grantResults[] == PackageManager.PERMISSION_GRANTED) {
install(apkPath);
} else {
//将用户引导至安装未知应用界面。
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);
}
break;
}
}

安装APK

    private void install(String apkPath) {
//7.0以上通过FileProvider
if (Environment.SYSTEM_VERSION_CODE >= ) {
Uri uri = FileProvider.getUriForFile(context, Environment.FILE_PROVIDER_AUTHORITY, new File(apkPath));
Intent intent = new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + apkPath), "application/vnd.android.package-archive");
context.startActivity(intent);
}
}

这里需要注意的是7.0引入了“私有目录被限制访问”,“StrictMode API 政策”。” StrictMode API 政策” 是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常。

上面用到的代码中的Uri.fromFile 其实就是生成一个file://URL。一旦我们通过这种办法打开其它程序(这里打开系统包安装器)就认为file:// URI类型的 Intent 离开你的应用。这样程序就会发生异常。

解决办法:

FileProvider来解决这一问题,首先在清单文件中添加:

         <!-- FileProvider配置访问路径,适配7.0及其以上-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>

authorities:app的包名;fileProvider grantUriPermissions:true;表示授予 URI 临时访问权限 exported:false ; resource:下一步添加的文件。

然后在res下新建一个名为xml的文件家,再新建文件provider_paths:

 <?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="files_root"
path="Android/data/com.example.downloadapk/"/>
<external-path
name="external_storage_root"
path="."/>
</paths>

path:需要临时授权访问的路径(.代表所有路径) name:给访问路径命名。

这样就可以完美解决7.0和8.0的问题啦!

BY LiYing

最新文章

  1. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
  2. VB6.0 和VB.NET 函数对比
  3. 常用JS效果 不断进步贴 不停更新~ 纪念用~
  4. 新增的querySelector、querySelectorAll测试
  5. ASP.NET fails to detect Internet Explorer 10
  6. BMP图像格式
  7. web前端面试试题总结---css篇
  8. CentOS安装与配置LNMP
  9. EnumMap demo
  10. iOS开发之如何修改导航栏的内容
  11. SQL_Server 常用语句以及语法整理
  12. linux开机默认启动命令行模式
  13. 【洛谷P1303 A*B Problem】
  14. Liunx之KVM搭建图形化的WEB
  15. web安全防范之SQL注入攻击、攻击原理和防范措施
  16. Mac上csv导入mysql提示错误[Error Code] 1290 - The MySQL server is running with the --secure-file-priv option解决办法
  17. 18B树、B++树和Trie树
  18. OAF 小知识
  19. Mongodb 与 SQL 语句对照表
  20. easyui------dialog如何固定位置

热门文章

  1. g++编译器的使用(转载)
  2. 动态规划:HDU3496-Watch The Movie(二维费用的背包问题)
  3. Python-S9-Day99——Web前端框架之Vue.js
  4. CentOS 7 编译安装最新版git
  5. 误删除pycharm项目中的文件,如何恢复?
  6. 用Excel的分列功能格式化时间
  7. linux开机关机自启动或自关闭服务的方式
  8. linux系统mysql密码修改脚本
  9. linux系统ssh远程连接检查脚本
  10. Mysql 死锁