疑问:

(1)了解APK安装流程有什么好处

(2)了解APK安装流程可以解决什么问题

一、可以在安装流程里做什么

安装就分为下面三个阶段,每个阶段可以做些什么工作,可以帮助我们优化安装流程,解决安装后的一些问题呢?

(1)安装前、安装中:这两个阶段,第三方应用做不了什么,一般是应用分发APP应用商店、游戏中心、浏览器、应用宝这些应用会关注这两个状态。

(2)安装后:这个阶段,无论是内置应用还是第三方应用,或多或少的会遇到一些问题,如so文件找不到,图片存储、缓存数据等出现异常等...

二、安装前

安装前无非是根据自己的应用情况,选择一种可以使用的安装方法。

2.1 pm命令安装方法

对于具有系统签名的厂商应用,具备静默安装能力,使用pm命令即可实现。

  1. String cmd = "pm install -r -d /data/data/android.apk"
  2. Runtime run = Runtime.getRuntime();
  3. Process process = run.exec(cmd);

2.2 包安装管理器安装

非系统签名的应用宝这种应用,只能使用包安装管理器进行安装。

  1. Intent intent = new Intent(Intent.ACTION_VIEW);
  2. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  3. intent.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android" + ".package-archive");
  4. mContext.startActivity(intent);

2.3 session命令安装

使用session安装的原因,是因为从Android 8.0开始,pm命令无法实现静默安装,否则会直接显示安装失败。但是网上并未发现对静默方法的适配方案,也许这是因为这个兼容只有厂商关注,第三方应用不关注这个方法的兼容。下面给出兼容方案:

  1. int sessionId = packageInstaller.createSession(params);
  2. InstallLog.d(TAG, "doPackageStage creat sessionId is : " + sessionId);
  3. final byte[] buffer = new byte[65536];
  4. session = packageInstaller.openSession(sessionId);
  5. final InputStream in = new FileInputStream(file);
  6. final long sizeBytes = file.length();
  7. final OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes);
  8. try {
  9. int c;
  10. while ((c = in.read(buffer)) != -1) {
  11. out.write(buffer, 0, c);
  12. }
  13. session.fsync(out);
  14. } catch (IOException ex) {
  15. InstallLog.e(TAG, "doPackageStage ioException : " + ex.getMessage(), ex);
  16. } finally {
  17. InstallUtils.closeQuietly(in);
  18. InstallUtils.closeQuietly(out);
  19. }

该方法是从packageManager中抽取出的代码,可实现应用的静默安装。

三、安装中

3.1 APK的结构

APK文件其实是zip格式,一般包含一个或多个dex文件、resources.arsc、AndroidManifest.xml、res目录、META-INF目录及包含so库的lib目录:

3.2 安装过程中涉及的存储目录

  • system/app——内置应用,也就是系统自带的应用程序,无法删除。

  • data/app——用户程序安装的目录,有删除权限。安装时把apk文件复制到此目录。

  • data/data——存放应用程序的数据,比如一些sp缓存数据。

  • data/dalvik-cache——将APK中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始APK文件大小的四分之一)。

3.3 安装主要流程

安装过程概括为:复制APK安装包到/data/app目录下,解压并扫描安装包,向资源管理器注入APK资源,解析AndroidManifest文件,并在/data/data目录下创建对应的应用数据目录,然后针对dalvik/art环境优化dex文件,保存到dalvik-cache目录,将AndroidManifest文件解析出的组件、权限注册到PackageManagerService,完成后发送广播。

3.4 安装中可以优化的点

安装中,这个过程看上去没有什么可以做的,但是对于厂商应用来说,应用的安装速度,却是可以有很大的提升空间的。如应用更新的差分包升级就是一种常见的增量更新方式。

经过一系列测试与验证,发现应用安装的速度,本身与一些因素有关,最主要的是CPU的使用频率。

众所周知,现在的手机较为高端,为8核,但是在应用安装过程中,分析trace文件,可以确认,并不是8核线程全负荷工作去完成一个应用的安装,而是一部分线程运行在高核,一部分在低核。

3.4.1 CPU的工作频率介绍

cpuinfo_max_freq cpuinfo_min_freq :分别给出了 CPU 硬件所支持的最高运行频率及最低运行频率,

  • cpuinfo_cur_freq 则会从CPU 硬件寄存器中读取CPU 当前所处的运行频率。

  • Governor 在选择合适的运行频率时只会在scaling_max_freq 和 scaling_min_freq 所确定的频率范围内进行选择。

  • scaling_cur_freq 返回的是cpufreq 模块缓存的CPU当前运行频率,而不会对CPU 硬件寄存器进行检查。

  • scaling_available_governors 会告诉用户当前有哪些 governors 可供用户使用。

  • scaling_driver 则会显示该 CPU 所使用的变频驱动程序。

  • Scaling_governor 则会显示当前的管理策略,往这个上 echo 其他类型会有相应的转变。

  • scaling_setspeed :需将 governor 类型切换为 userspace ,才会出现,往这个文件 echo 数值,会切换主频。

基于此,可以在应用安装时,提升CPU的工作频率,即可使CPU运行在合适的频率。

