android 混淆

Android 混淆对于开发者来说是个挑战,混淆时可能会遇到各种问题导致应用崩溃。本文提供了一份详细的混淆模板,包括基本配置、默认保留、其他设置和第三方库的处理。模板中包含了对Activity、Service等关键类的保留,以及对RXJava和百度地图SDK的混淆处理,以防止运行时错误。混淆还能删除Log相关代码和保留测试代码。混淆过程中要注意忽略警告,否则可能导致打包失败。

android 混淆对于独立开发者来,和app打包上线的人来说是一个大坑。虽然说规则其实我们不用去记住,只需要把

混淆模板复制粘贴就行(下面是模板),但是当你debug模式下没问题,release打包时候各种闪出,并且报各种类找不到时候,这时候注意了,很有可能是混淆出来了问题。顺便说一下,release出错解决办法,那就是 在androidstuoid上连接手机,选着手机,但是不选择进程。我知道很简单,但是我有一次忘了AS有这个功能,竟然

用 adb 命令去分析 运行时问题。好了。下面时 混淆模板,再下面是 2个常用问题的混淆。RXjava,这个不混淆会发现涉及到联网就闪退(看个人),曝出的问题是类找不到。 第2个是。百度地图,在倒sdk的时候把混淆忽视了,感觉不多,结果在程序初始化的时候就闪退。

还有gson和Serializable .和
// 忽略警告,否则打包可能会不成功=
-ignorewarnings

开启混淆:

在app mould 中的build.gradle中 设置 :

android {

buildTypes {

debug {

    minifyEnabled    true

    proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

}

release {

    minifyEnabled  true

    proguardFiles   getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

}

}

万能模板:

#-------------------------------------------基本不用动区域----------------------------------------------

-----------------------------基本 -----------------------------

指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。)

-optimizationpasses 5

混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名)

-dontusemixedcaseclassnames

指定不去忽略非公共的库类(不跳过library中的非public的类)

-dontskipnonpubliclibraryclasses

指定不去忽略包可见的库类的成员

-dontskipnonpubliclibraryclassmembers

#不进行优化,建议使用此选项,

-dontoptimize

不进行预校验,Android不需要,可加快混淆速度。

-dontpreverify

屏蔽警告

-ignorewarnings

指定混淆是采用的算法,后面的参数是一个过滤器

这个过滤器是谷歌推荐的算法,一般不做更改

-optimizations !code/simplification/arithmetic,!field/,!class/merging/

保护代码中的Annotation不被混淆

-keepattributes Annotation

避免混淆泛型, 这在JSON实体映射时非常重要

-keepattributes Signature

抛出异常时保留代码行号

-keepattributes SourceFile,LineNumberTable

#优化时允许访问并修改有修饰符的类和类的成员,这可以提高优化步骤的结果。

比如,当内联一个公共的getter方法时,这也可能需要外地公共访问。

虽然java二进制规范不需要这个,要不然有的虚拟机处理这些代码会有问题。当有优化和使用-repackageclasses时才适用。

#指示语:不能用这个指令处理库中的代码,因为有的类和类成员没有设计成public ,而在api中可能变成public

-allowaccessmodification

#当有优化和使用-repackageclasses时才适用。

-repackageclasses ‘’

混淆时记录日志(打印混淆的详细信息)

这句话能够使我们的项目混淆后产生映射文件

包含有类名->混淆后类名的映射关系

-verbose

----------------------------- 默认保留 -----------------------------

#----------------------------------------------------

保持哪些类不被混淆

#继承activity,application,service,broadcastReceiver,contentprovider…不进行混淆

-keep public class * extends android.app.Activity

-keep public class * extends android.app.Application

-keep public class * extends android.support.multidex.MultiDexApplication

-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 class android.support.** {*;}## 保留support下的所有类及其内部类

-keep public class com.google.vending.licensing.ILicensingService

-keep public class com.android.vending.licensing.ILicensingService

#表示不混淆上面声明的类,最后这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。

#----------------------------------------------------

保留继承的

-keep public class * extends android.support.v4.**

