From a90ae1be64688e7ec7ebb863d7b7c39e37ce5ddf Mon Sep 17 00:00:00 2001 From: gdlbo <41114720+gdlbo@users.noreply.github.com> Date: Wed, 15 Mar 2023 01:19:25 +0300 Subject: [PATCH] added appcenter metrics/crash logger --- .../lite/ui/components/CrashReporter.java | 3 + .../lite/ui/fragments/OtherFragment.java | 2 + .../lite/ui/fragments/SystemInfo.java | 3 + .../vtosters/lite/utils/AnalyticsHelper.java | 87 +++++++++++++++++++ .../ru/vtosters/lite/utils/AndroidUtils.java | 4 + .../ru/vtosters/lite/utils/Preferences.java | 2 + smali/res/xml/preferences_other.xml | 5 ++ 7 files changed, 106 insertions(+) create mode 100644 app/src/main/java/ru/vtosters/lite/utils/AnalyticsHelper.java diff --git a/app/src/main/java/ru/vtosters/lite/ui/components/CrashReporter.java b/app/src/main/java/ru/vtosters/lite/ui/components/CrashReporter.java index dc49599cd..766445f92 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/components/CrashReporter.java +++ b/app/src/main/java/ru/vtosters/lite/ui/components/CrashReporter.java @@ -21,6 +21,7 @@ import java.io.StringWriter; import ru.vtosters.lite.deviceinfo.DeviceInfoCollector; import ru.vtosters.lite.services.LogWriterService; +import ru.vtosters.lite.utils.AnalyticsHelper; import ru.vtosters.lite.utils.AndroidUtils; public class CrashReporter { @@ -41,6 +42,8 @@ public class CrashReporter { static void start(Thread.UncaughtExceptionHandler uncaughtExceptionHandler, Thread thread, Throwable th, Activity activity) { logString = getStackTrace(th) + "\n\n" + new DeviceInfoCollector().collect().toDeviceName(); + AnalyticsHelper.trackError(th); + if (Build.VERSION.SDK_INT >= 26) { var notificationChannel = new NotificationChannel("crashes", AndroidUtils.getString("crash_service_name"), NotificationManager.IMPORTANCE_DEFAULT); notificationChannel.enableVibration(true); diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java index 9674acbb1..aa1460c7d 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java @@ -206,6 +206,8 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment { return true; }); } + + findPreference("analyticsDisabled").setVisible(!AndroidUtils.isDebuggable()); } @SuppressLint({"CommitPrefEdits", "SetTextI18n"}) diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/SystemInfo.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/SystemInfo.java index 93924ece4..03339e6ec 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/SystemInfo.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/SystemInfo.java @@ -47,6 +47,7 @@ public class SystemInfo extends MaterialPreferenceToolbarFragment { var isValidSignature = Preferences.isValidSignature(); var isTablet = AndroidUtils.isTablet(); + var isDebuggable = AndroidUtils.isDebuggable(); PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "App information"); @@ -66,6 +67,8 @@ public class SystemInfo extends MaterialPreferenceToolbarFragment { PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isTablet", "Value: " + isTablet, 0, null); + PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isDebuggable", "Value: " + isDebuggable, 0, null); + PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "System information"); PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "SDK Version", sdkVersion, 0, preference -> { diff --git a/app/src/main/java/ru/vtosters/lite/utils/AnalyticsHelper.java b/app/src/main/java/ru/vtosters/lite/utils/AnalyticsHelper.java new file mode 100644 index 000000000..5698c4ca8 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/utils/AnalyticsHelper.java @@ -0,0 +1,87 @@ +package ru.vtosters.lite.utils; + +import android.app.Application; +import android.os.Handler; +import androidx.annotation.NonNull; +import com.microsoft.appcenter.AppCenter; +import com.microsoft.appcenter.analytics.Analytics; +import com.microsoft.appcenter.channel.AbstractChannelListener; +import com.microsoft.appcenter.channel.Channel; +import com.microsoft.appcenter.crashes.Crashes; +import com.microsoft.appcenter.ingestion.models.Log; + +import java.util.HashMap; + +public class AnalyticsHelper { + private static final boolean analyticsDisabled = Preferences.getBoolValue("analyticsDisabled", false);; + + private static final String key = "5028aa35-9f16-44ed-b306-c4ed471a57eb"; + + private static final Channel.Listener patchDeviceListener = new AbstractChannelListener() { + @Override + public void onPreparedLog(@NonNull Log log, @NonNull String groupName, int flags) { + var device = log.getDevice(); + device.setAppVersion(About.getBuildNumber()); + device.setAppBuild(About.getBuildNumber()); + } + }; + + private static void addPatchDeviceListener() { + try { + var channelField = AppCenter.class.getDeclaredField("mChannel"); + channelField.setAccessible(true); + var channel = (Channel) channelField.get(AppCenter.getInstance()); + assert channel != null; + channel.addListener(patchDeviceListener); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + } + + private static void patchDevice() { + try { + var handlerField = AppCenter.class.getDeclaredField("mHandler"); + handlerField.setAccessible(true); + var handler = ((Handler) handlerField.get(AppCenter.getInstance())); + assert handler != null; + handler.post(AnalyticsHelper::addPatchDeviceListener); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + } + + public static void start(Application application) { + if (analyticsDisabled) { + setAnalyticsStatus(false); + return; + } + + AppCenter.start(application, AnalyticsHelper.key, Analytics.class, Crashes.class); + patchDevice(); + setAnalyticsStatus(true); + } + + public static void trackEvent(String event) { + if (analyticsDisabled) return; + + AnalyticsHelper.trackEvent(event); + } + + public static void trackEvent(String event, HashMap map) { + if (analyticsDisabled) return; + + AnalyticsHelper.trackEvent(event, map); + } + + public static void trackError(Throwable th) { + if (analyticsDisabled) return; + + Crashes.trackError(th); + } + public static void setAnalyticsStatus(Boolean bool) { + Analytics.setEnabled(bool && Preferences.isValidSignature()); + Crashes.setEnabled(bool && !AndroidUtils.isDebuggable() && Preferences.isValidSignature()); + Preferences.getPreferences().edit().putBoolean("analyticsDisabled", !bool).apply(); + } +} + diff --git a/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java b/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java index b7de9826a..91ef40e58 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java +++ b/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationUserState; @@ -31,6 +32,9 @@ import java.util.Objects; import static ru.vtosters.lite.utils.Preferences.getBoolValue; public class AndroidUtils { + public static boolean isDebuggable() { + return 0 != (AndroidUtils.getGlobalContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE); + } public static boolean isTablet() { return Screen.l(getGlobalContext()); diff --git a/app/src/main/java/ru/vtosters/lite/utils/Preferences.java b/app/src/main/java/ru/vtosters/lite/utils/Preferences.java index 129627d5b..79d145470 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/Preferences.java +++ b/app/src/main/java/ru/vtosters/lite/utils/Preferences.java @@ -32,6 +32,8 @@ public class Preferences { setupFilters(); VTVerifications.load(application); LifecycleUtils.registerActivities(application); + + AnalyticsHelper.start(application); } // VK Init public static SharedPreferences getPreferences() { diff --git a/smali/res/xml/preferences_other.xml b/smali/res/xml/preferences_other.xml index bd06f0702..91c43bd4d 100644 --- a/smali/res/xml/preferences_other.xml +++ b/smali/res/xml/preferences_other.xml @@ -82,5 +82,10 @@ + \ No newline at end of file