美文网首页AndroidAndroidandroid
Android优雅的进行混淆——使用@Keep注解

Android优雅的进行混淆——使用@Keep注解

作者: Ziv_紫藤花开 | 来源:发表于2016-11-15 11:21 被阅读8958次

不能混淆的项

在AndroidManifest中配置的类,比如四大组件
JNI调用的方法
反射用到的类
WebView中JavaScript调用的方法
Layout文件引用到的自定义View
一些引入的第三方库

使用工具AndroidStudio

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

使用proguard混淆代码是对产品本身的一种保护,常见的方法就是编写projuard-rules.pro配置文件

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

//混淆时不使用大小写混合类名
-dontusemixedcaseclassnames
//不跳过library中的非public的类
-dontskipnonpubliclibraryclasses
//打印混淆的详细信息
-verbose
 
# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
//不进行优化,建议使用此选项,理由见上
-dontoptimize
//不进行预校验,预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.
 
//保留注解参数
-keepattributes *Annotation*
//保留Google原生服务需要的类
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
 
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
//保留native方法的类名和方法名
-keepclasseswithmembernames class * {
    native <methods>;
}
 
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
//保留自定义View,如"属性动画"中的set/get方法
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}
 
# We want to keep methods in Activity that could be used in the XML attribute onClick
//保留Activity中参数是View的方法,如XML中配置android:onClick=”buttonClick”属性,Activity中调用的buttonClick(View view)方法
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}
 
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
//保留混淆枚举中的values()和valueOf()方法
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
 
//Parcelable实现类中的CREATOR字段是绝对不能改变的,包括大小写
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}
 
//R文件中的所有记录资源id的静态字段
-keepclassmembers class **.R$* {
    public static <fields>;
}
 
# The support library contains references to newer platform versions.
# Dont warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
//忽略support包因为版本兼容产生的警告
-dontwarn android.support.**

Proguard关键字

关键字                      描述
keep                        保留类和类中的成员,防止被混淆或移除
keepnames                   保留类和类中的成员,防止被混淆,成员没有被引用会被移除
keepclassmembers            只保留类中的成员,防止被混淆或移除
keepclassmembernames        只保留类中的成员,防止被混淆,成员没有引用会被移除
keepclasseswithmembers      保留类和类中的成员,防止被混淆或移除,保留指明的成员
keepclasseswithmembernames  保留类和类中的成员,防止被混淆,保留指明的成员,成员没有引用会被移除

Proguard通配符

通配符      描述
<field>     匹配类中的所有字段
<method>    匹配类中所有的方法
<init>      匹配类中所有的构造函数
*           匹配任意长度字符,不包含包名分隔符(.)
**          匹配任意长度字符,包含包名分隔符(.)
***         匹配任意参数类型
...

指定混淆时可使用字典

-applymapping filename 指定重用一个已经写好了的map文件作为新旧元素名的映射。
-obfuscationdictionary filename 指定一个文本文件用来生成混淆后的名字。
-classobfuscationdictionary filename 指定一个混淆类名的字典
-packageobfuscationdictionary filename 指定一个混淆包名的字典
-overloadaggressively 混淆的时候大量使用重载,多个方法名使用同一个混淆名(慎用)

    # 这里巧妙地使用java中的关键字作字典,混淆之后的代码更加不利于阅读
    #
    # This obfuscation dictionary contains reserved Java keywords. They can't
    # be used in Java source files, but they can be used in compiled class files.
    # Note that this hardly improves the obfuscation. Decent decompilers can
    # automatically replace reserved keywords, and the effect can fairly simply be
    # undone by obfuscating again with simpler names.
    # Usage:
    #     java -jar proguard.jar ..... -obfuscationdictionary keywords.txt
    #
    
    do
    if
    for
    int
    new
    try
    byte
    case
    char
    else
    goto
    long
    this
    void
    break
    catch
    class
    const
    final
    float
    short
    super
    throw
    while
    double
    import
    native
    public
    return
    static
    switch
    throws
    boolean
    default
    extends
    finally
    package
    private
    abstract
    continue
    strictfp
    volatile
    interface
    protected
    transient
    implements
    instanceof
    synchronized

使用proguardgui对jar包进行混淆

proguardgui工具支持Shrinking(压缩)、Optimization(优化)、Obfuscation(混淆)、Preverification(预校验)四项操作