-keep public class * extends android.support.v7.**

-keep public class * extends android.support.annotation.**

#表示不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致

-keepclasseswithmembernames class * {

native ;

}

#这个主要是在layout 中写的onclick方法android:οnclick=“onClick”,不进行混淆

#表示不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性,

#当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了

-keepclassmembers class * extends android.app.Activity{

public void *(android.view.View);

}

#表示不混淆枚举中的values()和valueOf()方法,枚举我用的非常少,这个就不评论了

-keepclassmembers enum * {

public static **[] values();

public static ** valueOf(java.lang.String);

}

#表示不混淆任何一个View中的setXxx()和getXxx()方法,

#因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了。

-keep public class * extends android.view.View{

*** get*();

void set*(***);

public (android.content.Context);

public (android.content.Context, android.util.AttributeSet);

public (android.content.Context, android.util.AttributeSet, int);

}

-keepclasseswithmembers class * {

public (android.content.Context, android.util.AttributeSet);

public (android.content.Context, android.util.AttributeSet, int);

}

#表示不混淆Parcelable实现类中的CREATOR字段,

#毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。

-keep class * implements android.os.Parcelable {

public static final android.os.Parcelable$Creator *;

}

这指定了继承Serizalizable的类的如下成员不被移除混淆

-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();

}

保留R下面的资源

#-keep class *.R$ {

*;

#}

#不混淆资源类下static的

-keepclassmembers class *.R$ {

public static ;

}

对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆

-keepclassmembers class * {

void (**OnEvent);

void (**OnListener);

}

保留我们自定义控件(继承自View)不被混淆

-keep public class * extends android.view.View{

*** get*();

void set*(***);

public (android.content.Context);

public (android.content.Context, android.util.AttributeSet);

public (android.content.Context, android.util.AttributeSet, int);

}

#----------------------------- WebView(项目中没有可以忽略) -----------------------------

#webView需要进行特殊处理

-keepclassmembers class fqcn.of.javascript.interface.for.Webview {

public *;

}

-keepclassmembers class * extends android.webkit.WebViewClient {

public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);

public boolean *(android.webkit.WebView, java.lang.String);

}

-keepclassmembers class * extends android.webkit.WebViewClient {

public void *(android.webkit.WebView, jav.lang.String);

}

#在app中与HTML5的JavaScript的交互进行特殊处理

#我们需要确保这些js要调用的原生方法不能够被混淆,于是我们需要做如下处理:

-keepclassmembers class com.ljd.example.JSInterface {

;

}

#---------------------------------实体类---------------------------------

#--------(实体Model不能混淆,否则找不到对应的属性获取不到值)-----

-dontwarn com.suchengkeji.android.confusiondemo.md.**

#对含有反射类的处理

-keep class com.suchengkeji.android.confusiondemo.md.** { *; }

----------------------------- 其他的 -----------------------------

删除代码中Log相关的代码

-assumenosideeffects class android.util.Log {

public static boolean isLoggable(java.lang.String, int);

public static int v(…);

public static int i(…);

public static int w(…);

public static int d(…);

public static int e(…);

}

保持测试相关的代码

-dontnote junit.framework.**

-dontnote junit.runner.**

-dontwarn android.test.**

-dontwarn android.support.test.**

-dontwarn org.junit.**

----------------------------- 第三方 -----------------------------

-dontwarn com.orhanobut.logger.**

-keep class com.orhanobut.logger.**{*;}

-keep interface com.orhanobut.logger.**{*;}

-dontwarn com.google.gson.**

-keep class com.google.gson.**{*;}

-keep interface com.google.gson.**{*;}

#--------------------------------------百度地图-------------------------------

-keep class com.baidu.** {*;}

-keep class mapsdkvi.com.** {*;}

-dontwarn com.baidu.**

#RXjava 混淆问题

#---------------------------------------RXjava-----------------------------------

