Android 7.0解析包时出现问题 的解决方案(应用内更新)

原创 2017年02月16日 18:59:34

在工作上遇到了一个关于下载更新安装包无法安装的问题,解决之后特地在这里做一个笔记,遇到相似问题的朋友可以试试看能不能解决自己的问题。

问题描述

我们在进行Android开发的时候,一般都会在应用里检测有没有更新,并且从网上下载最新的版本包,覆盖本地的旧版本。在我的项目中,出现了一个问题,就是当安装包下载到本地的时候,产生了“解析包时出现问题”这样的错误,导致无法安装相应的新版本。同时,值得一提的是,这个问题只有在我们用代码调用去进行安装的时候才会发生,我们手动去用安装包覆盖本地的旧包则没有出现问题。经过反复的测试,发现这个问题只会发生在Android 7.0版本的设备上,在较低版本的设备上则无这个问题。

解决方案1

这也是在网上比较通用的方案,就是在打包的时候我们使用了V2签名导致无法进行安装。
Android 7.0 引入一项新的应用签名方案 APK Signature Scheme v2,它能提供更快的应用安装时间和更多针对未授权 APK 文件更改的保护。在默认情况下,Android Studio 2.2 和 Android Plugin for Gradle 2.2 会使用 APK Signature Scheme v2 和传统签名方案来签署应用。
这项新方案并非强制性的,如果应用在使用 APK Signature Scheme v2 时不能正确开发,可以停用这项新方案。禁用过程会导致 Android Studio 2.2 和 Android Plugin for Gradle 2.2 仅使用传统签名方案来签署应用。要仅用传统方案签署,打开模块级 build.gradle 文件,然后将行 v2SigningEnabled false 添加到版本签名配置中:

android {

defaultConfig { … }
signingConfigs {
release {
storeFile file(“myreleasekey.keystore”)
storePassword “password”
keyAlias “MyReleaseKey”
keyPassword “password”
v2SigningEnabled false
}
}
}
根据官方文档,就是在我们的gradle文件里的相应位置添加这行代码

v2SigningEnabled false

即可(如上)。

解决方案2

但是,在我的情境中,即使使用了方案一,仍然在更新包下载完成后显示了“解析包时出现问题”这样的字样,导致下载更新流程出错。
这个时候,就有可能是另外一种情况:当我们在7.0上使用系统服务去下载apk并且试图安装时,有可能由于权限问题导致安装失败。
每个Android版本的发布,对于安全性问题的要求越来越高,也为Android程序员增加了额外的工作量。Android6.0引入动态权限控制(Runtime Permissions),Android7.0引入私有目录被限制访问StrictMode API私有目录被限制访问是指在Android7.0中为了提高应用的安全性,在7.0上应用私有目录将被限制访问,这与iOS的沙盒机制类似。StrictMode API是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,则会报出异常。
以下是我原来在7.0上出问题的代码:

Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);

从代码中可以看出,Uri.fromFile导致我们在7.0上出现了问题,它其实就是生成一个file://URL。这就是为什么在下载完成后,调用这段代码去安装的时候出错,因为一旦我们通过这种办法打开系统安装器,就认为file:// URI类型的 Intent 离开我的应用,这样程序就会发生异常;而我们手动去把安装包覆盖原来的旧包则没有问题。

解决方案将使用FileProvider,它的步骤是:

  • 第一步:
    在AndroidManifest.xml中注册provider,provider可以向应用外提供数据。
<provider
   android:name="android.support.v4.content.FileProvider"
   android:authorities="com.dafangya.app.pro.fileprovider"
   android:grantUriPermissions="true"
   android:exported="false">
   <meta-data
       android:name="android.support.FILE_PROVIDER_PATHS"
       android:resource="@xml/file_paths" />
</provider>

其中com.dafangya.app.pro是我的应用包名。

  • 第二步:
    在res/xml/file_paths.xml创建文件。 内容为:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path path="" name="download"/>
    </paths>
</resources>
  • 第三步:
String fileName = cursor.getString(fileNameIdx);//承接我的代码,filename指获取到了我的文件相应路径
if (fileName != null) {
    if (fileName.endsWith(".apk")) {
        if(Build.VERSION.SDK_INT>=24) {//判读版本是否在7.0以上
            File file= new File(fileName);
            Uri apkUri = FileProvider.getUriForFile(context, "com.dafangya.app.pro.fileprovider", file);//在AndroidManifest中的android:authorities值
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
            install.setDataAndType(apkUri, "application/vnd.android.package-archive");
            context.startActivity(install);
        } else{
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(install);
        }
    }
}

因为对于7.0以下的设备,还是走以前的逻辑,所以上面的代码进行分情况讨论,6.0及其以下的设备还是走以前的逻辑。

  • 第四步
    按照大部分教程来说,第四步其实是不存在的,但是在我的项目中,运行到第三步中的代码时,还是报错了,错误如下:
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=com.dafangya.app.pro (has extras) } in com.b.b.a.a.e$1@457cfd2
    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1229)
    at android.os.Handler.handleCallback(Handler.java:755)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6524)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)
Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.android.providers.downloads/cache/product_other_V1.4.8ceshi.apk
    at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:678)
    at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:377)
    at com.example.xh.toolsdk.umeng.Downloads$1.onReceive(Downloads.java:95)
    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1219)
    ... 7 more

由Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains…可见应该是我们的安装包目录出现了问题。因为使用我们当前方法的时候,我们主要通过系统提供的DownloadManager进行下载,我们不妨从下载角度来看我们是否可以自己设置一个下载目录。
代码如下:

public void submit(String name, String url) {
    DownloadManager download = getDownLoadManager();
        Uri uri = Uri.parse(url);
        DownloadManager.Request request = new DownloadManager.Request(uri);
        request.setTitle(String.valueOf(name));
        //设置下载存放的文件夹和文件名字
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "dafangya_house.apk");
        try {
            downloadId = download.enqueue(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
}

我在原来的代码中添加了这一行:request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, “dafangya_house.apk”);
设置了它的下载路径,在进行测试的时候,发现无论在7.0还是低版本的设备上都可以正常下载更新了,我的这个bug算是解决了。

一般大家出现类似bug,可以先看方案一,方案一也是最主流的解决方式。但一旦不是签名的问题,也可以尝试方案二,看是否是代码调用系统安装器导致的权限问题。如果是安装路径的话,要保证安装路径和下载路径的一致性。
希望可以对遇到类似问题的朋友能有所帮助,本文参考了别的前辈的文章,再次感谢。

Android 7.0 开发者版本
下载安装APK

版权声明:本文为博主原创文章,未经博主允许不得转载。

android错误之解析包时出现问题(一)

类越来越多,有点乱,强迫症,多弄了几个包,整理的井井有条,心里那个舒服,结果问题就来了 无法安装了,总是显示“解析包时出现问题”,最烦的就是这种问题,一点技术含量都没有的小问题却要浪费大量时间去找原因...
  • jason0539
  • jason0539
  • 2013年10月01日 17:59
  • 45034

Android7.0应用程序自助更新跳转安装界面出现解析包出错

安卓APP检测到新版本,用户同意更新后,就到服务器下载最新的APP,下载到一个文件夹内,通过固定写法: Intent intent = new Intent(Intent.ACTION_VIEW); ...
  • qq_31588719
  • qq_31588719
  • 2017年08月16日 10:07
  • 1503

Android解析包时出现问题

今天使用Anroid Studio安装weiciyuan项目https://github.com/qii/weiciyuan 编译的时候发生了,解析包时出现问题错误。 在安装apk的时候弹...
  • zhuhai__yizhi
  • zhuhai__yizhi
  • 2015年03月04日 20:16
  • 577

安卓安装apk时出现“解析程序包时出现错误” 的解决方法

测试升级的时候发现安卓7.0以上的版本出现升不了级的情况    百度找到答案   第一步:根据安卓版本适配不同的apk打开方式 File file = new File(apkPath); //...
  • qq_34379916
  • qq_34379916
  • 2018年01月11日 11:00
  • 35

版本更新时出现解析包错误

问题场景是:软件从1.2.4升级到1.3.0的过程中出现了如题的问题即下载后安装时出现“解析包时出现问题”的错误后停止。而且不是所有的手机都会出现这个问题,在华为2.2系统的测试机上是可以成功安装的,...
  • zhourui_1021
  • zhourui_1021
  • 2016年11月17日 13:20
  • 1654

android之解析包时出现错误(二)

为什么是二呢,之前遇到过一次了,详见http://blog.csdn.net/jason0539/article/details/12222173 这次的原因不同,再记录下 public class ...
  • jason0539
  • jason0539
  • 2014年03月21日 20:44
  • 24351

安装apk解析包时出现错误(应用内更新)

最近遇到一个问题,有个别用户在应用内更新版本会出现解析包失败的情况,而且有的机型还是必现,浏览器下载就没问题,应用内就有问题,这就很让人费解,之前一直没关注过这种情况,但是用户就是上帝,有问题必须得解...
  • geqian2010
  • geqian2010
  • 2017年07月24日 10:59
  • 4675

安卓安装apk时出现“解析程序包时出现错误” 的解决方法

测试升级的时候发现安卓7.0以上的版本出现升不了级的情况    百度找到答案   第一步:根据安卓版本适配不同的apk打开方式 File file = new File(apkPath); //...
  • qq_34379916
  • qq_34379916
  • 2018年01月11日 11:00
  • 35

更新应用程序安卓apk时出现解析程序包时出现问题

在一次工作中,需求是进入应用程序splash时检测版本,发现新版本提示用户进行更新,更新好后就自动跳转安装界面。     我当时是把用户点击更新下载后的apk存放到data/data/package...
  • qq_31588719
  • qq_31588719
  • 2017年04月14日 09:26
  • 3368

Android APK安装常见错误列表

adb的安装过程分为传输与安装两步。 在出错后,adb会报告错误信息,但是信息可能只是一个代号,需要自己定位分析出错的原因。      下面是从网上找到的几种常见的错误及解决方法: 1、INST...
  • tyxkzzf
  • tyxkzzf
  • 2015年08月04日 23:53
  • 9117
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android 7.0解析包时出现问题 的解决方案(应用内更新)
举报原因:
原因补充:

(最多只允许输入30个字)