android代码混淆

本文介绍了Android代码混淆的设置,包括在build.gradle中启用混淆和指定混淆规则文件。详细解析了proguard-android.txt等默认混淆文件的作用,并给出了如何处理第三方库混淆问题和避免应用崩溃的建议。同时,讨论了哪些类和方法不应被混淆,如实体类、与JavaScript交互的类、反射相关类。最后,探讨了使用注解保持元素不被混淆的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近编辑于2018年4月30日

一、

都知道在build.gradle中设置如下代码即可开启混淆。

 

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

其中minifyEnabled为true时即开启混淆,而proguardFiles则指定了混淆规则的文件们,也就是代码会根据proguard-android.text和proguard-rules.pro里所写的规则来进行混淆。你也可以像下面这样进行混淆(只要你在这个文件里设置了混淆规则):

 

 

            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt')//在proguard-android.txt文件
//设置了混淆规则

那么proguard-android.txt文件在哪?就在你的sdk路径下的\tools\proguard文件夹里。

 

可以发现这儿有三个可疑文件,proguard-android.txt就是默认混淆文件,proguard-android-optimize.txt就是比proguad-android.txt多指定了压缩级别,而proguard-project.txt给我们一条建议:应该保证类中所有js方法不被混淆,这里使用关键词keepclassmembers。

 

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
 -keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
 }


二、

 

新建一个工程,即使你不指定混淆规则文件也能成功打包,如下:

 

    buildTypes {
        release {
            minifyEnabled true
        }
    }

那么我们什么时候不能成功打包?只要设置以下混淆规则就能成功打包。

 

-dontoptimize
-dontpreverify
-ignorewarnings

但是通常一打开应用就会崩。而且不推荐使用-ignorewarnings,推荐dontwarn。

 

三、

 

对于第三方包,首先肯定是按照其说明配置混淆规则,而如果你按照其说明仍然报错,首先可以放弃使用。其次,如果非要使用的话,报错信息与下面类似

 

Warning:retrofit2.Platform$Java8: can't find referenced class java.lang.invoke.MethodHandles$Lookup
Warning:retrofit2.Platform$Java8: can't find referenced class java.lang.invoke.MethodHandle
Warning:retrofit2.Platform$Java8: can't find referenced class java.lang.invoke.MethodHandles
Warning:retrofit2.Platform$Java8: can't find referenced class java.lang.invoke.MethodHandle
Warning:retrofit2.Platform$Java8: can't find referenced class java.lang.invoke.MethodHandles$Lookup
Warning:retrofit2.Platform$Java8: can't find referenced class org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
Warning:there were 8 unresolved references to classes or interfaces.
Warning:Exception while processing task java.io.IOException: Please correct the above warnings first.
Error:Execution failed for task ':app:transformClassesAndResourcesWithProguardForRelease'.
> Job failed, see logs for details

出现Please correct the above warnings first,而上面warning是can't find referenced class xxxxxxxx,可以观察前面的retrofit2,即可设置-dontwarn retrofit2来避免报错不能打包。

 

四、

参考点击打开链接

 

移除是指在压缩(Shrinking)时是否会被删除。

 

保持元素不参与混淆的规则如下:

 

 

[保持命令] [类] {
    [成员] 
}

“类”代表类相关的限定条件,它将最终定位到某些符合该限定条件的类。它的内容可以使用:

  • 具体的类
  • 访问修饰符(publicprotectedprivate
  • 通配符*,匹配任意长度字符,但不含包名分隔符(.)
  • 通配符**,匹配任意长度字符,并且包含包名分隔符(.)
  • extends,即可以指定类的基类
  • implement,匹配实现了某接口的类
  • $,内部类

 

 

“成员”代表类成员相关的限定条件,它将最终定位到某些符合该限定条件的类成员。它的内容可以使用:

  • <init> 匹配所有构造器
  • <fields> 匹配所有域
  • <methods> 匹配所有方法
  • 通配符*,匹配任意长度字符,但不含包名分隔符(.)
  • 通配符**,匹配任意长度字符,并且包含包名分隔符(.)
  • 通配符***,匹配任意参数类型
  • ,匹配任意长度的任意类型参数。比如void test(…)就能匹配任意 void test(String a) 或者是void test(int a, String b) 这些方法。
  • 访问修饰符(publicprotectedprivate

 

我们再看看proguard-android.txt里写了啥

1、

 

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    native <methods>;
}

 

不混淆native的方法

2、

 

# 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*();
}

 

不混淆继承View的所有类的set和get方法

3、

 

# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

 

不混淆继承Activity的所有类的中的参数类型为View的方法

4、

 

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

不混淆枚举类型的values和valueOf方法

 

5、

 

-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

不混淆继承Parcelable的所有类的CREATOR

 

6、

-keepclassmembers class **.R$* {
    public static <fields>;
}

不混淆R类中所有static字段

 

7、这是和build版本相关的内容

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep

-keep @android.support.annotation.Keep class * {*;}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}

五、

 

我们有那些东西不能被混淆呢?

1、实体类

2、与js互调的类

3、与反射相关的类
        例如你需要通过反射获取TabLayout的一些信息,则应该

-keep class android.support.design.widget.TabLayout{*;}

4、如果需要使用类名调用,则不应被混淆

六、

使用注解来保持元素。

在SDK\tools\proguard下还有一个examples文件夹比较可疑。进去后除了一些混淆案例,在SDK\tools\proguard\examples\annotations\src\proguard\annotation文件夹下有一些java类。

如果想通过注解使set和get方法不被混淆

S1、在你的工程中参照KeepPublicGettersSetters.java新建一个类。

 

package proguard.annotation;//改为你的包名

import java.lang.annotation.*;//安卓中不需要导lang下的包

/**
 * This annotation specifies to keep all public getters and setters of the
 * annotated class from being shrunk, optimized, or obfuscated as entry points.
 */
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.CLASS)
@Documented
public @interface KeepPublicGettersSetters {}

S2、参照SDK\tools\proguard\examples\annotations\lib文件,在proguard-android.pro文件中添加如下语句

 

 

    -keepclassmembers @你的类名 class * {
    void set*(***);
    void set*(int, ***);

    boolean is*();
    boolean is*(int);

    *** get*();
    *** get*(int);
    }

S3、参照SDK\tools\proguard\examples\annotations\examples文件,在你需要保持get和set方法不混淆的类的类名上添加@KeepPublicGettersSetters。

 

这样就通过注解完成keep了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值