之前我曾经写过一篇如何为用ADT创建的Android项目添加Proguard混淆支持的文章(
为Eclipse ADT创建的android项目通过ant添加proguard混淆支持
),当时我就说过,相信随着Google Android的不断更新发展以及Eclipse ADT插件的不断改进,总有一天,做Android项目时能够和J2ME项目一样方便的一键打包混淆。现在新版的SDK和ADT就已经添加了这样的功能(SDK Tools中已经整合了Proguard的发行包,连这步配置都省了!),虽然还不是一键,但也就是小改一个配置文件的事,相对以前的手改ant xml build file的做法来说已经是极大的简化了添加混淆支持的难度了。
先说说我写这篇文章时用的开发环境:Eclipse 3.5.2+ADT 9.0.0+SDK Tools R9+SDK Platform-tools R2。
声明我不保证在其他版本的IDE ADT和SDK Tools下我的方法是否可行且不会产生问题!
有一个问题需要先注意一下,就是现在版本的SDK和ADT的整合Proguard混淆对有空格的SDK路径和项目路径支持不好,所以混淆之前先把空格路径的问题解决一下,虽然我记得之前的手改xml方法好像不太会有空格路径问题,不过这次还是不要在SDK和项目路径中出现空格为好,免得自找没趣。
其实在用比较新版的SDK和ADT创建Android项目时,你会发现生成的项目结构里多了一个以前没有的文件:proguard.cfg,这就是SDK整合了Proguard的一个重要标志(具体从哪版开始变成这样我还真没注意),有兴趣你可以打开看一下,做过原来ant xml方式混淆的朋友可以看出来这里面写的就是当初Proguard混淆target里的混淆设置参数,什么keep啊之类的,当时是要自己写,这次是SDK直接生成好了!
虽然有proguard.cfg,但是默认情况下,混淆是没有启用的,想打开混淆支持,只需要在default.properties中加入这样一段参数:proguard.config=proguard.cfg就可以了(注意:这个文件里的注释写着类似这个文件是自动生成的,所作修改可能会被覆盖等等,让把自定义的东西加到额外的build.properties里,其实也无所谓,盖了也就是一句话的事!),简单明了。
然后在执行项目打包apk时sdk就会自动添加Proguard混淆支持了,可以右键项目->Android Tools->Export Signed (或Unsigned) Application Package…,生成的apk包可以用如apktool解包看看混淆效果。
PS:其实以前懒得弄Android混淆的一个原因是改xml太麻烦,加点外部lib就得更麻烦的加一些参数,同时还有另一个原因就是混淆的apk发布到market上,如果有用户的机器在程序出错时支持上传trace信息的话,那么你在market上看到的记录都是不可读的混淆后的名字,也是一件麻烦事。后来发现market上提了一句如果用proguard混淆后的apk可以有方法将trace信息反映射回去,成为可读信息的方法,查了一下,发现官方开发网站中就有提到,有兴趣的朋友可以研究一下:http://developer.android.com/guide/developing/tools/proguard.html (有墙,你懂),这样Proguard在Android上的实用性就更好了!
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。
你好,我遇到个问题,在我的工程里面我使用了其它的jar包,此时无法导出混淆的apk,我觉得我应该在proguard.cfg里添加
-libraryjars ${library-jar}/somejar.jar
但是添加了后还是不行,控制台输出以下错误:
Proguard returned with error code 1. See console
proguard.ParseException: Expecting class path separator ‘;’ before ‘{‘ in line 7 of file ‘E:\MyCode\proguard.cfg’,
included from argument number 1
at proguard.ConfigurationParser.parseClassPathArgument(ConfigurationParser.java:295)
at proguard.ConfigurationParser.parse(ConfigurationParser.java:111)
at proguard.ProGuard.main(ProGuard.java:491)
不知道我的方法对不对,对于jar包应该怎么做?
你好,你的错误提示cfg的第7行缺少;不知道是写错了格式?
不加这个参数会提示什么错误?
因为要用到其它的jar包
我就在第7行添加了这句话
-libraryjars ${library-jar}/ksoap2-android-2.5.4.jar
我觉得应该是这样写吧。
如果不加这句话,就提示
Warning: library class android.content.res.XmlResourceParser extends or implements program class org.xmlpull.v1.XmlPullParser
Warning: library class android.view.LayoutInflater depends on program class org.xmlpull.v1.XmlPullParser
Warning: library class android.view.LayoutInflater depends on program class org.xmlpull.v1.XmlPullParser
Warning: library class android.content.Intent depends on program class org.xmlpull.v1.XmlPullParser
You should check if you need to specify additional program jars.
Warning: there were 4 instances of library classes depending on program classes.
You must avoid such dependencies, since the program classes will
be processed, while the library classes will remain unchanged.
java.io.IOException: Please correct the above warnings first.
at proguard.Initializer.execute(Initializer.java:308)
at proguard.ProGuard.initialize(ProGuard.java:210)
at proguard.ProGuard.execute(ProGuard.java:85)
at proguard.ProGuard.main(ProGuard.java:499)
其中的org.xmlpull.v1.XmlPullParser就是那个包里的。
看样子你像是在代码里使用了xmlpull类库?Android系统的类库中已经包含了 xmlpull,这样混淆出现了冲突,这个可能得需要把涉及到这个类库的部分keep出来,不让proguard处理。
我不是要用xmlpull,我是要用那个jar包里的其它类,但是这个包里也有 xmlpull。
包里有org.xmlpull.v1.XmlPullParser,但是android系统里也有org.xmlpull.v1.XmlPullParser,说是重复定义了。
这个keep要keep哪些,我试了,还是不行。
就是那个jar包中有xmlpull,但是android系统也有xmlpull,提示说重复定义了,这个怎么处理呢,你那边能不能试下。
我不是要使用xmlpull,我是要使用那个包里的其它类,但是这个包里也有xmlpull。
如果你是说keep的话我试了还是不行,不知道是不是我没有keep对,希望你能试下,谢谢。
我试了一下你用的这个lib,确实会出现这个问题。然后这是在Proguard官网上找到的解释:
Warning: library class … depends on program class …
If any of your library classes depend on your program classes, by extending, implementing or just referencing them, your processed code will generally be unusable. Program classes can depend on library classes, but not the other way around. Program classes are processed, while library classes always remain unchanged. It is therefore impossible to adapt references from library classes to program classes, for instance if the program classes are renamed. You should define a clean separation between program code and library code, and try again.
按照这个解释的话可能需要你修改这个jar库的源代码,把它里面已存在的和系统库冲突的类去掉,直接换成android系统的类,这样应该就可以了。
按照你的回复我接着尝试了下,把jar包中的重复的类删掉后就能导出了。
非常感谢你的帮忙,这个问题困扰了我好几天,希望以后能再次与你交流。
呵呵,恭喜问题解决!
您好,请问您是如何把jar包中的重复的类删掉的?我把ksoap2的源码下载后,发现其中包括xmlpull类的代码在kxml包中啊。怎么删除?您能帮忙发一份给我吗?谢谢。我的邮箱:szhln@qq.com
你有源码的话不是更好办了,直接改源码吧。
把引用的系统已有的类库,用系统自带的替掉就好了,只是注意兼容问题。
-ignorewarnings ,其实加这句话就什么都不用修改了
你好,我在使用过程中也遇到了一个问题:
proguard.ParseException: Expecting class path separator ‘;’ before ‘{‘ in line 19 of file ‘E:\……..\proguard.cfg’,
也用到了
-libraryjars ${library-jar}/some.jar
如果不加这句话则显示
Proguard returned with error code 1. See console
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.TransformerFactory
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.TransformerFactory
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.Transformer
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.stream.StreamSource
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.stream.StreamSource
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.stream.StreamResult
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.stream.StreamResult
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.Transformer
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.TransformerFactory
Warning: org.jivesoftware.smackx.pubsub.util.XmlUtils: can’t find referenced class javax.xml.transform.Transformer
You should check if you need to specify additional program jars.
Warning: there were 10 unresolved references to classes or interfaces.
You may need to specify additional library jars (using ‘-libraryjars’),
or perhaps the ‘-dontskipnonpubliclibraryclasses’ option.
java.io.IOException: Please correct the above warnings first.
at proguard.Initializer.execute(Initializer.java:308)
at proguard.ProGuard.initialize(ProGuard.java:210)
at proguard.ProGuard.execute(ProGuard.java:85)
at proguard.ProGuard.main(ProGuard.java:499)
万分感谢!
检查一下libraryjars参数的格式吧,看提示可能是改cfg时缺了分号
请教一下,项目导出为jar时如何混淆?
你指的是用到的第三方lib的jar?
大哥,帮帮忙,碰到你博客地址http://blog.k-res.net/?p=929 上碰到的问题,求回复,求千万花几分钟解答一下疑问,不胜感激
Expecting class path separator ‘;’ before ‘{‘ 很可能是你输出路径有空格
Proguard returned with error code 1. See console[2014-12-04 11:43:07 – MainActivity] proguard.ParseException: Expecting separator ‘;’ before ‘(‘ in line 64 of file ‘D:testQuickReturnListView_masterbinproguard.txt’,[2014-12-04 11:43:07 – MainActivity] included from argument number 6哥们,我着是多出一个分号“;”,神马原因?64行的语句-keepclassmembers class * { *** myClick()(…); }
这行后面改成这样试试:myClick(); }试试