-keepclassmembers class rx.internal.util.unsafe.ArrayQueueField* {

long producerIndex;

long consumerIndex;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {

rx.internal.util.atomic.LinkedQueueNode producerNode;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {

rx.internal.util.atomic.LinkedQueueNode consumerNode;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {

long producerNode;

long consumerNode;

}

-keep class rx.schedulers.Schedulers {

public static ;

}

-keep class rx.schedulers.Schedulers {

public static ** test();

}

-keep class rx.schedulers.ImmediateScheduler {

public ;

}

-keep class rx.schedulers.TestScheduler {

public ;

}

-dontwarn sun.misc.**

-keepclassmembers class rx.internal.util.unsafe.ArrayQueueField* {

long producerIndex;

long consumerIndex;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {rx.internal.util.atomic.LinkedQueueNode producerNode;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {rx.internal.util.atomic.LinkedQueueNode consumerNode;

}

-dontnote rx.internal.util.PlatformDependent

#BaseRecyclviewApdter

-keep class com.chad.library.adapter.** {

*;

}

-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter

-keep public class * extends com.chad.library.adapter.base.BaseViewHolder

-keepclassmembers class $ extends com.chad.library.adapter.base.BaseViewHolder {

(…);

}

#保持 Serializable 不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient ;
!private ;
!private ;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#保持 Serializable 不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient ;
!private ;
!private ;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

忽略警告,否则打包可能会不成功=

-ignorewarnings

Android 开发中,代码混淆是保护应用安全、减小 APK 体积的重要手段。ProGuard 是 Android 官方早期提供的代码混淆工具,它通过对类名、方法名和字段名进行重命名,降低代码的可读性,并通过优化字节码提升性能[^2]。 ### 启用 ProGuard 混淆Android 项目中启用 ProGuard 非常简单,只需在模块级的 `build.gradle` 文件中配置 `minifyEnabled` 和 `proguardFiles` 即可: ```gradle android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } ``` - `minifyEnabled true` 表示启用代码混淆。 - `proguardFiles` 指定使用的 ProGuard 配置文件,通常包括系统默认的优化规则和自定义规则文件 `proguard-rules.pro`[^4]。 ### 编写 ProGuard 混淆规则 ProGuard 的核心在于编写合适的混淆规则。规则文件通常位于模块根目录下的 `proguard-rules.pro` 文件中。 #### 常用规则示例: ```proguard # 保留所有 Activity 类不被混淆 -keep public class * extends android.app.Activity # 保留所有 Application 类不被混淆 -keep public class * extends android.app.Application # 保留 Parcelable 实现类及其构造方法 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } # 保留所有使用了注解的类成员 -keepclassmembers class * { @android.webkit.JavascriptInterface <methods>; } # 保留枚举类 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } ``` 这些规则确保关键的 Android 组件和功能在混淆过程中不会被错误地移除或重命名[^1]。 ### 查看混淆日志与调试 构建混淆后的 APK 后,可以通过 `mapping.txt` 文件来查看混淆前后类名、方法名和字段名的映射关系。该文件通常位于 `app/build/outputs/mapping/release/` 目录下。 如果应用在运行时出现异常,可以通过 `retrace` 工具将混淆后的堆栈信息还原为原始类名和方法名: ```bash retrace.sh -verbose mapping.txt obfuscated_stack_trace.txt ``` 这有助于定位混淆导致的运行时错误[^1]。 ### 常见问题与解决方法 - **类或方法被错误移除**:使用 `-keep` 指令保留关键类或方法。 - **资源引用错误**:某些资源类(如 `R` 类)应保留不被混淆。 - **第三方库未正确处理**:为第三方库添加特定的 ProGuard 规则,通常可以在库的文档中找到。 - **启动崩溃或功能异常**:检查是否遗漏了对反射调用、JNI 接口或动态加载类的保留规则。 ### 优化建议 - 在启用混淆的同时,建议开启资源压缩和未用资源移除功能,以进一步减小 APK 体积: ```gradle android { buildTypes { release { minifyEnabled true shrinkResources true proguardFiles ... } } } ``` - 使用 `proguard-android-optimize.txt` 而非 `proguard-android.txt` 可启用更高级的优化策略,提升应用性能[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值