Android---APK 瘦身

news2024/12/28 20:37:41

在 APP 开发过程中,随着业务迭代,apk 体积逐渐变大。项目中累积的无用资源,未压缩的图片资源等,都为 apk 带来了不必要的体积增加。而 APK 的大小会影响应用加载速度、使用的内存量以及消耗的电量。

APK 结构

APK 文件由一个 Zip 压缩文件组成,其中包含构成应用的所有文件。这些文件包含 Java 类文件、资源文件和包含已编译资源的文件。

APK 包含以下目录:

  a. META_INF/: 包含 CERT.SF 和 CERT.RSA 签名文件,以及 MANIFEST.MF 清单文件。

  b. assets/: 包含应用的资源;应用可以使用 AssetManager 对象检索这些资源。

  c. res/: 包含未编译到 resource.arsc 中的资源(图片、音视频等)。

  d. lib/: 包含特定于处理器软件层的已编译代码。此目录包含每种平台类型的子目录,如 armeabi、armeabi-v7a、arm64-v8a、x86、x86_64 和 mips。

APK 还包含以下文件。在这些文件中,只有 AndroidManifest.xml 是必须的。

  a. resource.arsc: 包含已编译的资源。此文件包含 res/values/ 文件夹的所有配置中的 XML 内容。打包工具会提取此 XML 内容,将其编译为二进制文件形式,并压缩内容。此内容包括语言字符串和样式,以及未直接包含在 resources.arsc 文件中的内容(例如布局文件和图片)的路径。

  b. classes.dex: 包含以 Dalvik/ART 虚拟机可理解的 DEX 文件格式编译的类。

  c. AndroidManifest.xml: 包含核心 Android 清单文件。此文件列出了应用的名称、版本、访问权限和引用的库文件。该文件使用 Android 的二进制 XML 格式。

Android Size Analyzer 

Android Size Analyzer 工具可以轻松的发现和实施多种缩减应用大小的策略。

在 Android Studio 中插件市场下载安装 Android Size Analyzer。安装插件后,从菜单栏中依次选择 Analyze --> Analyze App Size,对当前项目运行应用大小分析。分析了项目后,系统会显示一个工具窗口,其中包含有关如何缩减应用大小的建议。

步骤1:下载安装插件。File --> Settings --> Plugins 然后搜索 Android Size Analyzer 插件,点击右侧的 Install 进行安装。

 步骤2:安装好插件后,对需要分析的项目使用该插件。

启用资源缩减(不打包)

如果在应用的 build.gradle 文件中启用了资源缩减:shrinkResouces,则 Gradle 在打包 APK 时可以自动忽略未使用资源。资源缩减只有在写代码缩减:minifyEnabled 配合使用时才能发挥作用。在代码缩减移除所有不使用的代码后,资源缩减器便可确定应用仍要使用的资源。

