1.任务目标

  在Android开发中经常用仓库依赖或者jar引入第三方功能库,这次我将混淆发布依赖的过程出个sdk给外部调用,利用在公司打包的经验说说,共同看看有什么更好方法。
先看我们打出的混淆jar会显示的代码样式:

2.环境准备

  开发中虽然喜欢稳定的编译环境,奈何每年google都发布新的Android,我们的AndroidStudio也只能跟着升级,不然无法使用高级的功能或兼容高级sdk。比较常遇到的编译级错误就有Android 11带来的广告id,清单文件中要query标签,要升级才行;另一个bugly大家常用的热修复功能,gradle文件下的插件在老鼠或者狐狸版直接失效,编译都不过,需要降级,除非你注释掉热修复不用(>_<)。

  整个混淆发布过程我在windows和mac独立做了一次,发布文章做的第3次,源码里存在windows的痕迹都注释掉了,开发sdk的项目是AndroidJar 中的sdk module,发布对外依赖的项目 UseJar,所有的app module都是测试业务的
创建项目的选Java语言(kotlin没研究过),我使用的gradle version:

classpath ‘com.android.tools.build:gradle:7.1.2’

3.业务开发

  我们开发sdk应该尽量使用原生api,不引入第三方库,而且保持功能的隔离,不应该引入无用的工具类,不然容易在开发者调用sdk时就疯狂报重复类、版本不一致、引入三方库会增大sdk的大小。

  开发这个sdk其实在我们眼中就是个library module,在此sdk module的build.gradle文件中编写常规配置脚本代码,,发现没有so库的打包其实很简单,但是们引入有so的库mmkv,一般的打包java代码就不行,每次调用就 libxx.so无法找到而拖蹦目标APP。c++的坑,我们的sdk module被app module依赖 implementation project(‘:sdk’),这种方式使用sdk时不会报错,c的so库没问题,但是以jar依赖就崩溃了,因为jar里面确实没有打包进so库,这就导致mmkv初始化就拖蹦 (>_<)。

使用的sdk module的build.gradle文件:

plugins {id 'com.android.library'
}android {compileSdk 32defaultConfig {minSdk 21targetSdk 32testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"consumerProguardFiles "consumer-rules.pro"ndk {abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86'}}buildTypes {release {minifyEnabled true //开启混淆proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' //根据混淆文件打包}debug {minifyEnabled trueproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}sourceSets{main{jniLibs.srcDirs = ['libs']}}lintOptions{abortOnError false}
}dependencies {implementation 'androidx.appcompat:appcompat:1.4.1'testImplementation 'junit:junit:4.13.2'androidTestImplementation 'androidx.test.ext:junit:1.1.3'androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'implementation 'com.tencent:mmkv:1.0.22'   //编译打包会生成soimplementation 'com.squareup.okhttp3:okhttp:3.6.0' //基础流行网络库implementation 'com.github.gzu-liyujiang:Android_CN_OAID:4.2.4' //兼容Android11以上的广告id,此库需要ide4.0以上版本
}

  注意点这里说下,为什么要okhttp3.6,现在都4.x了,开始我用的4.9.3,我在编译的时候展开Project->External Libraries,发现竟然存在kotlin的插件库,但是我全程没有用kotlin的库或文件,然后在目标app运行时,当初始化sdk就拖崩溃APP(>_<)。没道理啊,灵机一动感觉是依赖库使用了kotlin相关插件库,然后我就将mmkv,okhttp,oaid每次都单独依赖,其他两个注释掉,看哪个家伙导入的kotlin库,发现是okhttp,在仓库查看有什么历史版本,选中个热门降低版本,然后发现他缺okio这个库,在这里又下载okio-3.0.0.jar,放到libs文件夹。

  这里都已经一波三折了,要翻墙下载,各种库引入打出sdk的jar包后,放到开发的项目运行,然后崩溃又回到sdk中修复,而且崩溃可以是多样的,不一定是业务代码问题,很多靠经验才知道,混淆文件的配置,依赖库又引入其他恶心的库,还有c++等等,这里我算比较复杂的打包,网上基本就打个java代码给你调用成功就拜拜。。。

4.gradlew 打jar包

  百度基本打包就是构建makeJar的任务,这种打出来的是明文代码,代码无混淆,我们构建makeProguardJar任务是混淆jar,里面的类名、API名、变量名变成abcd…,在写完整个sdk功能后运行依赖了sdk的app module,这样就可以在sdk/build看到生成的临时文件库,整个任务构建包括:a.引入需要的代码库,这些都是/build/各依赖库.jar ;b.指定生成路径后完成整个任务代码编写并同步依赖,在ide右侧Gradle找到makeJar任务双击 ;c.在sdk/build/libs/xxlib-0.0.2.jar就是我们的jar。

  关键在a步骤,mac电脑和window电脑获取路径方式一样,只是路径挺大不同,我用window获取到时双反斜杠,mac是单斜杠路径。sdk需要引入的第三库,在Project->External Libraries下依赖的库copy path,自身业务代码一般是classes.jar,注意是debug或release下运行,选择build variants。

  非混淆包已经可以对外使用了,下面做混淆包jar,也有几个坑让我一一踩啦。百度获取makeProguardJar的任务代码,坑比来了,当时我做的是5月份开始做打包,type: proguard.gradle.ProGuardTask 这变量一直报错,百度看到所有文章都是这个类型没毛病?把自己的ide缓存啥的清理重启,都不行,为啥我不降级呢,因为引入了oaid这个库必须要Androidstudio4.0以上的,我就没想过要降级,实在搞不了我单独不依赖任务库,在gradle3.5.2能成功运行,当然获取classes.jar这路径都变了,就是gradle插件问题,当时只能百度、Google,csdn都没有当前gradle7.1.2的跑,基本都是3.x或者4.0.x,大家抄来抄去。无奈被迫放弃。

  后面8月又搞一波,接着坑直接找到gradle的github,因为我看文章说这开源的,直接去找它源码看到底弄啥,看issue发现有人提了,还是老外潮流,然后看到作者在7月份把开发出新版 com.guardsquare:proguard-gradle:7.2.2 ,注意只有这个可用progrardTask这个类。(https://github.com/Guardsquare/proguard)

**在高版本gradle创建项目setting.gradle、根build.gradle脚本结构完全改变,看到这个 id ‘com.android.library’ version 7.1.2 apply false ,跟以前的依赖代码 classpath ‘com.android.tools.build:gradle:7.1.2’ 导入的方式完全不会写,是分组织了还有冒号无法编译通过,被迫改成以前的脚本结构,有知道在高版本如何依赖gradle告诉我,没研究过。最后双击makeProguardJar就可以将明文jar包打成混淆包。

5.混淆协议编写

  上面打出混淆包发现依然没混淆,是混淆规则没搞对,我看百度基本写通用的混淆规则就可以混淆代码了,我这不行可能跟版本有关,只能老实处理混淆文件规则,而且更高级能为所欲为,也不少坑(>_<)。

  sdk的混淆规则有 consumer-rules.pro和proguard-rules.pro决定,不同是是否应用于项目所有module的混淆,混淆语句的错误使用会导致APP崩溃,而且可能无法指定崩溃代码行数,讲下遇到的坑。大体有内部类、匿名内部类、反射调用、接口的声明位置等,一开始不知道以上坑,每次编译都能正常生成混淆jar包,十分愉快,然后再拷贝到目标项目引入运行各种不知类名的无法找到的崩溃(><),每写个内部类就有崩的可能,而且代码量大的时候开发没注意后面真的排错能搞一天,而且都是正常打包调用就崩溃,每次大量重复的把jar拉到目标项目,gradle sync同步,当jar能成功引入会出现‘>’,能展开代码文件才能正常跑,而且由于ide缓存,经常同步无效要关掉项目窗口重开就行了 (><)。

  贴出完整的proguard-rules.pro代码,自己写的文件调试还算清晰,但是工作量是不少,由于混淆文件都是自己把握,基本掌握混淆的语法代码后是为所欲为(>.<),导致很多放宽的类没被混淆或者严格混淆,连对外API的参数名提示都变abc,要是多人写sdk就更复杂,每次都要打出混淆jar,依赖到目标项目才能看到jar里面的代码,手麻了已经。

#有效 不混淆整个包的文件
-keep class com.hwj.sdk.**#有效 不混淆某个类的public方法,但里面的内容会
#-keepclassmembers class com.hwj.sdk.SdkLibUtil{
# public *;
#}#不混淆某个类,看到所有信息
#-keep class com.hwj.sdk.SdkLibUtil {*;}
#看到类名
-keep class com.hwj.sdk.SdkLibUtil
#指定GreeNp类下的某些方法 testXX()不被混淆,注意修改返回值
-keep class com.hwj.sdk.SdkLibUtil {public java.lang.String test*(...);public void init(...);
}#这些都是sdk里的文件,如果写成文件名就会报红线
-keep class com.hwj.sdk.MMKVUtil
-keep class com.hwj.sdk.NpHttpUtil {*;}
-keep class com.hwj.sdk.NpHttpUtil#反射的使用,混淆后导致无法找到方法 ,这里必须找到类的具体路径
#需要直接在jar包中找到对应的三方库,每个层级下查看类路径,然后抽出来单独不混淆
#当然你要最简单,整个库都不混淆那就没技术含量了 (>_<)
-keep class okhttp3.internal.tls.TrustRootIndex {*;}
-keep class okhttp3.internal.tls.TrustRootIndex
-keep class java.security.cert.** {*;}
-keep class com.hwj.sdk.TrustAllCerts {*;}
-keep class com.hwj.sdk.TrustAllCerts#不混淆某个依赖库下的所有文件,只是类名清晰,里面的函数、内部类、接口依然混淆
-keep class com.tencent.mmkv.** {*;}
-keep class com.github.gzuliyujiang.oaid.** {*;}
-keep class okio.** {*;}
-keep class okhttp3.** {*;}
-keep class javax.net.ssl.** {*;}-keep class javax.net.ssl.HostnameVerifier{*;}
#内部类对象需要单独处理,否则依然混淆 ,如HostnameVerifier$.verifier()被混淆成a()
#代表保留  A$* 表示所有A的内部类都保留下来
-keep class javax.net.ssl.HostnameVerifier$* {*;}
-keep class com.lyentech.sdk.NpHttpUtil$* {*;}#是否混淆第三方jar
-dontskipnonpubliclibraryclasses#####混淆保护自己项目的部分代码以及引用的第三方jar包library#######
-libraryjars libs/okio-3.0.0.jar# java.io.IOException: Please correct the above warnings first. 66666忽略警告
-ignorewarnings#-dontwarn com.lyentech.sdk.**
#-dontwarn com.lyentech.reformcode.**-optimizationpasses 5
-dontskipnonpubliclibraryclassmembers
-printmapping proguardMapping.txt
-optimizations !code/simplification/cast,!field/*,!class/merging/*
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {native <methods>;
}#表示混淆时不使用大小写混合类名
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
#打印混淆的详细信息
-verbose#不优化,作用于全局
-dontoptimize-dontpreverify-keepattributes *Annotation*-dontwarn com.squareup.okhttp.**
-keep class com.squareup.okhttp.** {*;}
-keep interface com.squareup.okhttp.** {*;}
-dontwarn okio.**

6.github发布、jitpack仓库打包

  目前的混淆jar已经可以手动集成使用,但现在流行gradle集成依赖,所以另外建一个新的项目UseJar,一般大公司内外网,外网还要加域名隔离,不用公司网口或者私服连代码都拉不了。这里我们在AndroidJar项目下开发sdk的所有业务功能,打出混淆包后复制粘贴到UseJar项目中,创建Android library中引用jar,对标这里的UseJar:litesdk,然后对整个UseJar代码提交到github,push、tag、release、publish to jitpack。意思是UseJar项目托管这sdk,但是引用的jar代码是混淆过,部分接口端口可以用技术手段隐匿掉,只给外部用却不知道明码。


  因为sdk用到so库,所以在AndroidJar的app下运行后将apk解压获取所有的so,然后复制粘贴到UseJar的litesdk的libs,配置sourceSets{}引用so。


  发布前还要将把代理的配置注释掉,因为公司拉取github、google等库是龟速,所以开了代理,但是到jitpack打包时是直接根据gradle运行脚本,一直不通过,我就把gradle.properties文件的代理端口注释,这里坑大发了(>_<)。

7.外部调用依赖测试集成

  gradle集成是否成功,看控制台build是否通过,成功后External Libraries会出现仓库代码依赖地址,不行的要复验jitpack发布是否成功,看日志是否status:ok,error就是发布终止的不能下载到依赖代码,简单的校验命令(mac电脑):

./gradlew publishToMavenLocal

发现windows 带 ./ 会报错,呜呜windows直接gradlew。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pYfvicEK-1661995976564)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/32ec6e98471741689c37558021dc1ecb~tplv-k3u1fbpfcp-watermark.image?)]

小结

  其实打混淆包过程不复杂,但是在插件高版本,网域限制,使用的多样性(so库、三方库),依赖重复库,混淆警告编译不过,代码编写语法上的匿名内部类、内部接口或反射使用,多种情况叠加一起,有个在混淆文件写成库名(少个字母啥的没提示)。问题多了只能一步一步排查,需要具体到引用的库的类路径,不深入无法解决源头bug,没经验或者感觉的不到基本失败,自力更生~

电脑的内存和我都到极限了,歇息!

2022/08/31 何伟杰
掘金浏览 https://juejin.cn/post/7137968960997163045

Android混淆发布依赖相关推荐

  1. React Native App设置amp;Android版发布

    React Native系列 <逻辑性最强的React Native环境搭建与调试>  <ReactNative开发工具有这一篇足矣>  <解决React Native ...

  2. android 混淆规则作用,Android混淆规则

    简介 Java代码是非常容易反编译的.为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理. ProGuard是一个混淆代码的开源项目.它的主要作用就是混淆,当然它还能对字节码 ...

  3. 【我的Android进阶之旅】Android 混淆文件资源分类整理之二:将混淆文件拆分成更小粒度的混淆文件

    在我2017年的文章[我的Android进阶之旅]Android 混淆文件资源分类整理中,我已经提及过. 之前将所有的混淆都配置在一个 proguard-rules.pro 这个Android Stu ...

  4. Android混淆总结

    Proguard 混淆工具来帮助我们快速地对代码进行混淆.根据 Java 官方介绍,Proguard 对应的具体中文定义如下: 1.它是一个包含代码文件压缩.优化.混淆和校验等功能的工具 2.它能够检 ...

  5. Android 混淆那些事儿

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/WmJyiA3fDNriw5qXuoA9MA 作者:l ...

  6. Android混淆解析

    此文章转载来源https://www.jianshu.com/p/84114b7feb38点击打开链接 Android混淆解析 一.混淆的目的 一款发布到市场的软件原则上都应该做代码混淆. 通过代码混 ...

  7. Android混淆详解

    综述 毫无疑问,混淆是打包过程中最重要的流程之一,在没有特殊原因的情况下,所有 app 都应该开启混淆. 首先,这里说的的混淆其实是包括了代码压缩.代码混淆以及资源压缩等的优化过程.依靠 ProGua ...

  8. Android混淆从入门到精通

    Android混淆从入门到精通 简介 作为Android开发者,如果你不想开源你的应用,那么在应用发布前,就需要对代码进行混淆处理,从而让我们代码即使被反编译,也难以阅读.混淆概念虽然容易,但很多初学 ...

  9. Android混淆那些事儿

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园:追风917 Android混淆 Android混淆是Android开发者经常使用的一种用于代码防止被反编译的常见 ...

最新文章

  1. mysql 存储过程 invoker invoker
  2. sqlserver 标准系统数据库
  3. spring 事务笔记(四)
  4. 抓取流量分析恶意软件或泄密流量(精)
  5. 函数返回结构体指针_9.3 结构体指针
  6. ROS中阶笔记(十一):ROS 2.0
  7. notepad++ 自动保存设置
  8. MyBatis学习笔记(1)-MyBatis介绍
  9. 解决IDEA连接mysql时出现Server returns invalid timezone问题一劳永逸的方法
  10. ensp 移动主机搜索不到AP信道_H3C路由器GR2200 支持LAN/WAN切换,负载均衡 支持快速扩展无线AP 高性能企业级路由器_GR2200_支持LAN/WAN切换,负载均衡...
  11. python 修改图片尺寸 留白_php 图片指定留白叠加缩放
  12. 强网杯团队赛---Misc
  13. 在QT框架下进行仿照PS图像调整功能设计(亮度对比度,色相饱和度及明度)
  14. C#根据IP地址查询所属地区(调用免费的IP查询接口)
  15. 深入了解电容(三):陶瓷电容MLCC
  16. HDU 2977 Color Squares BFS
  17. 数据科学与机器学习案例之客户的信用风险与预测
  18. Oracle 12c新特性--LREG进程专门负责注册实例服务
  19. R语言中级图形:相关系数图及马赛克图
  20. 如何让学习变得有效率

热门文章

  1. PAT甲级题解 1030
  2. Python中NaN、nan和NAN的区别及使用方法
  3. 看书学习感悟系列(三)
  4. 爬取西瓜视频影视分类
  5. 计算机专业硕士毕业论文摘要,湖北计算机专业硕士毕业论文英文摘要,经济学专业本科毕业论文...
  6. 做了7年开源数据库开发,我学到了什么?
  7. “区块链技术创新要植根市场”
  8. 图像处理方面的sci期刊_图像处理类的SCI期刊
  9. tomcat服务器项目迁移到另外一台tomcat服务器
  10. 用Python自动计算Excel排班表的工时