Skip to content

Commit 4d336de

Browse files
move sentry integration to kotlin
Signed-off-by: androidacy-user <opensource@androidacy.com>
1 parent 48f2074 commit 4d336de

2 files changed

Lines changed: 130 additions & 125 deletions

File tree

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
1-
package com.fox2code.mmm.utils.sentry;
1+
package com.fox2code.mmm.utils.sentry
22

3-
import org.jetbrains.annotations.NotNull;
4-
import org.jetbrains.annotations.Nullable;
3+
import io.sentry.Breadcrumb
4+
import io.sentry.SentryLevel
5+
import java.util.Objects
56

6-
import java.util.Objects;
7+
class SentryBreadcrumb {
8+
@JvmField
9+
val breadcrumb: Breadcrumb = Breadcrumb()
710

8-
import io.sentry.Breadcrumb;
9-
import io.sentry.SentryLevel;
10-
11-
public class SentryBreadcrumb {
12-
public final Breadcrumb breadcrumb;
13-
14-
public SentryBreadcrumb() {
15-
breadcrumb = new Breadcrumb();
16-
breadcrumb.setLevel(SentryLevel.INFO);
11+
init {
12+
breadcrumb.level = SentryLevel.INFO
1713
}
1814

19-
public void setType(@Nullable String type) {
20-
breadcrumb.setType(type);
15+
fun setType(type: String?) {
16+
breadcrumb.type = type
2117
}
2218

23-
public void setData(@NotNull String key, @Nullable Object value) {
24-
if (value == null) value = "null";
25-
Objects.requireNonNull(key);
26-
breadcrumb.setData(key, value);
19+
fun setData(key: String, value: Any?) {
20+
@Suppress("NAME_SHADOWING") var value = value
21+
if (value == null) value = "null"
22+
Objects.requireNonNull(key)
23+
breadcrumb.setData(key, value)
2724
}
2825

29-
public void setCategory(@Nullable String category) {
30-
breadcrumb.setCategory(category);
26+
fun setCategory(category: String?) {
27+
breadcrumb.category = category
3128
}
32-
}
29+
}
Lines changed: 111 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,151 @@
1-
package com.fox2code.mmm.utils.sentry;
1+
package com.fox2code.mmm.utils.sentry
22

3-
import android.annotation.SuppressLint;
4-
import android.content.Context;
5-
import android.content.Intent;
6-
import android.content.SharedPreferences;
7-
import android.net.Uri;
3+
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import android.content.Intent
6+
import android.content.SharedPreferences
7+
import android.net.Uri
8+
import android.os.Process
9+
import com.fox2code.mmm.CrashHandler
10+
import com.fox2code.mmm.MainApplication
11+
import com.fox2code.mmm.androidacy.AndroidacyUtil.Companion.hideToken
12+
import com.fox2code.mmm.androidacy.AndroidacyUtil.Companion.isAndroidacyLink
13+
import io.sentry.Breadcrumb
14+
import io.sentry.Hint
15+
import io.sentry.Sentry
16+
import io.sentry.SentryEvent
17+
import io.sentry.SentryOptions.BeforeBreadcrumbCallback
18+
import io.sentry.SentryOptions.BeforeSendCallback
19+
import io.sentry.android.core.SentryAndroid
20+
import io.sentry.android.core.SentryAndroidOptions
21+
import io.sentry.android.fragment.FragmentLifecycleIntegration
22+
import io.sentry.android.timber.SentryTimberIntegration
23+
import org.matomo.sdk.extra.TrackHelper
24+
import timber.log.Timber
825

9-
import com.fox2code.mmm.CrashHandler;
10-
import com.fox2code.mmm.MainApplication;
11-
import com.fox2code.mmm.androidacy.AndroidacyUtil;
12-
13-
import org.matomo.sdk.extra.TrackHelper;
14-
15-
import java.util.Objects;
16-
17-
import io.sentry.Sentry;
18-
import io.sentry.android.core.SentryAndroid;
19-
import io.sentry.android.fragment.FragmentLifecycleIntegration;
20-
import io.sentry.android.timber.SentryTimberIntegration;
21-
import timber.log.Timber;
22-
23-
public class SentryMain {
24-
public static final boolean IS_SENTRY_INSTALLED = true;
25-
public static boolean isCrashing = false;
26-
private static boolean sentryEnabled = false;
26+
object SentryMain {
27+
const val IS_SENTRY_INSTALLED = true
28+
private var isCrashing = false
29+
private var isSentryEnabled = false
2730

2831
/**
2932
* Initialize Sentry
3033
* Sentry is used for crash reporting and performance monitoring.
3134
*/
32-
@SuppressLint({"RestrictedApi", "UnspecifiedImmutableFlag"})
33-
public static void initialize(final MainApplication mainApplication) {
34-
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
35-
isCrashing = true;
36-
TrackHelper.track().exception(throwable).with(MainApplication.getINSTANCE().getTracker());
37-
SharedPreferences.Editor editor = MainApplication.getINSTANCE().getSharedPreferences("sentry", Context.MODE_PRIVATE).edit();
38-
editor.putString("lastExitReason", "crash");
39-
editor.putLong("lastExitTime", System.currentTimeMillis());
40-
editor.putString("lastExitReason", "crash");
41-
editor.putString("lastExitId", String.valueOf(Sentry.getLastEventId()));
42-
editor.apply();
43-
Timber.e("Uncaught exception with sentry ID %s and stacktrace %s", Sentry.getLastEventId(), throwable.getStackTrace());
35+
@JvmStatic
36+
@SuppressLint("RestrictedApi", "UnspecifiedImmutableFlag")
37+
fun initialize(mainApplication: MainApplication) {
38+
Thread.setDefaultUncaughtExceptionHandler { _: Thread?, throwable: Throwable ->
39+
isCrashing = true
40+
TrackHelper.track().exception(throwable).with(MainApplication.getINSTANCE().tracker)
41+
val editor =
42+
MainApplication.getINSTANCE().getSharedPreferences("sentry", Context.MODE_PRIVATE)
43+
.edit()
44+
editor.putString("lastExitReason", "crash")
45+
editor.putLong("lastExitTime", System.currentTimeMillis())
46+
editor.putString("lastExitReason", "crash")
47+
editor.putString("lastExitId", Sentry.getLastEventId().toString())
48+
editor.apply()
49+
Timber.e(
50+
"Uncaught exception with sentry ID %s and stacktrace %s",
51+
Sentry.getLastEventId(),
52+
throwable.stackTrace
53+
)
4454
// open crash handler and exit
45-
Intent intent = new Intent(mainApplication, CrashHandler.class);
55+
val intent = Intent(mainApplication, CrashHandler::class.java)
4656
// pass the entire exception to the crash handler
47-
intent.putExtra("exception", throwable);
57+
intent.putExtra("exception", throwable)
4858
// add stacktrace as string
49-
intent.putExtra("stacktrace", throwable.getStackTrace());
59+
intent.putExtra("stacktrace", throwable.stackTrace)
5060
// put lastEventId in intent (get from preferences)
51-
intent.putExtra("lastEventId", String.valueOf(Sentry.getLastEventId()));
61+
intent.putExtra("lastEventId", Sentry.getLastEventId().toString())
5262
// serialize Sentry.captureException and pass it to the crash handler
53-
intent.putExtra("sentryException", throwable);
63+
intent.putExtra("sentryException", throwable)
5464
// pass crashReportingEnabled to crash handler
55-
intent.putExtra("crashReportingEnabled", isSentryEnabled());
65+
intent.putExtra("crashReportingEnabled", isSentryEnabled)
5666
// add isCrashing to intent
57-
intent.putExtra("isCrashing", isCrashing);
58-
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
59-
Timber.e("Starting crash handler");
60-
mainApplication.startActivity(intent);
61-
Timber.e("Exiting");
62-
android.os.Process.killProcess(android.os.Process.myPid());
63-
});
67+
intent.putExtra("isCrashing", isCrashing)
68+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
69+
Timber.e("Starting crash handler")
70+
mainApplication.startActivity(intent)
71+
Timber.e("Exiting")
72+
Process.killProcess(Process.myPid())
73+
}
6474
// If first_launch pref is not false, refuse to initialize Sentry
65-
SharedPreferences sharedPreferences = MainApplication.getSharedPreferences("mmm");
66-
if (!Objects.equals(sharedPreferences.getString("last_shown_setup", null), "v2")) {
67-
return;
75+
val sharedPreferences = MainApplication.getSharedPreferences("mmm")
76+
if (sharedPreferences.getString("last_shown_setup", null) != "v2") {
77+
return
6878
}
69-
sentryEnabled = sharedPreferences.getBoolean("pref_crash_reporting_enabled", false);
79+
isSentryEnabled = sharedPreferences.getBoolean("pref_crash_reporting_enabled", false)
7080
// set sentryEnabled on preference change of pref_crash_reporting_enabled
71-
sharedPreferences.registerOnSharedPreferenceChangeListener((sharedPreferences1, s) -> {
72-
if (s.equals("pref_crash_reporting_enabled")) {
73-
sentryEnabled = sharedPreferences1.getBoolean(s, false);
81+
sharedPreferences.registerOnSharedPreferenceChangeListener { sharedPreferences1: SharedPreferences, s: String ->
82+
if (s == "pref_crash_reporting_enabled") {
83+
isSentryEnabled = sharedPreferences1.getBoolean(s, false)
7484
}
75-
});
76-
SentryAndroid.init(mainApplication, options -> {
85+
}
86+
SentryAndroid.init(mainApplication) { options: SentryAndroidOptions ->
7787
// If crash reporting is disabled, stop here.
7888
if (!MainApplication.isCrashReportingEnabled()) {
79-
sentryEnabled = false; // Set sentry state to disabled
80-
options.setDsn("");
89+
isSentryEnabled = false // Set sentry state to disabled
90+
options.dsn = ""
8191
} else {
8292
// get pref_crash_reporting_pii pref
83-
boolean crashReportingPii = sharedPreferences.getBoolean("crashReportingPii", false);
84-
sentryEnabled = true; // Set sentry state to enabled
85-
options.addIntegration(new FragmentLifecycleIntegration(mainApplication, true, true));
93+
val crashReportingPii = sharedPreferences.getBoolean("crashReportingPii", false)
94+
isSentryEnabled = true // Set sentry state to enabled
95+
options.addIntegration(FragmentLifecycleIntegration(mainApplication,
96+
enableFragmentLifecycleBreadcrumbs = true,
97+
enableAutoFragmentLifecycleTracing = true
98+
))
8699
// Enable automatic activity lifecycle breadcrumbs
87-
options.setEnableActivityLifecycleBreadcrumbs(true);
100+
options.isEnableActivityLifecycleBreadcrumbs = true
88101
// Enable automatic fragment lifecycle breadcrumbs
89-
options.addIntegration(new SentryTimberIntegration());
90-
options.setCollectAdditionalContext(true);
91-
options.setAttachThreads(true);
92-
options.setAttachStacktrace(true);
93-
options.setEnableNdk(true);
94-
options.addInAppInclude("com.fox2code.mmm");
95-
options.addInAppInclude("com.fox2code.mmm.debug");
96-
options.addInAppInclude("com.fox2code.mmm.fdroid");
97-
options.addInAppExclude("com.fox2code.mmm.utils.sentry.SentryMain");
102+
options.addIntegration(SentryTimberIntegration())
103+
options.isCollectAdditionalContext = true
104+
options.isAttachThreads = true
105+
options.isAttachStacktrace = true
106+
options.isEnableNdk = true
107+
options.addInAppInclude("com.fox2code.mmm")
108+
options.addInAppInclude("com.fox2code.mmm.debug")
109+
options.addInAppInclude("com.fox2code.mmm.fdroid")
110+
options.addInAppExclude("com.fox2code.mmm.utils.sentry.SentryMain")
98111
// Respect user preference for sending PII. default is true on non fdroid builds, false on fdroid builds
99-
options.setSendDefaultPii(crashReportingPii);
100-
options.enableAllAutoBreadcrumbs(true);
112+
options.isSendDefaultPii = crashReportingPii
113+
options.enableAllAutoBreadcrumbs(true)
101114
// in-app screenshots are only sent if the app crashes, and it only shows the last activity. so no, we won't see your, ahem, "private" stuff
102-
options.setAttachScreenshot(true);
115+
options.isAttachScreenshot = true
103116
// It just tell if sentry should ping the sentry dsn to tell the app is running. Useful for performance and profiling.
104-
options.setEnableAutoSessionTracking(true);
117+
options.isEnableAutoSessionTracking = true
105118
// disable crash tracking - we handle that ourselves
106-
options.setEnableUncaughtExceptionHandler(false);
119+
options.isEnableUncaughtExceptionHandler = false
107120
// Add a callback that will be used before the event is sent to Sentry.
108121
// With this callback, you can modify the event or, when returning null, also discard the event.
109-
options.setBeforeSend((event, hint) -> {
122+
options.beforeSend = BeforeSendCallback { event: SentryEvent?, _: Hint? ->
110123
// in the rare event that crash reporting has been disabled since we started the app, we don't want to send the crash report
111-
if (!sentryEnabled) {
112-
return null;
113-
}
114-
if (isCrashing) {
115-
return null;
124+
if (!isSentryEnabled || isCrashing) {
125+
return@BeforeSendCallback null
116126
}
117-
return event;
118-
});
127+
event
128+
}
119129
// Filter breadcrumb content from crash report.
120-
options.setBeforeBreadcrumb((breadcrumb, hint) -> {
121-
String url = (String) breadcrumb.getData("url");
122-
if (url == null || url.isEmpty()) return breadcrumb;
123-
if ("cloudflare-dns.com".equals(Uri.parse(url).getHost())) return null;
124-
if (AndroidacyUtil.Companion.isAndroidacyLink(url)) {
125-
breadcrumb.setData("url", AndroidacyUtil.hideToken(url));
130+
options.beforeBreadcrumb =
131+
BeforeBreadcrumbCallback { breadcrumb: Breadcrumb, _: Hint? ->
132+
val url = breadcrumb.getData("url") as String?
133+
if (url.isNullOrEmpty()) return@BeforeBreadcrumbCallback null
134+
if ("cloudflare-dns.com" == Uri.parse(url).host) {
135+
return@BeforeBreadcrumbCallback null
136+
}
137+
if (isAndroidacyLink(url)) {
138+
breadcrumb.setData("url", hideToken(url))
139+
}
140+
breadcrumb
126141
}
127-
return breadcrumb;
128-
});
129142
}
130-
});
143+
}
131144
}
132145

133-
public static void addSentryBreadcrumb(SentryBreadcrumb sentryBreadcrumb) {
146+
fun addSentryBreadcrumb(sentryBreadcrumb: SentryBreadcrumb) {
134147
if (MainApplication.isCrashReportingEnabled()) {
135-
Sentry.addBreadcrumb(sentryBreadcrumb.breadcrumb);
148+
Sentry.addBreadcrumb(sentryBreadcrumb.breadcrumb)
136149
}
137150
}
138-
139-
@SuppressWarnings("unused")
140-
public static boolean isSentryEnabled() {
141-
return sentryEnabled;
142-
}
143-
}
151+
}

0 commit comments

Comments
 (0)