Google Drive API无法与ProGuard(NPE)配合使用

时间:2022-07-11 15:21:20

Currently, I'm having experience that, a piece of code, which makes use of Google Drive API is running fine without introducing ProGuard.

目前,我有经验,使用Google Drive API的一段代码在没有引入ProGuard的情况下运行正常。

However, after introducing ProGuard, I'm getting the following run-time error.

但是,在引入ProGuard之后,我遇到了以下运行时错误。

    at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.NullPointerException
    at com.google.api.client.util.Types.getActualParameterAtPosition(Types.java:329)
    at com.google.api.client.util.Types.getIterableParameter(Types.java:309)
    at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:546)
    at com.google.api.client.json.JsonParser.parse(JsonParser.java:350)
    at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:586)
    at com.google.api.client.json.JsonParser.parse(JsonParser.java:289)
    at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:76)
    at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:71)
    at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:491)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:456)
    at com.jstock.c.b.a(CloudFile.java:136)

Note, the crash happens at my code (which is com.jstock.c.b.a if I retrace using mapping.txt)

请注意,崩溃发生在我的代码中(如果我使用mapping.txt进行回溯,则为com.jstock.c.b.a)

// request is Files.List
FileList files = request.execute();

In my proguard, I thought having the following 2 key instructions, able to prevent the crash from happen : I tell ProGuard never touch on jackson and Google libraries.

在我的项目中,我认为有以下2个关键指令,能够防止崩溃发生:我告诉ProGuard永远不要触及jackson和Google库。

-keep class org.codehaus.** { *; }
-keep class com.google.** { *; }
-keep interface org.codehaus.** { *; }
-keep interface com.google.** { *; }

But that doesn't work. NPE still happen at Types.java

但这不起作用。 NPE仍然发生在Types.java上

Note that, I had another try is that, I thought obfuscate process causes NPE happens. Hence, I try to disable it using -dontobfuscate. But this time, I will not able to generate APK file, and getting a popular error message : Conversion to Dalvik format failed with error 1

请注意,我还有另一种尝试是,我认为混淆过程会导致NPE发生。因此,我尝试使用-dontobfuscate禁用它。但这一次,我将无法生成APK文件,并收到一条流行的错误消息:转换为Dalvik格式失败,错误1

Here is the proguard configuration which causes NPE at Google Drive API.

以下是在Google Drive API中导致NPE的proguard配置。

-optimizationpasses 1
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

# Comment out the following line, will cause popular "Conversion to Dalvik format failed with error 1"
##-dontobfuscate

-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-dontwarn javax.swing.**
-dontwarn java.awt.**
-dontwarn org.jasypt.encryption.pbe.**
-dontwarn java.beans.**
-dontwarn org.joda.time.**
-dontwarn com.google.android.gms.**
-dontwarn org.w3c.dom.bootstrap.**
-dontwarn com.ibm.icu.text.**
-dontwarn demo.**

# Hold onto the mapping.text file, it can be used to unobfuscate stack traces in the developer console using the retrace tool
-printmapping mapping.txt

# Keep line numbers so they appear in the stack trace of the develeper console 
-keepattributes *Annotation*,EnclosingMethod,SourceFile,LineNumberTable

-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
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }

# https://sourceforge.net/p/proguard/discussion/182456/thread/e4d73acf
-keep class org.codehaus.** { *; }
-keep class com.google.** { *; }
-keep interface org.codehaus.** { *; }
-keep interface com.google.** { *; }

-assumenosideeffects class android.util.Log {
  public static int d(...);
  public static int i(...);
  public static int e(...);
  public static int v(...);  
}

-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

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

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
}

-keepclasseswithmembers class com.google.common.base.internal.Finalizer{
    <methods>;
}

Is there anything else I can try?

还有什么我可以尝试的吗?

I'm not sure it might be caused by the combination of the libraries. (Although things run pretty well without introducing ProGuard)

我不确定它可能是由库的组合引起的。 (虽然在没有引入ProGuard的情况下运行良好)

Google Drive API无法与ProGuard(NPE)配合使用

If I look at the NPE crash location (Types.getActualParameterAtPosition(Types.java:329))

如果我查看NPE崩溃位置(Types.getActualParameterAtPosition(Types.java:329))

private static Type getActualParameterAtPosition(Type type, Class<?> superClass, int position) {
    ParameterizedType parameterizedType = Types.getSuperParameterizedType(type, superClass);
    Type valueType = parameterizedType.getActualTypeArguments()[position];
    // this is normally a type variable, except in the case where the class of iterableType is
    // superClass, e.g. Iterable<String>
    if (valueType instanceof TypeVariable<?>) {
      Type resolve = Types.resolveTypeVariable(Arrays.asList(type), (TypeVariable<?>) valueType);
      if (resolve != null) {
        return resolve;
      }
    }
    return valueType;
}

