如何在应用程序在debugging时运行时禁用Firebase崩溃报告?

我已经成功实现了Firebase崩溃报告,但是我需要在应用程序运行时取消该服务,以撤消“debugging”Build Variant,以避免在开发过程中发生非实际的崩溃。

官方文件没有提到这一点。

更新:使用Google Play服务/ Firebase 11+,您现在可以在运行时禁用崩溃报告。 FirebaseCrash.setCrashCollectionEnabled() (谢谢@Tyler Carberry )

老解答:

就社区所能猜测的来说,没有官方的支持。 我build议这样做的最好方法是在仪表板中设置多个Firebase应用程序,每个构buildtypes一个,并根据构build版本设置多个指向每个不同应用程序的google_services.json文件。

使用Google Play Services 11.0,您现在可以在运行时禁用崩溃报告。

 FirebaseCrash.setCrashCollectionEnabled(!BuildConfig.DEBUG); 

在我的应用程序类中,onCreate()

 if (BuildConfig.DEBUG) { Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread paramThread, Throwable paramThrowable) { Log.wtf("Alert", paramThrowable.getMessage(), paramThrowable); System.exit(2); //Prevents the service/app from freezing } }); } 

这是因为它采用了包含Firebase的旧处理程序

  final UncaughtExceptionHandler oldHandler = Thread.getDefaultUncaughtExceptionHandler(); 

走出处理path

您可以将Firebase崩溃依赖项更改为仅发布依赖项。

为此,可以将其定义为releaseCompile依赖项

 releaseCompile 'com.google.firebase:firebase-crash:9.4.0' 

现在只会包含在发布版本中。 如果您有其他需要崩溃报告的自定义生成types,则可以将其添加到它们。

 customBuildTypeCompile 'com.google.firebase:firebase-crash:9.4.0' 

受到这个相关答案和其他人的启发,我想出了这个方便的解决scheme。

使用Timber进行日志logging,我为debugging和发布版本创build了一个Tree子类的不同实现。 在debugging中,它遵循写入logcat的DebugTree。 在发行版中,它将exception和高优先级日志转发给Firebase,其余部分则放弃。

的build.gradle

 dependencies { ... compile 'com.jakewharton.timber:timber:4.3.0' releaseCompile 'com.google.firebase:firebase-crash:9.0.2' } 

SRC /debugging/ JAVA / [包] /ForestFire.java

 import timber.log.Timber; public class ForestFire extends Timber.DebugTree {} 

的src /释放/ JAVA / [包] /ForestFire.java

 import android.util.Log; import com.google.firebase.crash.FirebaseCrash; import timber.log.Timber; public class ForestFire extends Timber.Tree { @Override protected void log(int priority, String tag, String message, Throwable t) { if (Log.WARN <= priority) { FirebaseCrash.log(message); if (t != null) { FirebaseCrash.report(t); } } } } 

应用程序启动

 Timber.plant(new ForestFire()); 

我使用的简单而简单的技巧是只在build.gradle文件中添加发布版本中的build.gradle崩溃报告依赖build.gradle

这将从debugging版本types中移除崩溃报告库,并仅在发布版本中添加。

 dependencies { releaseCompile 'com.google.firebase:firebase-crash:10.2.0' } 

首先初始化gradle文件中的variables,并检查它是处于debugging还是处于释放模式。 提交崩溃报告的最好方法是在Application类中。

的build.gradle

  buildTypes { release { buildConfigField "Boolean", "REPORT_CRASH", '"true"' debuggable false } debug { buildConfigField "Boolean", "REPORT_CRASH", '"false"' debuggable true } } 

现在先检查模式,如果崩溃,则提交崩溃报告。

Application.java

  /** Report FirebaseCrash Exception if application crashed*/ Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException (Thread thread, Throwable e) { /** Check whether it is development or release mode*/ if(BuildConfig.REPORT_CRASH) { FirebaseCrash.report( e); } } }); 

最近推出了以官方方式禁用Firebase崩溃报告的可能性。 您需要将Firebase Android SDK升级到至less11.0.0版本

为了做到这一点,你需要编辑你的AndroidManifest.xml并添加:

 <meta-data android:name="firebase_crash_collection_enabled" android:value="false" /> 

<application>块内。

您可以使用FirebaseCrash.isCrashCollectionEnabled()检查是否在运行时启用了Firebase崩溃报告。

下面是一个完整的示例,在您的debugging版本中禁用Firebase崩溃报告。

build.gradle

 ... buildTypes { release { ... resValue("bool", "FIREBASE_CRASH_ENABLED", "true") } debug { ... resValue("bool", "FIREBASE_CRASH_ENABLED", "false") } } ... dependencies { ... compile "com.google.firebase:firebase-core:11.0.0" compile "com.google.firebase:firebase-crash:11.0.0" ... } 

