2013-04-03 68 views
3

我已經嘗試了無數次的事情,但是我無法防止我的應用在使用Proguard縮小代碼時崩潰(禁用模糊處理)。我總是在Proguard的啓用了以下異常:我在Android的Proguard配置中缺少什麼?

04-03 10:26:37.277 E/AndroidRuntime(29460): FATAL EXCEPTION: main 
04-03 10:26:37.277 E/AndroidRuntime(29460): java.lang.ExceptionInInitializerError 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.company.nativeapp.activitycontrollers.LoginController.onLogInSuccess(LoginController.java:199) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.company.datamanager.BfAccountStateManager$AccountWebViewClient.shouldOverrideUrlLoading(BfAccountStateManager.java:326) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at android.webkit.CallbackProxy.uiOverrideUrlLoading(CallbackProxy.java) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at android.os.Handler.dispatchMessage(Handler.java) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at android.os.Looper.loop(Looper.java) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at android.app.ActivityThread.main(ActivityThread.java) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at java.lang.reflect.Method.invokeNative(Native Method) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at java.lang.reflect.Method.invoke(Method.java:511) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at dalvik.system.NativeStart.main(Native Method) 
04-03 10:26:37.277 E/AndroidRuntime(29460): Caused by: java.lang.ExceptionInInitializerError 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.company.android.bfsdk.diffusion.requests.mcs.BaseMCSRequest.<clinit>(BaseMCSRequest.java:28) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  ... 12 more 
04-03 10:26:37.277 E/AndroidRuntime(29460): Caused by: java.lang.ExceptionInInitializerError 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.company.mobile.mcs.service.descriptor.inplay.Inplay.<clinit>(Inplay.java:20585) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  ... 13 more 
04-03 10:26:37.277 E/AndroidRuntime(29460): Caused by: java.lang.RuntimeException: Generated message class "com.company.mobile.mcs.service.descriptor.Mcs$MCSRequestMessage$Builder" missing method "getUserAgent". 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.google.protobuf.GeneratedMessage.getMethodOrDie(GeneratedMessage.java:1359) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.google.protobuf.GeneratedMessage.access$1300(GeneratedMessage.java:57) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.google.protobuf.GeneratedMessage$FieldAccessorTable$SingularFieldAccessor.<init>(GeneratedMessage.java:1485) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.google.protobuf.GeneratedMessage$FieldAccessorTable.<init>(GeneratedMessage.java:1432) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.company.mobile.mcs.service.descriptor.Mcs$1.assignDescriptors(Mcs.java:2083) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.google.protobuf.Descriptors$FileDescriptor.internalBuildGeneratedFileFrom(Descriptors.java:298) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.company.mobile.mcs.service.descriptor.Mcs.<clinit>(Mcs.java:2109) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  ... 14 more 
04-03 10:26:37.277 E/AndroidRuntime(29460): Caused by: java.lang.NoSuchMethodException: getUserAgent [] 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at java.lang.Class.getConstructorOrMethod(Class.java:460) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at java.lang.Class.getMethod(Class.java:915) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  at com.google.protobuf.GeneratedMessage.getMethodOrDie(GeneratedMessage.java:1357) 
04-03 10:26:37.277 E/AndroidRuntime(29460):  ... 20 more 

除了Android應用程序的標準配置Proguard的,我已經添加了以下行:

-keep public class com.company.** 

-keep class com.company.* { *; } 
-keepclassmembernames class com.company.* { *; } 

-keep class * extends com.google.protobuf.GeneratedMessage { *; } 
-keepclassmembernames class * extends com.google.protobuf.GeneratedMessage { *; } 

但是我還是上面提到的異常...

我錯過了什麼?

+1

我傾向於認爲Proguard的主要好處在於它的迷惑而不是它的縮小能力。所以我只是在我的配置中有「-dontshrink」這一行, – NickT

+0

@NickT是的,但我真的需要收縮功能......請參閱:http://stackoverflow.com/questions/15436956/how-to-solve-the -issue-with-dalvik-compiler-limitation-on-64k-methods –

+0

@RicardoAmaral:你設法解決這個問題嗎?如果是,請分享你的發現?我很長一段時間都陷入了同樣的問題。 – Atul

回答

4

問題是ProtocolBuffers使用反射來調用方法,但Proguard無法看到反射調用。 Proguard可以改變方法/對象的名稱,也可以移除方法/對象,反射方法無法找到它。

選項:

  • 你可以嘗試尋找各種可能的反射調用,將在適當的Proguard的報表,但您可能需要更改此爲協議緩衝區的每個新版本。 我個人不會走這條路

  • 你可以嘗試添加optimize_for SPEED選項協議定義和重新生成Java代碼,這將導致不使用反射,可以使用ProGuard可以使用更大的類。

  • 嘗試其中一種JavaMe protobuf解決方案 - 它們要小得多。看到previous question

問題代碼:

private static Method getMethodOrDie(
     final Class clazz, final String name, final Class... params) { 
    try { 
     return clazz.getMethod(name, params); 
    } catch (NoSuchMethodException e) { 
     throw new RuntimeException(
     "Generated message class \"" + clazz.getName() + 
     "\" missing method \"" + name + "\".", e); 
    } 
    } 
+1

但這正是我不明白的...... Proguard沒有看到反射調用,因此檢測到一些「未被使用」的方法並將它們移除。但是他們不應該被刪除,因爲我告訴Proguard不要刪除com.company下的任何內容。**,或者他們應該刪除嗎? –

+0

我們已經在使用優化速度的原始文件,但由於某種原因反射仍在使用!?但是,我下載了最新的Proto Buffer庫和編譯器,生成了所有再次針對速度進行了優化的.java文件,現在它似乎正在工作。也許我們正在使用舊的.proto文件,或者這種新版本的Protocol Buffers幫助。它現在已經修復,這是重要的。 –

+0

@Ricardo爲了將_everything_保留在com.company下,您需要「-keep class com.company。** {*;}」。然而,這將在很大程度上打敗優化和混淆的觀點。 –

0

我也遇到了這個問題:了java.lang.RuntimeException生成的消息類 「XXX」 中籤署APK失蹤法 「XXX」,但在調試模式下它的沒有問題。我確定Proguard配置是可以的。

通過分析堆棧跟蹤日誌,我發現了問題的根源:打印protobuf的文件記錄過於龐大,像

List<UserPb.UserInfo> userInfos = obj.getUserInfoList(); 

Log.d(TAG, "userInfos: " + userInfos); 

包含超過50000行代碼,這UserPb.java文件是如此巨大。

所以不要打印protobuf相關登錄已簽名的apk