I suspect Types.getSuperParameterizedType returning null. So, I further look into Types.getSuperParameterizedType.

我怀疑Types.getSuperParameterizedType返回null。所以,我进一步研究了Types.getSuperParameterizedType。

public static ParameterizedType getSuperParameterizedType(Type type, Class<?> superClass) {
    if (type instanceof Class<?> || type instanceof ParameterizedType) {
    outer: while (type != null && type != Object.class) {
     Class<?> rawType;
     if (type instanceof Class<?>) {
       // type is a class
       rawType = (Class<?>) type;
     } else {
       // current is a parameterized type
       ParameterizedType parameterizedType = (ParameterizedType) type;
       rawType = getRawClass(parameterizedType);
       // check if found Collection
       if (rawType == superClass) {
         // return the actual collection parameter
         return parameterizedType;
       }
       if (superClass.isInterface()) {
         for (Type interfaceType : rawType.getGenericInterfaces()) {
           // interface type is class or parameterized type
           Class<?> interfaceClass =
               interfaceType instanceof Class<?> ? (Class<?>) interfaceType : getRawClass(
                   (ParameterizedType) interfaceType);
           if (superClass.isAssignableFrom(interfaceClass)) {
             type = interfaceType;
             continue outer;
           }
         }
       }
     }
     // move on to the super class
     type = rawType.getGenericSuperclass();
    }
    }
    return null;
}

What is the possible root cause that may cause getSuperParameterizedType returning null, after processed by ProGuard?

在ProGuard处理后,可能导致getSuperParameterizedType返回null的可能根本原因是什么?

6 个解决方案

#1


31  

A combination of the following has worked for me:

以下组合对我有用:

-keep class com.google.** { *;}
-keep interface com.google.** { *;}
-dontwarn com.google.**

-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-keepattributes *Annotation*,Signature
-keep class * extends com.google.api.client.json.GenericJson {
*;
}
-keep class com.google.api.services.drive.** {
*;
}

This provided a working proguard compatible solution for a recent Google Drive project.

这为最近的Google云端硬盘项目提供了一个有效的兼容解决方案。

Cannot take all credit for this solution though, originally found at this link here

虽然最初在此链接中找到,但是不能为此解决方案带来所有功劳

#2


6  

Proper combination is :

适当的组合是:

-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault

There's proguard configuration prepared by Google for project google-api-java-client

Google为项目google-api-java-client准备了proguard配置

https://github.com/google/google-api-java-client/blob/57fe35766cbba0a0d5a9a296be81468d730a29f8/google-api-client-assembly/proguard-google-api-client.txt

#3


1  

First -keeping a class does not mean to not touch it. It means do not change its name, and use it as a basis for determining if other classes are not referenced & can be deleted.

第一级课并不意味着不接触它。这意味着不要更改其名称,并将其用作确定是否未引用其他类并可以删除的基础。

Optimization still occurs, which is likely your problem. Next step I would do is try with: -dontoptimize

优化仍然会发生,这可能是你的问题。我要做的下一步是尝试:-dontoptimize

This should cause your other optimizations to be ignored.

这应该会导致您的其他优化被忽略。

BTW, not sure what version of SDK you are using. Am using 15, 20 is latest, and a proguard-project.txt file is create with the project. The optimization options it uses is:

顺便说一句,不知道你使用的是哪个版本的SDK。使用15,20是最新的,并且使用项目创建proguard-project.txt文件。它使用的优化选项是:

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*

