Android制作AAR包并混淆后加载调用

本文介绍了如何在Android中制作AAR包并实现代码混淆,包括创建项目、编写可调用类、混淆配置、生成AAR包的步骤。同时,详细讲解了代码混淆的基本规则和模板,以及如何在新工程中引入并调用AAR包中的方法。
摘要由CSDN通过智能技术生成

学更好的别人,

做更好的自己。

——《微卡智享》

6ac73142cb3d0f929cce17bea1f00781.png

本文长度为4389,预计阅读12分钟

前言

最近准备做新版本产品研发,部分相关算法原来用的Webapi调用返回,考虑到速度问题,需要在Andriod端实现, 就想到了制作AAR包加代码混淆的方法,以前主要没有用过,所以这次就做个Demo来技术验证。

403d82ae627201f6692f61289d248c17.png

实现效果

23061e7ee069d3636de0744a57f88b9c.png

上图中可以看到,制作了一个TAAR的包,打开后里面可以看到MathFun的类和类下公开的Add方法。

da83b51119909d5989e2fc0c0713b54b.png

在新的工程中直接引入AAR包,调用里面的实现方法后,在虚拟机中直接显示了出来。

代码实现

0719ecbc0fa41e360f12615268de2112.png

微卡智享

制作AAR包

1.创建新的项目

新建一个Android Project,选择No Activity

4625ee3b2273efb5c8e3323f5658e85f.png

2.创建外部调用类

145f3346166827dd8864df146cf6737a.png

在包下创建一个MathFun的类,里面写了一个Add的静态方法可以让外部调用,实现时又调用了MathMinify.Plus的方法,下一部就说明为啥这样处理。

3.创建实现类

4814f9525f73ef90455ca00793b58031.png

创建了一个Minify的Package名,然后在下面创建了MathMinify的类,里面的Plus很简单,就是两个数字相加。

重点:多这一步的原因是为了后面的代码混淆,主要这里测试好多次,如果都放在相同的包名下,保持MathFun的类不混淆,在外部看到的AAR包时里面是没有方法的,如果都不混淆那MathMinify也会在AAR包中看到,所以最终采用的新建了一个包将MathMinify的类放到新的包下后解决。

4.修改Gradle配置

45be159890e846c95b48c51502b35abc.png

修改build.gradle配置,将plugins中的application改为library,然后将defaultConfig下面的applicationId屏蔽。做完这一步,AAR包就可以生成了,非常简单。

5.代码混淆

f88e19c3dd76e0ffa649129f19a1d132.png

同样的刚才的build.gradle文件中,将minifyEnabled改为true即可混淆,下面的zipAlignEnabled可加可不加。

13b00625453d8d5ea0055cf9aeb497ef.png

0e011811b5c5e28d5c7ac1d127e2d830.png

接下来就是修改混淆规则了,在proguard-rules.pro中加入了下面这句,将taar包下面所有的类全部都不混淆

-keep class com.example.taar.**{*;}

从图中可以看到,我们改的是release版本的代码混淆,所以Build Variants中改也将Debug改为Release.

73b7b456939791d56bcc5fca1bf630d3.png

6.编译AAR包

058068bbb88693926cb64ecfb3c639d9.png

点击Build--Make Module 'TAAR.app'生成AAR包

61dfb2b3a11a6b948162406aaafdc095.png

app-build-outputs-aar下即可看到生成的release.arr的包,这样AAR包就制作完成了。

调用AAR包

1.创建新的Project拷贝AAR包

4766353ccad021f1c234d8b2faedb874.png

新建了一个名叫Demo的工程

777f1ec135ffbed15f9eabcf581a2c6c.png

40a730f7fece86b702b1f9595d359f32.png

将刚才创建好的AAR包拷冂到Demo工程下的libs目录中,并改为名TAAR.aar

2.配置build.gradle

6cfbcec40e36375f18665e1d740de4a7.png

打开build.gradle,然后加入repositories配置和compile,在Compile中name就是AAR包的名字,ext设置为aar,设置好后重新Rebuild Project一下。

repositories {
    flatDir {
        dirs 'libs'
    }
}


dependencies {
    compile(name: 'TAAR', ext: 'aar')


}

3.调用函数

cb1f17e47e8b12c4657c360a5bb07987.png

在MainActivity中引入包名,即可直接调用包中的方法了。

import com.example.taar.MathFun

c2806d4c051753692f48f3928909c369.png

通过Project里查看TAAR.aar包,classes.jar中也可以直接看到包中的方法。

实现效果

5274474fa6968cc9861b6ea88feaefe5.gif

7e5a15986cbe282a1d686011c133be7c.gif

代码混淆基本规则‍

01‍

 混淆配置

通过配置proguard-rules.pro文件,对生成的apk和jar进行加密,在‍build.gradle 来开启混淆功能。‍‍

buildTypes {
        release {                      
            minifyEnabled true // 混淆            
            zipAlignEnabled true // Zipalign优化          
            shrinkResources true  // 移除无用的resource文件           
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'  // 加载默认混淆配置文件
            signingConfig signingConfigs.relealse  // 签名
        }
    }

‍‍

02

混淆规则

