2018-02-22 13:30:36 +01:00
|
|
|
package info.nightscout.utils;
|
|
|
|
|
|
|
|
import com.crashlytics.android.Crashlytics;
|
|
|
|
import com.crashlytics.android.answers.Answers;
|
|
|
|
import com.crashlytics.android.answers.CustomEvent;
|
2018-08-17 10:27:46 +02:00
|
|
|
|
2018-07-09 23:05:48 +02:00
|
|
|
import info.nightscout.androidaps.BuildConfig;
|
2018-07-10 17:55:50 +02:00
|
|
|
import info.nightscout.androidaps.Config;
|
2018-07-09 23:05:48 +02:00
|
|
|
import info.nightscout.androidaps.MainApp;
|
|
|
|
import info.nightscout.androidaps.R;
|
|
|
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
|
|
|
|
|
|
|
import java.util.Date;
|
2018-02-22 13:30:36 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Created by jamorham on 21/02/2018.
|
2018-08-17 10:27:46 +02:00
|
|
|
* <p>
|
2018-02-22 13:30:36 +01:00
|
|
|
* Some users do not wish to be tracked, Fabric Answers and Crashlytics do not provide an easy way
|
|
|
|
* to disable them and make calls from a potentially invalid singleton reference. This wrapper
|
|
|
|
* emulates the methods but ignores the request if the instance is null or invalid.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class FabricPrivacy {
|
|
|
|
|
|
|
|
private static final String TAG = "FabricPrivacy";
|
|
|
|
private static volatile FabricPrivacy instance;
|
|
|
|
|
|
|
|
|
|
|
|
public static FabricPrivacy getInstance() {
|
|
|
|
if (instance == null) {
|
|
|
|
initSelf();
|
|
|
|
}
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static synchronized void initSelf() {
|
|
|
|
if (instance == null) {
|
|
|
|
instance = new FabricPrivacy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Crashlytics logException
|
|
|
|
public static void logException(Throwable throwable) {
|
|
|
|
try {
|
|
|
|
final Crashlytics crashlytics = Crashlytics.getInstance();
|
|
|
|
crashlytics.core.logException(throwable);
|
|
|
|
} catch (NullPointerException | IllegalStateException e) {
|
|
|
|
android.util.Log.d(TAG, "Ignoring opted out non-initialized log: " + throwable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Crashlytics log
|
|
|
|
public static void log(String msg) {
|
|
|
|
try {
|
|
|
|
final Crashlytics crashlytics = Crashlytics.getInstance();
|
|
|
|
crashlytics.core.log(msg);
|
|
|
|
} catch (NullPointerException | IllegalStateException e) {
|
|
|
|
android.util.Log.d(TAG, "Ignoring opted out non-initialized log: " + msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Crashlytics log
|
|
|
|
public static void log(int priority, String tag, String msg) {
|
|
|
|
try {
|
|
|
|
final Crashlytics crashlytics = Crashlytics.getInstance();
|
|
|
|
crashlytics.core.log(priority, tag, msg);
|
|
|
|
} catch (NullPointerException | IllegalStateException e) {
|
|
|
|
android.util.Log.d(TAG, "Ignoring opted out non-initialized log: " + msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean fabricEnabled() {
|
|
|
|
return SP.getBoolean("enable_fabric", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Answers logCustom
|
|
|
|
public void logCustom(CustomEvent event) {
|
|
|
|
try {
|
|
|
|
final Answers answers = Answers.getInstance();
|
|
|
|
if (fabricEnabled()) {
|
|
|
|
answers.logCustom(event);
|
|
|
|
} else {
|
|
|
|
android.util.Log.d(TAG, "Ignoring recently opted-out event: " + event.toString());
|
|
|
|
}
|
|
|
|
} catch (NullPointerException | IllegalStateException e) {
|
|
|
|
android.util.Log.d(TAG, "Ignoring opted-out non-initialized event: " + event.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-11 20:19:42 +02:00
|
|
|
public static void uploadDailyStats() {
|
2018-07-10 17:55:50 +02:00
|
|
|
if (!fabricEnabled()) return;
|
2018-07-09 23:05:48 +02:00
|
|
|
|
|
|
|
long lastUploadDay = SP.getLong(MainApp.gs(R.string.key_plugin_stats_report_timestamp), 0L);
|
|
|
|
|
|
|
|
Date date = new Date();
|
|
|
|
date.setHours(0);
|
|
|
|
date.setMinutes(0);
|
|
|
|
date.setSeconds(0);
|
|
|
|
long today = date.getTime() - date.getTime() % 1000;
|
|
|
|
|
|
|
|
if (today > lastUploadDay) {
|
2018-07-11 20:19:42 +02:00
|
|
|
uploadAppUsageType();
|
|
|
|
uploadPluginStats();
|
|
|
|
|
2018-07-09 23:05:48 +02:00
|
|
|
SP.putLong(MainApp.gs(R.string.key_plugin_stats_report_timestamp), today);
|
|
|
|
}
|
|
|
|
}
|
2018-07-11 20:19:42 +02:00
|
|
|
|
|
|
|
private static void uploadPluginStats() {
|
|
|
|
CustomEvent pluginStats = new CustomEvent("PluginStats");
|
|
|
|
pluginStats.putCustomAttribute("version", BuildConfig.VERSION);
|
2018-08-27 20:19:30 +02:00
|
|
|
pluginStats.putCustomAttribute("HEAD", BuildConfig.HEAD);
|
2018-10-04 23:04:32 +02:00
|
|
|
pluginStats.putCustomAttribute("language", SP.getString(R.string.key_language,"default"));
|
2018-07-11 20:19:42 +02:00
|
|
|
for (PluginBase plugin : MainApp.getPluginsList()) {
|
2018-10-17 15:54:33 +02:00
|
|
|
if (plugin.isEnabled(plugin.getType()) && !plugin.pluginDescription.alwaysEnabled) {
|
|
|
|
// Fabric allows no more than 20 attributes attached to an event. By reporting disabled plugins as
|
|
|
|
// well, we would exceed that threshold, so only report what is enabled
|
|
|
|
// TODO >2.0: consider reworking this to upload an event per enabled plugin instead.
|
|
|
|
pluginStats.putCustomAttribute(plugin.getClass().getSimpleName(), "enabled");
|
2018-07-11 20:19:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getInstance().logCustom(pluginStats);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void uploadAppUsageType() {
|
|
|
|
CustomEvent type = new CustomEvent("AppUsageType");
|
|
|
|
if (Config.NSCLIENT)
|
|
|
|
type.putCustomAttribute("type", "NSClient");
|
|
|
|
else if (Config.PUMPCONTROL)
|
|
|
|
type.putCustomAttribute("type", "PumpControl");
|
|
|
|
else if (MainApp.getConstraintChecker().isClosedLoopAllowed().value())
|
|
|
|
type.putCustomAttribute("type", "ClosedLoop");
|
|
|
|
else
|
|
|
|
type.putCustomAttribute("type", "OpenLoop");
|
|
|
|
|
|
|
|
getInstance().logCustom(type);
|
|
|
|
}
|
|
|
|
|
2018-02-22 13:30:36 +01:00
|
|
|
}
|