已签名的应用程序崩溃且未签名的APK运行

时间:2018-07-12 16:56:12

标签: android proguard android-proguard

这个问题可能与某些SO问题有关,因为我在这里搜索了很多内容,但是没有任何帖子对我有所帮助。我的应用程序在未签名的情况下运行,但在运行已签名的APK时立即崩溃。我将它debuggable true放入了gradle并检查是否发现了此错误logcat。

java.lang.NoSuchFieldError: No static field REPLACE of type Lcom/a/a/a$a; in class Lcom/a/a/a$a; or its superclasses (declaration of 'com.a.a.a$a' appears in /data/app/com.aami.aruman.com-J1sPXkw9O_ZNL4zfcpqgMQ==/base.apk)
    at java.lang.reflect.Field.getAnnotationNative(Native Method)
    at java.lang.reflect.Field.getAnnotation(Field.java:847)
    at com.a.g.<init>(Unknown Source:94)
    at com.a.f.a(Unknown Source:97)
    at com.a.f.a(Unknown Source:126)
    at com.a.f.<init>(Unknown Source:27)
    at com.a.b.a(Unknown Source:22)
    at com.a.a.a(Unknown Source:3)
    at com.a.a.a(Unknown Source:1)
    at com.a.a.a(Unknown Source:9)
    at com.a.b.a.onCreate(Unknown Source:3)
    at com.aami.aruman.com.codingnation.base.DroiderApplication.onCreate(Unknown Source:0)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1120)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5747)
    at android.app.ActivityThread.-wrap1(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1656)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6501)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
07-12 22:22:18.355 13073-13073/com.aami.aruman.com E/UncaughtException: java.lang.NoSuchFieldError: No static field REPLACE of type Lcom/a/a/a$a; in class Lcom/a/a/a$a; or its superclasses (declaration of 'com.a.a.a$a' appears in /data/app/com.aami.aruman.com-J1sPXkw9O_ZNL4zfcpqgMQ==/base.apk)
    at java.lang.reflect.Field.getAnnotationNative(Native Method)
    at java.lang.reflect.Field.getAnnotation(Field.java:847)
    at com.a.g.<init>(Unknown Source:94)
    at com.a.f.a(Unknown Source:97)
    at com.a.f.a(Unknown Source:126)
    at com.a.f.<init>(Unknown Source:27)
    at com.a.b.a(Unknown Source:22)
    at com.a.a.a(Unknown Source:3)
    at com.a.a.a(Unknown Source:1)
    at com.a.a.a(Unknown Source:9)
    at com.a.b.a.onCreate(Unknown Source:3)
    at com.aami.aruman.com.codingnation.base.DroiderApplication.onCreate(Unknown Source:0)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1120)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5747)
    at android.app.ActivityThread.-wrap1(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1656)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6501)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

我在帖子中看到,发布build.gradle可以使错误更容易理解,所以在这里。

buildscript {
repositories {
    maven { url 'https://maven.fabric.io/public' }
}

dependencies {
    classpath 'io.fabric.tools:gradle:1.+'
 }
}

apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

repositories {
    maven { url 'https://maven.fabric.io/public' }
}


