I am using com.crashlytics.sdk.android:crashlytics:2.3.2#aar version of crashlytics and i disable crash reporting if user opt out.
I tried this solution but still it is not working, crash reports are still being sent to Fabric.
I am doing it as:
Preference errorReportingEnabled = findPreference(MatlistanPrefs.BUGREPORTS_SEND_AUTOMATICALLY);
errorReportingEnabled.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Boolean value = (Boolean) newValue;
Fabric.with(DataCollectionSettingsActivity.this, new Crashlytics.Builder().
core(new CrashlyticsCore.Builder().disabled(!value).build())
.build());
return true;
}
});
Is there any working solution for this problem?
Thanks.
Fabric on initialization creates a singleton instance and returns same instance whenever you call Fabric.with(...). So, your code inside onPreferenceChangehas no effect on Fabric class.
The only solution to this problem can be if library itself provide methods for enabling or disabling crashlytics. So, up-till now (crashlytics:2.5.2) there is no solution to enable/disable crashlytics at run-time. You have to do it at startup like this:
Fabric.with(this, new Crashlytics.Builder()
.core(new CrashlyticsCore.Builder()
.disabled(true).build()).build());
Related
I have Firebase Crashlytics completely operational, and I'm using the CrashlyticsListener with crashlyticsDidDetectCrashDuringPreviousExecution() method to display a pop up when the app restarts after the crash.
I can't seem to find a way to access the custom keys and/or the stacktrace from the crash to display to the end-user. I've scoured through here and can't find anyone else wanting to do the same as me.
Can anyone please help?
final CrashlyticsListener listener = new CrashlyticsListener() {
#Override
public void crashlyticsDidDetectCrashDuringPreviousExecution() {
AlertDialog.Builder adb = new AlertDialog.Builder(BaseActivity.this);
adb.setTitle("ERROR!");
adb.setMessage(**WOULD LIKE STACKTRACE HERE/OR SOME CUSTOM KEYS THAT WERE SET AT CRASH INIT**);
adb.setPositiveButton("DISMISS", null);
AlertDialog ad = adb.create();
ad.show();
}
};
It is not possible to get any data form the previous crash report, although what you can provide are the custom keys from the current session, assuming they are always same for a particular user.
With Google sending out waves of warnings about the need to let users opt-in to crash reporting (source) I'm trying to build an opt-in dialog for Firebase Crashlytics.
To be able to do this I would need to know whether Crashlytics is currently enabled (to decide whether to show the dialog or not). It seems CrashlyticsCore.disabled is responsible for tracking this but I haven't found any way to access the value because it's package private and doesn't have an accessor. How can I know during runtime if Firebase Crashlytics is enabled?
The second thing I'd need to do is disable crash reporting by default and enable it when the user agrees to opt-in. How I suspected to be able to do this:
AndroidManifest:
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false" />
Activity:
boolean userAgrees = true;
CrashlyticsCore core = new CrashlyticsCore.Builder().disabled(!userAgrees).build();
Fabric.with(this, new Crashlytics.Builder().core(core).build());
throw new RuntimeException("why doesn't this show up in Firebase Crashlytics?");
Why isn't my RuntimeException showing up in Firebase Crashlytics?
P.S. Crashlytics is working fine when removing these attempts to create an opt-in dialog.
It seems toggling Crashlytics will only take effect after your app restarts. Fabric is a singleton and all calls to its Fabric.with method will simply be ignored after it's been initialized. Source code below.
public static Fabric with(Context context, Kit... kits) {
if (singleton == null) {
Class var2 = Fabric.class;
synchronized(Fabric.class) {
if (singleton == null) {
setFabric((new Fabric.Builder(context)).kits(kits).build());
}
}
}
return singleton;
}
One way around it is to keep track of the value yourself using SharedPreferences or other persistent storage methods and update your UI accordingly.
Is it possible to lazily initialize Fabric Kits? for example, right now I do:
Fabric.with(this, crashlytics, twitterCore, tweetUi); // 500ms
I would like to initialize only Crashlytics (no twitter stuff), like below, because it is 10x faster, and I don't need the Twitter stuff right away
Fabric.with(this, crashlytics); // 50ms
Later on, when the user visits an activity where I need TwitterCore & TweetUi, I'd like to add them to Fabric on the fly before using them.
Is this possible ?
Edit: I managed to do it with reflection, which is obviously not ideal, but it works for the time being. I'm still looking for a proper solution to this. Here's how I did it:
try {
final Fabric newFabric = (new Fabric.Builder(context)).kits(crashlytics, twitterCore, tweetUi).build();
final Method method = Fabric.class.getDeclaredMethod("setFabric", Fabric.class);
method.setAccessible(true);
method.invoke(null, newFabric);
} catch (Exception e) {
Timber.e(e, e.getMessage());
}
You can use builder pattern for the initialisation and can disable the crash reporting in debug mode:
CrashlyticsCore core =
new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build();
Fabric.with(this, new Crashlytics.Builder().core(core).build(), new Crashlytics());
Update 1: Add more Kit afterwards or Lazy initialization of Fabric kits?:
CrashlyticsCore core =
new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build();
//Store the below fabric as an instance member
Fabric fabric = Fabric.with(this, new Crashlytics.Builder().core(core).build(), new Crashlytics
());
//To add later:
fabric.getKits().add(YOUR_NEW_KIT);
Mike from Fabric here. Currently, we only respect the first initialization of Fabric. One option would to be initialize everything up front or if you're ok for missing some crashes, not initialize Twitter and Crashlytics until later in your app's code.
I want to initialise CrashlyticsCore, which just has error reporting, not Crashlytics, which has automatic built in usage reporting.
I have found this answer:
How do i initialize the new version of crashlytics?
Which says to do this:
Fabric.with(this, new CrashlyticsCore.getInstance());
I am not sure whether the "new" keyword is meant to be there. However, with or without "new", it gives the following error:
java.lang.IllegalStateException: Must Initialize Fabric before using singleton()
Does anyone know how to just initialise CrashlyticsCore without Crashlytics?
You can try the answer in this thread
Fabric.with(this, new Crashlytics.Builder().core(new CrashlyticsCore.Builder().build()).build());
Or you can create a method that only enables sending Answer events based on a boolean flag:
public static void logCustom(boolean isEnabled, String eventText) {
if (isEnabled) {
Answers.getInstance().logCustom(new CustomEvent(eventText));
}
}
According to the terms for Google analytics you need to provide the user with a option to opt out of the tracking. But I feel, documentation is not very clear on how to do that. This what I got so far.
GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);
Tracker t = analytics.newTracker(R.xml.tracker);
t.enableAdvertisingIdCollection(false);
t.enableAutoActivityTracking(false);
t.enableExceptionReporting(false);
Will this disable all tracking including events like this.
t.send(new HitBuilders.EventBuilder()
.setCategory("category")
.setAction("test")
.setLabel("label")
.build());
If not how do I completely disable tracking during run on user device?
You need to use GoogleAnalytics.getInstance(this).setAppOptOut(true);.
In Google Analytics documentation(1), there is simple example with shared preferences.
SharedPreferences userPrefs = PreferenceManager.getDefaultSharedPreferences(this);
userPrefs.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener () {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(TRACKING_PREF_KEY)) {
GoogleAnalytics.getInstance(getApplicationContext()).setAppOptOut(sharedPreferences.getBoolean(key, false));
} else {
// Any additional changed preference handling.
}
}
});
Note: This is different from disabling Google Analytics during testing / development. If your aim is to disable during test/development, use (2)
GoogeAnalytics.getInstance(this).setDryRun(true);
You can set a SharedPreference setting and if the user opt-out Analytics tracking you don't send the Analytics update.