Android 应用程序在发布模式下启动时崩溃:java.lang.NoSuchFieldError: BUILD 错误

Posted

技术标签:

【中文标题】Android 应用程序在发布模式下启动时崩溃:java.lang.NoSuchFieldError: BUILD 错误【英文标题】:Android app crashed on launch in release mode : java.lang.NoSuchFieldError: BUILD error 【发布时间】:2016-05-05 09:07:18 【问题描述】:

我有一个应用程序,我正在为新版本更新。该应用程序在调试模式下运行良好,当我创建一个签名的 APK 并在我的设备上运行它时,它会崩溃。我检查了 logcat,以下是堆栈跟踪:

java.lang.NoSuchFieldError: BUILD
E/androidRuntime(28433):        at java.lang.Class.getDeclaredAnnotation(Native Method)
E/AndroidRuntime(28433):        at java.lang.Class.getAnnotation(Class.java:290)
E/AndroidRuntime(28433):        at org.a.a.a(SourceFile:115)
E/AndroidRuntime(28433):        at com.package.utils.MyApplication.onCreate(SourceFile:42)
E/AndroidRuntime(28433):        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1030)
E/AndroidRuntime(28433):        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4409)
E/AndroidRuntime(28433):        at android.app.ActivityThread.access$1500(ActivityThread.java:139)
E/AndroidRuntime(28433):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1270)
E/AndroidRuntime(28433):        at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(28433):        at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime(28433):        at android.app.ActivityThread.main(ActivityThread.java:5086)
E/AndroidRuntime(28433):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(28433):        at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime(28433):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
E/AndroidRuntime(28433):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
E/AndroidRuntime(28433):        at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager(  861):   Force finishing activity com.package.activities/.SplashActivity

在我的 MyApplication 文件中是这样的:

package com.package.utils;

import android.app.Application;
import android.content.Context;
import android.support.multidex.MultiDex;

import com.facebook.FacebookSdk;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.StandardExceptionParser;
import com.google.android.gms.analytics.Tracker;
import com.package.activities.R;

import org.acra.ACRA;
import org.acra.ReportField;
import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;

@ReportsCrashes(formUri = "", mailTo = AppUtils.CRASH_REPORT_EMAIL, customReportContent = ReportField.BUILD,
    ReportField.USER_APP_START_DATE, ReportField.USER_CRASH_DATE, ReportField.USER_EMAIL, ReportField.APP_VERSION_NAME,
    ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL, ReportField.CUSTOM_DATA, ReportField.STACK_TRACE,
    ReportField.LOGCAT,, mode = ReportingInteractionMode.TOAST, resToastText = R.string.crashed_report)
public class MyApplication extends Application 

public static final String TAG = MyApplication.class.getSimpleName();

private static MyApplication mInstance;
private static Context context;

public static synchronized MyApplication getInstance() 
    return mInstance;


@Override
public void onCreate() 
    super.onCreate();
    FacebookSdk.sdkInitialize(getApplicationContext());
    FacebookSdk.setApplicationId(getResources().getString(R.string.facebook_app_id));
//        MyApplication.context = getApplicationContext();
    //reference: https://github.com/ACRA/acra/wiki/BasicSetup
    //The following line triggers the initialization of ACRA
    ACRA.init(this);

    mInstance = this;

    AnalyticsTrackers.initialize(this);
    AnalyticsTrackers.getInstance().get(AnalyticsTrackers.Target.APP);


ACRA.init(this) 是行号。 42 在这个。

如何消除此错误?

编辑: 以下是我完整的 proguead 文件:

-keep class * extends java.util.ListResourceBundle 
protected Object[][] getContents();
    

-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable 
public static final *** NULL;
    
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html    #manual/usage.html

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

-keepnames class org.apache.** *;    
-keep class org.apache.** *;    
-keep class android.support.v4.**  *;     
-keep interface android.support.v4.app.**  *;     
-dontnote android.support.v4.**
-keep class org.joda.time.**  *;     
-keep interface org.joda.time.**  *;    
-keep class android.support.v7.app.**  *;     
-keep interface android.support.v7.app.**  *;     
-keep class org.acra.**  *;     

# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA 
*;


# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode 
*;


-keepnames class org.acra.sender.HttpSender$** 
*;


-keepnames class org.acra.ReportField 
*;


# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
public void addCustomData(java.lang.String,java.lang.String);
public void putCustomData(java.lang.String,java.lang.String);
public void removeCustomData(java.lang.String);


# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
public void handleSilentException(java.lang.Throwable);


-keepclassmembers class * implements java.io.Serializable
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();


-keep class com.viewpagerindicator.**  *;     
-dontskipnonpubliclibraryclassmembers

