Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Drive API doesn't play well with ProGuard (NPE)

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

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

    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)

// 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.

-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

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

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

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

enter image description here

If I look at the NPE crash location (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.

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?

like image 461
Cheok Yan Cheng Avatar asked Jan 19 '13 02:01

Cheok Yan Cheng


1 Answers

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.

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

like image 154
biddulph.r Avatar answered Oct 09 '22 08:10

biddulph.r