android sdk 代码混淆

前言

各位同学大家好 有段时间没有给大家更新文章了, 最近在做海外项目 所以有时间就跟各位聊一下安卓代码混淆的 因为我这这边是做手游sdk开发的 所以跟app的混淆还不不一样 我们就边专门将一下这个知识点 。

准备工作

1、首先module必须是library

2、build.gradle写的应用aar和module,要改成compileOnly,这样打包的时候就不会报错,因为aar不允许包含其他aar

我们再开发sdk 我们需要在build.gradle 里面打开混淆的配置

app和aar包混淆:

java 复制代码
android {
 ...

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

然后就是白名单的配置

我们开启这个混淆开关 如果不配置白名单 那么默认所有类都会混淆的

混淆规则

常见两条指令: 两颗星星表示把本包和所含子包下的类名都保持(类中的内容也会被混淆)

arduino 复制代码
-keep class 包名.**

一颗星表示只是保持该包下的类名,而子包下的类名还是会被混淆(类中的内容也会被混淆)

arduino 复制代码
-keep class 包名.*

以上两个方法保持类后,具体的方法跟变量都是会被混淆的,如果不想被混淆内容则:

arduino 复制代码
-keep class 包名.** { *; }

具体示例

kotlin 复制代码
-keep class com.yuanxuzhen.bean.*   本包下的类名保持
-keep class com.yuanxuzhen.bean.**  把本包和所含子包下的类名都保持
-keep class com.yuanxuzhen.bean.** {*;} 把本包和所含子包下的类名都保持,同时保持里面的内容不被混淆
-keep class com.yuanxuzhen.YUAN{*;} 保持类名,同时保持里面的内容不被混淆

2.什么时候不被混淆

一般以下情况都会不混淆:

  • 使用了自定义控件那么要保证它们不参与混淆
  • 使用了枚举要保证枚举不被混淆
  • 对第三方库中的类不进行混淆
  • 运用了反射的类也不进行混淆
  • 使用了 Gson 之类的工具要使 JavaBean 类即实体类不被混淆
  • 在引用第三方库的时候,一般会标明库的混淆规则的,建议在使用的时候就把混淆规则添加上去,免得到最后才去找
  • 有用到 WebView 的 JS 调用也需要保证写的接口方法不混淆,原因和第一条一样
  • Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常
ini 复制代码
#############################################
#
# 对于一些基本指令的添加
#
#############################################
# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses 5

# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames

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

# 这句话能够使我们的项目混淆后产生映射文件
# 包含有类名->混淆后类名的映射关系
-verbose

# 指定不去忽略非公共库的类成员
-dontskipnonpubliclibraryclassmembers

# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
-dontpreverify

# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses

# 避免混淆泛型
-keepattributes Signature

# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable

# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/cast,!field/*,!class/merging/*


#############################################
#
# Android开发中一些需要保留的公共部分
#
#############################################

# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
# 因为这些子类都有可能被外部调用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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


# 保留support下的所有类及其内部类
-keep class android.support.** {*;}

# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

# 保留R下面的资源
-keep class **.R$* {*;}

# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

# 保留在Activity中的方法参数是view的方法,
# 这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}

# 保留枚举类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 保留我们自定义控件(继承自View)不被混淆
-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);
}

# 保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

# 保留Serializable序列化的类不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
    void *(**On*Listener);
}

# webView处理,项目中没有使用到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);
}

这里我粘贴一下我自己混淆配置 然后看下

scala 复制代码
 #实体类不参与混淆
-keep class com.common.lib.mwomentity.** { *; }
#自定义控件不参与混淆
-keep class com.common.lib.mwomcustom.** { *; }
#悬浮窗不参与混淆
-keep class com.common.lib.mwomwidget.** { *; }
#自定义·控件不参与混淆
-keep class com.common.lib.mwomcustom.** { *; }
#回调接口不参与混淆
-keep class com.common.lib.mwomlistener.** { *; }
# 对外接口类不参与混淆
-keep class com.common.lib.BaseCommonApi{*;}
# 对外接口类不参与混淆
-keep class com.common.lib.BaseApi{*;}
# fastjson
-keep class com.common.lib.mwomutils.FastJson{*;}
# DataStore
-keep class com.common.lib.DataStore{*;}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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
# 保留support下的所有类及其内部类
-keep class android.support.** {*;}

# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

# 保留R下面的资源
-keep class **.R$* {*;}

# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

# 保留在Activity中的方法参数是view的方法,
# 这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}

# 保留枚举类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 保留我们自定义控件(继承自View)不被混淆
-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);
}

# 保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

# 保留Serializable序列化的类不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
    void *(**On*Listener);
}

# webView处理,项目中没有使用到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);
}
#okhttputils
-dontwarn com.zhy.http.**
-keep class com.zhy.http.**{*;}
#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}
#okio
-dontwarn okio.**
-keep class okio.**{*;}
#混淆本地jar gson
-libraryjars libs/gson-2.3.1.jar
-keep class com.google.gson.** {*;}
#-keep class com.google.**{*;}
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.** {
    <fields>;
    <methods>;
}
-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();
}
-dontwarn com.google.gson.**

我们测试一把把library 工程打包出aar 然后解压这个aar 在解压出来的文件加里面找到classes.jar 我们把classes.jar 这个文件拖拽到 jd-gui-1.4.0.jar这个工具里面

我们可以清楚的看到我们的jar包里面 的内容 没有配置白名单的代码和类都变成a b c d 这样就可以做到sdk混淆 做到差异化 的效果 。

sdk 混淆的要求

因为我们开发sdk 要给别人接入的人去对接 那么我们对外的那些暴露出的方法和那些需要导入的bean 类我们是坚决不能混淆的 不然后接入的人没有办法导入 导致不能接入。 一些关键的启动类和application 和四大组件也不能混淆 可能会调用到。

最后总结:

为什么要混淆 因为我们做海外项目 我们出了换UI 的同时也需要 用google 的自带的 proguard-rules.pro 工具对我们的sdk 代码进行混淆 一来是我们内部的逻辑可以不会轻易被别人破解盗用 而来是我们在做马甲包的时候可以 避免被官方 判断我们为马甲包和重复应用的行为。 最后希望我的文章能帮助到各位解决问题 ,以后我还会贡献更多有用的代码分享给大家。各位同学如果觉得文章还不错 ,麻烦给关注和star,小弟在这里

相关推荐
薛晓刚5 分钟前
MySQL的replace使用分析
android·adb
DengDongQi28 分钟前
Jetpack Compose 滚轮选择器
android
stevenzqzq29 分钟前
Android Studio Logcat 基础认知
android·ide·android studio·日志
代码不停37 分钟前
MySQL事务
android·数据库·mysql
朝花不迟暮42 分钟前
使用Android Studio生成apk,卡在Running Gradle task ‘assembleDebug...解决方法
android·ide·android studio
yngsqq1 小时前
使用VS(.NET MAUI)开发第一个安卓APP
android·.net
Android-Flutter1 小时前
android compose LazyVerticalGrid上下滚动的网格布局 使用
android·kotlin
Android-Flutter1 小时前
android compose LazyHorizontalGrid水平滚动的网格布局 使用
android·kotlin
千里马-horse1 小时前
RK3399E Android 11 将自己的库放到系统库方法
android·so·设置系统库
美狐美颜sdk1 小时前
Android直播美颜SDK:选择指南与开发方案
android·人工智能·计算机视觉·第三方美颜sdk·视频美颜sdk·人脸美型sdk