2.4.2 提升CPU的工作频率

除了可以直接根据安装速度判断安装速度是否提升外,也可以根据下面日志判断提频是否有效:

  1. adb shell cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
  2. adb shell cat /sys/devices/system/cpu/cpu7/cpufreq/cpuinfo_cur_freq

可以直接看到频率变化:

微信安装速度可以由前面CPU低频时的20s,提升到CPU频率较高时的10s左右。

注意:频率不是越高越好,频率越高,手机耗电会越高,容易发热。

四、安装后

应用安装后,会遇到各种各样的问题,启动失败,合规整改(这个其实在应用开发时就要完成),那么哪些问题又是可能遇到,又可以借助apk的安装流程去解决的

4.1 targetsdkversion=30 不得不做的事情

《符合 Google Play 的目标 API 级别要求》 一文中,根据google官方要求,需要对隐私权限进行管控,强制执行分区存储,这就要求,每个应用不得在sd卡进行资源存储。那么问题来了,假如你的项目使用了Glide,Glide的存储路径之前设置到了sd卡下面,现在又无法使用外部存储目录,该怎么办?

当了解了apk的安装流程之后,知道应用的数据会存储在data/data/packagename下面,这就给Glide的资源存储提供了一个内部文件夹,唯一要做的事情,就是为了防止data/data占用过大,把Glide的存储目录设置个上限即可。

4.2 libmmkv.so无法找到问题解决

4.2.1 现象

如果你的应用接了腾讯的mmkv,你可能遇到了这样的问题:

  1. java.lang.UnsatisfiedLinkError dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/packagename-Sxe4_uU3WXx-ckI5DyG3UA==/base.apk"],nativeLibraryDirectories=[/data/app/packagename-Sxe4_uU3WXx-ckI5DyG3UA==/lib/arm, /system/fake-libs, /data/app/packagename-Sxe4_uU3WXx-ckI5DyG3UA==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib, /system/vendor/lib/hw]]] couldn't find "libmmkv.so"
  2. Runtime.java 1011
  3. java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/packagename-Sxe4_uU3WXx-ckI5DyG3UA==/base.apk"],nativeLibraryDirectories=[/data/app/packagename-Sxe4_uU3WXx-ckI5DyG3UA==/lib/arm, /system/fake-libs, /data/app/packagename-Sxe4_uU3WXx-ckI5DyG3UA==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib, /system/vendor/lib/hw]]] couldn't find "libmmkv.so"
  4. at java.lang.Runtime.loadLibrary0(Runtime.java:1011)
  5. at java.lang.System.loadLibrary(System.java:1657)
  6. at com.tencent.mmkv.MMKV.a(SourceFile:3)

这个表示应用加载libmmkv.so出现异常。

4.2.2 分析原因

出现问题的原因是什么:根据日志可以确认,是找不到应用data/app/文件夹下面的libmmkv.so文件。

4.2.3 解决问题

前面提到,应用的数据会存储在data/data下面,这个路径下面也包含了应用解压之后的so库,所以可以做一件事情解决上面libmmkv.so的问题,重链接data/data下面的资源到data/app下面,实现资源共享。实践证明该方案完全可行,有效解决了so库找不到的问题。

五、疑问解答

(1)了解APK安装流程有什么好处

从apk发起安装,安装中、一直到安装结束,应用状态的变化,CPU的使用,资源的共享,牵涉到一系列知识点,这些知识点是可以串联起来的,对提升个人的知识体系有帮助。当然,由于文章篇幅有限,本文章只是作为一个引导,大致说明安装过程中存在什么知识点,PMS、文件管理、进程拉起等等安全可以另起一章节进行介绍,后续会介绍这些方面的内容。

(2)了解APK安装流程可以解决什么问题

厂商应用更多的关注安装前、安装中遇到的问题,第三方应用关注安装后遇到的问题。掌握了安装过程中的每一个环节,通过上面的分析,可以知道,能够快速帮助定位问题。

作者:vivo互联网客户端团队-Xu Jie

