Proguard 部分类不混淆的技巧
最近比较忙,博客和 codeKK 都两个月没怎么更新了。赶在月末分享个小技巧。
一、场景
两年前在 Proguard 语法及常用 proguard.cfg 代码 中介绍过一些 Proguard 的基础知识,其中提到一些类不能混淆,比如实现了 Serializable 接口的,否则反序列化时会出错。这种情况我们可以简单的通过在 proguard-rules.pro 配置文件中添加配置,对于较早 Android 项目默认配置文件可能为 proguard.cfg,如下:
|
- keepnames class * implements java . io . Serializable
- keepclassmembers class * implements java . io . Serializable {
static final long serialVersionUID ;
private static final java . io . ObjectStreamField [ ] serialPersistentFields ;
! static ! transient <fields> ;
private void writeObject ( java . io . ObjectOutputStream ) ;
private void readObject ( java . io . ObjectInputStream ) ;
java . lang . Object writeReplace ( ) ;
java . lang . Object readResolve ( ) ;
}
|
表示所有实现了 Serializable 接口的类及其成员都不进行混淆。
但有时我们可能需要防止一些没有明显共同特征的类被混淆,比如个别控制层类需要反射、个别实体类需要 JSON 化存本地,这时我们怎么做呢,一个个添加到 proguard-rules.pro(或 proguard.cfg) 中吗?
这样会导致 proguard 配置文件变得杂乱无章,同时需要团队所有成员对其语法有所了解。
这里分享个小技巧,通过给这些类、属性、函数添加共同标识,然后统一过滤。
二、解决方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package cn . trinea . android . common . annotation ;
import java . lang . annotation . ElementType ;
import java . lang . annotation . Retention ;
import java . lang . annotation . RetentionPolicy ;
import java . lang . annotation . Target ;
/**
* NotProguard, Means not proguard something, like class, method, field<br/>
*
* @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2015-08-07
*/
@Retention ( RetentionPolicy . CLASS )
@Target ( { ElementType . TYPE , ElementType . METHOD , ElementType . CONSTRUCTOR , ElementType . FIELD } )
public @interface NotProguard {
}
|
NotProguard 是个编译时注解,不会对运行时性能有任何影响。可修饰类、方法、构造函数、属性。
关于注解更多的知识可见:Java Annotation 介绍及几个常用开源项目注解原理简析
2. 在 Proguard 配置文件中过滤被这个注解修饰的元素
|
# Keep annotated by NotProguard
- keep @cn . trinea . android . lib . annotation . NotProguard class * { * ; }
- keep , allowobfuscation @interface cn . trinea . android . lib . annotation . NotProguard
- keepclassmembers class * {
@cn . trinea . android . lib . annotation . NotProguard * ;
}
|
表示不混淆被 NotProguard 修饰的类、属性和方法。
3. 使用
(1) 整个类不混淆
|
@NotProguard
public class User { }
|
(2) 单个属性不混淆
|
@NotProguard
public int id ;
|
(3) 单个方法不混淆
|
@NotProguard
public boolean isValid ( ) {
…
}
|
这样我们便解决了每个类都需要在 proguard 配置文件中配置的问题。
三、关于混淆
混淆一般在 Release 模式生效,主要有三个作用:
(1) 压缩、优化、删除代码;
(2) 一定程度上提高反编译后被读懂的难度;
(3) 通过删除代码功能实现的特殊作用。
比如在 Proguard 语法及常用 proguard.cfg 代码 中介绍的利用 Progurad 使得线上版本不打印 Log.d 和 Log.v 的技巧,防止调试的敏感信息被泄露。
一些应用的代码可能从来都没混淆过,虽说这些代码实际价值可能不大,本身可能也是开源代码凑起来的,再者该破解的还是能破解,但本着做事要专业的态度,还是混淆吧。
关于 Proguard 基础可参考:
Proguard 语法及常用 proguard.cfg 代码
ProGuard 的作用、使用及 Bug 分析
四、杂谈
感谢不少朋友的关心,九月份博客会恢复正常更新。虽然很忙,还是抽空完善了 codeKK。
透露下下周 codeKK 会发布一个大功能模块,对,跟源码解析、职位内推并列的顶级模块,相信会对大家有用,希望大家到时多支持。
文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/jacke121/article/details/73756949
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
评论(0)