android {
    compileSdkVersion 26
    useLibrary 'org.apache.http.legacy'
    buildToolsVersion '27.0.3'
    defaultConfig {
        multiDexEnabled true
        applicationId "com.aami.aruman.com"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"


    }
    android {
        lintOptions {
            checkReleaseBuilds false
            abortOnError false
        }
        packagingOptions {
            exclude 'META-INF/DEPENDENCIES.txt'
            exclude 'META-INF/LICENSE.txt'
            exclude 'META-INF/maven/pom.properties'
            exclude 'META-INF/NOTICE.txt'
            exclude 'META-INF/NOTICE'
            exclude 'META-INF/LICENSE'
            exclude 'META-INF/DEPENDENCIES'
            exclude 'META-INF/notice.txt'
            exclude 'META-INF/license.txt'
            exclude 'META-INF/dependencies.txt'
            exclude 'META-INF/LGPL2.1'
            exclude 'META-INF/gson/FieldAttributes.class'
            exclude '.readme'
        }
    }
    buildTypes {
        release {
            debuggable true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.google.firebase:firebase-messaging:12.0.1'
    implementation 'com.android.support:appcompat-v7:26.1.+'
    implementation 'com.android.support:gridlayout-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.facebook.android:facebook-android-sdk:4.10.0'
    implementation 'com.android.support:design:26.1.+'
    implementation 'com.android.support:recyclerview-v7:26.1.0'
    implementation 'com.android.support:cardview-v7:26.1.0'
    implementation 'de.hdodenhof:circleimageview:1.3.0'
    implementation 'com.google.android.gms:play-services-places:12.0.1'
    implementation 'com.android.support:support-v4:26.1.0'
    implementation 'com.google.android.gms:play-services-maps:12.0.1'
    implementation 'com.android.volley:volley:1.1.0'
    implementation 'com.github.bumptech.glide:glide:3.7.0'
    implementation 'com.squareup.picasso:picasso:2.71828'
    implementation 'com.github.lzyzsd:circleprogress:1.2.1'
    implementation 'com.romandanylyk:pageindicatorview:0.2.0'
    implementation 'com.nshmura:snappysmoothscroller:1.0.0'
    implementation 'com.codemybrainsout.rating:ratingdialog:1.0.8'
    implementation 'org.adw.library:discrete-seekbar:1.0.1'
    implementation 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
    implementation 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    implementation 'com.google.firebase:firebase-auth:12.0.1'
    implementation 'com.google.firebase:firebase-storage:12.0.1'
    implementation 'com.google.firebase:firebase-core:12.0.1'
    implementation 'com.facebook.fresco:fresco:1.3.0'
    implementation 'com.google.android.gms:play-services-auth:12.0.1'
    implementation 'com.google.android.gms:play-services-location:12.0.1'
    implementation 'com.rengwuxian.materialedittext:library:2.1.4'
    implementation 'com.nispok:snackbar:2.11.+'
    implementation 'com.github.ybq:Android-SpinKit:1.1.0'
    implementation 'com.gmail.samehadar:iosdialog:1.0'
    implementation 'com.android.support:multidex:1.0.3'
    implementation 'joda-time:joda-time:2.9.4'
    implementation 'com.crystal:crystalrangeseekbar:1.1.3'
    implementation 'com.google.firebase:firebase-crash:12.0.1'
    implementation 'com.github.clans:fab:1.6.2'
    implementation('com.crashlytics.sdk.android:crashlytics:2.9.2@aar')      {
        transitive = true
    }
    implementation 'com.github.florent37:singledateandtimepicker:2.0.5'
    implementation 'com.getbase:floatingactionbutton:1.10.1'
    implementation 'com.payumoney.sdkui:plug-n-play:1.3.0'
    implementation 'com.amitshekhar.android:jackson-android-networking:1.0.1'
    implementation 'com.daasuu:animateHorizontalProgressBar:0.2.4'
}
apply plugin: 'com.google.gms.google-services'

最后是proguard

-dontwarn org.apache.**
-dontwarn javax.annotation.**
-dontwarn com.squareup.picasso.**
-dontwarn okio.**
-keep class com.google.**
-dontwarn com.google.**
-keepattributes Signature
-dontwarn retrofit2.Platform$Java8
# For using GSON @Expose annotation
-keepattributes *Annotation*
-dontwarn org.**
-dontwarn javax.**
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }


-keep class com.squareup.okhttp.{ *; }
-dontwarn com.squareup.okhttp.**
-keep class com.facebook.{ *; }
-dontwarn com.facebook.**
-keep class ohttp3.{ *; }
-dontwarn okhttp3.**
-keep class org.joda.{ *; }
-dontwarn org.joda.**
-keepclassmembers class * {

    private <fields>;
    }
    # Proguard configuration for Jackson 2.x (fasterxml package instead of codehaus package)
    -keep class com.fasterxml.jackson.databind.ObjectMapper {
        public <methods>;
        protected <methods>;
    }
    -keep class com.fasterxml.jackson.databind.ObjectWriter {
        public ** writeValueAsString(**);
    }
    -keepnames class com.fasterxml.jackson.** { *; }

-keepclassmembers class com.aami.aruman.com.codingnation.beans.** { *; }


-dontwarn com.fasterxml.jackson.databind.**
-dontwarn org.springframework.**

1 个答案:

答案 0 :(得分:5)

关于Proguard

Proguard通过做两件事基本上使您的代码更小,更难进行反向工程:

  1. 剥离未使用的代码
  2. 通过重命名您写成尽可能小(且难以阅读)的名称的可读符号来混淆包和符号名。

关于您的问题

看起来有些东西正在使用Java反射来查找名为REPLACE的字段,但是该字段被proguard混淆了。

从您发布的堆栈跟踪中,这:

com.a.g.<init>(Unknown Source:94)

是进行反射调用的代码。

那么com.a.g.<init>到底是什么?这是一个类的混淆名称。  <init>告诉我这是某种类的构造函数。

但是要弄清楚ag是什么,您需要在真实符号和proguard为其分配的符号之间进行某种映射。

解决方案

运行proguard时,它将生成一个符号映射文件。您可以使用Android SDK随附的proguard工具随附的retrace.sh脚本(如果您在Windows上进行开发,则可以使用retrace.bat)来模糊处理堆栈跟踪,前提是您仍然有此映射文件并弄清楚了该映射文件的位置在您的代码中。

类似的东西:

<androidsdkroot>/tools/proguard/bin/retrace.sh -verbose mapping.txt stacktrace.txt > out.txt

位置:

  • mapping.txt是proguard运行时创建的映射文件
  • stacktrace.txt包含您在问题中发布的原始堆栈跟踪
  • out.txt是用于接收未混淆的堆栈跟踪的文件名。

确定了这一点之后,就需要在Proguard配置文件中添加一个keep rule来防止混淆。或者,如果可以的话,请摆脱反射代码。

最后,如果进行反射调用的代码来自您不拥有的库,那么我会去查看该库的文档,看看它是否调用了您应该添加到proguard中的任何保留规则配置文件并添加它们。

有关解码混淆的堆栈跟踪的更多信息,请参见Android Shrink Code文档。