AndroidManifest.xml

  <application> <meta-data android:name="firebase_crash_collection_enabled" android:value="@bool/FIREBASE_CRASH_ENABLED"/> ... 

目前,您无法停用Firebase崩溃报告function,但可以停用Firebase分析function。

因此,一种方法是在同一个Firebase项目中创build另一个具有不同ID的应用程序。 在此之后,您只需更改appID以启用或禁用Firebase崩溃报告。 为了我的方便,我创build了两个应用程序:

AppID:com.android – 用于发布构buildtypes

AppID:com.android.debug – 用于debugging构buildtypes

请按照以下链接了解更多详情:

https://firebase.googleblog.com/2016/08/organizing-your-firebase-enabled-android-app-builds.html

编辑:有一个更好的方法来使用不同的applicationIddebugging构buildtypes –

 android { ... buildTypes { debug { applicationIdSuffix ".debug" } } } 

查看链接了解更多详情:

https://developer.android.com/studio/build/application-id.html

对于FirebaseAnalytics类。
禁用集合: setAnalyticsCollectionEnabled(false);
启用集合: setAnalyticsCollectionEnabled(true); 或在应用程序标记中写入AndroidManifest.xml<meta-data android:name="firebase_analytics_collection_enabled" android:value="false" />

可能的用途:

 if (BuildConfig.DEBUG){ //disable for debug mFirebaseAnalytics.setAnalyticsCollectionEnabled(false); } 

资源

首先,您将不得不创builddebugrelease构build变体,然后使用布尔值设置variables。 然后,您将需要从您的java文件中获取该值,该文件扩展了application即从启用Fabric崩溃报告的位置开始。

代码示例如下。

在您的应用程序的build.gradle文件中,添加以下行来创build2个构build变体debugrelease ,然后添加一个带有布尔值的variables。

 defaultConfig { buildConfigField 'boolean', 'ENABLE_ANALYTICS', 'true' } buildTypes { debug { applicationIdSuffix ".debug" versionNameSuffix 'DEBUG' buildConfigField 'boolean', 'ENABLE_ANALYTICS', 'false' } release { minifyEnabled false } } 

然后,当您尝试添加Fabric崩溃报告时,请检查ENABLE_ANALYTICS的值

公共类Test扩展应用程序{

 private GoogleAnalytics googleAnalytics; private static Tracker tracker; @Override public void onCreate() { super.onCreate(); if (BuildConfig.ENABLE_ANALYTICS) Fabric.with(this, new Crashlytics()); } } 

您可以通过按ctrl +点击值来查看ENABLE_ANALYTICS的值。 希望这可以帮助。

我使用versionCode作为本地/生产版本的filter。

gradle.properties

 VERSION_CODE=1 

应用程序/的build.gradle

 android { defaultConfig { versionCode VERSION_CODE as int } } 

发布新版本的应用程序时,只需从命令行设置新的值:

 ./gradlew build -PVERSION_CODE=new_value 

否则,从Android Studio构build时,您将始终使用相同的versionCode ,因此您可以轻松地在Firebase控制台中区分崩溃报告。

如前所述 – 没有正式的方法来做到这一点。 但是对于我所提到的@ mark-d最糟糕的解决方法是重置DefaultUncaughtExceptionHandlerhttps://stackoverflow.com/a/39322734/4245651 )。

但是,如果您只是按照build议调用System.exit(2) – 应用程序将立即closuresexception,没有任何对话框消息和难以获取debugging日志。 如果这对你很重要,有一种方法可以恢复默认处理程序:

 if (BuildConfig.DEBUG) { final Thread.UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler(); if (currentHandler.getClass().getPackage().getName() .startsWith("com.google.firebase")) { final Thread.UncaughtExceptionHandler defaultHandler = getPrivateFieldByType(currentHandler, Thread.UncaughtExceptionHandler.class); Thread.setDefaultUncaughtExceptionHandler(defaultHandler); } } 

哪里

 public static <T> T getPrivateFieldByType(Object obj, Class<T> fieldType) { if (obj != null && fieldType != null) { for (Field field : obj.getClass().getDeclaredFields()) { if (field.getType().isAssignableFrom(fieldType)) { boolean accessible = field.isAccessible(); if (!accessible) field.setAccessible(true); T value = null; try { //noinspection unchecked value = (T) field.get(obj); } catch (IllegalAccessException e) { e.printStackTrace(); } if (!accessible) field.setAccessible(false); return value; } } } return null; } 
 public class MyApp extends Application { public static boolean isDebuggable; public void onCreate() { super.onCreate(); isDebuggable = (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)); FirebaseCrash.setCrashCollectionEnabled(!isDebuggable); } }