热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Proguard混淆Android项目所遇问题及总结

Proguard混淆Android项目所遇问题及总结最近一个老项目需要添加混淆,因此又对混淆有了更深入的了解.在此过程中遇到了一下问题,记录如下:1.编译打包错误a.类重复,错误信息如下
Proguard混淆Android项目所遇问题及总结

最近一个老项目需要添加混淆, 因此又对混淆有了更深入的了解. 在此过程中遇到了一下问题, 记录如下: 


1. 编译打包错误

a. 类重复, 错误信息如下

:xyz:compileReleaseNdk UP-TO-DATE
:xyz:compileReleaseSources
:xyz:proguardRelease
Note: there were 1276 duplicate class definitions.
      (http://proguard.sourceforge.net/manual/troubleshooting.html#duplicateclass)
Exception while processing task 
java.io.IOException: Can't write [/Users/stone/xyz/build/intermediates/classes-proguard/release/classes.jar] (Can't read [/Users/stone/xyz/abc/build/intermediates/exploded-aar/xyz/emojicon/unspecified/jars/libs/android-support-v4.jar(;;;;;;!META-INF/MANIFEST.MF)] (Duplicate zip entry [android-support-v4.jar:android/support/v4/hardware/display/DisplayManagerCompat.class]))
at proguard.OutputWriter.writeOutput(OutputWriter.java:187)
at proguard.OutputWriter.execute(OutputWriter.java:79)
at proguard.ProGuard.writeOutput(ProGuard.java:427)
at proguard.ProGuard.execute(ProGuard.java:175)
at proguard.gradle.ProGuardTask.proguard(ProGuardTask.java:1074)
at com.android.build.gradle.tasks.AndroidProGuardTask.doMinification(AndroidProGuardTask.java:139)
at com.android.build.gradle.tasks.AndroidProGuardTask$1.run(AndroidProGuardTask.java:115)
at com.android.builder.tasks.Job.runTask(Job.java:48)
at com.android.build.gradle.tasks.SimpleWorkQueue$EmptyThreadContext.runTask(SimpleWorkQueue.java:41)
at com.android.builder.tasks.WorkQueue.run(WorkQueue.java:227)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Can't read [/Users/stone/xyz/build/intermediates/exploded-aar/xyz/emojicon/unspecified/jars/libs/android-support-v4.jar(;;;;;;!META-INF/MANIFEST.MF)] (Duplicate zip entry [android-support-v4.jar:android/support/v4/hardware/display/DisplayManagerCompat.class])
at proguard.InputReader.readInput(InputReader.java:188)
at proguard.InputReader.readInput(InputReader.java:158)
at proguard.OutputWriter.writeOutput(OutputWriter.java:176)
... 10 more
Caused by: java.io.IOException: Duplicate zip entry [android-support-v4.jar:android/support/v4/hardware/display/DisplayManagerCompat.class]
at proguard.io.JarWriter.getOutputStream(JarWriter.java:138)
at proguard.io.FilteredDataEntryWriter.getOutputStream(FilteredDataEntryWriter.java:105)
at proguard.io.FilteredDataEntryWriter.getOutputStream(FilteredDataEntryWriter.java:105)
at proguard.io.FilteredDataEntryWriter.getOutputStream(FilteredDataEntryWriter.java:92)
at proguard.io.ClassRewriter.read(ClassRewriter.java:68)
at proguard.io.FilteredDataEntryReader.read(FilteredDataEntryReader.java:87)
at proguard.io.FilteredDataEntryReader.read(FilteredDataEntryReader.java:87)
at proguard.io.FilteredDataEntryReader.read(FilteredDataEntryReader.java:87)
at proguard.io.JarReader.read(JarReader.java:65)
at proguard.io.DirectoryPump.readFiles(DirectoryPump.java:65)
at proguard.io.DirectoryPump.pumpDataEntries(DirectoryPump.java:53)
at proguard.InputReader.readInput(InputReader.java:184)
... 12 more
:xyz:dexRelease FAILED


出现原因: 

主项目引用了几个library, 而这几个library都引用了同一个jar包, library引用jar包的方式是: 将jar包放在module的libs目录下并配置如下gradle脚本

 

dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
}

 

解决过程:

以前用eclipse开发android项目遇到过这样的编译问题, 错误信息如下: 

com.android.dex.DexException: Multiple dex files define Lcom/alibaba/fastjson/JSONStreamAware;
at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:594)
at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:552)
at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:533)
at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:170)
at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)
at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:439)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:287)
at com.android.dx.command.dexer.Main.run(Main.java:230)
at com.android.dx.command.dexer.Main.main(Main.java:199)
at com.android.dx.command.Main.main(Main.java:103)

导致这个编译错误的原因如上, 当是只要jar包改成同一个文件, 就会编译通过 (由于编译出的class文件的版本不一致, 导致无法合并), 

然而在anroid studio中, 这样做并无卵用. 

