今天说android混淆,有点老生常谈了.不过还是说点基础的吧。首先上图:
从上面图中解释一下名称:
其中:proguardFiles getDefaultProguardFile(‘proguard-android.txt’)表示获取SDK下’proguard-android.txt‘文件中的默认混淆规则。
‘proguard-rules.pro’表示使用项目根目录下的 ‘proguard-rules.pro’文件中的混淆规则。
提示:proguard-rules.pro文件名可以任意,只要在配置文件中指明即可。比如,从其它项目中复制一个proguard.cfg混淆规则文件,只需将上面的代码改成 proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard.cfg’即可,这句话表示使用项目中根目录下的proguard.cfg文件作为本项目的混淆规则文件。proguard-android.txt文件在Android_SDK_Home/tools/proguard 文件夹下,是google官方提供的一个android app项目的默认通用配置文件,适用于所有android app项目。而proguard-rules.pro默认为空,可以在这里放置一些和特定app相关的配置。
但是其实是想说混淆反射
同时混淆后的输出文件为:
构建时Proguard都会输出:dump.txt(说明APK中所有类文件的内部结构)、mapping.txt(提供原始与混淆过的类、方法和字段名称之间的转换)、seeds.txt(列出未进行混淆的类和成员)、usage.txt(列出从APK移除的代码),
正常开启混淆后,项目中的所有文件都是要被混淆掉,如果说项目中用到了反射,混淆编译后,就会出现反射到的资源文件找不到.所以就要让反射不能被混淆
网上有很多混淆的例子;就不说了,基本的写法 用法都是一样的
-dontwarn
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
#-dontpreverify
#-dontwarn
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#-----------keep-------------------
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-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
-keepattributes Signature
-keepattributes Exceptions,InnerClasses
-keep public class com.alipay.android.app.** {
public <fields>;
public <methods>;
}
# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,allowshrinking class * {
native <methods>;
}
-keepclasseswithmembers,allowshrinking class * {
public <init>(android.content.Context,android.util.AttributeSet);
}
-keepclasseswithmembers,allowshrinking class * {
public <init>(android.content.Context,android.util.AttributeSet,int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * extends android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-ignorewarning
-keep public class * extends android.widget.TextView
#-----fangshe start *; ---
-keepclasseswithmembernames class com.mhyx.lzhy.quantumsdk_ansamsung.util.ResId.**{
public <fields>;
public <methods>;
}
-keep class **.R$* {*;}
-keep public class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumInitCallback{public *;}
-keep class * implements com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumInitCallback {
<methods>;
<fields>;
}
-keep public class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback.Data{public *;}
-keep public class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback{public *;}
//接口的内部类不被混淆
-keep class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback$Data{*;}
-keepnames class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback.Data$*{
public <fields>;
public <methods>;
}
-keep class * implements com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback {
<methods>;
<fields>;
}
-keep public class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumPayCallback{public *;}
-keep class * implements com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumPayCallback {
<methods>;
<fields>;
}
-keep class com.mhyx.lzhy.quantumsdk_ansamsung.util.QuanTumManager{public *;}
#-----fangshe end interface----
#---activity start---
-keepclassmembers class * extends android.app.Activity{
public void *(android.view.View);
}
-keep class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumActivity{}
-keep class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumPayActivity{}
#--activity end----
#------webview start--------
-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);
}
#-----webview end --------
#------gson start-------
-keep public class com.google.gson.**
-keep public class com.google.gson.** {public private protected *;}
-keepattributes Signature
-keepattributes *Annotation*
-keep public class com.liangzi.quantumsdkansamsung.util.** { *; }
#------gson end------
#-----------keep httpclient -------------------
-keep class org.apache.** {
public <fields>;
public <methods>;
}
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*
#--------------alipay-------------
-keep class com.ta.utdid2.** {
public <fields>;
public <methods>;
}
-keep class com.ut.device.** {
public <fields>;
public <methods>;
}
-keep class com.alipay.android.app.** {
public <fields>;
public <methods>;
}
-keep class com.alipay.sdk.** {
public <fields>;
public <methods>;
}
-keep class com.alipay.mobilesecuritysdk.** {
public <fields>;
public <methods>;
}
-keep class HttpUtils.** {
public <fields>;
public <methods>;
}
-keep class org.json.alipay.** {
public <fields>;
public <methods>;
}
#-----------keep statistics -------------------
-keep class com.iapppay.service {*;}
-keep class com.iapppay.apppaysystem {*;}
#-----------keep iapppay -------------------
-keep class com.samsung.utils.RSAHelper {*;}
-keep class com.samsung.sdk.main.** {
public <fields>;
public <methods>;
}
-keep class com.samsung.interfaces.callback.** {*;}
-keep class com.samsung.interfaces.** {
public <fields>;
public <methods>;
}
-keep public class com.samsung.ui.activity.** {
public <fields>;
public <methods>;
}
-keep public class com.samsung.ui.widget.**{
public <fields>;
public <methods>;
}
-keep public class com.samsung.ui.view.**{
public <fields>;
public <methods>;
}
-keep public class com.samsung.pay.channel.** {
public <fields>;
public <methods>;
}
-keep public class com.samsung.name.auth.** {
public <fields>;
public <methods>;
}
以上,只是自己项目里面配置的混淆
还有2个不混淆也是容易被忽略掉的
不混淆所以的接口的某个字段:
-keep class com._65.sdk.Constants{
int PLUGIN_TYPE_USER;
int PLUGIN_TYPE_PAY;
}
不混淆所以的接口:
-keep interface *{
<methods>;
<fields>;
}
如果加了android.support包的话,那么要加上
1. -keep class android.support.**{*;}
1. -dontwarn android.support.**
当有注解的时候
1. -keepattributes Signature
2. -keepattributes *Annotation*
//接口的内部类不被混淆
//经过验证,可行
//接口不被混淆
-keep public class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback{public *;}
//接口内部类不被混淆
-keep class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback$Data{*;}
//未经过验证
-keep public class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback.Data{public *;}
-keepnames class com.mhyx.lzhy.quantumsdk_ansamsung.QuanTumLoginCallback.Data$*{
public <fields>;
public <methods>;
}
以上:
第二种混淆的方式,比较少见
在build.gradle里面配置如下:
task makeJar(type: proguard.gradle.ProGuardTask, dependsOn: "build") {
// 未混淆的jar路径
injars 'build/intermediates/intermediate-jars/release/classes.jar'
// 混淆后的jar输出路径
outjars 'build/outputs/ltsdk.jar'
// 混淆协议
configuration 'proguard-rules.pro'
}
混淆时的注意点:
哪些不应该混淆:像混淆jar 需要对外暴露的方法和接口以及变量保持不变
使用了自定义控件那么要保证它们不参与混淆
使用了枚举要保证枚举不被混淆
运用了反射的类和方法也不进行混淆,反射原理就是通过方法名和类名去实例化相应的对象,调用相关的方法
使用了 Gson 之类的工具要使 JavaBean 类即实体类不被混淆
有用到 WebView 的 JS 调用也需要保证写的接口方法不混淆,原因和第一条一样
Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常
使用的四大组件,自定义的Application* 实体类
JNI中调用的类
Layout布局使用的View构造函数(自定义控件)、android:onClick等。
本地方法:因为本地方法是根据方法名去调用的,若混淆后会导致找不到此方法名。
setXX和getXX方法:这里指的是通过配置文件直接生成相应的set和get方法的相关库,所以javabean类很多情况下不能做混淆。
注解用了反射,所以不能混淆。 不混淆任何包含native方法的类的类名以及native方法名,否则找不到本地方法。
混淆文件配置如下:
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# 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 *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#如果引用了v4或者v7包
#表示混淆时不使用大小写混合类名
-dontusemixedcaseclassnames
#表示不跳过library中的非public的类
-dontskipnonpubliclibraryclasses
#打印混淆的详细信息
-verbose
-dontoptimize
##表示不进行校验,这个校验作用 在java平台上的
-dontpreverify
-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
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
-libraryjars 'D:\as\AndroidStudio\android-studio\jre\jre\lib\rt.jar'
-libraryjars 'D:\as\android-sdk\Sdk\platforms\android-19\android.jar'
-optimizationpasses 5
-dontusemixedcaseclassnames
# -keep public class * extends android.app.Activity
-dontwarn com.google.gson.**
-keep class com.google.gson.** { *;}
#忽略警告
-ignorewarnings
#保证是独立的jar,没有任何项目引用,如果不写就会认为我们所有的代码是无用的,从而把所有的代码压缩掉,导出一个空的jar
-dontshrink
#保护泛型
-keepattributes Signature
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application # 保持哪些类不被混淆
-keep class * implements Android.os.Parcelable { # 保持Parcelable不被混淆
public static final Android.os.Parcelable$Creator *;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclasseswithmembers class * { # 保持自定义控件类不被混淆
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
public void *(android.view.View);
}
-keep class * implements android.os.Parcelable {#保持Parcelable不被混淆
public static final android.os.Parcelable$Creator *;
}
-keep public class * implements java.io.Serializable {*;}
-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();
}
-keepclassmembers class * {
public <init> (org.json.JSONObject);
}
-keep class com.letui.LTSdk{*; }
-keep class com.letui.modle.GameUser{*; }
-keep class com.letui.modle.LogData{*; }
-keep class com.letui.modle.AppInfo{*; }
-keep class com.letui.modle.PayParams{*; }
-keep class com.letui.util.Debug{*; }
-keep class com.letui.listener.ILTLoginListener{*; }
-keep class com.letui.listener.ILTPayListener{*; }
#混淆命令 gradlew makeJar
mac混淆命令可能不一样