Android代码混淆

来源:互联网 发布:组策略限制软件安装 编辑:程序博客网 时间:2024/06/11 02:59

最近碰到很多人都在讨论代码混淆,本人在此分享下Android代码混淆打包,如有不足之处希望大神能多多指教,首先我们来了解下什么是代码混淆:

Java 是一种跨平台的、解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中。由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码。为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆。

混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的缩短变量和函数名以及丢失部分信息的原因, 编译后 jar 文件体积大约能减少25% ,这对当前费用较贵的无线网络传输是有一定意义的。

混淆文件 proguard.cfg 参数详解:

-optimizationpasses 5                                                          
 # 指定代码的压缩级别(0-7)-dontusemixedcaseclassnames                                                     
# 是否使用大小写混合-dontskipnonpubliclibraryclasses                                                
# 是否混淆第三方jar-dontpreverify                                                                  
# 混淆时是否做预校验-verbose                                                                       
 # 混淆时是否记录日志-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*        
# 混淆时所采用的算法
<pre name="code" class="java"># 保持哪些类不被混淆
-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
<pre name="code" class="java"># 保持 native 方法不被混淆
-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);}
# 保持枚举 enum 类不被混淆
-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String);}
# 保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}
# 保持自己定义的类不被混淆
-keep class MyClass;
如果想混淆第三方的jar包可以这样做,我只是用我的项目目中用到的jar包为列,需要的可以参考下,

#Baidu -libraryjars libs/BaiduLBS_Android.jar-dontwarn com.baidu.**-dontwarn pvi.com.gdi.bgl.android.java.**-dontwarn vi.com.gdi.bgl.android.java.**-keep class com.baidu.** { *; }-keep class pvi.com.gdi.bgl.android.java.** { *; }-keep class vi.com.gdi.bgl.android.java.** { *; }#Umeng-libraryjars libs/umeng-update-v2.6.0.1.jar -dontwarn com.alimama.mobile.**-dontwarn com.umeng.update.**-dontwarn u.upd.**-keep class com.alimama.mobile.** { *; }-keep class com.umeng.update.** { *; }-keep class u.upd.** { *; }-libraryjars libs/umeng-analytics-v5.5.3.jar-dontwarn com.umeng.analytics.**-dontwarn u.aly.**-keep class com.umeng.analytics.** { *; }-keep class u.aly.** { *; }#Image-loader-libraryjars libs/universal-image-loader-1.8.6-with-sources.jar-keep class com.nostra13.universalimageloader.** {*;}#Gson-libraryjars libs/gson-2.2.4.jar-dontwarn com.google.gson.**-keep class com.google.gson.* { *;}#support-v4-libraryjars libs/android-support-v4.jar-dontwarn android.support.v4.**-keep class android.support.v4.** { *; }#jpush-libraryjars libs/jpush-sdk-release1.7.5.jar-dontwarn cn.jpush.android.**-keep class cn.jpush.android.** { *; }#ShareSDK -keep class cn.sharesdk.**{*;}-keep class com.sina.**{*;}-keep class **.R$* {*;}-keep class **.R{*;}-dontwarn cn.sharesdk.**-dontwarn **.R$*


代码混淆的方法

根据 SDK 的版本不同有 2 中不同的代码混淆方式,以上的 proguard.cfg 参数详解中所涉及到的信息是在较低版本 SDK 下的混淆脚本,事实上在高版本的 SDK 下混淆的原理和参数也与低版本的相差无几,只是在不同 SDK 版本的环境下引入混淆脚本的方式有所不同。具体方法如下:

  • 低版本 SDK 下,项目中同时包含 proguard.cfg 和 project.properties 文件,则只需在 project.properties 文件末尾添加 proguard.config=proguard.cfg 再将项目 Export 即可。
  • 高版本 SDK 下,项目中同时包含 proguard-project.txt 和 project.properties 文件,这时需要在 proguard-project.txt 文件中进行如下信息的配置,然后再将项目 Export 即可。下面以真实的文件进行演示说明。
# This file is automatically generated by Android Tools.# Do not modify this file -- YOUR CHANGES WILL BE ERASED!## This file must be checked in Version Control Systems.## To customize properties used by the Ant build system edit# "ant.properties", and override values to adapt the script to your# project structure.## To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txtproguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt# Project target.target=android-16

以上的配置信息即是 project.properties 文件中内容,蓝色文字为我们在代码混淆过程中需要添加的配置信息,其中:sdk.dir 为你在当前机器上 SDK 的安装路径。如果想保留某个包下的文件不被混淆,可以在 proguard-project.txt 文件中加入保留对应包名的语句即可。

# To enable ProGuard in your project, edit project.properties# to define the proguard.config property as described in that file.## Add project specific ProGuard rules here.# By default, the flags in this file are appended to flags specified# in ${sdk.dir}/tools/proguard/proguard-android.txt# You can edit the include path and order by changing the ProGuard# include property in project.properties.## For more details, see#   http://developer.android.com/guide/developing/tools/proguard.html# Add any project specific keep options here:-dontwarn com.cnki.android.cnkireader.** -keep class com.cnki.android.cnkireader.** { *; }# 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 *;#}


0 0