android 7.0 download and install apk遇到的问题

android 7.0 download and install apk遇到的问题



背景:还有十天过年,哈哈,今年的成就就是四川移动项目了。不过,最近android7.0出来以后,同事反馈,他的华为mate9,在下载完更新包以后,无法进入到安装流程,这这这。。。这是什么情况,于是进入到了一天的埋头挖土环节。下面就将这天的经历记录下来,供解决问题的思路和参考。


问题1:先说说下载过程,下载完成后,曾经出现过安装包解析错误的问题。

分析:安装包解析错误,一般原因有:
1,、intent配置有误(可以对照google官方intent参数配置,下面的例子也会给出);
2、下载的安装包缺失或者不完整(可以通过adb shell命令查看安装包是否正常);
3、下载到了错误的路径(安装包如果储存在internal中,会遇到安装包解析错误)。

解决方案:我这里出现安装包解析错误的原因是下载到了internal中(也就是context.getFilesDir()),解决方案就是将下载路径切换到external存储中。这里的external存储可以通过Context.getExternalxxx()和Enviroment.getExternalxxx()两种方式配置,区别在于:Context.getExternalxxx()是context当前app的外部存储,6.0以后不需要授予外部存储权限也能进行读写操作;而Enviroment.getExternalxxx()是整个操作系统环境的外部存储,6.0以后,进行读写操作需要授予外部存储权限。以下是异步下载任务的安装包文件创建过程代码片段:
[html]  view plain  copy
  1. public DownloadTask() {  
  2.     File tempPath = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "apk");//外部存储路径  
  3.     if (!tempPath.exists()) {//创建目录  
  4.         try {  
  5.             tempPath.mkdir();  
  6.         } catch (Exception e) {  
  7.             e.printStackTrace();  
  8.         }  
  9.     }  
  10.     File apkFile = new File(tempPath, "apk.apk");//外部存储路径下的apk文件  
  11.     if (apkFile.exists()) {//防止文件过多  
  12.         try {  
  13.             apkFile.delete();  
  14.         } catch (Exception e) {  
  15.             e.printStackTrace();  
  16.         }  
  17.     }  
  18. }  


问题2:上面的文件创建好以后,就是进入到下载过程,下载过程就是根据网络url将apk写入上述文件中,这里就不说明了,不清楚可以google。下面就来说说apk文件下载完毕后的安装,在安装的时候啊,7.0不能启动apk的安装页面。

分析:不行了,不行了,怎么就不行了呢,后来通过google和查询官方文档,找到原因。启动安装页面的思路通常是往intent里面传递action个、flags、uri等参数,然后通过startActivity(Intent)的方式。7.0以前和7.0以后这些参数的配置就不太一样了。
7.0以前,配置action:Intent.setAction(Intent.ACTION_VIEW);配置flags:Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);配置uri:Intent.setDataAndType(Uri.fromFile(问题1中的apkFile),"application/vnd.android.package-archive")。
7.0以后,配置action:Intent.setAction(Intent.ACTION_INSTALL_PACKAGE);配置flags:Intent.setFlags(Intent.FLAG_GRANT_URI_PERMISSION);配置uri:Intent.setDataAndType(FileProvider.getUriForFile(context, "manifest中的provider,下面的例子会讲到", 问题1中的apkFile),"application/vnd.android.package-archive")。

解决方案:android7.0以前,下面的例子涉及较少,不过完全够用,这里重点讲android7.0以后,正确启动apk安装页面的3个姿势,姿势不对,可能无法安装可能抛出如FileUriExposedException的异常(所有的姿势,都是依据google android7.0新玩儿法api: 7.0Changes 和  FileProvider)。
1、在工程的res目录下,创建xml目录,并在xml目录中,创建file_paths.xml文件:作用是存放uri需要提供的文件信息。
[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <paths>  
  3.     <external-files-path        //对应的是Context.getExternalCacheDir()  
  4.         name="apk"<span style="white-space:pre;">       </span>//名字,传递给uri的,可以随意  
  5.         path="Download/apk/" <span style="white-space:pre;">    </span>//文件路径,填写上面问题1中的tempPath路径  
  6.         />  
  7. </paths>  
2、在manifest的application中,创建android.support.v4.content.FileProvider:作用是以provider的形式,提供uri所需的apk文件信息。
[html]  view plain  copy
  1. <provider  
  2.     android:name="android.support.v4.content.FileProvider"  
  3.     android:authorities="com.xxx.xxx.fileprovider"<!--com.xxx.xxx为项目包名-->  
  4.     android:exported="false"  
  5.     android:grantUriPermissions="true">  
  6.     <meta-data  
  7.         android:name="android.support.FILE_PROVIDER_PATHS"  
  8.         android:resource="@xml/file_paths" />  
  9. </provider>  
3、启动apk安装页面。
[html]  view plain  copy
  1. Intent intent = new Intent();  
  2. Uri uri;  
  3. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//7.0启动姿势  
[html]  view plain  copy
  1. //com.xxx.xxx.fileprovider为上述manifest中provider所配置相同;apkFile为问题1中的外部存储apk文件  
uri = FileProvider.getUriForFile(context, "com.xxx.xxx.fileprovider", apkFile);
intent.setAction(Intent.ACTION_INSTALL_PACKAGE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//7.0以后,系统要求授予临时uri读取权限,安装完毕以后,系统会自动收回权限,次过程没有用户交互} else {//7.0以下启动姿势 uri = Uri.fromFile(apkFile); intent.setAction(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}intent.setDataAndType(uri, "application/vnd.android.package-archive");context.startActivity(intent);
 
 

当然,详细的姿势,可以参考google官网。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值