玩安卓必须要掌握的性能优化之APK极限压缩

简介: 玩安卓必须要掌握的性能优化之APK极限压缩

前言

Apk的压缩很有必要,比如你的应用比你的竞争对手的要大很多,但是功能上都差不多,客户会怎么选择呢?就拿微信来说,如果微信不进行压缩的话,那么它的apk绝对比现在要大好几倍。微信不能不用,即使它变得特别大,咱们还是不得不用,但是咱们开发的软件,客户却有很多选择,所以,尽量使自己的app竞争力大一些。下面开始进入正文:

第一步:将图片转为webp格式

webp格式类似与jpeg、png,但是体积要远比jpeg和png小。下面是百度百科对webp的解释:


2020022120271873.png

WebP编码对于哈夫曼压缩性能更优异些,哈夫曼与WebP本质上都是从编码来解决图像压缩,哈夫曼是对rgb的元数据进行变频压缩而WebP编码是通过预测技术对图片压缩。


WebP 压缩使用的图像编码方式与 VP8 视频编码对关键帧压缩方式相同,换句话解释:Google将视频编码技术搬到了图片上 形成了Webp编码格式。


再详细不说了,就偏离主题了,今天的主题是apk的压缩,所以我们要做的就是---将我们应用中的png和jpeg图片全部转换成WebP格式的图片。


你的内心可能要想:啊~我的项目中这么多图片,我该怎么去转啊。


不要担心,你想的谷歌已经替你想好了,在Android Studio中一键就可以进行转换了,只需要将图片全选,然后点击右键,选择如下图的按钮即可:

20200221203505185.png

点击之后就进入了预览界面,你可以随意选择需要的质量,默认的是原图的75%。

20200221203654438.png


然后点击Finish即可完成,这里要提醒的是:

1.转换会默认把原图删除,请提前做好备份

2.Android4.3之前无法识别WebP格式的图片,需要进行(libwebp库)编译

不过现在的手机基本没有4.3以下的了,基本默认最低开发版本都是19(Android4.4)。但如果开发电视或者固定设备就必须进行兼容编译,这里就不详细说明了。

第二步:去除多语言

好多人没有注意过这一点,的确,这一步优化的效果可能不是特别大,但----蚊子再小也是肉啊!

大家可以在Android Studio中打开自己的apk文件,找见resources.arsc,在下面找见string,如下图所示:

20200221204725129.png

AS默认将所有语言全部打包进入咱们的apk,但是咱们基本使用的只有中文和英语,默认是英语,所以无需配置,只需配置中文。


那么,需要怎样配置呢?且听我娓娓道来:首先,打开moudle的build.gradle,在android中的defaultConfig里加入下面的代码即可:

resConfigs "zh", "zh-rCN"

配置了之后在进行打APK包就不会有那些乱七八糟的语言存在了。

第三步:去除无用动态库

20200221210645425.png

千万要注意:这里说的是去除无用动态库,不是不使用动态库。动态库在咱们的项目中使用的非常多,比如使用三方地图服务:百度地图、高德地图、腾讯地图等等,都需要导入动态库,都会有几个不同的版本:armeabi、armeabi-v7a、x86、x86_64、mips等,而且每一个版本都很大,但目前市面上的手机有99%以上都是用的armeabi-v7a,咱们可以只保留armeabi-v7a的即可,大家如果不信的话可以解压市面上比较流行的APK,你会发现他们的包也都是只有armeabi和armeabi-v7a,包括微信、支付宝,所以咱们这么做也是没有问题的。

这一步是减少应用体积最明显的,但具体该怎么做呢?很简单,还是在moudle的build.gradle中,还是上一步的位置:android中的defaultConfig中,修改以下代码即可:

ndk {
       abiFilters 'armeabi'/*,'x86', 'armeabi-v7a'*/
            // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
    }

简单说一下armeabi和armeabi-v7a的区别吧:armeabi和armeabi-v7a都表示cpu的类型,不同的cpu的特性不一样,armeabi就是针对普通的或旧的arm cpu,armeabi-v7a是针对有浮点运算或高级扩展功能的arm cpu。

第四步:移除无用资源

我们的应用在开发过程中往往会有很多忘记清理的垃圾图片、布局或者其他资源,所以要进行清理,这也是APK极限压缩的一大步。有两种方式可以进行移除无用资源。


第一种(不推荐):一键移除,如果出现使用动态id使用资源会出现问题(比如使用反射调用或者使用getIdentifier)

20200221211447784.png


第二种(推荐):使用Android Studio自带的Lint工具,有人可能不知道Lint是什么,Lint 是Android Studio 提供的 代码扫描分析工具,它可以帮助我们发现代码结构/质量 问题,同时提供一些解决方案,而且这个过程不需要我们手写测试用例。下面是操作方式:

20200221211447784.png

然后输入unused resource

20200221211620360.png


然后点击回车进入选择Lint界面,可以选择是整个项目或者某个moudle:

20200221213103412.png

点击OK进入Lint详情界面


20200221213146204.png


在这个界面可以看到未使用的所有资源,进行判断是否有用之后即可进行清理。

清理之后应用APK的大小又减小了一部分,接着来看下一步。

第五步:开启混淆ProGuard

这一步很关键,并不是为了减小APK的体积才开启的混淆,最主要是为了安全,如果你不想你的应用代码直接被别人很轻松的看到的话(当然混淆后也可通过某些技术进行查看,但起码会比不开启混淆要安全一些)

混淆有三大作用:

1、压缩:移除未被使用的类、属性、方法等,并且会在优化动作执行之后再次执行(因为优化后可能会再次暴露一些未被使用的类和成员。

2、优化:优化字节码,并删除未使用的结构。

3、混淆:将类名、属性名、方法名混淆为难以读懂的字母

混淆开启的方式也很简单,还是在moudle的builg.gradle中,还是android中,不过这次不是defaultConfig中了,而是buildTypes中:

buildTypes {
        release {
            minifyEnabled true // 开启混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

我只在release包中开启了混淆,大家如果有需要也可以在debug中加上混淆。

这样就完了?不不不,混淆没有这么简单,上面说到:混淆将类名、属性名、方法名混淆为了难懂的字母。这很好,可以保证安全的情况下又减小了APK的体积,但是-----如果你的项目中用到了反射呢?通过你的包名和类名找不到你的文件(因为雷鸣属性名已经改变),那么肯定会崩溃,不只是你的项目中自己写的代码,还有你所使用的三方库中如果也使用了反射的话也需要进行处理。

那么问题来了,在哪里进行处理呢?上面的配置文件中其实已经写到了:proguard-rules.pro中,在里面需要写上不需要进行混淆的类或属性、或者是你的native方法也要注意加上。使用的三方库一般在Github介绍中会写明混淆需要添加的内容。在这里就,简单贴一段常用的混淆规则吧:

# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses 5
# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames
# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 这句话能够使我们的项目混淆后产生映射文件
# 包含有类名->混淆后类名的映射关系
-verbose
# 指定不去忽略非公共库的类成员
-dontskipnonpubliclibraryclassmembers
# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
-dontpreverify
# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses
# 避免混淆泛型
-keepattributes Signature
# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/cast,!field/*,!class/merging/*
# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
# 因为这些子类都有可能被外部调用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
# 保留support下的所有类及其内部类
-keep class android.support.** {*;}
# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
# 保留R下面的资源
-keep class **.R$* {*;}
# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

OK,混淆就说到这里,现在再进行打包的话你会发现应用APK的体积又减小了很大一部分。

第六步:开启删除无用资源(和第四步的Lint不同)

这一步很简单,只要在上一步混淆下面添加下面的一行代码即可:

buildTypes {
        release {
            minifyEnabled true // 混淆
            shrinkResources true // 去除无用资源 与lint不同
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

需要注意的是,删除无用资源的配置必须在开启混淆下才有用,如果关闭混淆的话,那么这个配置即不起作用。

第七步:AndResGuard微信资源压缩

什么是AndResGuard呢?

AndResGuard是一个缩小APK大小的工具,它的原理类似Java Proguard,但是只针对资源。它会将原本冗长的资源路径变短,例如将res/drawable/wechat变为r/d/a。

那为什么要使用AndResGuard呢?

在以往的开发中,我们通常只混淆了代码,资源文件却暴露在他人面前,res文件夹下所有文件名的可读性过强。微信的开源库AndResGuard 7zip压缩正好解决这种问题,对资源进行混淆,保护res资源文件的可读性,同时,可以减少APP的大小。一举两得的事情当然要干!

首先需要在项目的build.gradle中的buildscript中的dependencies中加入以下配置:

dependencies {
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.17'
    }

然后在下面加上以下配置:

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.17'
    }
}
andResGuard {
    // mappingFile = file("./resource_mapping.txt")
    mappingFile = null
    use7zip = true
    useSign = true
    // It will keep the origin path of your resources when it's true
    keepRoot = false
    // If set, name column in arsc those need to proguard will be kept to this value
    fixedResName = "arg"
    // It will merge the duplicated resources, but don't rely on this feature too much.
    // it's always better to remove duplicated resource from repo
    mergeDuplicatedRes = true
    whiteList = [
        // your icon
        "R.drawable.icon",
        // for fabric
        "R.string.com.crashlytics.*",
        // for google-services
        "R.string.google_app_id",
        "R.string.gcm_defaultSenderId",
        "R.string.default_web_client_id",
        "R.string.ga_trackingId",
        "R.string.firebase_database_url",
        "R.string.google_api_key",
        "R.string.google_crash_reporting_api_key"
    ]
    compressFilePattern = [
        "*.png",
        "*.jpg",
        "*.jpeg",
        "*.gif",
    ]
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.2.17'
        //path = "/usr/local/bin/7za"
    }
}

如果嫌放在这里有点乱的话可以新建一个配置文件放进去,这里就不赘述了。

这里需要注意,如果你的项目中有软引用的话需要注明:例如上面的:R.drawable.icon。

现在再打包,解压之后你会发现,你的资源文件和微信的类似,都变成了乱码。下面是压缩前后的对比图:

20200221220952104.png

到这里资源压缩就完成了。

总结

经过了上面七步的极限压缩,应用APK的大小肯定会有明显的减小,有的没做过APK压缩的甚至会比之前的小好几倍也是有可能的。本来只是想简单记录一下的,没想到写了这么久,这是性能优化我写的第二篇文章,上一篇是玩安卓必须要掌握的性能优化之内存泄漏。


目录
相关文章
|
1月前
|
算法 数据处理 Android开发
掌握安卓性能优化的秘诀:电池寿命与运行效率的提升
【10月更文挑战第6天】 本文深入探讨了安卓应用开发中的性能优化技巧,重点分析了影响电池寿命和运行效率的关键因素,并提供了针对性的优化策略。通过代码优化、资源管理、后台任务处理等方法,开发者可以显著提升应用的续航能力和流畅度。同时,结合具体案例,展示了如何在实际开发中应用这些技巧,确保应用在各种场景下都能保持高效运行。本文旨在为安卓开发者提供实用的性能优化指导,助力其打造更优质的应用体验。
47 2
|
3月前
|
缓存 监控 Android开发
探索iOS与安卓开发中的性能优化策略
在移动应用开发的竞技场上,iOS和安卓这两大操作系统不断推动着技术的边界。性能优化,作为提升用户体验的关键因素,已成为开发者们关注的焦点。本文将深入探讨两大平台上的性能优化实践,揭示如何通过工具、技术和策略来提升应用的响应速度和流畅度,同时考虑到电池寿命和内存管理等关键指标。
|
4月前
|
存储 Java 编译器
🔍深入Android底层,揭秘JVM与ART的奥秘,性能优化新视角!🔬
【7月更文挑战第28天】在Android开发中,掌握底层机制至关重要。从Dalvik到ART, Android通过采用AOT编译在应用安装时预编译字节码至机器码,显著提升了执行效率。ART还优化了垃圾回收,减少内存占用及停顿。为了优化性能,可减少DEX文件数量、优化代码结构利用内联等技术、合理管理内存避免泄漏,并使用ART提供的调试工具。
117 7
|
11天前
|
Android开发 开发者
Android性能优化——内存管理的艺术
Android性能优化——内存管理的艺术
|
17天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
28 5
|
17天前
|
缓存 数据库 Android开发
安卓开发中的性能优化技巧
【10月更文挑战第29天】在移动应用的海洋中,性能是船只能否破浪前行的关键。本文将深入探讨安卓开发中的性能优化策略,从代码层面到系统层面,揭示如何让应用运行得更快、更流畅。我们将以实际案例和最佳实践为灯塔,引领开发者避开性能瓶颈的暗礁。
36 3
|
1月前
|
存储 缓存 网络协议
5个Android性能优化相关的深度面试题
本文涵盖五个Android面试题及其解答,包括优化应用启动速度、内存泄漏的检测与解决、UI渲染性能优化、减少内存抖动和内存溢出、优化网络请求性能。每个问题都提供了详细的解答和示例代码。
26 2
|
1月前
|
监控 测试技术 Android开发
掌握安卓性能优化的关键策略
【10月更文挑战第7天】 在移动应用开发领域,性能优化是一项至关重要的任务。本文将探讨安卓应用性能优化的重要性、关键策略以及实际操作建议,帮助开发者提升应用的用户体验和竞争力。通过深入浅出的方式,我们将从背景介绍到具体实践,全面解析安卓性能优化的各个维度。
|
2月前
|
存储 Java 编译器
🔍深入Android底层,揭秘JVM与ART的奥秘,性能优化新视角!🔬
【9月更文挑战第12天】在Android开发领域,深入了解其底层机制对提升应用性能至关重要。本文详述了从早期Dalvik虚拟机到现今Android Runtime(ART)的演变过程,揭示了ART通过预编译技术实现更快启动速度和更高执行效率的奥秘。文中还介绍了ART的编译器与运行时环境,并提出了减少DEX文件数量、优化代码结构及合理管理内存等多种性能优化策略。通过掌握这些知识,开发者可以从全新的角度提升应用性能。
65 11
|
3月前
|
人工智能 缓存 数据库
安卓应用开发中的性能优化技巧AI在医疗诊断中的应用
【8月更文挑战第29天】在安卓开发的广阔天地里,性能优化是提升用户体验、确保应用流畅运行的关键所在。本文将深入浅出地探讨如何通过代码优化、资源管理和异步处理等技术手段,有效提升安卓应用的性能表现。无论你是初学者还是资深开发者,这些实用的技巧都将为你的安卓开发之路增添光彩。