If turning off optimization gets it running, maybe turning off all the optimizations (that's what ! does) the SDK does, will allow you to do optimization as well.

如果关闭优化使其运行,可能关闭SDK所做的所有优化(那就是!),也可以让你进行优化。

#4


0  

The method Types.getSuperParameterizedType relies on information about generics. Generics are erased in Java. The compiler only adds them as annotation attributes, the JVM ignores them, and ProGuard discards them unless you tell it not to. So this might help:

Types.getSuperParameterizedType方法依赖于有关泛型的信息。泛型在Java中被删除。编译器只将它们添加为注释属性,JVM忽略它们,ProGuard会丢弃它们,除非你告诉它不要。所以这可能有所帮助:

-keepattributes *Annotation*

#5


0  

does your code use any thing that implement Serializable? All of those need to be excluded too.

您的代码是否使用任何实现Serializable的东西?所有这些都需要被排除在外。

#6


0  

There have been few update to GooglePlayServices lately. I don't like the new API. I had the same problems.

最近GooglePlayServices的更新很少。我不喜欢新的API。我遇到了同样的问题。

I couldn't compile signed app with proguard. Proguard template from Google didn't work for me.

我无法使用proguard编译已签名的应用程序。谷歌的Proguard模板对我不起作用。

I add these four lines to my proguard config and it is working:

我将这四行添加到我的proguard配置中,它正在工作:

-dontwarn com.google.android.gms.**
-keep interface com.google.** { *; }
-keep class * extends com.google.api.client.json.GenericJson {*;}
-keep class com.google.api.services.drive.** {*;}

This is strange. Previous version of google-api-services-drive-v2 compiled without any problems.

这很奇怪。以前版本的google-api-services-drive-v2编译没有任何问题。

I'm using the latest version at the moment: google-api-services-drive-v2-rev47-1.12.0-beta.jar

我目前正在使用最新版本:google-api-services-drive-v2-rev47-1.12.0-beta.jar

#1


31  

A combination of the following has worked for me:

以下组合对我有用:

-keep class com.google.** { *;}
-keep interface com.google.** { *;}
-dontwarn com.google.**

-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-keepattributes *Annotation*,Signature
-keep class * extends com.google.api.client.json.GenericJson {
*;
}
-keep class com.google.api.services.drive.** {
*;
}

This provided a working proguard compatible solution for a recent Google Drive project.

这为最近的Google云端硬盘项目提供了一个有效的兼容解决方案。

Cannot take all credit for this solution though, originally found at this link here

虽然最初在此链接中找到,但是不能为此解决方案带来所有功劳

#2


6  

Proper combination is :

适当的组合是:

-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault

There's proguard configuration prepared by Google for project google-api-java-client

Google为项目google-api-java-client准备了proguard配置

https://github.com/google/google-api-java-client/blob/57fe35766cbba0a0d5a9a296be81468d730a29f8/google-api-client-assembly/proguard-google-api-client.txt

#3


1  

First -keeping a class does not mean to not touch it. It means do not change its name, and use it as a basis for determining if other classes are not referenced & can be deleted.

第一级课并不意味着不接触它。这意味着不要更改其名称,并将其用作确定是否未引用其他类并可以删除的基础。

Optimization still occurs, which is likely your problem. Next step I would do is try with: -dontoptimize

优化仍然会发生,这可能是你的问题。我要做的下一步是尝试:-dontoptimize

This should cause your other optimizations to be ignored.

这应该会导致您的其他优化被忽略。

BTW, not sure what version of SDK you are using. Am using 15, 20 is latest, and a proguard-project.txt file is create with the project. The optimization options it uses is:

顺便说一句,不知道你使用的是哪个版本的SDK。使用15,20是最新的,并且使用项目创建proguard-project.txt文件。它使用的优化选项是:

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*

If turning off optimization gets it running, maybe turning off all the optimizations (that's what ! does) the SDK does, will allow you to do optimization as well.

如果关闭优化使其运行,可能关闭SDK所做的所有优化(那就是!),也可以让你进行优化。

#4


0  

The method Types.getSuperParameterizedType relies on information about generics. Generics are erased in Java. The compiler only adds them as annotation attributes, the JVM ignores them, and ProGuard discards them unless you tell it not to. So this might help:

Types.getSuperParameterizedType方法依赖于有关泛型的信息。泛型在Java中被删除。编译器只将它们添加为注释属性,JVM忽略它们,ProGuard会丢弃它们,除非你告诉它不要。所以这可能有所帮助:

-keepattributes *Annotation*

#5


0  

does your code use any thing that implement Serializable? All of those need to be excluded too.

您的代码是否使用任何实现Serializable的东西?所有这些都需要被排除在外。

#6


0  

There have been few update to GooglePlayServices lately. I don't like the new API. I had the same problems.

最近GooglePlayServices的更新很少。我不喜欢新的API。我遇到了同样的问题。

I couldn't compile signed app with proguard. Proguard template from Google didn't work for me.

我无法使用proguard编译已签名的应用程序。谷歌的Proguard模板对我不起作用。

I add these four lines to my proguard config and it is working:

我将这四行添加到我的proguard配置中,它正在工作:

-dontwarn com.google.android.gms.**
-keep interface com.google.** { *; }
-keep class * extends com.google.api.client.json.GenericJson {*;}
-keep class com.google.api.services.drive.** {*;}

This is strange. Previous version of google-api-services-drive-v2 compiled without any problems.

这很奇怪。以前版本的google-api-services-drive-v2编译没有任何问题。

I'm using the latest version at the moment: google-api-services-drive-v2-rev47-1.12.0-beta.jar

我目前正在使用最新版本:google-api-services-drive-v2-rev47-1.12.0-beta.jar