Google Drive API nie gra dobrze z ProGuard (NPE)

Obecnie mam doświadczenie, że kawałek kodu, który korzysta z Google Drive API działa dobrze bez wprowadzania ProGuard.

Jednak po wprowadzeniu ProGuard, dostaję następujący błąd czasu wykonania.

    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)

Uwaga, awaria dzieje się na moim kodzie (który jest com.jstock.c. b. a jeśli odtworzę za pomocą mapowania.txt)

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

W moim proguard, myślałem, że mając następujące 2 Kluczowe instrukcje, w stanie zapobiec awarii od: mówię ProGuard nigdy nie dotykać jackson i Google libraries.

-keep class org.codehaus.** { *; }
-keep class com.google.** { *; }
-keep interface org.codehaus.** { *; }
-keep interface com.google.** { *; }
Ale to nie działa. NPE nadal występują w typach .java

Zauważ, że miałem kolejną próbę, myślałem, że obfuscate proces powoduje, że NPE się dzieje. Dlatego staram się go wyłączyć za pomocą -dontobfuscate. Ale tym razem Nie będę w stanie wygenerować pliku APK i uzyskać popularnego Komunikatu o błędzie: Konwersja do formatu Dalvik nie powiodła się z błędem 1

Oto konfiguracja proguard powodująca NPE w 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>;
}
Czy Mogę spróbować czegoś jeszcze?

Nie jestem pewien, czy może to być spowodowane kombinacją bibliotek. (Chociaż wszystko działa całkiem dobrze bez wprowadzenia ProGuard)

Tutaj wpisz opis obrazka

Jeśli spojrzę na miejsce awarii NPE (typy.getActualParameterAtPosition(Typ.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;
}

Podejrzewam Types.getSuperParameterizedType powrót null. Więc dalej przyglądam się 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;
}

Jaka jest możliwa przyczyna, która może spowodować getSuperParameterizedType powrót null, po przetworzeniu przez ProGuard?

Author: Ali Afshar, 2013-01-19

6 answers

Dla mnie zadziałała kombinacja:

-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.** {
*;
}

To zapewniło działające rozwiązanie zgodne z proguard dla niedawnego projektu Dysku Google.

Nie można jednak przypisać sobie całego uznania za to rozwiązanie, pierwotnie znalezione pod tym linkiem tutaj

 32
Author: biddulph.r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-24 15:13:33

Właściwa kombinacja to:

- keepattributes Signature,RuntimeVisibleAnnotations, AnnotationDefault

Jest konfiguracja proguard przygotowana przez Google dla projektu google-api-java-client

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

 7
Author: lanx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-19 13:16:07

Pierwsze-prowadzenie klasy nie oznacza nie dotykania jej. Oznacza to, że nie zmieniaj jej nazwy i używaj jej jako podstawy do określania, czy inne klasy nie są odwołane i można je usunąć.

Optymalizacja nadal występuje, co jest prawdopodobnie Twoim problemem. Następnym krokiem, który chciałbym zrobić, to spróbować z: -dontoptimize

To powinno spowodować, że inne optymalizacje będą ignorowane.

BTW, Nie wiem, jakiej wersji SDK używasz. Używam 15, 20 jest najnowsze, i proguard-projekt.plik txt jest tworzenie wraz z projektem. Stosowane opcje optymalizacji to:

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

Jeśli wyłączenie optymalizacji powoduje, że działa, może wyłączenie wszystkich optymalizacji (o to chodzi ! czy) SDK robi, pozwoli Ci zrobić optymalizację, jak również.

 1
Author: Jeff Palmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-21 20:57:42

Typy metod.getSuperParameterizedType opiera się na informacjach o generykach. Generyczne są usuwane w Javie. Kompilator dodaje je tylko jako atrybuty adnotacji, JVM je ignoruje, a ProGuard je odrzuca, chyba że każesz mu tego nie robić. To może pomóc:

-keepattributes *Annotation*
 0
Author: Eric Lafortune,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-21 23:52:45

Czy twój kod używa czegoś, co implementuje Serializable? Wszystkie one również muszą zostać wykluczone.

 0
Author: Ray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-22 20:45:55

Ostatnio było kilka aktualizacji do GooglePlayServices. Nie podoba mi się nowe API. Miałem te same problemy.

Nie mogłem skompilować podpisanej aplikacji z proguard. Szablon Proguard od Google nie działał dla mnie.

Dodaję te cztery linie do mojego ProGuard config i działa:

-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.** {*;}
To dziwne. Poprzednia wersja google-api-services-drive-v2 skompilowana bez żadnych problemów.

Używam najnowszej wersji w tej chwili: google-api-services-drive-v2-rev47-1.12.0-beta.jar

 0
Author: adek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-08 09:44:25