Android 7.0下载Apk后自动安装

今日科技快讯

有爆料称:自6月1日起,大量的乐视手机供应商聚集在朝阳区乐视大厦门口,口中高喊“乐视还钱!”这些供应商有的来自河南,有的来自成都。现场目击者称直到6月2日下午5点,乐视手机方面无人出面安抚一众供应商。

作者简介

大家早上好,新一周又开始啦!

本篇来自 cfy137000 的投稿,分享了如何在7.0下下载并安装apk,希望对大家有所帮助。

cfy137000 的博客地址:

http://blog.csdn.net/cfy137000

整体需求

1. 下载APK文件

  • 使用 DownloadManager 来下载

  • 在应用界面中展示下载进度

2. 安装下载后的APK文件

  • root模式: 可以自动安装,不需要用户主动点击

  • 正常模式: 弹出安装应用页面,需要兼容7.0以上版本

DownloadManager

DownloadManager 是 Android 提供的用于下载的类,使用起来比较简单,它包含两个静态内部类 DownloadManager.Query 和 DownloadManager.Request;

DownloadManager.Request 用来请求一个下载,DownloadManager.Query 用来查询下载信息

下载

1. 获取 DownloadManager 对象

DownloadManager对象 属于系统服务,通过 getSystemService 来进行安装

DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

一般获取完成后会变成全局变量,方便之后使用

2. 开始下载

在使用 DownloadManager 进行下载的时候,就会用到 DownloadManager.Request

首先会创建出一个 DownloadManager.Request对象,在构造方法中接收 Uri,其实就是下载地址.

然后是文件的存放路径,这里需要说明,DownloadManager 下载的位置是不能放到内置存贮位置的,必须放到 Enviroment 中,这里建议放到自己应用的文件夹,不要直接放到 SD卡 中,也就是通过 getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) 获取到的路径,该位置的文件是属于应用自己的,在应用卸载时也会随着应用一起被删除掉,并且在使用该文件夹的时候,是不需要 SD卡 读写权限的

然后通过 request.setDestinationUri 来设置存储位置,最后将请求加入到 downloadManager 中,会获得一个 downloadID,这个 downloadID 比较重要,之后下载状态,进度的查询都靠这个 downloadID

进度查询

在查询下载进度的时候,会通过 downloadId 来指定查询某一任务的具体进度:

在查询进度的时候会使用到 DownloadManager.Query 这个类,在查询的时候,也是使用的 Cursor,跟查询数据库是一样的,进度信息会需要拿到文件的总大小,和当前大小,自己算一下,最后 Cursor对象 在使用过后不要忘记关闭了

下载完成

下载完成后,DownloadManager 会发送一个广播,并且会包含 downloadId 的信息:

注册这个广播接收者

其他

这里需要注意一点,在下载完成后需要提升一下文件的读写权限,否则在安装的时候会出现apk解析失败的页面,就是别人访问不了我们的apk文件

chmod 是Linux下设置文件权限的命令,后面的三个数字每一个代表不同的用户组 
权限分为三种:读(r=4),写(w=2),执行(x=1)

那么这三种权限就可以组成7种不同的权限,分别用1-7这几个数字代表,例如7 = 4 + 2 + 1,那么就代表该组用户拥有可读,可写,可执行的权限;5 = 4 + 1,就代表可读可执行权限

而三位数字就带包,该登陆用户,它所在的组,以及其他人

安装

普通模式

  • 7.0之前

在7.0之前安装的时候,只需要通过 隐式Intent 来跳转,并且指定安装的文件 Uri 即可

  • 7.0之后

在Android7.0之后的版本运行上述代码会出现 android.os.FileUriExposedException 
“私有目录被限制访问”是指在 Android7.0 中为了提高私有文件的安全性,面向 Android N 或更高版本的应用私有目录将被限制访问。

而7.0的” StrictMode API 政策” 是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常。之前代码用到的Uri.fromFile就是商城一个file://的Uri 在7.0之后,我们需要使用 FileProvider 来解决

第一步:在 AndroidManifest.xml 清单文件中注册 provider

需要注意一下几点:

  • exported:必须为 false

  • grantUriPermissions : true,表示授予 URI 临时访问权限。

  • authorities 组件标识,都以包名开头,避免和其它应用发生冲突。

第二步: 指定共享文件的目录,需要在 res文件夹 中新建 xml 目录,并且创建 file_paths

path=”“,是有特殊意义的,它代表根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了。

第三步:使用 FileProvider

相较于之前的代码,会把 Uri 改成使用 FiliProvider 创建的 Uri,并且添加 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) 来对目标应用临时授权该 Uri 所代表的文件,而且 getUriForFile 中的 authority 参数需要填写清单文件中的 authorities 的值

  • 混合

兼容 7.0 的安装代码是不能在 7.0 之前的版本运行的,这个时候就需要进行版本的判断了:

root模式

如果应用已经获取了 root 权限了,那么我们可以实现自动安装,即不会出现应用安装的页面,会在后台自己慢慢的安装,这个时候使用的就是用代码去写命令行了

这个方法就是将命令写入到手机的 shell 中,su 就代表 root 权限了,而命令执行成功的话,会返回0的,接下来是安装命令

String command = "pm install -r " + mApkPath;

-r 代表强制安装,否则如果手机中已有该应用的话就会安装失败了,值得注意的是,要想等待命令执行的结果这个过程是很漫长的,所以在使用命令的时候是需要放到主线程中的

整体项目

在写完整代码的时候需要把下载的代码写到 Service 中,否则你的 downloadid 就得通过别的方式去存储了,而查询下载进度,也是需要一直去查了,那么就需要写一个循环,并且放到子线程中,我们用 RxJava 做会比较舒服

由于代码偏多,我这边就不贴出了,感兴趣的朋友可以点击最后 阅读原文 查看,或者访问下面地址, 下载源码查看:

http://download.csdn.net/download/cfy137000/9820195

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值