Android8.0、9.0安装包解析失败

2023-10-29

根据google官网得知,在8.0以上权限控制的更加严格,应用内安装下载更新的apk都需要申请“安装外面应用”权限才能去安装新应用,如果没有申请否则无法安装。

顺便附上6.0、7.0设备解决方案:

一、设备6.0

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
   
   private fun requestPermissions() {
        val permissionsList = arrayListOf(
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE
        )
        if (ContextCompat.checkSelfPermission(this,  permissionsList[0])!= PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,  permissionsList[1])!= PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this, permissionsList.toTypedArray(), 100)
        }
    }

  override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (grantResults.isNotEmpty() && requestCode == 100) {
            //授权后操作哦
        } else {
            Toast.makeText(this, "请开启相关权限!", Toast.LENGTH_LONG).show()
        }
    }

二、设备7.0 ,在以上代码上新增如下:

1.需要在AndroidManifest.xml中配置FileProvider

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="{包名}.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

2.xml目录下新建file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <root-path
        name="external_storage_root"
        path="." />
    <root-path
        name="camera_photos"
        path="." />
    <root-path
        name="files_root"
        path="." />
    <root-path
        name="files_root"
        path="." />
    <root-path
        name="external_files"
        path="." />
</paths>

三、设备8.0+ 

1.在 AndroidManifest.xml新增权限:

 <!--android O更新了未知来源的权限-->
 <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

四、 打开安装包的代码

public class InstallUtil {

    private Activity mAct;
    private String mPath;//下载下来后文件的路径
    public static int UNKNOWN_CODE = 2018;


    public InstallUtil(Activity mAct, String mPath) {
        this.mAct = mAct;
        this.mPath = mPath;
    }

    public void install() {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startInstallO();
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                startInstallN();
            } else {
                startInstall();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * android1.x-6.x
     */
    public void startInstall() throws Exception {
        Intent install = new Intent(Intent.ACTION_VIEW);
        install.setDataAndType(Uri.parse("file://" + mPath), "application/vnd.android.package-archive");
        install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mAct.startActivity(install);
    }

    /**
     * android7.x
     */
    public void startInstallN() throws Exception {
        //参数1 上下文, 参数2 在AndroidManifest中的android:authorities值, 参数3  共享的文件
        Uri apkUri = FileProvider.getUriForFile(mAct, getAuthority(mAct, ".FileProvider"), new File(mPath));
        Intent install = new Intent(Intent.ACTION_VIEW);
        //由于没有在Activity环境下启动Activity,设置下面的标签
        install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //添加这一句表示对目标应用临时授权该Uri所代表的文件
        install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        install.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        install.setDataAndType(apkUri, "application/vnd.android.package-archive");
        mAct.startActivity(install);
    }

    /**
     * android8.x
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startInstallO() throws Exception {

        boolean isGranted = mAct.getPackageManager().canRequestPackageInstalls();
        if (isGranted) {
            startInstallN();//安装应用的逻辑(写自己的就可以)
        } else {
            new AlertDialog.Builder(mAct)
                    .setCancelable(false)
                    .setTitle("安装应用需要打开未知来源权限,请去设置中开启权限")
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface d, int w) {
                            //https://blog.csdn.net/changmu175/article/details/78906829
                            Uri packageURI = Uri.parse("package:" + mAct.getPackageName());
                            //注意这个是8.0新API
                            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
                             mAct.startActivityForResult(intent, INSTALL_PERMISS_CODE);
                        }
                    })
                    .show();
        }
    }


    /**
     * 获取FileProvider
     * 返回: "此处为你的包名.FileProvider"
     * china.test.provider
     */
    private String getAuthority(Context context, String authority) {

        return getAppProcessName(context) + authority;
    }

    /**
     * 获取当前应用程序的包名
     *
     * @param context 上下文对象
     * @return 返回包名
     */
    private String getAppProcessName(Context context) {
        //当前应用pid
        int pid = android.os.Process.myPid();
        //任务管理类
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        //遍历所有应用
        List<ActivityManager.RunningAppProcessInfo> infos = manager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo info : infos) {
            if (info.pid == pid)//得到当前应用
            {
                return info.processName;//返回包名
            }
        }
        return "";
    }
}

五、运行后发现还是有问题、安装失败