打通“任督二脉”:Android 应用安装优化实战的更多相关文章

  1. Linux就这个范儿 第13章 打通任督二脉

    Linux就这个范儿 第13章 打通任督二脉 0111010110……你有没有想过,数据从看得见或看不见的线缆上飞来飞去,是怎么实现的呢?数据传输业务的未来又在哪里?在前面两章中我们学习了Linux网 ...

  2. Appium+python自动化(十)- 元素定位秘籍助你打通任督二脉 - 上卷(超详解)

    简介 你有道灵光从天灵盖喷出来你知道吗,年纪轻轻就有一身横练的筋骨,简直百年一见的练武奇才啊,如果有一天让你打通任督二脉,那还不飞龙上天啊.正所谓我不入地狱谁入地狱,警恶惩奸维护世界和平这个任务就交个 ...

  3. 天河微信小程序入门《三》:打通任督二脉,前后台互通

    原文链接:http://www.wxapp-union.com/forum.php?mod=viewthread&tid=505&extra=page%3D1 天河君在申请到https ...

  4. English learning method ---学英语重中之重打通“任督二脉”

    漫漫十年艰辛路,英语学习之旅 曾经秉承“路漫漫其修远兮,吾将上下而求索”的信念,初一那年了解到原来(a b c d e f g) 不仅仅读作(啊,波,词,的,额,佛,哥),在英语的世界中它有另外的读法 ...

  5. 一个典型的后台软件系统的设计复盘——(三)打通任督二脉-context

    武侠小说练功讲究打通任督二脉.程序设计练到一定程度也讲究打通任督二脉.好奇心强的同学可以搜搜“打通任督二脉有什么感觉”. spring的任督二脉ApplicationContext 最经典的任督二脉莫 ...

  6. TCP的慢启动、拥塞避免、重传、快恢复乱七八糟总是记不清?11个连环问让你一次性打通任督二脉

    摘要:如果你的开发过程涉及数据传输,一直在重传.超时之类的方案里有困惑的话,不妨重新学一学可靠性最精致的TCP协议. 本文分享自华为云社区<TCP的慢启动.拥塞避免.重传.快恢复乱七八糟总是记不 ...

  7. 深度讲解Linux内存管理和Linux进程调度-打通任督二脉

    我在多年的工程生涯中发现很多工程师碰到一个共性的问题:Linux工程师很多,甚至有很多有多年工作经验,但是对一些关键概念的理解非常模糊,比如不理解CPU.内存资源等的真正分布,具体的工作机制,这使得他 ...

  8. Appium+python自动化(十一)- 元素定位秘籍助你打通任督二脉 - 下卷(超详解)

    简介 宏哥看你骨骼惊奇,印堂发亮,必是练武之奇才! 按照上一篇的节目预告,这一篇还是继续由宏哥给小伙伴们分享元素定位,是不是按照上一篇的秘籍修炼,是不是感觉到头顶盖好像被掀开,内气从头上冒出去,顿时觉 ...

  9. css3 flex弹性盒子布局梳理,打通任督二脉

    挺早就接触了css的flex布局,深入使用也就是在近期移动端开发.老来多健忘,只能自己梳理一下知识点,当做温故知新吧. ,请原谅小白的才疏学浅,写的不到位的地方请指正. flex属性用于设置或检索弹性 ...

随机推荐

  1. IT菜鸟之路由器基础配置(静态、动态、默认路由)

    路由器:连接不同网段的设备 企业级路由和家用级路由的区别: 待机数量不同(待机量) 待机量:同时接通的终端设备的数量 待机量的值越高,路由的性能越好 别墅级路由,表示信号好,和性能无关 交换机:背板带 ...

  2. 串口配合DMA接收不定长数据(空闲中断+DMA接收)-(转载)

    1.空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断: 2.空闲中断是接收到一个数据以后,接收停顿超过一字节时间  认为桢收完,总线空闲中断是在检测到在接收数据后, ...

  3. mysql基础之帮助信息

    在mysql中获取帮助 1.当连接到mysql数据库以后,使用help命令或者\?表示获取帮助信息: MariaDB [ren]> help General information about ...

  4. 【数据结构与算法】多种语言(VB、C、C#、JavaScript)系列数据结构算法经典案例教程合集目录

    目录 1. 专栏简介 2. 专栏地址 3. 专栏目录 1. 专栏简介 2. 专栏地址 「 刘一哥与GIS的故事 」之<数据结构与算法> 3. 专栏目录 [经典回放]多种语言系列数据结构算法 ...

  5. CyclicBarrier分析

    简介 CyclicBarrier 是什么? CyclicBarrier 使用 CyclicBarrier 源码解析 CyclicBarrier 简单实现 barrierAction 是由哪个线程执行的 ...

  6. 关于LSTM核心思想的部分理解

    具体资料可以查阅网上,这里提到一些难理解的点.别人讲过的知识点我就不重复了. LSTM 的关键就是细胞状态,按照水平线从左向右运行,如同履带,在整个链上运行. 根据时间t-1,t,t+1,我们可以看出 ...

  7. 如何在CPU上优化GEMM(上)

    如何在CPU上优化GEMM(上) (TL:DR)TVM提供了抽象接口,用户分别描述算法和算法的实现组织(所谓的调度).通常,在高性能调度中编写算法会破坏算法的可读性和模块性.尝试各种看似有希望的时间表 ...

  8. SpringAOP 原理解析

    什么是AOP? 1: 传统的OOP编程他的代码逻辑是一种自上向下, 而在这些自上而下的过程中会产生一些横切性的问题,比如说:日志信息,权限校验认证,事务等, 2: 这些横切性问题,往往与我们的主业务逻 ...

  9. 如果攻击者操控了 redirect_uri,会怎样?

    读者在看这篇文章之前,请先了解 Oauth2.0 的 Authorization Code 授权流程,可以看 Authorization Code 授权原理和实现方法 在 Token Enpoint ...

  10. java后端知识点梳理——多线程与高并发

    进程与线程 进程是一个"执行中的程序",是系统进行资源分配和调度的一个独立单位 线程是进程的一个实体,一个进程中一般拥有多个线程. 线程和进程的区别 进程是操作系统分配资源的最小单 ...