混淆会用无意义的短变量去重命名类、变量、方法,但是对于外部的一些引用是通过名字找到对应的方法和类。混淆过后通过原来的名字去找混淆后的名字,是找不到对应方法和类,就会出异常报错。所以有些情况是不能进行混淆的。

  • 自定义控件不进行混淆

  • 枚举类不被混淆

  • 反射类不进行混淆

  • 实体类不被混淆

  • JS调用的Java方法

  • 四大组件不进行混淆

  • JNI中调用类不进行混淆

  • Layout布局使用的View构造函数、android:onClick等

  • Parcelable的子类和Creator静态成员变量不混淆

  • 第三方开源库或者引用其他第三方的SDK包不进行混淆

先看如下两个比较常用的命令,很多童鞋可能会比较迷惑以下两者的区别。

-keep class cn.hadcn.test.**
-keep class cn.hadcn.test.*

一颗星表示只是保持该包下的类名,而子包下的类名还是会被混淆;两颗星表示把本包和所含子包下的类名都保持;用以上方法保持类后,你会发现类名虽然未混淆,但里面的具体方法和变量命名还是变了,这时如果既想保持类名,又想保持里面的内容不被混淆,我们就需要以下方法了

-keep class cn.hadcn.test.* {*;}

在此基础上,我们也可以使用Java的基本规则来保护特定类不被混淆,比如我们可以用extend,implement等这些Java规则。如下例子就避免所有继承Activity的类被混淆

-keep public class * extends android.app.Activity

如果我们要保留一个类中的内部类不被混淆则需要用$符号,如下例子表示保持ScriptFragment内部类JavaScriptInterface中的所有public内容不被混淆。

-keepclassmembers class cc.ninty.chat.ui.fragment.ScriptFragment$JavaScriptInterface {
   public *;
}

再者,如果一个类中你不希望保持全部内容不被混淆,而只是希望保护类下的特定内容,就可以使用

<init>;     //匹配所有构造器
<fields>;   //匹配所有域
<methods>;  //匹配所有方法方法

你还可以在<fields>或<methods>前面加上private 、public、native等来进一步指定不被混淆的内容,如

-keep class cn.hadcn.test.One {
    public <methods>;
}

表示One类下的所有public方法都不会被混淆,当然你还可以加入参数,比如以下表示用JSONObject作为入参的构造函数不会被混淆

-keep class cn.hadcn.test.One {
   public <init>(org.json.JSONObject);
}

有时候你是不是还想着,我不需要保持类名,我只需要把该类下的特定方法保持不被混淆就好,那你就不能用keep方法了,keep方法会保持类名,而需要用keepclassmembers ,如此类名就不会被保持,为了便于对这些规则进行理解,官网给出了以下表格

保留防止被移除或者被重命名防止被重命名
类和类成员-keep-keepnames
仅类成员-keepclassmembers-keepclassmembernames
如果拥有某成员,保留类和类成员-keepclasseswithmembers-keepclasseswithmembernames

移除是指在压缩(Shrinking)时是否会被删除。以上内容时混淆规则中需要重点掌握的,了解后,基本所有的混淆规则文件你应该都能看懂了。再配合以下几点注意事项,开启你为自己代码,实现混淆规则之旅吧。

03

混淆模版

基本指令

# 设置混淆的压缩比率 0 ~ 7
-optimizationpasses 5  
# 混淆时不使用大小写混合,混淆后的类名为小写
-dontusemixedcaseclassnames  
# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 指定不去忽略非公共库的成员
-dontskipnonpubliclibraryclassmembers 
# 混淆时不做预校验
-dontpreverify           
# 混淆时不记录日志
-verbose             
# 忽略警告
-ignorewarning          
# 代码优化
-dontshrink  
# 不优化输入的类文件                
-dontoptimize 
# 保留注解不混淆             
-keepattributes *Annotation*,InnerClasses
# 避免混淆泛型
-keepattributes Signature  
# 保留代码行号,方便异常信息的追踪
-keepattributes SourceFile,LineNumberTable  
# 混淆采用的算法
-optimizations !code/simplification/cast,!field/*,!class/merging/*  


# dump.txt文件列出apk包内所有class的内部结构
-dump class_files.txt        
# seeds.txt文件列出未混淆的类和成员
-printseeds seeds.txt
# usage.txt文件列出从apk中删除的代码
-printusage unused.txt
# mapping.txt文件列出混淆前后的映射
-printmapping mapping.txt

不需混淆的Android类

-keep public class * extends android.app.Fragment
-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.preference.Preference
-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下的所有类及其内部类



support:
-keep class android.support.** {*;}
-dontwarn android.support.**
-keep interface android.support.** { *; }




androidx:
-keep class androidx.** {*;}
-keep interface androidx.** {*;}
-keep public class * extends androidx.**
-dontwarn androidx.**

support v4/7库

-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**

support design库

support:
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }


androidx:
-keep class com.google.android.material.** {*;}
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**

代码混淆引用的文章出处:

Android混淆从入门到精通 - 简书 (jianshu.com)

Android常用混淆配置 - 简书 (jianshu.com)

e3d5bdfec9601b581f97e051dcaabc60.png

扫描二维码

获取更多精彩

微卡智享

99b5104fc23dc12371e0b1da5bcd4967.png

「 往期文章 」

Android使用Flow检测版本升级自动下载安装

.Net5中WebApi使用MEF2框架的使用

PaddleOCR C++(三)---动态库返回识别结果及矩形位置

 

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值