简体   繁体   English

我在这款适用于Android的Proguard配置中缺少什么?

[英]What am I missing in this Proguard configuration for Android?

I've tried countless things but I'm not being able to prevent my app to crash while using Proguard to shrink the code (obfuscation is disabled). 我已经尝试了无数的东西但是我无法阻止我的应用程序在使用Proguard缩小代码时崩溃(混淆被禁用)。 I always get the following exception when Proguard is enabled: 启用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

Besides the standard Proguard configuration for Android apps, I've added the following lines: 除了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 { *; }

But I still get the exception mentioned above... 但我仍然得到上面提到的例外......

What am I missing? 我错过了什么?

The problem is ProtocolBuffers is using reflection to call methods but Proguard can not see the reflection calls. 问题是ProtocolBuffers使用反射调用方法,但Proguard无法看到反射调用。 Proguard could either change the name of a Method / Object or remove the Method / Object, either way reflection will not find it. Proguard可以更改方法/对象的名称或删除方法/对象,无论是反射都找不到它。

Options: 选项:

  • You could try Finding every possible reflection call and adding the appropriate Proguard statements in. But you might need to change this for each new version of protocol buffers. 您可以尝试查找每个可能的反射调用并添加适当的Proguard语句。但是您可能需要为每个新版本的协议缓冲区更改此值。 Personally I would not go this way 我个人不会这样

  • You could try adding optimize_for SPEED option to the Proto Definition and regenerating the java code, this will result in much larger class that does not use reflection and could be used with Proguard. 您可以尝试将optimize_for SPEED选项添加到Proto Definition并重新生成java代码,这将导致更大的类不使用反射并且可以与Proguard一起使用。

  • Try one of the JavaMe protobuf solutions - they are much smaller. 尝试使用JavaMe protobuf解决方案之一 - 它们要小得多。 see previous question 看上一个问题

Problem Code : 问题代码:

 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);
    }
  }

I also encountered this issue: java.lang.RuntimeException Generated message class "xxx" missing method "xxx" in signed apk, but in debug mode it's out of question. 我也遇到过这个问题:java.lang.RuntimeException在签名的apk中生成的消息类“xx​​x”缺少方法“xxx”,但在调试模式下它是不可能的。 And I'm sure the Proguard configuration is OK. 我确信Proguard配置没问题。

By analyzing the stack trace log, I found the root cause of the problem: print protobuf file log too huge, like 通过分析堆栈跟踪日志,我找到了问题的根本原因:打印protobuf文件日志太大了,比如

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

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

this UserPb.java file is so huge that contains over 50000 lines of code. 这个UserPb.java文件非常庞大,包含超过50000行代码。

So DO NOT print protobuf related log in signed apk . 因此, 请勿在签名的apk中打印protobuf相关的日志

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM