Commit 227c4bea authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch 'master' of https://git.frostnerd.com/PublicAndroidApps/smokescreen into translations

parents 0fc505ec 9778c56a
...@@ -45,8 +45,4 @@ captures/ ...@@ -45,8 +45,4 @@ captures/
libs/ libs/
libs/** libs/**
\ No newline at end of file
.idea/markdown-navigator-enh.xml
.idea/markdown-navigator.xml
.idea/navEditor.xml
\ No newline at end of file
...@@ -46,7 +46,7 @@ There are two options on how to use the DNS rules:<br> ...@@ -46,7 +46,7 @@ There are two options on how to use the DNS rules:<br>
You can either define your own rules - for example to block single hosts - or import *rule sources* which contain a list of rules.<br><br> You can either define your own rules - for example to block single hosts - or import *rule sources* which contain a list of rules.<br><br>
There are multiple lists maintained by independent people you can use in Nebulo. There are multiple lists maintained by independent people you can use in Nebulo.
They cover different topics, from blocking ads, tracking to blocking porn or social media.<br> They cover different topics, from blocking ads, tracking to blocking porn or social media.<br>
I recommend checking out [Energized](energized.pro). I recommend checking out [Energized](https://energized.pro).
It has multiple types of lists, covering use cases mentioned above. It has multiple types of lists, covering use cases mentioned above.
If you have the F-Droid version the Energized lists are already added as sources. If you have the F-Droid version the Energized lists are already added as sources.
......
...@@ -12,13 +12,16 @@ android { ...@@ -12,13 +12,16 @@ android {
applicationId "com.frostnerd.smokescreen" applicationId "com.frostnerd.smokescreen"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 30 targetSdkVersion 30
versionCode 74 versionCode 75
versionName "2.0.3" versionName "2.0.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
def sentryDSN = String.valueOf(getSystemVariableOrDefault("NEBULO_SENTRY_DSN", "dummy"))
def sentryConfigServer = String.valueOf(getSystemVariableOrDefault("NEBULO_SENTRY_CONFIGSERVER", "dummy"))
buildConfigField("Boolean", "FROM_CI", String.valueOf(getSystemVariableOrDefault("CI_COMMIT_SHORT_SHA", "") != "")) buildConfigField("Boolean", "FROM_CI", String.valueOf(getSystemVariableOrDefault("CI_COMMIT_SHORT_SHA", "") != ""))
buildConfigField("String", "COMMIT_HASH", '"' + getGitCommitHash() + '"') buildConfigField("String", "COMMIT_HASH", '"' + getGitCommitHash() + '"')
buildConfigField("String", "SENTRY_DSN", '""') buildConfigField("String", "SENTRY_DSN", '"' + sentryDSN+ '"') // A valid Sentry DSN, or "dummy"
buildConfigField("String", "SENTRY_DSN_CONFIGSERVER", '"' + sentryConfigServer + '"') // A host which returns a valid Sentry DSN on GET, or "dummy". If both are dummy Sentry is disabled.
buildConfigField("Boolean", "SHOW_DOQ", 'false') buildConfigField("Boolean", "SHOW_DOQ", 'false')
buildConfigField("Boolean", "SHOW_INTRO", 'false') buildConfigField("Boolean", "SHOW_INTRO", 'false')
buildConfigField("Boolean", "IN_APP_UPDATES", "false") buildConfigField("Boolean", "IN_APP_UPDATES", "false")
...@@ -99,7 +102,7 @@ android { ...@@ -99,7 +102,7 @@ android {
matchingFallbacks = ['default'] matchingFallbacks = ['default']
dimension "version" dimension "version"
versionNameSuffix "-adblock" versionNameSuffix "-adblock"
versionCode 75 versionCode 76
} }
normal { normal {
matchingFallbacks = ['default'] matchingFallbacks = ['default']
...@@ -147,10 +150,10 @@ dependencies { ...@@ -147,10 +150,10 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
implementation 'com.frostnerd.utilskt:lifecycle:1.2.0' implementation 'com.frostnerd.utilskt:lifecycle:1.2.1'
implementation 'com.frostnerd.utilskt:preferences:1.5.30' // https://git.frostnerd.com/AndroidUtils/preferenceskt implementation 'com.frostnerd.utilskt:preferences:1.5.30' // https://git.frostnerd.com/AndroidUtils/preferenceskt
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.4.0' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.4.2' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:2.1.20' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:2.1.21' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:general:1.0.25' // https://git.frostnerd.com/AndroidUtils/generalkt implementation 'com.frostnerd.utilskt:general:1.0.25' // https://git.frostnerd.com/AndroidUtils/generalkt
implementation 'com.frostnerd.utilskt:adapters:1.2.0' // https://git.frostnerd.com/AndroidUtils/Adapters implementation 'com.frostnerd.utilskt:adapters:1.2.0' // https://git.frostnerd.com/AndroidUtils/Adapters
...@@ -169,9 +172,8 @@ dependencies { ...@@ -169,9 +172,8 @@ dependencies {
implementation 'io.sentry:sentry-android:3.2.0' implementation 'io.sentry:sentry-android:3.2.0'
implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar' implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar'
implementation 'com.squareup.leakcanary:leaksentry:2.0-alpha-3'
leakCanaryImplementation 'com.squareup.leakcanary:leakcanary-android:2.5' leakCanaryImplementation 'com.squareup.leakcanary:leakcanary-android:2.6'
implementation "com.squareup.okhttp3:okhttp:4.9.0" implementation "com.squareup.okhttp3:okhttp:4.9.0"
implementation 'com.github.AppIntro:AppIntro:6.0.0' implementation 'com.github.AppIntro:AppIntro:6.0.0'
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INSTALL_SHORTCUT" /> <uses-permission android:name="android.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" /> <uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission <uses-permission
android:name="android.permission.INTERACT_ACROSS_USERS" android:name="android.permission.INTERACT_ACROSS_USERS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
......
...@@ -38,7 +38,6 @@ import com.frostnerd.smokescreen.util.proxy.IpTablesPacketRedirector ...@@ -38,7 +38,6 @@ import com.frostnerd.smokescreen.util.proxy.IpTablesPacketRedirector
import io.sentry.NoOpLogger import io.sentry.NoOpLogger
import io.sentry.android.core.BuildInfoProvider import io.sentry.android.core.BuildInfoProvider
import io.sentry.android.core.util.RootChecker import io.sentry.android.core.util.RootChecker
import leakcanary.LeakSentry
import java.net.Inet4Address import java.net.Inet4Address
import java.net.Inet6Address import java.net.Inet6Address
import java.net.InetAddress import java.net.InetAddress
...@@ -63,6 +62,7 @@ import java.util.logging.Level ...@@ -63,6 +62,7 @@ import java.util.logging.Level
* You can contact the developer at daniel.wolf@frostnerd.com. * You can contact the developer at daniel.wolf@frostnerd.com.
*/ */
@Suppress("DEPRECATION")
fun Context.canUseFingerprintAuthentication(): Boolean { fun Context.canUseFingerprintAuthentication(): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false
val mgr = getSystemService(Context.FINGERPRINT_SERVICE) as? FingerprintManager val mgr = getSystemService(Context.FINGERPRINT_SERVICE) as? FingerprintManager
...@@ -73,6 +73,7 @@ fun Context.canUseFingerprintAuthentication(): Boolean { ...@@ -73,6 +73,7 @@ fun Context.canUseFingerprintAuthentication(): Boolean {
return true return true
} }
@Suppress("unused")
fun Context.registerReceiver(intentFilter: IntentFilter, receiver: (intent: Intent?) -> Unit): BroadcastReceiver { fun Context.registerReceiver(intentFilter: IntentFilter, receiver: (intent: Intent?) -> Unit): BroadcastReceiver {
val actualReceiver = object : BroadcastReceiver() { val actualReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
...@@ -158,6 +159,7 @@ fun AppCompatActivity.registerLocalReceiver( ...@@ -158,6 +159,7 @@ fun AppCompatActivity.registerLocalReceiver(
mgr.registerReceiver(actualReceiver, filter) mgr.registerReceiver(actualReceiver, filter)
if(unregisterOnDestroy) lifecycle.addObserver(object:LifecycleObserver { if(unregisterOnDestroy) lifecycle.addObserver(object:LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
@Suppress("unused")
fun onDestroy() { fun onDestroy() {
mgr.unregisterReceiver(actualReceiver) mgr.unregisterReceiver(actualReceiver)
} }
...@@ -399,7 +401,7 @@ private fun createHttpsUpstreamAddress(url: String): HttpsUpstreamAddress { ...@@ -399,7 +401,7 @@ private fun createHttpsUpstreamAddress(url: String): HttpsUpstreamAddress {
} }
private fun createTlsUpstreamAddress(host: String): TLSUpstreamAddress { private fun createTlsUpstreamAddress(host: String): TLSUpstreamAddress {
var parsedHost = "" val parsedHost:String
var port: Int? = null var port: Int? = null
if (host.contains(":")) { if (host.contains(":")) {
parsedHost = host.split(":")[0] parsedHost = host.split(":")[0]
...@@ -410,18 +412,6 @@ private fun createTlsUpstreamAddress(host: String): TLSUpstreamAddress { ...@@ -410,18 +412,6 @@ private fun createTlsUpstreamAddress(host: String): TLSUpstreamAddress {
else TLSUpstreamAddress(parsedHost) else TLSUpstreamAddress(parsedHost)
} }
fun LeakSentry.watchIfEnabled(watchedInstance: Any) {
if(BuildConfig.LEAK_DETECTION) {
refWatcher.watch(watchedInstance)
}
}
fun LeakSentry.watchIfEnabled(watchedInstance: Any, name:String) {
if(BuildConfig.LEAK_DETECTION) {
refWatcher.watch(watchedInstance, name)
}
}
fun String.equalsAny(vararg options:String, ignoreCase:Boolean = false):Boolean { fun String.equalsAny(vararg options:String, ignoreCase:Boolean = false):Boolean {
return options.any { return options.any {
it.equals(this, ignoreCase) it.equals(this, ignoreCase)
......
...@@ -11,7 +11,6 @@ import io.sentry.Sentry ...@@ -11,7 +11,6 @@ import io.sentry.Sentry
import io.sentry.SentryEvent import io.sentry.SentryEvent
import io.sentry.SentryLevel import io.sentry.SentryLevel
import io.sentry.protocol.Message import io.sentry.protocol.Message
import leakcanary.LeakSentry
import java.io.* import java.io.*
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
...@@ -65,7 +64,6 @@ private fun Context.logErrorSentry(e: Throwable, extras: Map<String, String>? = ...@@ -65,7 +64,6 @@ private fun Context.logErrorSentry(e: Throwable, extras: Map<String, String>? =
this.message = e.message this.message = e.message
} }
level = SentryLevel.ERROR level = SentryLevel.ERROR
setExtra("retainedInstanceCount", LeakSentry.refWatcher.retainedInstanceCount)
}) })
} else if (getPreferences().crashreportingType == Crashreporting.FULL && extras != null && extras.isNotEmpty()) { } else if (getPreferences().crashreportingType == Crashreporting.FULL && extras != null && extras.isNotEmpty()) {
log("Sending exception with extras") log("Sending exception with extras")
...@@ -78,7 +76,6 @@ private fun Context.logErrorSentry(e: Throwable, extras: Map<String, String>? = ...@@ -78,7 +76,6 @@ private fun Context.logErrorSentry(e: Throwable, extras: Map<String, String>? =
extras.forEach { (key, value) -> extras.forEach { (key, value) ->
setTag(key, value) setTag(key, value)
} }
setExtra("retainedInstanceCount", LeakSentry.refWatcher.retainedInstanceCount)
}) })
} else { } else {
log("Sending exception to Sentry without extras") log("Sending exception to Sentry without extras")
...@@ -121,7 +118,7 @@ fun Context.log(e: Throwable, extras: Map<String, String>? = null) { ...@@ -121,7 +118,7 @@ fun Context.log(e: Throwable, extras: Map<String, String>? = null) {
"${Logger.logFileNameTimeStampFormatter.format(System.currentTimeMillis())}.err" "${Logger.logFileNameTimeStampFormatter.format(System.currentTimeMillis())}.err"
) )
if (errorFile.createNewFile()) { if (errorFile.tryCreateNewFile()) {
val writer = BufferedWriter(FileWriter(errorFile, false)) val writer = BufferedWriter(FileWriter(errorFile, false))
writer.write("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}, Commit: ${BuildConfig.COMMIT_HASH})\n") writer.write("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}, Commit: ${BuildConfig.COMMIT_HASH})\n")
writer.write("Android SDK version: ${Build.VERSION.SDK_INT} (${Build.VERSION.RELEASE} - ${Build.VERSION.CODENAME})\n") writer.write("Android SDK version: ${Build.VERSION.SDK_INT} (${Build.VERSION.RELEASE} - ${Build.VERSION.CODENAME})\n")
...@@ -141,7 +138,7 @@ fun Context.closeLogger() { ...@@ -141,7 +138,7 @@ fun Context.closeLogger() {
fun Context.deleteAllLogs() { fun Context.deleteAllLogs() {
if (Logger.isOpen()) if (Logger.isOpen())
Logger.getInstance(this).destroy() Logger.getInstance(this).destroy()
Logger.getLogDir(this).listFiles().forEach { Logger.getLogDir(this).listFiles()!!.forEach {
it.delete() it.delete()
} }
} }
...@@ -181,7 +178,7 @@ class Logger private constructor(context: Context) { ...@@ -181,7 +178,7 @@ class Logger private constructor(context: Context) {
"${id}_${logFileNameTimeStampFormatter.format(System.currentTimeMillis())}.log" "${id}_${logFileNameTimeStampFormatter.format(System.currentTimeMillis())}.log"
) )
logDir.mkdirs() logDir.mkdirs()
logFile.createNewFile() logFile.tryCreateNewFile()
fileWriter = BufferedWriter(FileWriter(logFile, false)) fileWriter = BufferedWriter(FileWriter(logFile, false))
log("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") log("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
...@@ -309,8 +306,12 @@ class Logger private constructor(context: Context) { ...@@ -309,8 +306,12 @@ class Logger private constructor(context: Context) {
if (printToConsole) { if (printToConsole) {
(oldSystemOut ?: System.out).println(textBuilder) (oldSystemOut ?: System.out).println(textBuilder)
} }
fileWriter.write(textBuilder.toString()) try {
fileWriter.flush() fileWriter.write(textBuilder.toString())
fileWriter.flush()
} catch (ex:Throwable) {
}
} }
} }
} }
...@@ -325,7 +326,7 @@ class Logger private constructor(context: Context) { ...@@ -325,7 +326,7 @@ class Logger private constructor(context: Context) {
"${id}_${logFileNameTimeStampFormatter.format(System.currentTimeMillis())}.err" "${id}_${logFileNameTimeStampFormatter.format(System.currentTimeMillis())}.err"
) )
if (errorFile.createNewFile()) { if (errorFile.tryCreateNewFile()) {
val writer = BufferedWriter(FileWriter(errorFile, false)) val writer = BufferedWriter(FileWriter(errorFile, false))
writer.write("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n") writer.write("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n")
writer.write("Android SDK version: ${Build.VERSION.SDK_INT} (${Build.VERSION.RELEASE} - ${Build.VERSION.CODENAME})\n") writer.write("Android SDK version: ${Build.VERSION.SDK_INT} (${Build.VERSION.RELEASE} - ${Build.VERSION.CODENAME})\n")
...@@ -343,6 +344,14 @@ class Logger private constructor(context: Context) { ...@@ -343,6 +344,14 @@ class Logger private constructor(context: Context) {
} }
} }
fun File.tryCreateNewFile():Boolean {
return try {
createNewFile()
} catch (ex:Throwable) {
false
}
}
fun Context.zipAllLogFiles(): File? { fun Context.zipAllLogFiles(): File? {
val dir = Logger.getLogDir(this) val dir = Logger.getLogDir(this)
if (!dir.canWrite() || !dir.canRead()) return null if (!dir.canWrite() || !dir.canRead()) return null
...@@ -351,7 +360,7 @@ fun Context.zipAllLogFiles(): File? { ...@@ -351,7 +360,7 @@ fun Context.zipAllLogFiles(): File? {
if (zipFile.exists() && (!zipFile.canRead() || !zipFile.canWrite())) return null if (zipFile.exists() && (!zipFile.canRead() || !zipFile.canWrite())) return null
if (zipFile.exists()) zipFile.delete() if (zipFile.exists()) zipFile.delete()
var filesToBeZipped = dir.listFiles() var filesToBeZipped = dir.listFiles()!!
val dest = FileOutputStream(zipFile) val dest = FileOutputStream(zipFile)
val out = ZipOutputStream(BufferedOutputStream(dest)) val out = ZipOutputStream(BufferedOutputStream(dest))
val buffer = ByteArray(2048) val buffer = ByteArray(2048)
......
...@@ -24,16 +24,13 @@ import io.sentry.Sentry ...@@ -24,16 +24,13 @@ import io.sentry.Sentry
import io.sentry.SentryOptions import io.sentry.SentryOptions
import io.sentry.android.core.* import io.sentry.android.core.*
import io.sentry.protocol.User import io.sentry.protocol.User
import kotlinx.coroutines.Dispatchers import okhttp3.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import leakcanary.LeakSentry
import org.minidns.dnsmessage.DnsMessage import org.minidns.dnsmessage.DnsMessage
import org.minidns.dnsmessage.Question import org.minidns.dnsmessage.Question
import org.minidns.record.A import org.minidns.record.A
import org.minidns.record.AAAA import org.minidns.record.AAAA
import org.minidns.record.Record import org.minidns.record.Record
import java.net.InetAddress import java.io.IOException
import java.util.* import java.util.*
import kotlin.system.exitProcess import kotlin.system.exitProcess
...@@ -68,15 +65,15 @@ class SmokeScreen : Application() { ...@@ -68,15 +65,15 @@ class SmokeScreen : Application() {
else { else {
context.log("Using fallback server: $to") context.log("Using fallback server: $to")
val configs = to.serverConfigurations.values val configs = to.serverConfigurations.values
AddressCreator.globalResolve = { AddressCreator.globalResolve = { domain ->
val responsesIpv4 = configs.random().query(Question(it, Record.TYPE.A))?.takeIf { val responsesIpv4 = configs.random().query(Question(domain, Record.TYPE.A))?.takeIf {
it.responseCode == DnsMessage.RESPONSE_CODE.NO_ERROR it.responseCode == DnsMessage.RESPONSE_CODE.NO_ERROR
}?.answerSection?.map { }?.answerSection?.map {
it.payload as A it.payload as A
}?.map { }?.map {
it.inetAddress it.inetAddress
} }
val responsesIpv6 = configs.random().query(Question(it, Record.TYPE.AAAA))?.takeIf { val responsesIpv6 = configs.random().query(Question(domain, Record.TYPE.AAAA))?.takeIf {
it.responseCode == DnsMessage.RESPONSE_CODE.NO_ERROR it.responseCode == DnsMessage.RESPONSE_CODE.NO_ERROR
}?.answerSection?.map { }?.answerSection?.map {
it.payload as AAAA it.payload as AAAA
...@@ -135,16 +132,14 @@ class SmokeScreen : Application() { ...@@ -135,16 +132,14 @@ class SmokeScreen : Application() {
} }
override fun onCreate() { override fun onCreate() {
if(!BuildConfig.LEAK_DETECTION) LeakSentry.config = LeakSentry.config.copy(enabled = false)
initSentry() initSentry()
defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler() defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler(customUncaughtExceptionHandler) Thread.setDefaultUncaughtExceptionHandler(customUncaughtExceptionHandler)
super.onCreate() super.onCreate()
log("Application created.") log("Application created.")
LeakSentry.watchIfEnabled(this)
handleFallbackDns() handleFallbackDns()
loadKnownDNSServers() loadKnownDNSServers()
AbstractQuicDnsHandle.installProvider(this, {}) AbstractQuicDnsHandle.installProvider(this) {}
} }
private fun handleFallbackDns() { private fun handleFallbackDns() {
...@@ -175,75 +170,122 @@ class SmokeScreen : Application() { ...@@ -175,75 +170,122 @@ class SmokeScreen : Application() {
} }
fun initSentry(forceStatus: Status = Status.NONE) { fun initSentry(forceStatus: Status = Status.NONE) {
if (!BuildConfig.DEBUG && BuildConfig.SENTRY_DSN != "dummy") { val enabledType = getPreferences().crashreportingType
log("Sentry will be initialized.") if (forceStatus == Status.NONE &&
GlobalScope.launch(Dispatchers.IO) { enabledType == Crashreporting.OFF) return
log("Initializing Sentry.") log("Maybe initializing Sentry")
sentryReady = false getSentryDSN { resolvedDSN ->
try { log("Initializing Sentry.")
val hostName = InetAddress.getLocalHost().hostName sentryReady = false
if(!hostName.startsWith("mars-sandbox", true)) { try {
val enabledType = getPreferences().crashreportingType if (sentryReady) {
if (forceStatus != Status.DATASAVING && (enabledType == Crashreporting.FULL || forceStatus == Status.ENABLED)) { log("Reinitializing Sentry with new DSN")
// Enable Sentry in full mode SentryAndroid.init(this@SmokeScreen) {
// This passes some device-related data, but nothing which allows user actions to be tracked across the app it.dsn = resolvedDSN
// Info: Some data is attached by the AndroidEventBuilderHelper class, which is present by default }
} else {
if (forceStatus != Status.DATASAVING && (enabledType == Crashreporting.FULL || forceStatus == Status.ENABLED)) {
// Enable Sentry in full mode
// This passes some device-related data, but nothing which allows user actions to be tracked across the app
// Info: Some data is attached by the AndroidEventBuilderHelper class, which is present by default
SentryAndroid.init(this@SmokeScreen) { SentryAndroid.init(this@SmokeScreen) {
it.dsn = BuildConfig.SENTRY_DSN it.dsn = resolvedDSN
} }
Sentry.setUser(User().apply { Sentry.setUser(User().apply {
this.username = getPreferences().crashReportingUUID this.username = getPreferences().crashReportingUUID
}) })
Sentry.setTag("user.language", Locale.getDefault().displayLanguage) Sentry.setTag("user.language", Locale.getDefault().displayLanguage)
Sentry.setTag( Sentry.setTag(
"app.database_version", "app.database_version",
AppDatabase.currentVersion.toString() AppDatabase.currentVersion.toString()
) )
Sentry.setTag( Sentry.setTag(
"app.dns_server_name", "app.dns_server_name",
getPreferences().dnsServerConfig.name getPreferences().dnsServerConfig.name
) )
Sentry.setTag( Sentry.setTag(
"app.dns_server_primary", "app.dns_server_primary",
getPreferences().dnsServerConfig.servers[0].address.formatToString() getPreferences().dnsServerConfig.servers[0].address.formatToString()
) )
Sentry.setTag( Sentry.setTag(
"app.dns_server_secondary", "app.dns_server_secondary",
getPreferences().dnsServerConfig.servers.getOrNull(1)?.address?.formatToString() getPreferences().dnsServerConfig.servers.getOrNull(1)?.address?.formatToString()
?: "" ?: ""
) )
Sentry.setTag( Sentry.setTag(
"app.installer_package", "app.installer_package",
packageManager.getInstallerPackageName(packageName) ?: "" packageManager.getInstallerPackageName(packageName) ?: ""
) )
Sentry.setTag("richdata", "true") Sentry.setTag("richdata", "true")
Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString()) Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString())
Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH) Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH)
sentryReady = true sentryReady = true
} else if (enabledType == Crashreporting.MINIMAL || forceStatus == Status.DATASAVING) { } else if (enabledType == Crashreporting.MINIMAL || forceStatus == Status.DATASAVING) {
// Inits Sentry in datasaving mode // Inits Sentry in datasaving mode
// Only data absolutely necessary is transmitted (Android version, app version). // Only data absolutely necessary is transmitted (Android version, app version).
// Only crashes will be reported, no regular events. // Only crashes will be reported, no regular events.
SentryAndroid.init(this@SmokeScreen) { SentryAndroid.init(this@SmokeScreen) {
it.dsn = BuildConfig.SENTRY_DSN it.dsn = resolvedDSN
setupSentryForDatasaving(it) setupSentryForDatasaving(it)
}
Sentry.setUser(User().apply {
this.username = "anon-" + BuildConfig.VERSION_CODE
})
Sentry.setTag("richdata", "false")
Sentry.setTag("dist", BuildConfig.VERSION_CODE.toString())
Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH)
Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString())
sentryReady = true
} }
Sentry.setUser(User().apply {
this.username = "anon-" + BuildConfig.VERSION_CODE
})
Sentry.setTag("richdata", "false")
Sentry.setTag("dist", BuildConfig.VERSION_CODE.toString())
Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH)
Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString())
sentryReady = true
} }
} catch(ex:Throwable) {
ex.printStackTrace()
} }
log("Sentry ready.") log("Sentry ready.")
} catch (ex: Throwable) {
log("Creating Sentry errored")
log(ex)
}
}
}
private fun getSentryDSN(then:(dsn:String) -> Unit) {
if(BuildConfig.DEBUG) return
try {
val primaryDSN = BuildConfig.SENTRY_DSN
val configServer = BuildConfig.SENTRY_DSN_CONFIGSERVER
if(primaryDSN.contains("@")) then(primaryDSN)
else log("Primary Sentry DSN not set, maybe retrieving from server")
if(configServer.isNotBlank() && configServer.startsWith("http")