我是这样做的: 将不同的library共同引用的jar包放在一个目录下(project跟目录的libs木下), 并配置如下gradle脚本

dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile fileTree(dir: '../libs', include: '*.jar')
}

最终解决方案: 

把module下面的libs目录下的jar包(其他项目也引用的那个jar)删除, 并配置改module的gradle脚本(注意: 各个library引用的库的版本必须一致------------红色标出部分一致)

dependencies {
compile fileTree(dir: 'libs', include: '*.jar')

   compile 'com.alibaba:fastjson:1.1.43'
}

注: 这样依赖的是maven仓库中的jar或则aar.


2. 运行时错误

a. 空指针

主要是由 新版的butterknife生成的类的类名规则改变 引起的, 

butterknife 7.x之前的版本生成的类的名称形如: **$$ViewBinder

butterknife 7.x即之后的版本生成的类的名称形如: **$$ViewInjector

不混淆butterknife生成的类的规则如下:

-keep class **$$ViewBinder { *; } #butterknife 7.x即之后的版本生成的类
-keep class **$$ViewInjector { *; }
#butterknife 7.x 版之前生成的类

我的规则文件是从另一个项目中拷贝过来的, 所以就出现了上述问题:


b. 反射时无法取到某个属性

主要是由于 "没有保持orm框架注解过的数据库实体类" 引起的, 

这个添加规则就可以解决了, 如下: (具体规则则需要根据你的具体情况而定)

#xutils定义的实体类
-dontwarn com.lidroid.xutils.**
-keep class com.lidroid.xutils.** { *; }

#此段只能保持使用xutils注解过的字段或方法不能被混淆, db数据库的所有字段都不能被混淆, 因此需要结合下面一段
-keepclasseswithmembernames class * {
@com.lidroid.xutils.db.annotation.* ;
@com.lidroid.xutils.db.annotation.* ;
}
#使用xutils注解过的数据库实体类
-keep class a.b.c.** { *; }
-keep class a.abc.cbd.User { *; }


c. 没有CREATOR

保持CREATOR字段不被混淆的规则/tools/proguard/proguard-android.txt 文件中已经定义过了

如下: 

-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

当是有些人在定义CREATOR时会少些一个final, 实际上CREATOR是一个常量, 如果你少些一个final那就只是一个类变量

因此在自定义的规则文件中添加了一条规则, 如下第二条: 

#不混淆CREATOR常量, 有人定义CREATOR时不写final关键字 -_-!!
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
public static android.os.Parcelable$Creator *;
}



3. 总结: 

1. 混淆的原理

把源代码中的 "包名/类名/变量名/方法名" 改成无意义的字符串, 以达到保护源码的目的.


2. 容易出问题的地方

a. 反射 (包名类名, 方法名, 变量名)

如果你把类名混淆了, 下面的语句会出什么问题? !

if(obj.getClass().getName().equals("a.b.c.SomeClass")) {
//do something
}

变量名和方法名同理!!

b. xml文件, 如下标注的部分如果混淆了, 会发生什么问题?!!



当然xml文件还有AndroidManifest.xml, 这个文件会用到四大组件, 因此有以下避免混淆的规则保持四大组件的类名(外加自定义的Application): 

-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.content.ContentProvider


3. 一个总原则

所有硬编码的名称都不能混淆. 

所谓硬编码: 

a. xml中的东西, 如上.

b. 字符串中写死的类名, 变量名, 方法名, 包名........

c. 反射 ------ 这个其实在上一条中有所体现, 如放射去方法或变量时就是用了硬编码 ------- 字符串!

如下: 

Class a = getSomeClass(2);
a.getMethod("methodName", int.class);
a.getField("aField");

当然只是列举了所谓"硬编码"中的一部分, 更多的混淆问题和"硬编码" 有待读者发现


proguard及混淆规则===> 点击这里

错误之处再所难免, 希望你能帮我更正! 大笑















推荐阅读
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • Final关键字的含义及用法详解
    本文详细介绍了Java中final关键字的含义和用法。final关键字可以修饰非抽象类、非抽象类成员方法和变量。final类不能被继承,final类中的方法默认是final的。final方法不能被子类的方法覆盖,但可以被继承。final成员变量表示常量,只能被赋值一次,赋值后值不再改变。文章还讨论了final类和final方法的应用场景,以及使用final方法的两个原因:锁定方法防止修改和提高执行效率。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • Firefox火狐浏览器关闭到http://detectportal.firefox.com的流量问题解决办法
    本文介绍了使用Firefox火狐浏览器时出现关闭到http://detectportal.firefox.com的流量问题,并提供了解决办法。问题的本质是因为火狐默认开启了Captive portal技术,当连接需要认证的WiFi时,火狐会跳出认证界面。通过修改about:config中的network.captive-portal-service.en的值为false,可以解决该问题。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 网址:https:vue.docschina.orgv2guideforms.html表单input绑定基础用法可以通过使用v-model指令,在 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
author-avatar
手机用户2502934901
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有