26

現在、私は、Google Drive APIを利用するコードが、ProGuardを導入しなくても正常に実行されていることを経験しています。

ただし、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)

クラッシュは私のコードで発生することに注意してください(mapping.txtを使用してリトレースするとcom.jstock.cbaになります)

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

私のプロガードでは、クラッシュの発生を防ぐことができる次の2つの重要な指示があると思いました。プロガードはジャクソンとGoogleのライブラリには絶対に触れないように言っています。

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

しかし、それはうまくいきません。NPEはTypes.javaで引き続き発生します

注意してください、私は別の試みをしました、私は難読化されたプロセスがNPEを引き起こすと思ったということです。したがって、を使用して無効にしようとし-dontobfuscateます。しかし、今回はAPKファイルを生成できず、一般的なエラーメッセージが表示されます:Dalvik形式への変換がエラー1で失敗しました

これは、GoogleドライブAPIでNPEを引き起こすプロガード構成です。

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

他に試すことができるものはありますか?

ライブラリの組み合わせが原因かどうかはわかりません。(ただし、ProGuardを導入しなくても問題はありません)

ここに画像の説明を入力してください

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

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

ProGuardによって処理された後、getSuperParameterizedType戻る原因となる可能性のある根本的な原因は何ですか?null

4

6 に答える 6

35

以下の組み合わせが私のために働いた:

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

これにより、最近のGoogleドライブプロジェクトに有効なプロガード互換ソリューションが提供されました。

ただし、このソリューションのすべての功績を認めることはできません。元々はこのリンクにあります。

于 2013-01-24T15:13:33.680 に答える
7

適切な組み合わせは次のとおりです。

-keepattributes Signature、RuntimeVisibleAnnotations、AnnotationDefault

プロジェクトgoogle-api-java-clientのためにGoogleによって準備されたプロガード構成があります

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

于 2013-01-30T19:43:17.943 に答える
1

まず、クラスを維持することは、それに触れないことを意味するものではありません。これは、名前を変更せず、他のクラスが参照されておらず、削除できるかどうかを判断するための基礎として使用することを意味します。

最適化は引き続き発生しますが、これが問題である可能性があります。次のステップは、次のことを試してみることです。-dontoptimize

これにより、他の最適化が無視されるはずです。

ところで、使用しているSDKのバージョンがわかりません。15、20を使用しており、最新のものであり、proguard-project.txtファイルがプロジェクトで作成されます。使用する最適化オプションは次のとおりです。

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

最適化をオフにすると実行される場合は、SDKが実行するすべての最適化(これが!)をオフにすると、最適化も実行できるようになります。

于 2013-01-21T16:47:07.490 に答える
0

メソッドTypes.getSuperParameterizedTypeは、ジェネリックスに関する情報に依存しています。ジェネリックはJavaで消去されます。コンパイラはそれらを注釈属性としてのみ追加し、JVMはそれらを無視し、ProGuardは、指示しない限りそれらを破棄します。したがって、これは役立つ可能性があります。

-keepattributes *Annotation*
于 2013-01-21T23:52:45.523 に答える
0

最近、GooglePlayServicesのアップデートはほとんどありません。新しいAPIは好きではありません。私も同じ問題を抱えていました。

署名付きアプリをproguardでコンパイルできませんでした。GoogleのProguardテンプレートは私には機能しませんでした。

これらの4行を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.** {*;}

これは奇妙です。以前のバージョンのgoogle-api-services-drive-v2は問題なくコンパイルされました。

現在、最新バージョンを使用しています:google-api-services-drive-v2-rev47-1.12.0-beta.jar

于 2013-02-08T09:44:25.610 に答える
-1

あなたのコードはSerializableを実装するものを使用していますか?それらもすべて除外する必要があります。

于 2013-01-22T20:45:55.520 に答える