在app.gradle中添加signingConfigs配置,这样在不打包的前提下也可以安装成功啦!


android { 

defaultConfig { … } 
 signingConfigs {
        debug {
            storeFile file("./xxx.keystore")
            storePassword 'password'
            keyAlias 'xxx'
            keyPassword 'password'
        }
        release {
            storeFile file("./xxx.keystore")
            storePassword 'password'
            keyAlias 'xxx'
            keyPassword 'password'
            v2SigningEnabled false
        }
    }

参考文献:

android 6.0以上系统部分需要动态授权代码_一直向钱的博客-CSDN博客

Android8.0+应用内更新安装apk失败_fplei的博客-CSDN博客

android 7.0、8.0、9.0适配时遇到更新安装问题解决_Bentley_li的博客-CSDN博客

Android8.0 允许安装未知来源权限(一)_飞奔的小付的博客-CSDN博客

记 Android 7.0 8.0版本更新安装遇到的坑 - 简书

android 调用系统播放器播放视频,适配android 7.0以上_书中有颜如玉的博客-CSDN博客_android 调用系统播放器

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android8.0、9.0安装包解析失败 的相关文章

  • 如何快速自动发送FCM或APNS消息?

    我正在开发一项后端服务 通过 FCM 或 APNS 向移动应用程序发送推送通知 我想创建一个可以在一分钟内运行的自动化测试 并验证服务器是否可以成功发送通知 请注意 我不一定需要检查通知是否已送达 只需检查 FCM 或 APNS 是否已成功
  • 类型容器“Android 依赖项”引用不存在的库 android-support-v7-appcompat/bin/android-support-v7-appcompat.jar

    我在尝试在我的项目中使用 Action Bar Compat 支持库时遇到了某种错误 我不知道出了什么问题 因为我已按照此链接中的说明进行操作 gt http developer android com tools support libr
  • Android - 从资产中解析巨大(超大)JSON 文件的最佳方法

    我正在尝试从资产文件夹中解析一些巨大的 JSON 文件 我如何加载并添加到 RecyclerView 我想知道解析这种大文件 大约 6MB 的最佳方法是什么 以及您是否知道可以帮助我处理此文件的良好 API 我建议您使用GSON lib h
  • 无法获取log.d或输出Robolectrict + gradle

    有没有人能够将 System out 或 Log d 跟踪从 robolectric 测试输出到 gradle 控制台 我在用Robolectric Gradle 测试插件 https github com robolectric robo
  • 如何以编程方式检查 AndroidManifest.xml 中是否声明了服务?

    我正在编写一个库 该库提供了一项服务 其他开发人员可以通过将其包含在他们的项目中来使用该服务 因此 我无法控制 AndroidManifest xml 我在文档中解释了要做什么 但一个常见的问题是人们忽略了将适当的 标记添加到其清单中 或者
  • Adobe 是否为其 PDF 阅读器提供 Android SDK 或 API? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我希望能够在我们的应用程序内的视图中显示本地 PDF 文件 在 Android 4 03 下的平板电脑上运行 目前 我们将 Adob eR
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • 是否必须删除 Intent extra?

    这可能是一个愚蠢的问题 但是是否有一条规则规定消费活动必须显式删除 Intent 额外内容 或者只有在回收 Intent 对象时才如此 换句话说 如果我总是通过执行以下操作来链接到下一个活动 Intent i new Intent MyCu
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • 如何使用 Cordova 获取当前安装的应用程序的版本?

    我已经找到了应用程序可用性插件 https github com ohh2ahh AppAvailability它主要检查用户是否在其设备上安装了某个应用程序 是否有可能获得应用程序的当前版本 开发者名称 重要 以及所有可能的信息 一般来说
  • 是否有 ADB 命令来检查媒体是否正在播放

    我想使用 ADB 命令检查根植于终端的外部设备中是否正在播放音频 视频 我无法找到任何 ADB 命令 如果有 我尝试过 adb shell dumpsys media player 我想要一个命令来指定视频是否正在运行 您可以使用以下命令查
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 发布android后更改应用内购买项目的价格

    在 Google Play 上发布后 是否可以更改应用内购买商品的价格 我假设该应用程序也已发布 完整的在线文档位于http developer android com http developer android com也http sup
  • 在 SQLite 中搜索时排除 HTML 标签和一些 UNICODE 字符

    更新 4 我已经成功运行了firstchar例如 但现在的问题是使用regex 即使包含头文件 它也无法识别regex操作员 有什么线索可以解决这个问题吗 更新 2 我已经编译了sqlite3我的项目中的库 我现在正在寻找任何人帮助我为我的
  • 如何默认在 ActionOpenDocument 意图中显示“内部存储”选项

    我需要用户选择一个自定义文件类型的文件 并将其从 Windows 文件资源管理器拖到 Android 设备上 但默认情况下内部存储选项不可用 当我使用以下命令启动意图时 var libraryIntent new Intent Intent
  • 尝试在 ubuntu 中编译 android 内核时出错

    我正在尝试从源代码编译 Android 内核 并且我已经下载了所有正确的软件包来执行此操作 但由于某种原因我收到此错误 arm linux androideabi gcc error unrecognized command line op
  • 如何根据 gradle 风格设置变量

    我想传递一个变量test我为每种风格设置了不同的值作为 NDK 的定义 但出于某种原因 他总是忽略了最后味道的价值 这是 build gradle apply plugin com android library def test andr
  • 一次显示两条Toast消息?

    我希望在一个位置显示一条 Toast 消息 并在另一位置同时显示另一条 Toast 消息 多个 Toast 消息似乎总是按顺序排队和显示 是否可以同时显示两条消息 是否有一种解决方法至少可以提供这种外观并且不涉及扰乱活动布局 Edit 看来
  • 将 Intent 包装在 LabeledIntent 中以用于显示目的

    要求 我的应用程序中有一个 共享 按钮 我需要通过 Facebook 分享 我需要选择是否安装原生 Facebook 应用程序 我们的决定是 如果未安装该应用程序 则将用户发送到 facebook com 进行分享 当前状态 我可以检测何时
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview

随机推荐

  • vue.config.js基本配置

    方法一 vue3 vue config js const defineConfig require vue cli service module exports defineConfig transpileDependencies true
  • visual studio下C4146错误分析与整理

    C4146报错原因分析 标签 空格分隔 C C4146 一元负运算符应用于无符号类型 结果仍为无符号型 文章目录 C4146报错原因分析 toc 事发现场 翻车过程 翻车原因 解决方案 番外篇 事发现场 include
  • 如何看待越来越多年轻人追捧「摸鱼哲学」,拒绝努力的年轻人真比老一辈活得更通透吗?

    题目是我在知乎上看到的 有些小伙伴应该也看到了 不知道有没有触动到你 反正我是心有戚戚焉 上周五 我去了一趟郑州 见了几个大学同学 吃了一顿饭 喝了点小酒之后 我们谈了很多各自的现状 龙仔和小龙都说 公司现在的年轻人 真不知道在想些什么 任
  • Linux主流架构运维工作简单剖析

    随着IT运维的不断发展 尤其的Linux的飞速发展 越来越多的企业开始使用Linux操作系统平台 例如CentOS RedHat Ubuntu Fedora等等 成千上亿个网站涌现在当今互联网 互联网已经成为必不可少的工具 那今天我们跟大家
  • 数据库原理 知识点总结

    名词积累 数据库 Database 存放和提供数据的 库房 数据 Data 数据库中存储的基本对象 数据库管理系统 DBMS 位于用户与操作系统之间的一层数据管理软件 数据库系统 Database System 包括数据库 DBMS 应用系
  • Git提交代码或文件

    一 直接通过git命令提交 1 git add 将所有文件加到提交区 2 git commit m 注释 提交注释 3 git pull rebase origin master 拉去代码 且把提交的线路融合在一起 4 git push u
  • Java中转化Stream流及多个Stream流如何合并

    题目 如何将对象转化为Stream流及多个Stream流如何合并 特别注意基本类型数组转化成的流 准备 Java中Stream流是JDK1 8出现的新特性 Stream流多用于过滤 转换 统计等 Stream类的静态方法 Stream co
  • javaScript-----数组使用字符串作为下标

    原文地址 http blog csdn net chenssy article details 7366160 首先Array是从Object那里继承下 它具备Object所有的功能和特性 下面是Object的情况 html view pl
  • 完美的Apache静态.htaccess文件 [discuz和home带301重定向]

    完美的Apache静态 htaccess文件 discuz和home带301重定向 本帖最后由 下砂 于 2009 11 13 10 32 编辑 先后修改过三次 加了301重定向 顶级域名和论坛二级域名 后rewrite base保持 状态
  • 无法加载训练好的.h5权重

    Unable to open file unable to open file name h5 errno 2 error message No such file or directory 确认模型是正确的情况下 最好的办法是升级h5py
  • AD中如何做出爱心❤的丝印

    不知道有没有小伙伴试过在AD中做一个爱心的丝印 今天在这里就跟大家分享一下 如何做一个带爱心 的丝印 具体方法就是我们在字符串输入框中输入相应的内容和 爱心 的话可以通过搜狗输入法打一个 心 字就会弹出哦 选择字体 MS UI Gothic
  • 《逻辑与计算机设计基础(原书第5版)》——2.9 硬件描述语言—VHDL

    2 9 硬件描述语言 VHDL 由于硬件描述语言用来描述和设计硬件 故在使用该语言编程时 应牢记底层的硬件实现 特别是当你的设计将用来综合时 例如 如果忽略将要生成的硬件 那么你可能会用低效的硬件描述语言设计出一个大且复杂的门级结构 而实际
  • Harmony Codelab 样例—弹窗基本使用

    一 介绍 本篇 Codelab 主要基于 dialog 和 button 组件 实现弹窗的几种自定义效果 具体效果有 1 警告弹窗 点击确认按钮弹窗关闭 2 确认弹窗 点击取消按钮或确认按钮 触发对应操作 3 加载弹窗 展示加载中效果 4
  • 我与西门子的面试全过程(一面+二面)_2008校园招聘_笔试与面试分享_UNUS.CN

    导读 很庆幸自己能够参加世界500强企业 西门子的面试 经过了一面和二面 虽然最后没有被录取 但高兴的是我们广工有两个进了 在这里祝福他们 今天终于有空 写下自己与西门子的全过程 写下这篇文章 并不是想炫耀 而是真心希望对后来者有帮助 在学
  • 【LeetCode】426. 将二叉搜索树转化为排序的双向链表(剑指 Offer 36)

    一 题目 将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 对于双向循环列表 你可以将左右孩子指针作为双向循环链表的前驱和后继指针 第一个节点的前驱是最后一个节点 最后一个节点的后继是第一个节点 特别地 我们希望可以 就地 完成转换
  • 【PaddlePaddle】 mnist手写数字识别(卷积神经网络)

    这篇文章主要讲解了卷积神经网络的使用 卷积神经网络可以用来提取图像特征 所以在计算机视觉上有很好的效果 系统 ubuntu18 04 python版本 python2 7 目录 训练模型 进行预测 完整代码 训练模型 先把需要用到的模块导入
  • 【日常总结】c++静态成员为啥要在类外进行初始化

    解释 类的静态成员变量内存不属于实例化的类 在类内只起到申明的作用 必须要在类外进行初始化 这个说法不严谨 类外主要是进行定义 分配内存 同时也可以赋初始值 代码例子 test h pragma once include
  • 【云原生之Docker实战】使用Docker部署Wizard文档管理系统

    云原生之Docker实战 使用Docker部署Wizard文档管理系统 一 Wizard介绍 1 Wizard简介 2 Wizard特点 二 检查宿主机系统版本 三 检查本地docker环境 1 检查docker服务状态 2 检查docke
  • 你看鱿鱼这么便宜,所以是不是很可怜?

    本文非技术分享 可能属于逻辑思考 再一次做梦 如下片段 有个朋友聊天问我 你看鱿鱼 那么便宜 是不是很可怜 我的内心 贵或者不贵 从哪能体现出它可怜不可怜呢 这逻辑有问题 我的回答 有点 又一次从梦中醒来 立马记录下做了什么梦 仅此而已 好
  • Android8.0、9.0安装包解析失败

    根据google官网得知 在8 0以上权限控制的更加严格 应用内安装下载更新的apk都需要申请 安装外面应用 权限才能去安装新应用 如果没有申请否则无法安装 顺便附上6 0 7 0设备解决方案 一 设备6 0