使用proguard进行代码混淆

1.在需要混淆的工程目录下(package/apps/下的工程)添加proguard.flags文件,
然后再Android.mk中添加如 下两句:
LOCAL_PROGUARD_ENABLED := full
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
上面的full 也可以是custom,如果不写这句,那还得添加如下一句:
TARGET_BUILD_VARIANT := user或者TARGET_BUILD_VARIANT := userdebug
问题:full和custom有什么区别?实验了一下,custom的话proguard.flags中未提到的java文件不在生成的jar中
  
2.android在编译时默认关闭了混淆选项,需要将build/core目录下的
proguard.flags文件里如下句子注释掉便 可实现混淆编译:
# Don't obfuscate. We only need dead code striping.
-dontobfuscate(将该句加个#号注释掉)
  
这样后在工程目录下执行mm便可以看到在out目录下生成了形如
proguard.classes.jar的东东,这就说明已在编译中启动 了proguard
  
  
proguard.flag文件内容:
maodejun@maodejun-OptiPlex-755:~/source/qrd-smartdroid/packages/apps/Mms$ cat proguard.flag
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
  
-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 com.android.vending.licensing.ILicensingService
  
-keepclasseswithmembernames class * {
     native <methods>;
}
  
-keepclasseswithmembers class * {
     public <init>(android.content.Context, android.util.AttributeSet);
}
  
-keepclasseswithmembers class * {
     public <init>(android.content.Context, android.util.AttributeSet, int);
}
  
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}
  
-keepclassmembers enum * {
     public static **[] values();
     public static ** valueOf(java.lang.String);
}
  
-keep class * implements android.os.Parcelable {
   public static final android.os.Parcelable$Creator *;
}
  
  
3.一般的apk可以用附件的proguard.flags文件即可
 
代码混淆注意:由于混淆是将类的名字给改了,因此凡是在代码中用到发射机制取得类的对象的地方都不能给混淆,需要用下面方式skip混淆。 -keep class com.android.mms.ui.SlideshowPresenter { *; } 原因:反射是通过类名去得到实例,但是如果混淆将此类的名字给改掉后,反射的 Class.forName(className)方法就不能找到该类了。因此代码中所有调用 Class.forName(className)的地方都应该需要分析。
 
 
相关参数:
-include {filename}    从给定的文件中读取配置参数

-basedirectory {directoryname}    指定基础目录为以后相对的档案名称

-injars {class_path}    指定要处理的应用程序jar,war,ear和目录

-outjars {class_path}    指定处理完后要输出的jar,war,ear和目录的名称

-libraryjars {classpath}    指定要处理的应用程序jar,war,ear和目录所需要的程序库文件

-dontskipnonpubliclibraryclasses    指定不去忽略非公共的库类。

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


保留选项
-keep {Modifier} {class_specification}    保护指定的类文件和类的成员

-keepclassmembers {modifier} {class_specification}    保护指定类的成员,如果此类受到保护他们会保护的更好

-keepclasseswithmembers {class_specification}    保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。

-keepnames {class_specification}    保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)

-keepclassmembernames {class_specification}    保护指定的类的成员的名称(如果他们不会压缩步骤中删除)

-keepclasseswithmembernames {class_specification}    保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)

-printseeds {filename}    列出类和类的成员-keep选项的清单,标准输出到给定的文件

压缩
-dontshrink    不压缩输入的类文件

-printusage {filename}

-whyareyoukeeping {class_specification}    

优化
-dontoptimize    不优化输入的类文件

-assumenosideeffects {class_specification}    优化时假设指定的方法,没有任何副作用

-allowaccessmodification    优化时允许访问并修改有修饰符的类和类的成员

混淆
-dontobfuscate    不混淆输入的类文件

-printmapping {filename}

-applymapping {filename}    重用映射增加混淆

-obfuscationdictionary {filename}    使用给定文件中的关键字作为要混淆方法的名称

-overloadaggressively    混淆时应用侵入式重载

-useuniqueclassmembernames    确定统一的混淆类的成员名称来增加混淆

-flattenpackagehierarchy {package_name}    重新包装所有重命名的包并放在给定的单一包中

-repackageclass {package_name}    重新包装所有重命名的类文件中放在给定的单一包中

-dontusemixedcaseclassnames    混淆时不会产生形形色色的类名

-keepattributes {attribute_name,...}    保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.

-renamesourcefileattribute {string}    设置源文件中给定的字符串常量

附:
好奇的同志还可以继续看看,为什么TARGET_BUILD_VARIANT := user和LOCAL_PROGUARD_ENABLED := full二选一即可,详见build/core/package.mk:

LOCAL_PROGUARD_ENABLED:=$(strip $(LOCAL_PROGUARD_ENABLED))
ifndef LOCAL_PROGUARD_ENABLED
ifneq ($(filter user userdebug, $(TARGET_BUILD_VARIANT)),)
    # turn on Proguard by default for user & userdebug build
    LOCAL_PROGUARD_ENABLED :=full
endif
endif
ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
    # the package explicitly request to disable proguard.
    LOCAL_PROGUARD_ENABLED :=
endif
proguard_options_file :=
ifneq ($(LOCAL_PROGUARD_ENABLED),custom)
ifneq ($(all_resources),)
    proguard_options_file := $(package_expected_intermediates_COMMON)/proguard_options
endif # all_resources
endif # !custom
LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
具体我就不解释了,大家自己理解吧哈

 
其他:

Android ProGuard使用要点

1.基本的的使用可以很容易百度到,

 但是当你使用了android-support-v4或者android-support-v7或者android-support-v11包之后,你发现导出的时候,

警告相当得多,这个时候,就算百度,Google都不太好使了,因为他们都是回答了一部分,没有很好的解决你的问题:

 其实要解决你的问题的方法就在你的android-sdk路径的proguard中的文档中:

特别是Examples示例中:

示例中有专门针对android的说明:

  以下是第一点:

If you're using additional Google APIs, you'll have to specify those as well, for instance:

如果你使用了Google API,你还需要添加如下声明 

-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar

If you're using the Android Compatibility library, you should add the following line, to let ProGuard know it's ok that the library references some classes that are not available in all versions of the API:

如果你使用了android-support包,你需要使用以下声明设置,让ProGuard知道库中的一些类并不是在所有版本的API中可用:

-dontwarn android.support.**

 

如果你还有其它问题,那还是参见proguard文档吧..

2.使用ProGuard删除日志输出语句,

 Thanks to:statckoverflow

  (1)http://stackoverflow.com/questions/4435773/android-proguard-removing-all-log-statements-and-merging-packages

 (2)http://stackoverflow.com/questions/7086920/removing-logging-with-proguard-doesnt-remove-the-strings-being-logged

在开发android的时候,经常要使用Log.d()语句,但是发布的时候,如果一行一行的注释还是有点麻烦的.

这个时候可以使用如下的指令让proguard帮助我们删除他:

-assumenosideeffects class android.util.Log{ public static *** d(...); public static *** i(...); }


  转:http://my.oschina.net/banxi/blog/55622

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值