android {
    // Other settings
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

 

使用 Lint 分析器(物理删除)

lint 工具是 Android Studio 中附带的静态代码分析器,可检测到 res/ 文件夹中未被代码引用的资源。

步骤:将鼠标放在代码区 --> 右键 --> Analyze --> Inspect Code --> 界面选择你要检测的模块 -- > 点击确认开始检测,如下图:

lint 工具不会扫描 assets/ 文件夹、通过反射引用的资源或已链接至应用的库文件。此外,它也不会移除资源,只会提醒它们存在。与资源缩减不同,这里点击删除,那就是把文件删除了。

自定义要保留的资源

如果有要特别声明需要保留或舍弃的特定资源,在项目中创建一个包含 <resources> 标记的 XML 文件,并在 tools:keep 属性中指定每个要保留的资源,在 tools:discard 属性中指定每个要舍弃的资源。这两个属性都接受以逗号分隔的资源名称列表。还可以将星号字符用作通配符。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
    tools:discard="@layout/unused2" />

将该文件保存在项目资源文件中,例如,保存在 res/raw/keep.xml 中。构建系统不会将此文件打包到 APK 中。

一键删除无用资源

Android Studio 给我们提供了一键移除所有无用的资源。鼠标光标放在项目名上右键 --> Refactor -->  Remove Unused Resources,但是这种方式不建议使用,因为如果某资源仅存在动态获取资源 id 的方式,那么这个资源会被认为没有使用过,从而会直接被删除。

动态库打包配置

so 文件是由 NDK 编译出来的动态库,是 C/C++ 写的,所以不是跨平台的。ABI 是应用程序二进制接口简称(Application Binary Interface),定义了二进制文件(尤其是 .so 文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。在 Android 系统中,每一个 CPU 架构对应一个 ABI,目前支持的有:armeabi-v7a, arm64-v8a, x86, x86_64。目前市面上手机设备基本上都是 arm 架构,armeabi-v7a 几乎能兼容所有设备。因此可用配置:

android{
    defaultConfig{
        ndk{
            abiFilters "armeabi-v7a"
        }
    }
}

对于第三方服务,如百度地图,Bugly 等会提供全平台的 cpu 架构。进行了上面的配置之后,表示只会把 armeabi-v7a 打包进入 APK。从而减少 APK 大小。

对于 arm64 架构的设备,如果使用 armeabi-v7a 也能够兼容,但是不如使用 arm64 性能。因此现在部分应用市场会根据设备提供不同架构的 APK 安装。此时我们需要打包出针对 arm64 的 apk 与 armv7a 的 apk,可用使用 productFlavor

flavorDimensions "default"
    productFlavors{
        arm32{
            dimension "default"
        ndk{
            abiFilters "armeabi-v7a"
        }
    }

        arm64{
            dimension "default"
        ndk{
            abiFilters "arm64-v8a"
        }
    }
}

或者使用:

splits {
    abi {
        enable true
        reset()
        include 'arm64-v8a','armeabi-v7a'
        // exclude 'armeabi'
        universalApk true //是否打包一个包含所有so的apk
    }
}

 

使用矢量图

APK 中图片应该算是占用空间最多的资源。我们可以使用 webp 减少 png、jpg 图片占用空间的大小。对于小图标也可以使用矢量图。

矢量图可以创建与分辨率无关的图标和其他可伸缩媒体。使用这些图形可以极大的减少 APK 占用的空间。矢量图在 Android 中以 VectorDrawable 对象的形式表示。借助 VectorDrawable 对象,100 字节的文件可以生成与屏幕大小相同的清晰图片。

不过,系统渲染每个 VectorDrawable 对象需要花费大量时间,而较大的图片则需要更长的时间才能显示在屏幕上。因此,建议仅在显示小图片时使用这些矢量图

重复使用矢量图

现在我们有一个矢量图

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="?attr/colorControlNormal">
        <path
            android:fillColor="@android:color/white"
            android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/>
</vector>

显示的效果为

如果我们需要让矢量图显示为红色(或其它颜色)怎么办?这种情况,我们不需要再去创建一个新的矢量图。可以直接给 ImageView 设置 android:tint 属性来完成颜色的修改。

<ImageView
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:tint="@color/colorAccent"
    android:src="@drawable/tabbar_home_vector" />

选择器

如果需要让矢量图实现触摸变色,只需要创建 selector,设置给 Tint 即可。

<!-- tabbar_home_tint_selector -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorPrimary" android:state_pressed="true" />
    <item android:color="@color/colorAccent" />
</selector>

        <ImageView
            android:clickable="true"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/tabbar_home_vector"
            android:tint="@color/tabbar_home_tint_selector" />

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/565276.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅析Koa2中控制器

控制器 什么是控制器 拿到路由分配的任务&#xff0c;并执行 路由的功能是根据不同的 url, 来分配不同的任务。 控制器是拿到路由分配的任务并执行&#xff0c;是注册在路由中的中间件。 所以在 koa 中, 控制器也是一个中间件。 为什么要使用控制器 获取HTTP请求参数处理…

article-码垛机器人admas仿真

按照运动学仿真的类似步骤为机器人添加材料、运动副和关节驱动&#xff0c;给机器人手腕末端施加50N最大负载&#xff0c;仿真模型如图5-17。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AXYQVZPq-1684936426972)(data:image/svgxml;utf8, )] 图…

OpenGL之纹理

文章目录 什么是纹理加载与创建纹理stb_image.h加载并生成纹理 纹理环绕方式纹理过滤多级渐远纹理 纹理单元 什么是纹理 我们已经了解到&#xff0c;我们可以为每个顶点添加颜色来增加图形的细节&#xff0c;从而创建出有趣的图像。但是&#xff0c;如果想让图形看起来更真实&a…

unity制作一款塔防游戏

文章目录 介绍寻路系统怪物生成器制作3种初级炮台、3种升级炮台设置炮台属性选择炮台&#xff0c;添加监听事件炮弹追踪攻击敌人拖动鼠标实现相机视角转换鼠标光标放在cube上变色文字动画 介绍 关键技术&#xff1a; 寻路系统 生成怪物算法 粒子系统 line renderer制作追踪射线…

python基本操作1(速通版)

目录 一、input输入函数 二、格式化字符输出 三、函数的基本操作 1.return返回值的问题 2.参数传递 四、运算符 1.关系比较符 2.逻辑运算符 五、if语句 六、随机数 七、循环 1.while语句的基本应用 2.break语句 2.continue语句 3.猜拳游戏 4.三目运算符 6.for…

让input框只输入英文

解决扫码枪在中文输入法时扫码冲突 扫码枪在扫完码时会自动回车&#xff0c;这时如果是中文输入法就会触发输入法联想&#xff0c;再加一个回车&#xff0c;那么input框输入的就成中文了。如果可以控制input框只能输入英文那就好了。css有一个属性&#xff08;ime-mode&#xf…

ChatGpt论文指令,很全!

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了人工智能中文站https://ai.weoknow.com 每天给大家更新可用的国内可用chatGPT资源 ChatGPT的能力大家肯定都听说过&#xff0c;很多学生应该都亲身体验过。它在自然语言处理方面的出色 除了写代码 写论文也是超…

【计算思维题】少儿编程 蓝桥杯青少组计算思维真题及详细解析第4套

少儿编程 蓝桥杯青少组计算思维真题及详细解析第4套 1、下面哪个图形与其它图形不同 A、 B、 C、 D、 答案:D 考点分析:主要考查小朋友们的观察能力,从给定的图中可以看到前三个选项都是90度直角,最后一个是锐角,所以答案D 2、下列哪个选项是由下图旋转得到的

位运算【算法基础】

目录 知识点&#xff1a; 题目&#xff1a; 模板 关于为什么负数要用补码 知识点&#xff1a; 如果想看整数n的二进制表示中的第k位&#xff08;从0开始&#xff09;是几&#xff1f; &#xff08;1&#xff09;把第k位右移到个位n>>k &#xff08;2&#xff09;看x…

大模型时代,「重识」云知声

在山海大模型发布会现场&#xff0c;黄伟有一句话令人印象深刻&#xff0c;“云知声的过去十年&#xff0c;就是为山海而生。 作者| 皮爷 出品|产业家 “谁能做成中国最好的大模型&#xff1f;”在今年3月一个北京投资人的内部分享会上&#xff0c;有人满怀期待地提出这样…

Java SPI 一 之SPI(Service Provider Interface)进阶 AutoService

​ 一、SPI&#xff08;Service Provider Interface&#xff09; 1.1 介绍 SPI&#xff08;Service Provider Interface&#xff09;&#xff0c;是JDK内置的一种 服务提供发现机制(为某个接口寻找服务实现的机制)&#xff0c;可以用来启用框架扩展和替换组件&#xff0c;其…

Admin.NET管理系统(c#+vue3)前后端学习笔记

我的学习笔记 - 9iAdmin.NET 欢迎学习交流&#xff08;一&#xff09;前端笔记1.1 关于.env的设置1.2 关于路由模式问题1.3 关于 vue.config.ts1.4 关于 打包&#xff08;pnpm run build&#xff09;溢出问题1.5 关于 打包&#xff08;pnpm run build&#xff09;后部署到IIS重…

article-六轴码垛机器人admas正逆运动学仿真

基座自由度、大臂摆动自由度、小臂摆动自由度、腕部Y轴摆动自由度、腕部Z轴摆动自由度及其腕部末端X轴旋转自由度 其导入过程为&#xff1a; 机器人三维模型总体有6个部分。打开机器人的SolidWork三维模型&#xff0c;依次另存为6个“Parasolid(x_t)”类型的文件。打开ADAMS/…

【MATLAB第36期】基于MATLAB的QOWOA-LSTM鲸鱼优化算法准反向策略的WOA优化LSTM时间序列预测模型 优势明显,注释详细,绘图丰富

【MATLAB第36期】基于MATLAB的QOWOA-LSTM鲸鱼优化算法准反向策略的QOWOA优化LSTM时间序列预测模型&#xff0c;优势明显&#xff0c;注释详细&#xff0c;绘图丰富 一、代码优势 1.使用优化后的QOWOA算法优化LSTM超参数&#xff08;学习率&#xff0c;隐藏层节点&#xff0c;…

2020下半年上午题

2020下半年 d a b 小阶向大阶对齐 b b 平均cpi: MIPS: d c 公加验&#xff0c;私解签 加密防止被动攻击&#xff0c;认证防止主动攻击 a 访问控制包括&#xff1a;授权&#xff0c;确定存取权限&#xff0c;实施存取权限 c a c a 先申请先得 b b 著作权包括&…

OpenCV使用SURF和SIFT算法报错解决记录

OpenCV使用SURF和SIFT算法报错解决记录 1.报错代码&#xff0c;使用以下两种写法都会报错 # 创建SIFT和SURF特征提取器 # 写法1 sift cv2.xfeatures2d.SIFT_create() surf cv2.xfeatures2d.SURF_create() # 写法2 sift cv2.SIFT_create() surf cv2.SURF_create()第一种报…

架构整洁之道下篇(实现细节)

目录 1.实现细节 1.1.数据库只是实现细节 1.2.Web是实现细节 1.3.应用程序框架是实现细节 1.4.案例分析&#xff1a;视频销售网站 1.5.拾遗 1.5.1.按层封装 1.5.2.按功能封装 1.5.3.端口和适配器 1.5.4.按组件封装 1.5.5.组织形式和封装的区别 2.总结 1.实现细节 …

13_Uboot移植

目录 查找NXP官方的开发板默认配置文件 编译NXP官方开发板对应的uboot 烧写验证与驱动测试 SD卡和EMMC驱动检查 LCD驱动检查 网络驱动 在U-Boot中添加自己的开发板 添加开发板默认配置文件 添加开发板对应的头文件 添加开发板对应的板级文件夹 修改mx6ull_alientek_…

Vue——状态管理库Pinia

写在前面&#xff1a;本文参考小满大牛的pinia专栏 一、Vuex与Pinia Vuex 和 Pinia 均是 Vue.js 的状态管理库&#xff0c;它们为 Vue 应用程序提供了一种集中式的、可预测的状态管理解决方案。 Vuex 是 Vue.js 官方推荐的状态管理库之一。它的核心概念包括 state、mutation…

【C++初阶】类与对象(中)之取地址及const取地址操作符重载

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…