如何在应用程序在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); }
资源
首先,您将不得不创builddebug
和release
构build变体,然后使用布尔值设置variables。 然后,您将需要从您的java文件中获取该值,该文件扩展了application
即从启用Fabric
崩溃报告的位置开始。
代码示例如下。
在您的应用程序的build.gradle
文件中,添加以下行来创build2个构build变体debug
和release
,然后添加一个带有布尔值的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最糟糕的解决方法是重置DefaultUncaughtExceptionHandler
( https://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); } }