Files
vpnhotspotmod/mobile/src/main/java/be/mygod/vpnhotspot/App.kt
2021-05-27 13:33:26 -04:00

141 lines
6.2 KiB
Kotlin

package be.mygod.vpnhotspot
import android.annotation.SuppressLint
import android.app.Application
import android.content.ClipboardManager
import android.content.res.Configuration
import android.os.Build
import android.util.Log
import androidx.annotation.Size
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.core.provider.FontRequest
import androidx.emoji.text.EmojiCompat
import androidx.emoji.text.FontRequestEmojiCompatConfig
import androidx.preference.PreferenceManager
import be.mygod.librootkotlinx.NoShellException
import be.mygod.vpnhotspot.net.DhcpWorkaround
import be.mygod.vpnhotspot.room.AppDatabase
import be.mygod.vpnhotspot.root.RootManager
import be.mygod.vpnhotspot.util.DeviceStorageApp
import be.mygod.vpnhotspot.util.Services
import com.google.firebase.analytics.ktx.ParametersBuilder
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.ktx.Firebase
import com.google.firebase.ktx.initialize
import kotlinx.coroutines.DEBUG_PROPERTY_NAME
import kotlinx.coroutines.DEBUG_PROPERTY_VALUE_ON
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.*
class App : Application() {
companion object {
@SuppressLint("StaticFieldLeak")
lateinit var app: App
}
override fun onCreate() {
super.onCreate()
app = this
if (Build.VERSION.SDK_INT >= 24) @SuppressLint("RestrictedApi") {
deviceStorage = DeviceStorageApp(this)
// alternative to PreferenceManager.getDefaultSharedPreferencesName(this)
deviceStorage.moveSharedPreferencesFrom(this, PreferenceManager(this).sharedPreferencesName)
deviceStorage.moveDatabaseFrom(this, AppDatabase.DB_NAME)
} else deviceStorage = this
Services.init { this }
// overhead of debug mode is minimal: https://github.com/Kotlin/kotlinx.coroutines/blob/f528898/docs/debugging.md#debug-mode
System.setProperty(DEBUG_PROPERTY_NAME, DEBUG_PROPERTY_VALUE_ON)
Firebase.initialize(deviceStorage)
when (val codename = Build.VERSION.CODENAME) {
"REL" -> { }
else -> FirebaseCrashlytics.getInstance().apply {
setCustomKey("codename", codename)
if (Build.VERSION.SDK_INT >= 23) setCustomKey("preview_sdk", Build.VERSION.PREVIEW_SDK_INT)
}
}
Timber.plant(object : Timber.DebugTree() {
@SuppressLint("LogNotTimber")
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
if (t == null) {
if (priority != Log.DEBUG || BuildConfig.DEBUG) Log.println(priority, tag, message)
FirebaseCrashlytics.getInstance().log("${"XXVDIWEF".getOrElse(priority) { 'X' }}/$tag: $message")
} else {
if (priority >= Log.WARN || priority == Log.DEBUG) {
Log.println(priority, tag, message)
Log.w(tag, message, t)
}
if (priority >= Log.INFO && t !is NoShellException) {
FirebaseCrashlytics.getInstance().recordException(t)
}
}
}
})
ServiceNotification.updateNotificationChannels()
EmojiCompat.init(FontRequestEmojiCompatConfig(deviceStorage, FontRequest(
"com.google.android.gms.fonts",
"com.google.android.gms",
"Noto Color Emoji Compat",
R.array.com_google_android_gms_fonts_certs)).apply {
setEmojiSpanIndicatorEnabled(BuildConfig.DEBUG)
registerInitCallback(object : EmojiCompat.InitCallback() {
override fun onInitialized() = Timber.d("EmojiCompat initialized")
override fun onFailed(throwable: Throwable?) = Timber.d(throwable)
})
})
EBegFragment.init()
if (DhcpWorkaround.shouldEnable) DhcpWorkaround.enable(true)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
ServiceNotification.updateNotificationChannels()
}
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
if (level == TRIM_MEMORY_RUNNING_CRITICAL || level >= TRIM_MEMORY_BACKGROUND) GlobalScope.launch {
RootManager.closeExisting()
}
}
/**
* This method is used to log "expected" and well-handled errors, i.e. we care less about logs, etc.
* logException is inappropriate sometimes because it flushes all logs that could be used to investigate other bugs.
*/
fun logEvent(@Size(min = 1L, max = 40L) event: String, block: ParametersBuilder.() -> Unit = { }) {
val builder = ParametersBuilder()
builder.block()
Timber.i(if (builder.bundle.isEmpty) event else "$event, extras: ${builder.bundle}")
Firebase.analytics.logEvent(event, builder.bundle)
}
lateinit var deviceStorage: Application
val english by lazy {
createConfigurationContext(Configuration(resources.configuration).apply {
setLocale(Locale.ENGLISH)
})
}
val pref by lazy { PreferenceManager.getDefaultSharedPreferences(deviceStorage) }
val clipboard by lazy { getSystemService<ClipboardManager>()!! }
val hasTouch by lazy { packageManager.hasSystemFeature("android.hardware.faketouch") }
val customTabsIntent by lazy {
CustomTabsIntent.Builder().apply {
setColorScheme(CustomTabsIntent.COLOR_SCHEME_SYSTEM)
setColorSchemeParams(CustomTabsIntent.COLOR_SCHEME_LIGHT, CustomTabColorSchemeParams.Builder().apply {
setToolbarColor(ContextCompat.getColor(app, R.color.light_colorPrimary))
}.build())
setColorSchemeParams(CustomTabsIntent.COLOR_SCHEME_DARK, CustomTabColorSchemeParams.Builder().apply {
setToolbarColor(ContextCompat.getColor(app, R.color.dark_colorPrimary))
}.build())
}.build()
}
}