-dontwarn org.apache.commons.logging.LogFactory
-dontwarn org.apache.http.annotation.ThreadSafe
-dontwarn org.apache.http.annotation.Immutable
-dontwarn org.apache.http.annotation.NotThreadSafe
-dontwarn org.jodatime.time.**
-dontwarn org.joda.convert.**
-dontwarn org.apache.http.**
-dontwarn android.net.**
# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize
-dontpreverify

# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html    #native
-keepclasseswithmembernames class * 
native <methods>;


# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html    #beans
-keepclassmembers public class * extends android.view.View 
   void set*(***);
   *** get*();


# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity 
   public void *(android.view.View);


# For enumeration classes, see     http://proguard.sourceforge.net/manual/examples.html    #enumerations
-keepclassmembers enum * 
public static **[] values();
public static ** valueOf(java.lang.String);


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


-keepclassmembers class **.R$* 
public static <fields>;



#    #---------------Begin: proguard configuration for Gson  ----------

# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# Gson specific classes
-keep class sun.misc.Unsafe  *;     

# Application classes that will be serialized/deserialized over Gson



#    #---------------End: proguard configuration for Gson  ----------
# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * 
@com.google.android.gms.common.annotation.KeepName *;


-keepnames class * implements android.os.Parcelable 
public static final ** CREATOR;


-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

编辑 2: 我认为 ACRA 没有任何问题,因为我在从项目中删除 ACRA 后尝试签名,但错误仍然相同。

编辑 3: 经过多次尝试,我发现这个问题的原因是谷歌分析。当我在没有 Google Analytics 的情况下构建 APK 时(通过删除 MyApplication 中的最后两行 onCreate,它可以正常工作,而使用这些行时它会崩溃,并且 logcat 仍然如上所示。

【问题讨论】:

上面的stacktrace是什么版本的ACRA? 我尝试过的 2 个版本的 ACRA 以及 4.7.0 和 4.8.1 的堆栈跟踪是相同的。 没有。那是来自 acra-4.8.1 的 NOT 堆栈跟踪。它确实与 acra-4.7.0 匹配,它告诉我您的 progurded 代码已被剥离注释。 我是第一次从 android studio 创建一个签名的 APK。我不太了解这个 proguard 文件。我不明白您所说的“您的 progurded 代码已被剥夺注释”是什么意思。我只是在尝试,发现当我从项目中删除 ACRA 然后构建时,这个错误仍然存​​在。 如果您从项目中完全删除 ACRA 并且仍然出现此错误,则意味着其他库或您自己的代码已被 proguard 剥离。 【参考方案1】:

你应该为发布版本准备你的 proguard 配置。

阅读here 如何为 ACRA 设置 proguard。

将其包含在您的 proguard 配置文件中:

#ACRA specifics
# Restore some Source file names and restore approximate line numbers in the stack traces,
# otherwise the stack traces are pretty useless
-keepattributes SourceFile,LineNumberTable

# ACRA needs "annotations" so add this... 
# Note: This may already be defined in the default "proguard-android-optimize.txt"
# file in the SDK. If it is, then you don't need to duplicate it. See your
# "project.properties" file to get the path to the default "proguard-android-optimize.txt".
-keepattributes *Annotation*

# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA 
    *;


# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode 
    *;


-keepnames class org.acra.sender.HttpSender$** 
    *;


-keepnames class org.acra.ReportField 
    *;


# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter

    public void addCustomData(java.lang.String,java.lang.String);
    public void putCustomData(java.lang.String,java.lang.String);
    public void removeCustomData(java.lang.String);


# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter

    public void handleSilentException(java.lang.Throwable);

【讨论】:

我添加了上面的代码并尝试构建签名的 APK,但仍然是相同的错误日志。我正在使用 ACRA 4.7.0。【参考方案2】:

我同意 @Fiil,这看起来像是一个 proguard 错误。

我建议切换到 ACRA 4.8.1 或更高版本,因为其中包含一个 proguard 配置文件。

【讨论】:

我将我的 ACRA 库更改为 4.8.1,但仍然出现错误。我已经编辑了我的帖子以添加完整的 proguard 文件。请看一下,如果其中有问题,请告诉我。

以上是关于Android 应用程序在发布模式下启动时崩溃:java.lang.NoSuchFieldError: BUILD 错误的主要内容,如果未能解决你的问题,请参考以下文章

应用程序在飞行模式下启动时崩溃

具有 Objective-C 和 swift 代码的应用程序在发布模式下启动时崩溃,调试模式正常

Android 模拟器在 Mac 上崩溃

android 应用程序在首次尝试在发布模式下使用 Facebook sdk 共享数据时崩溃

当我在没有调试器的情况下方便地启动 Android Studio 应用程序时崩溃

Xamarin PCL Android 应用程序在发布模式下突然崩溃