昨天,客户想看一下目前项目开发到什么程度了,于是需要将项目签名打包成apk,结果打包的时候出错了,吃惊,什么情况。等成功打包以后,安装起来发现部分功能又报错了,囧,所幸最后还是解决了。在这里记录一下遇到的错误和解决方法。
1.如何混淆
将代码混淆起来,这样可以防止在apk被人反编译后而被别人直接看到源码,混淆方法很简单,当我们创建好项目时,已经自动为我们生成了混淆文件,老版的ADT生成的是proguard.cfg文件,而新版的ADT则是以proguard-project.txt替代了它。两则配置方法一致,只要在project.properties文件中引入就好。前者是将project.properties的“# proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”的“#”去掉就可以了,后者加入一句proguard.config=proguard.cfg即可。
2.如何防止第三方jar包混淆
我使用的混淆文件是proguard.cfg。
开头提到的第一个打包失败的原因是因为引入了第三方jar包。
所报错误如下
1 Proguard returned with error code 1. See console 2 Note: there were 1465 duplicate class definitions. 3 Warning: library class android.net.http.AndroidHttpClient extends or implements program class org.apache.http.client.HttpClient 4 Warning: org.apache.http.client.protocol.RequestAddCookies: can't find referenced class org.apache.commons.logging.LogFactory 5 Warning: org.apache.http.client.protocol.RequestAddCookies: can't find referenced class org.apache.commons.logging.LogFactory 6 Warning: org.apache.http.client.protocol.RequestAuthCache: can't find referenced class org.apache.commons.logging.LogFactory 7 Warning: org.apache.http.client.protocol.RequestAuthCache: can't find referenced class org.apache.commons.logging.LogFactory 8 Warning: org.apache.http.client.protocol.RequestAuthenticationBase: can't find referenced class org.apache.commons.logging.LogFactory 9 Warning: org.apache.http.client.protocol.RequestAuthenticationBase: can't find referenced class org.apache.commons.logging.LogFactory 10 Warning: org.apache.http.client.protocol.RequestClientConnControl: can't find referenced class org.apache.commons.logging.LogFactory 11 Warning: org.apache.http.client.protocol.RequestClientConnControl: can't find referenced class org.apache.commons.logging.LogFactory 12 Warning: org.apache.http.client.protocol.ResponseAuthCache: can't find referenced class org.apache.commons.logging.LogFactory 13 Warning: org.apache.http.client.protocol.ResponseAuthCache: can't find referenced class org.apache.commons.logging.LogFactory 14 Warning: org.apache.http.client.protocol.ResponseProcessCookies: can't find referenced class org.apache.commons.logging.LogFactory 15 Warning: org.apache.http.client.protocol.ResponseProcessCookies: can't find referenced class org.apache.commons.logging.LogFactory 16 Warning: org.apache.http.impl.auth.BasicScheme: can't find referenced class org.apache.commons.codec.binary.Base64 17 Warning: org.apache.http.impl.auth.BasicScheme: can't find referenced class org.apache.commons.codec.binary.Base64 18 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.apache.commons.logging.LogFactory 19 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.apache.commons.codec.binary.Base64 20 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.apache.commons.codec.binary.Base64 21 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSManager 22 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSName 23 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSManager 24 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSName 25 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSManager 26 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSContext 27 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSContext 28 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSContext 29 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSException 30 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSException 31 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSException 32 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.apache.commons.codec.binary.Base64 33 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.apache.commons.codec.binary.Base64 34 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.apache.commons.logging.LogFactory 35 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSManager 36 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSName 37 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSContext 38 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.apache.commons.codec.binary.Base64 39 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSManager 40 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.Oid 41 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.Oid 42 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSManager 43 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSName 44 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSContext 45 Warning: org.apache.http.impl.auth.GGSSchemeBase: can't find referenced class org.ietf.jgss.GSSException 46 Warning: org.apache.http.impl.auth.KerberosScheme: can't find referenced class org.ietf.jgss.Oid 47 Warning: org.apache.http.impl.auth.KerberosScheme: can't find referenced class org.ietf.jgss.Oid 48 Warning: org.apache.http.impl.auth.KerberosScheme: can't find referenced class org.ietf.jgss.GSSException 49 Warning: org.apache.http.impl.auth.NTLMEngineImpl$NTLMMessage: can't find referenced class org.apache.commons.codec.binary.Base64 50 Warning: org.apache.http.impl.auth.NTLMEngineImpl$NTLMMessage: can't find referenced class org.apache.commons.codec.binary.Base64 51 Warning: org.apache.http.impl.auth.NTLMEngineImpl$NTLMMessage: can't find referenced class org.apache.commons.codec.binary.Base64 52 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.apache.commons.logging.LogFactory 53 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.ietf.jgss.Oid 54 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.ietf.jgss.Oid 55 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.ietf.jgss.GSSException 56 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.ietf.jgss.GSSException 57 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.apache.commons.logging.LogFactory 58 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.ietf.jgss.GSSException 59 Warning: org.apache.http.impl.auth.NegotiateScheme: can't find referenced class org.ietf.jgss.Oid 60 Warning: org.apache.http.impl.auth.SPNegoScheme: can't find referenced class org.ietf.jgss.Oid 61 Warning: org.apache.http.impl.auth.SPNegoScheme: can't find referenced class org.ietf.jgss.Oid 62 Warning: org.apache.http.impl.auth.SPNegoScheme: can't find referenced class org.ietf.jgss.GSSException 63 Warning: org.apache.http.impl.client.AbstractAuthenticationHandler: can't find referenced class org.apache.commons.logging.LogFactory 64 Warning: org.apache.http.impl.client.AbstractAuthenticationHandler: can't find referenced class org.apache.commons.logging.LogFactory 65 Warning: org.apache.http.impl.client.AbstractHttpClient: can't find referenced class org.apache.commons.logging.LogFactory 66 Warning: org.apache.http.impl.client.AbstractHttpClient: can't find referenced class org.apache.commons.logging.LogFactory 67 Warning: org.apache.http.impl.client.AuthenticationStrategyAdaptor: can't find referenced class org.apache.commons.logging.LogFactory 68 Warning: org.apache.http.impl.client.AuthenticationStrategyAdaptor: can't find referenced class org.apache.commons.logging.LogFactory 69 Warning: org.apache.http.impl.client.AuthenticationStrategyImpl: can't find referenced class org.apache.commons.logging.LogFactory 70 Warning: org.apache.http.impl.client.AuthenticationStrategyImpl: can't find referenced class org.apache.commons.logging.LogFactory 71 Warning: org.apache.http.impl.client.AutoRetryHttpClient: can't find referenced class org.apache.commons.logging.LogFactory 72 Warning: org.apache.http.impl.client.AutoRetryHttpClient: can't find referenced class org.apache.commons.logging.LogFactory 73 Warning: org.apache.http.impl.client.DefaultRedirectHandler: can't find referenced class org.apache.commons.logging.LogFactory 74 Warning: org.apache.http.impl.client.DefaultRedirectHandler: can't find referenced class org.apache.commons.logging.LogFactory 75 Warning: org.apache.http.impl.client.DefaultRedirectStrategy: can't find referenced class org.apache.commons.logging.LogFactory 76 Warning: org.apache.http.impl.client.DefaultRedirectStrategy: can't find referenced class org.apache.commons.logging.LogFactory 77 Warning: org.apache.http.impl.client.DefaultRequestDirector: can't find referenced class org.apache.commons.logging.LogFactory 78 Warning: org.apache.http.impl.client.DefaultRequestDirector: can't find referenced class org.apache.commons.logging.LogFactory 79 Warning: org.apache.http.impl.client.HttpAuthenticator: can't find referenced class org.apache.commons.logging.LogFactory 80 Warning: org.apache.http.impl.client.HttpAuthenticator: can't find referenced class org.apache.commons.logging.LogFactory 81 Warning: org.apache.http.impl.conn.BasicClientConnectionManager: can't find referenced class org.apache.commons.logging.LogFactory 82 Warning: org.apache.http.impl.conn.BasicClientConnectionManager: can't find referenced class org.apache.commons.logging.LogFactory 83 Warning: org.apache.http.impl.conn.DefaultClientConnection: can't find referenced class org.apache.commons.logging.LogFactory 84 Warning: org.apache.http.impl.conn.DefaultClientConnection: can't find referenced class org.apache.commons.logging.LogFactory 85 Warning: org.apache.http.impl.conn.DefaultClientConnection: can't find referenced class org.apache.commons.logging.LogFactory 86 Warning: org.apache.http.impl.conn.DefaultClientConnectionOperator: can't find referenced class org.apache.commons.logging.LogFactory 87 Warning: org.apache.http.impl.conn.DefaultClientConnectionOperator: can't find referenced class org.apache.commons.logging.LogFactory 88 Warning: org.apache.http.impl.conn.DefaultHttpResponseParser: can't find referenced class org.apache.commons.logging.LogFactory 89 Warning: org.apache.http.impl.conn.DefaultHttpResponseParser: can't find referenced class org.apache.commons.logging.LogFactory 90 Warning: org.apache.http.impl.conn.DefaultResponseParser: can't find referenced class org.apache.commons.logging.LogFactory 91 Warning: org.apache.http.impl.conn.DefaultResponseParser: can't find referenced class org.apache.commons.logging.LogFactory 92 Warning: org.apache.http.impl.conn.IdleConnectionHandler: can't find referenced class org.apache.commons.logging.LogFactory 93 Warning: org.apache.http.impl.conn.IdleConnectionHandler: can't find referenced class org.apache.commons.logging.LogFactory 94 Warning: org.apache.http.impl.conn.InMemoryDnsResolver: can't find referenced class org.apache.commons.logging.LogFactory 95 Warning: org.apache.http.impl.conn.InMemoryDnsResolver: can't find referenced class org.apache.commons.logging.LogFactory 96 Warning: org.apache.http.impl.conn.PoolingClientConnectionManager: can't find referenced class org.apache.commons.logging.LogFactory 97 Warning: org.apache.http.impl.conn.PoolingClientConnectionManager: can't find referenced class org.apache.commons.logging.LogFactory 98 Warning: org.apache.http.impl.conn.SingleClientConnManager: can't find referenced class org.apache.commons.logging.LogFactory 99 Warning: org.apache.http.impl.conn.SingleClientConnManager: can't find referenced class org.apache.commons.logging.LogFactory 100 Warning: org.apache.http.impl.conn.tsccm.AbstractConnPool: can't find referenced class org.apache.commons.logging.LogFactory 101 Warning: org.apache.http.impl.conn.tsccm.AbstractConnPool: can't find referenced class org.apache.commons.logging.LogFactory 102 Warning: org.apache.http.impl.conn.tsccm.ConnPoolByRoute: can't find referenced class org.apache.commons.logging.LogFactory 103 Warning: org.apache.http.impl.conn.tsccm.ConnPoolByRoute: can't find referenced class org.apache.commons.logging.LogFactory 104 Warning: org.apache.http.impl.conn.tsccm.RouteSpecificPool: can't find referenced class org.apache.commons.logging.LogFactory 105 Warning: org.apache.http.impl.conn.tsccm.RouteSpecificPool: can't find referenced class org.apache.commons.logging.LogFactory 106 Warning: org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager: can't find referenced class org.apache.commons.logging.LogFactory 107 Warning: org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager: can't find referenced class org.apache.commons.logging.LogFactory 108 You should check if you need to specify additional program jars. 109 Warning: there were 104 unresolved references to classes or interfaces. 110 You may need to specify additional library jars (using '-libraryjars'). 111 Warning: there were 1 instances of library classes depending on program classes. 112 You must avoid such dependencies, since the program classes will 113 be processed, while the library classes will remain unchanged. 114 java.io.IOException: Please correct the above warnings first. 115 at proguard.Initializer.execute(Initializer.java:321) 116 at proguard.ProGuard.initialize(ProGuard.java:211) 117 at proguard.ProGuard.execute(ProGuard.java:86) 118 at proguard.ProGuard.main(ProGuard.java:492)
解决方法很简单,就是在proguard.cfg中加入句-dontwarn即可。
第二个运行时报错,我用真机调试查看了下LogCat日志输出,发现报的错误是找不到资源,而报错地方是引入第三方jar的时候,原来是混淆时将第三方jar包也混淆了,那么只要不混淆第三方jar就可以吧。
以下是我最后的proguard.cfg配置。
1 -keep class **.R$* { *; }//不混淆R文件 2 -optimizationpasses 5 3 -dontusemixedcaseclassnames 4 -dontskipnonpubliclibraryclasses 5 -dontpreverify 6 -ignorewarnings 7 -verbose 8 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 9 10 //不混淆的jar包,脚本中去掉该句 11 -libraryjars libs/jar包名称 12 13 -dontwarn//不警告,脚本中去掉该句 14 -dontskipnonpubliclibraryclassmembers 15 16 -keep public class * extends android.app.Activity 17 -keep public class * extends android.app.Application 18 -keep public class * extends android.app.Service 19 -keep public class * extends android.content.BroadcastReceiver 20 -keep public class * extends android.content.ContentProvider 21 -keep public class * extends android.app.backup.BackupAgentHelper 22 -keep public class * extends android.preference.Preference 23 -keep public class com.android.vending.licensing.ILicensingService 24 25 -keepclasseswithmembernames class * { 26 native <methods>; 27 } 28 29 -keepclasseswithmembers class * { 30 public <init>(android.content.Context, android.util.AttributeSet); 31 } 32 33 -keepclasseswithmembers class * { 34 public <init>(android.content.Context, android.util.AttributeSet, int); 35 } 36 37 -keepclassmembers class * extends android.app.Activity { 38 public void *(android.view.View); 39 } 40 41 -keepclassmembers enum * { 42 public static **[] values(); 43 public static ** valueOf(java.lang.String); 44 } 45 46 -keep class * implements android.os.Parcelable { 47 public static final android.os.Parcelable$Creator *; 48 } 49 50 //不混淆某包中的指定内容,脚本中去掉该句 51 -keep class 包名.** {*;}
至此,就ok了