详细步骤:
    1 Load configuration --> Next
    2 Add input/Add output
    3 添加jar包依赖
        JAVA_HOME/jre/lib/rt.jar
        Android_SDK/platfroms/android-23/android.jar
        AndroidStudioProjects/ProjectName/app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.4.0/jars/classes.jar
        AndroidStudioProjects/ProjectName/app/build/intermediates/exploded-aar/com.android.support/support-v4/23.4.0/jars/classes.jar
        AndroidStudioProjects/ProjectName/app/build/intermediates/exploded-aar/com.android.support/support-v4/23.4.0/jars/libs/internal_impl-23.4.0.jar
        其他第三方jar文件
    4 Don`t use Shrink --> Next
    5 Add --> Extends/implements class --> android.app.Activity --> ok --> Next
    6 Next
    7 Next
    8 View configuration
tips:
    AndroidStudio中生成jar文件方法:
    jar -cvf filename.jar -C app/build/intermediates/classes/debug

5分钟快速混淆

#-------------------------------------------定制化区域----------------------------------------------
#---------------------------------1.实体类---------------------------------

-keep class com.demo.login.bean.** { *; }
-keep class com.demo.main.bean.** { *; }

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

#---------------------------------2.第三方包-------------------------------

#eventBus
-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

#glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}

#log4j
-libraryjars log4j-1.2.17.jar
-dontwarn org.apache.log4j.**
-keep class  org.apache.log4j.** { *;}

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

#---------------------------------3.与js互相调用的类------------------------

-keepclasseswithmembers class com.demo.login.bean.ui.MainActivity$JSInterface { 
      <methods>; 
}

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

#---------------------------------4.反射相关的类和方法-----------------------
# 有
#----------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------

#-------------------------------------------基本不用动区域--------------------------------------------
#---------------------------------基本指令区----------------------------------
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-printmapping proguardMapping.txt
-optimizations !code/simplification/cast,!field/*,!class/merging/*
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
#----------------------------------------------------------------------------

#---------------------------------默认保留区---------------------------------
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-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
-keep class android.support.** {*;}

-keepclasseswithmembernames class * {
    native <methods>;
}
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
-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 **.R$* {
 *;
}
-keepclassmembers class * {
    void *(**On*Event);
}
#----------------------------------------------------------------------------

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

# 删除代码中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(...);
}

网上有很多5分钟完成混淆规则的教程,但如何更优雅的完成这一枯燥的过程,即使用@Keep注解,使混淆变得轻松愉快

在proguard-rules.pro配置文件中加入以下规则

#手动启用support keep注解
#http://tools.android.com/tech-docs/support-annotations
-dontskipnonpubliclibraryclassmembers
-printconfiguration
-keep,allowobfuscation @interface android.support.annotation.Keep

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

哪里不对@Keep哪里,妈妈再也不用担心我不会混淆啦……

参考资料
http://blog.csdn.net/guolin_blog/article/details/50451259
http://www.jianshu.com/p/60e82aafcfd0

相关文章

  • Android优雅的进行混淆——使用@Keep注解

    不能混淆的项 使用工具AndroidStudio 使用proguard混淆代码是对产品本身的一种保护,常见的方法就...

  • Keep混淆

    keep注解 支持变量、方法、构造方法、类、注解 混淆文件proguard-rules.pro android代码...

  • 优雅的处理 Android 代码混淆 Keep 问题

    为了源码安全以及缩小 APK 体积,Android 应用发布前是必须要进行混淆打包的。而混淆打包并不是全量打包,特...

  • Android使用Eventbus遇到的混淆问题

    问题描述: 打开混淆,release一个包。 在使用Eventbus和注解的Android项目中,通过反射机制调用...

  • Android中的代码混淆

    混淆规则 因为Android是使用Java开发的,所以开发者可以使用ProGuard对代码进行混淆。SDK已经集成...

  • 如何优雅地使用NDK

    如何优雅地使用NDK ANDROID STUDIO 终于可以进行NDK!!

  • 不能使用混淆的情况

    不能使用混淆的情况 反射使用的元素 最好不要让一些Bean对象混淆 四大组件不能混淆 注解不能混淆 不能混淆枚举中...

  • Proguard优雅的混淆注解方案

    Proguard可以移除无用代码,或者使用语意模糊的名称来重命名类、变量和方法,以此达到压缩、优化和混淆代码的目的...

  • 关于Android混淆的一些经验

    一些关于混淆的好文章 Android混淆从入门到精通 写给Android开发者的混淆使用手册 读懂 Android...

  • java注解

    内容: 注解的定义 注解的语法 源码级别的注解的使用 运行时注解的使用 编译时注解的使用 Android 预置的注...

网友评论

  • coder_yu:# Optimization is turned off by default. Dex does not like code run
    # through the ProGuard optimize and preverify steps (and performs some
    # of these optimizations on its own).
    //不进行优化,建议使用此选项,理由见上
    -dontoptimize
    //不进行预校验,预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度
    -dontpreverify

    请问这两个内容是哪里查到的?
    coder_yu:@Ziv_紫藤花开 感谢,已经找到了
    Ziv_紫藤花开:@coder_yu Android SDK中进入`tools-->proguard-->proguard-android.txt`文件查看
  • outer199:very nice!
  • 1fdd5c458944:好,看到最全的了,谢谢
    Ziv_紫藤花开:不用谢,能帮到你就好

本文标题:Android优雅的进行混淆——使用@Keep注解

本文链接:https://www.haomeiwen.com/subject/ubwkpttx.html