1韵洋、對第三方類庫的混淆方法
項(xiàng)目代碼一直使用加固的方案茉唉,從而忽略了混淆相關(guān)的問題,好多個大大小小的版本迭代之后授艰,再使用一條命令打包
gradle assembleRelease
然后就出現(xiàn)好幾百個警告辨嗽、錯誤提示,無法入手淮腾,一開始就是看著哪些類庫有問題就無腦的使用
-keep class com.xx.** { *; }
然而很多都沒作用糟需,挺打擊的,然后開始好好的分析一下日志谷朝,發(fā)現(xiàn)主要有以下幾類混淆出錯的問題
Warning: library class android.webkit.WebView depends on program class android.net.http.SslCertificate
Warning: okio.Okio: can't find referenced class org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
Note: the configuration refers to the unknown class 'fqcn.of.javascript.interface.for.webview'
Note: com.alibaba.wireless.security.framework.b: can't find dynamically referenced class libcore.io.Libcore
google了很多信息洲押,找到了解決方法,我這里的修改方案如下圆凰,在每個需要混淆第三方類庫的都添加
-dontnote com.xx.**
-dontwarn com.xx.**
-keep class com.xx.** { *; }
然后奇跡般的打包成功了杈帐!具體也可以參考這篇文章
Eclipse打包Android項(xiàng)目時用到proguard.cfg后,出現(xiàn)的Warning:can't find referenced class問題的解決方案
2、AndroidManifest.xml配置的相關(guān)類不能混淆
然而好景不長挑童,Apk安裝后一打開就崩潰累铅。然后打開日志,查看報(bào)錯的問題站叼,主要日志如下:
java.lang.IllegalArgumentException: Unable to find GlideModule implementation
at com.bumptech.glide.module.ManifestParser.parseModule(ManifestParser.java:46)
at com.bumptech.glide.module.ManifestParser.parse(ManifestParser.java:30)
at com.bumptech.glide.Glide.get(Glide.java:149)
at com.bumptech.glide.RequestManager.<init>(RequestManager.java:62)
at com.bumptech.glide.RequestManager.<init>(RequestManager.java:53)
at com.bumptech.glide.manager.RequestManagerRetriever.supportFragmentGet(RequestManagerRetriever.java:198)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:104)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:87)
at com.bumptech.glide.Glide.with(Glide.java:629)
at com.company.business.global.imageloader.a.a.a(ImageLoaderImpl.java:91)
at com.company.business.global.imageloader.a.a.a(ImageLoaderImpl.java:85)
at com.company.ui.billing.a.c.a(SaleProductAda
Caused by: java.lang.ClassNotFoundException: com.company.common.config.GlideConfiguration
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:308)
at java.lang.Class.forName(Class.java:272)
at com.bumptech.glide.module.ManifestParser.parseModule(ManifestParser.java:44)
... 103 more
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.company.common.config.GlideConfiguration" on path: DexPathList[[zip file "/data/app/com.company-2/base.apk"],nativeLibraryDirectories=[/data/app/com.company-2/lib/x86, /vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
... 107 more
Suppressed: java.lang.ClassNotFoundException: com.company.common.config.GlideConfiguration
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 108 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
項(xiàng)目里用到了Glide圖片緩存框架娃兽,我們在AndroidManifest.xml里面有這樣的定義
<!-- Glide 相關(guān)配置 -->
<meta-data
android:name="com.company.common.config.GlideConfiguration"
android:value="GlideModule" />
如果GlideConfiguration這個類被混淆了,程序當(dāng)然找不到尽楔,從而導(dǎo)致配置出錯投储,程序一進(jìn)入使用到圖片緩存框架的地方就崩潰了,所以應(yīng)該在混淆文件里面再添加上一句
-keep public class * implements com.bumptech.glide.module.GlideModule
打包編譯阔馋,運(yùn)行OK沒有崩潰玛荞。
3、如果使用json解析庫呕寝,不要混淆model類
運(yùn)行后發(fā)現(xiàn)程序運(yùn)行依然沒有達(dá)到預(yù)期勋眯,有些跟后臺交互的接口會請求出錯,查看日志壁涎,原來是json解析出錯凡恍,本地代碼找不到某個字段,可是我本地代碼明明是有的呀怔球!
public class Book {
private String name;
private Long id;
private String title;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
于是添加了fastJson的忽略注解
@JsonIgnoreProperties(ignoreUnknown = true)
但這治標(biāo)不治本嚼酝,雖然接口沒報(bào)異常,但可能會把后臺返回來的相關(guān)字段給忽略掉了竟坛。
于是使出了殺手锏闽巩,反編譯自己的apk,出奇的發(fā)現(xiàn)反編譯出來的代碼確實(shí)是少了一些變量
@JsonIgnoreProperties(ignoreUnknown = true)
public class a {
private Long a;
private String c;
public Long a() {
return this.a;
}
public String c() {
return this.c;
}
}
這是什么原因呢担汤?再google一番涎跨,原來是代碼被優(yōu)化,有些沒使用到的字段崭歧、代碼在混淆的過程中被優(yōu)化去除掉了隅很。一直都有聽說混淆代碼會幫助優(yōu)化代碼,減少apk體積率碾,但不知道具體是怎么優(yōu)化的叔营,原來這里是自動幫去除了一些沒有調(diào)用的方法、資源所宰。這是proguard-rules.pro原有的optimize配置
# From Proguard-android-optimize
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification
-dontpreverify
實(shí)際上我們使用了一些數(shù)據(jù)庫框架的時候绒尊,自然不會調(diào)用model所有字段的getter、setter方法仔粥,比如ormLite數(shù)據(jù)庫框架婴谱,一句create(model)就存入數(shù)據(jù)庫了蟹但,自然的很多model的方法就被優(yōu)化去掉了。
因此在使用gson谭羔、fastJson時华糖,model類不需要混淆,否則會出錯口糕,因?yàn)樗麄兪抢冒l(fā)射來解析json缅阳,混淆后找不到對應(yīng)的變量的getter、setter方法就會報(bào)空指針景描。
所以,加上一句
-keep com.model.** { *; }
打包編譯秀撇,OK超棺,正常運(yùn)行。
關(guān)于混淆更多詳細(xì)的知識點(diǎn)呵燕,也推薦查看這篇文章
4棠绘、關(guān)于混淆的一些發(fā)現(xiàn)
發(fā)現(xiàn)一些有趣的事情,原生的混淆文件proguard-rules.pro已經(jīng)默認(rèn)添加了很多配置再扭,平時不看的話根本不知道的事情
比如不混淆所有序列化的類
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class * implements java.io.Serializable {
public <methods>;
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
不混淆R資源文件氧苍,不然找不著相應(yīng)的id
-keep public class com.company.R$*{
public static final int *;
}
不混淆自定義View類、Activity類泛范,不然在layout布局文件让虐、AndroidManifest.xml里面找不找對應(yīng)的類
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep class extends Activity
-keep class * extends android.app.Activity{*;}
5、總結(jié)
通過混淆的實(shí)踐疲吸,擴(kuò)充了一部分混淆的相關(guān)知識捍岳,也只有踩過坑之后咖气,才知道如何走好后面的路。對于一些技術(shù)原理惭缰,應(yīng)該要多實(shí)踐、多總結(jié)笼才,為自己做好技術(shù)積累漱受。