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

这也是在网上比较通用的方案,就是在打包的时候我们使用了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

          

Android 解析包时出现问题 的解决方案(应用检查更新)的更多相关文章

  1. 解析包时出现错误,用代码安装apk出现问题

    Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file),"appli ...

  2. 抓包工具 - Fiddler(如何捕获Android数据包)

    如何捕获Android数据包 一.移动设备访问网络原理 先看看移动设备是怎么去访问网络,如图1所示,可以看到,移动端的数据包是从wifi出去的. 图1(移动设备访问网络) 所以我们可以把自己的电脑开启 ...

  3. android手机上安装apk时出现解析包错误的一个解决办法

    今天下午在学习安卓开发时,学习开发文档中的gridview时,在模拟器上调试程序一切正常,如下图所示: 但当将bin目录下的HelloGridView.apk拷贝到M8安卓系统后进行安装时,出现了“解 ...

  4. android之apk自动更新解析包失败问题

    在apk自动更新(相关问题可以看我的博客http://blog.csdn.net/caicongyang) 从服务器下载完成后,点击notification提示安装时,每次都报解析包失败错误!首先我想 ...

  5. 深入解析Android Design包——Behavior

    已经说过了,在AndroidDesign包中主要有两个核心概念:一是NestedScroll,另一个就是Behavior. 相比于NestedScroll这个概念来说,Behavior分析起来会难很多 ...

  6. Android程序进行混淆,在导出签名apk包时出错!

    今天终于完成了近一个月的App开发工作,对程序进行混淆导出签名apk包时,却出现了如下的错误: Proguard returned with error code 1. See console Not ...

  7. cocos2dx android版本移植时的Error format not a string literal and no format arguments解决方案

    原文地址 : http://www.cnblogs.com/hhuang2012/p/3336911.html cocos2dx android版本移植时的Error format not a str ...

  8. 【Android测试工具】Android抓包解析全过程

    需求原因 在android开发中,遇到socket编程,无法从log日志中查看到与之通讯的socket发送和返回的数据包是什么,这里介绍一个工具,tcpdump工具和wireshark工具查看抓到的内 ...

  9. Android 7.0 出现 ”FileUriExposedException“ 和 ”解析包出现错误“ 异常的解决办法

    问题1 :android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.xxx.xxx.xxx.rel ...

随机推荐

  1. 『忘了再学』Shell基础 — 6、Bash基本功能(输入输出重定向)

    目录 1.Bash的标准输入输出 2.输出重定向 (1)标准输出重定向 (2)标准错误输出重定向 (3)正确输出和错误输出同时保存 3.输入重定向 1.Bash的标准输入输出 我们前边一直在说,在Li ...

  2. 单例模式 | C++ | Singleton模式

    Singleton 模式 单例模式(Singleton Pattern)是 C++/Java等语言中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式实 ...

  3. printf()函数压栈a++与++a的输出

    printf()中a++与++a的输出问题 在C语言中有个很常用的函数printf(),使用时从右向左压栈,也就是说在printf("%d %d %d %d\n",a,a++,++ ...

  4. C语言泛型编程——泛型冒泡排序

    在实际编程中,常常会需要一些方法(函数),比如排序,它们具体实现基本一致,仅仅只有参数类型不同, 那么可不可以有一种通用的函数,不管是什么类型的参数都可以通用呢? 泛型编程:泛型即是指具有在多种数据类 ...

  5. MOS管防反接电路设计

    转自嵌入式单片机之家公众号 问题的提出 电源反接,会给电路造成损坏,不过,电源反接是不可避免的.所以,我们就需要给电路中加入保护电路,达到即使接反电源,也不会损坏的目的 01二极管防反接 通常情况下直 ...

  6. 居中的css:完全指南(翻译)

    这里主要参考的是CHRIS COYIER写的一篇的文章(点击查看),主要讲了关于css水平.垂直居中的一些方法,每个方法后面都有一个demo,可以在线查看效果. 1 水平 水平居中有行内元素和块元素, ...

  7. z-index和层叠上下文

    z-index基础介绍:三维坐标空间里,x轴通常用来表示水平位置,y轴来表示垂直位置,还有z轴来表示在纸面内外方向上的位置,像下面的图片一样: css允许的z-index的值是 ● auto (自动, ...

  8. 安卓性能测试之Lint测试

    pre { direction: ltr; color: rgba(0, 0, 10, 1); text-align: left } pre.western { font-family: " ...

  9. vuejs兄弟组件之间的通信

    var Event = new Vue();//准备一个空的实例对象 //A组件 var A = { template: ` <div> <span>我是A组件的数据-> ...

  10. linux 后台运行

    一般用 nohup program & 运行状态用cat nohup.txt查询 下面这种关了终端也不会停止 setsid program &>xx.log & 若是不需 ...