-
Notifications
You must be signed in to change notification settings - Fork 565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update crashlytics global data collection #1434
Changes from all commits
7eb1b44
89cb018
c29b842
811732e
09da19b
ffb1c77
d6ea273
48deb69
4f2068b
e29abd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -463,4 +463,23 @@ public boolean didCrashOnPreviousExecution() { | |
public void setCrashlyticsCollectionEnabled(boolean enabled) { | ||
core.setCrashlyticsCollectionEnabled(enabled); | ||
} | ||
|
||
/** | ||
* Enables/disables/clears automatic data collection config by Crashlytics. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest replacing line 468 with: "* Allows you to enable or disable the automatic data collection configuration in Crashlytics." |
||
* | ||
* <p>If this is set, it overrides the data collection settings provided by the Android Manifest, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest replacing lines 470 and 471 with: "* If not set, defaults to |
||
* as well as any Firebase-wide automatic data collection settings. | ||
* | ||
* <p>If automatic data collection is disabled for Crashlytics, crash reports are stored on the | ||
* device. To check for reports, use the {@link #checkForUnsentReports()} method. Use {@link | ||
* #sendUnsentReports()} to upload existing reports even when automatic data collection is | ||
* disabled. Use {@link #deleteUnsentReports()} to delete any reports stored on the device without | ||
* sending them to Crashlytics. | ||
* | ||
* @param enabled whether to enable automatic data collection. The value of null would clear the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest replacing line 479 with: " |
||
* Crashlytics config and the enablement of data collection would depend on other settings. | ||
*/ | ||
public void setCrashlyticsCollectionEnabled(@Nullable Boolean enabled) { | ||
core.setCrashlyticsCollectionEnabled(enabled); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,15 +29,15 @@ public class DataCollectionArbiter { | |
private static final String FIREBASE_CRASHLYTICS_COLLECTION_ENABLED = | ||
"firebase_crashlytics_collection_enabled"; | ||
|
||
private final SharedPreferences sharedPreferences; | ||
private final FirebaseApp firebaseApp; | ||
|
||
// State for waitForDataCollectionEnabled(). | ||
private Object taskLock = new Object(); | ||
private final Object taskLock = new Object(); | ||
TaskCompletionSource<Void> dataCollectionEnabledTask = new TaskCompletionSource<>(); | ||
boolean taskResolved = false; | ||
|
||
private final SharedPreferences sharedPreferences; | ||
private volatile boolean crashlyticsDataCollectionExplicitlySet; | ||
private volatile boolean crashlyticsDataCollectionEnabled; | ||
private final FirebaseApp firebaseApp; | ||
private Boolean crashlyticsDataCollectionEnabled; | ||
|
||
/** | ||
* A Task that will be resolved when explicit data collection permission is granted by calling | ||
|
@@ -47,43 +47,17 @@ public class DataCollectionArbiter { | |
new TaskCompletionSource<>(); | ||
|
||
public DataCollectionArbiter(FirebaseApp app) { | ||
this.firebaseApp = app; | ||
Context applicationContext = app.getApplicationContext(); | ||
if (applicationContext == null) { | ||
throw new RuntimeException("null context"); | ||
} | ||
final Context applicationContext = app.getApplicationContext(); | ||
|
||
firebaseApp = app; | ||
sharedPreferences = CommonUtils.getSharedPrefs(applicationContext); | ||
|
||
boolean enabled = true; | ||
boolean explicitlySet = false; | ||
|
||
if (sharedPreferences.contains(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED)) { | ||
enabled = sharedPreferences.getBoolean(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED, true); | ||
explicitlySet = true; | ||
} else { | ||
try { | ||
final PackageManager packageManager = applicationContext.getPackageManager(); | ||
if (packageManager != null) { | ||
final ApplicationInfo applicationInfo = | ||
packageManager.getApplicationInfo( | ||
applicationContext.getPackageName(), PackageManager.GET_META_DATA); | ||
if (applicationInfo != null | ||
&& applicationInfo.metaData != null | ||
&& applicationInfo.metaData.containsKey(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED)) { | ||
enabled = applicationInfo.metaData.getBoolean(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED); | ||
explicitlySet = true; | ||
} | ||
} | ||
} catch (PackageManager.NameNotFoundException e) { | ||
// This shouldn't happen since it's this app's package, but fall through to default | ||
// if so. | ||
Logger.getLogger().d("Unable to get PackageManager. Falling through", e); | ||
} | ||
Boolean dataCollectionEnabled = getDataCollectionValueFromSharedPreferences(sharedPreferences); | ||
if (dataCollectionEnabled == null) { | ||
dataCollectionEnabled = getDataCollectionValueFromManifest(applicationContext); | ||
} | ||
|
||
crashlyticsDataCollectionEnabled = enabled; | ||
crashlyticsDataCollectionExplicitlySet = explicitlySet; | ||
crashlyticsDataCollectionEnabled = dataCollectionEnabled; | ||
|
||
synchronized (taskLock) { | ||
if (isAutomaticDataCollectionEnabled()) { | ||
|
@@ -93,27 +67,21 @@ public DataCollectionArbiter(FirebaseApp app) { | |
} | ||
} | ||
|
||
public boolean isAutomaticDataCollectionEnabled() { | ||
if (crashlyticsDataCollectionExplicitlySet) { | ||
return crashlyticsDataCollectionEnabled; | ||
} | ||
return firebaseApp.isDataCollectionDefaultEnabled(); | ||
} | ||
|
||
public Task<Void> waitForAutomaticDataCollectionEnabled() { | ||
synchronized (taskLock) { | ||
return dataCollectionEnabledTask.getTask(); | ||
} | ||
public synchronized boolean isAutomaticDataCollectionEnabled() { | ||
return crashlyticsDataCollectionEnabled != null | ||
? crashlyticsDataCollectionEnabled | ||
: firebaseApp.isDataCollectionDefaultEnabled(); | ||
} | ||
|
||
@SuppressLint({"CommitPrefEdits", "ApplySharedPref"}) | ||
public void setCrashlyticsDataCollectionEnabled(boolean enabled) { | ||
crashlyticsDataCollectionEnabled = enabled; | ||
crashlyticsDataCollectionExplicitlySet = true; | ||
sharedPreferences.edit().putBoolean(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED, enabled).commit(); | ||
public synchronized void setCrashlyticsDataCollectionEnabled(Boolean enabled) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can help our future selves by adding some comments here :)
mrwillis21 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
crashlyticsDataCollectionEnabled = | ||
(enabled != null) | ||
? enabled | ||
: getDataCollectionValueFromManifest(firebaseApp.getApplicationContext()); | ||
storeDataCollectionValueInSharedPreferences(sharedPreferences, enabled); | ||
|
||
synchronized (taskLock) { | ||
if (enabled) { | ||
if (isAutomaticDataCollectionEnabled()) { | ||
if (!taskResolved) { | ||
dataCollectionEnabledTask.trySetResult(null); | ||
taskResolved = true; | ||
|
@@ -127,6 +95,12 @@ public void setCrashlyticsDataCollectionEnabled(boolean enabled) { | |
} | ||
} | ||
|
||
public Task<Void> waitForAutomaticDataCollectionEnabled() { | ||
synchronized (taskLock) { | ||
return dataCollectionEnabledTask.getTask(); | ||
} | ||
} | ||
|
||
/** | ||
* Returns a task which will be resolved when either: 1) automatic data collection has been | ||
* enabled, or 2) grantDataCollectionPermission has been called. | ||
|
@@ -150,4 +124,55 @@ public void grantDataCollectionPermission(boolean dataCollectionToken) { | |
} | ||
dataCollectionExplicitlyApproved.trySetResult(null); | ||
} | ||
|
||
@SuppressLint({"ApplySharedPref"}) | ||
private static void storeDataCollectionValueInSharedPreferences( | ||
SharedPreferences sharedPreferences, Boolean enabled) { | ||
final SharedPreferences.Editor prefsEditor = sharedPreferences.edit(); | ||
if (enabled != null) { | ||
prefsEditor.putBoolean(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED, enabled); | ||
} else { | ||
prefsEditor.remove(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED); | ||
} | ||
prefsEditor.commit(); | ||
} | ||
|
||
private static Boolean getDataCollectionValueFromSharedPreferences( | ||
SharedPreferences sharedPreferences) { | ||
if (sharedPreferences.contains(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED)) { | ||
return sharedPreferences.getBoolean(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED, true); | ||
} | ||
return null; | ||
} | ||
|
||
private static Boolean getDataCollectionValueFromManifest(Context applicationContext) { | ||
final Boolean manifestSetting = | ||
readCrashlyticsDataCollectionEnabledFromManifest(applicationContext); | ||
if (manifestSetting == null) { | ||
return null; | ||
} | ||
return Boolean.TRUE.equals(manifestSetting); | ||
} | ||
|
||
private static Boolean readCrashlyticsDataCollectionEnabledFromManifest( | ||
Context applicationContext) { | ||
try { | ||
final PackageManager packageManager = applicationContext.getPackageManager(); | ||
if (packageManager != null) { | ||
final ApplicationInfo applicationInfo = | ||
packageManager.getApplicationInfo( | ||
applicationContext.getPackageName(), PackageManager.GET_META_DATA); | ||
if (applicationInfo != null | ||
&& applicationInfo.metaData != null | ||
&& applicationInfo.metaData.containsKey(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED)) { | ||
return applicationInfo.metaData.getBoolean(FIREBASE_CRASHLYTICS_COLLECTION_ENABLED); | ||
} | ||
} | ||
} catch (PackageManager.NameNotFoundException e) { | ||
// This shouldn't happen since it's this app's package, but fall through to default | ||
// if so. | ||
Logger.getLogger().d("Unable to get PackageManager. Falling through", e); | ||
} | ||
return null; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you split this up into separate tests that express the conditions they check?