2019-12-01 15:35:42 -06:00
|
|
|
/*
|
|
|
|
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package pl.szczodrzynski.edziennik
|
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
import android.content.Intent
|
|
|
|
import android.content.pm.PackageManager
|
|
|
|
import android.content.pm.ShortcutInfo
|
|
|
|
import android.content.pm.ShortcutManager
|
|
|
|
import android.graphics.drawable.Icon
|
|
|
|
import android.os.Build
|
|
|
|
import android.provider.Settings
|
2019-12-01 15:35:42 -06:00
|
|
|
import android.util.Log
|
2020-01-19 12:07:27 -06:00
|
|
|
import androidx.appcompat.app.AppCompatDelegate
|
|
|
|
import androidx.multidex.MultiDexApplication
|
2019-12-01 15:35:42 -06:00
|
|
|
import androidx.work.Configuration
|
2020-01-19 12:07:27 -06:00
|
|
|
import cat.ereza.customactivityoncrash.config.CaocConfig
|
|
|
|
import com.chuckerteam.chucker.api.ChuckerCollector
|
|
|
|
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
|
|
|
import com.chuckerteam.chucker.api.RetentionManager
|
|
|
|
import com.google.firebase.FirebaseApp
|
|
|
|
import com.google.firebase.FirebaseOptions
|
|
|
|
import com.google.firebase.iid.FirebaseInstanceId
|
|
|
|
import com.google.firebase.messaging.FirebaseMessaging
|
|
|
|
import com.google.gson.Gson
|
|
|
|
import com.hypertrack.hyperlog.HyperLog
|
|
|
|
import com.mikepenz.iconics.Iconics
|
|
|
|
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
|
|
|
|
import im.wangchao.mhttp.MHttp
|
|
|
|
import im.wangchao.mhttp.internal.cookie.PersistentCookieJar
|
|
|
|
import im.wangchao.mhttp.internal.cookie.cache.SetCookieCache
|
|
|
|
import im.wangchao.mhttp.internal.cookie.persistence.SharedPrefsCookiePersistor
|
|
|
|
import kotlinx.coroutines.*
|
|
|
|
import me.leolin.shortcutbadger.ShortcutBadger
|
|
|
|
import okhttp3.OkHttpClient
|
|
|
|
import org.greenrobot.eventbus.EventBus
|
|
|
|
import pl.szczodrzynski.edziennik.config.Config
|
|
|
|
import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent
|
|
|
|
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
|
|
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
|
|
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
|
|
|
import pl.szczodrzynski.edziennik.network.NetworkUtils
|
|
|
|
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
|
|
|
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
|
|
|
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity
|
|
|
|
import pl.szczodrzynski.edziennik.utils.*
|
2020-02-16 06:42:14 -06:00
|
|
|
import pl.szczodrzynski.edziennik.utils.managers.NotificationChannelsManager
|
|
|
|
import pl.szczodrzynski.edziennik.utils.managers.UserActionManager
|
2020-01-19 12:07:27 -06:00
|
|
|
import java.util.concurrent.TimeUnit
|
2019-12-01 15:35:42 -06:00
|
|
|
import kotlin.coroutines.CoroutineContext
|
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
2019-12-01 15:35:42 -06:00
|
|
|
companion object {
|
2020-01-19 12:07:27 -06:00
|
|
|
@Volatile
|
|
|
|
lateinit var db: AppDb
|
|
|
|
val config: Config by lazy { Config(db) }
|
|
|
|
var profile: Profile by mutableLazy { Profile(0, 0, 0, "") }
|
|
|
|
val profileId
|
|
|
|
get() = profile.id
|
|
|
|
|
2019-12-01 15:35:42 -06:00
|
|
|
var devMode = false
|
|
|
|
}
|
|
|
|
|
2020-02-16 06:42:14 -06:00
|
|
|
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
|
|
|
|
val userActionManager by lazy { UserActionManager(this) }
|
2020-01-19 12:07:27 -06:00
|
|
|
|
|
|
|
val db
|
|
|
|
get() = App.db
|
|
|
|
val config
|
|
|
|
get() = App.config
|
|
|
|
val profile
|
|
|
|
get() = App.profile
|
|
|
|
val profileId
|
|
|
|
get() = App.profileId
|
2019-12-01 15:35:42 -06:00
|
|
|
|
|
|
|
private val job = Job()
|
|
|
|
override val coroutineContext: CoroutineContext
|
|
|
|
get() = job + Dispatchers.Main
|
|
|
|
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
|
|
|
.setMinimumLoggingLevel(Log.VERBOSE)
|
|
|
|
.build()
|
|
|
|
|
|
|
|
val permissionChecker by lazy { PermissionChecker(this) }
|
2020-01-19 12:07:27 -06:00
|
|
|
val networkUtils by lazy { NetworkUtils(this) }
|
|
|
|
val gson by lazy { Gson() }
|
2019-12-01 15:35:42 -06:00
|
|
|
|
|
|
|
/* _ _ _______ _______ _____
|
|
|
|
| | | |__ __|__ __| __ \
|
|
|
|
| |__| | | | | | | |__) |
|
|
|
|
| __ | | | | | | ___/
|
|
|
|
| | | | | | | | | |
|
|
|
|
|_| |_| |_| |_| |*/
|
|
|
|
val http: OkHttpClient by lazy {
|
|
|
|
val builder = OkHttpClient.Builder()
|
|
|
|
.cache(null)
|
|
|
|
.followRedirects(true)
|
|
|
|
.followSslRedirects(true)
|
|
|
|
.retryOnConnectionFailure(true)
|
|
|
|
.cookieJar(cookieJar)
|
|
|
|
.connectTimeout(20, TimeUnit.SECONDS)
|
|
|
|
.writeTimeout(5, TimeUnit.SECONDS)
|
|
|
|
.readTimeout(10, TimeUnit.SECONDS)
|
2020-01-19 12:07:27 -06:00
|
|
|
builder.installHttpsSupport(this)
|
2019-12-01 15:35:42 -06:00
|
|
|
|
|
|
|
if (devMode || BuildConfig.DEBUG) {
|
|
|
|
HyperLog.initialize(this)
|
|
|
|
HyperLog.setLogLevel(Log.VERBOSE)
|
|
|
|
HyperLog.setLogFormat(DebugLogFormat(this))
|
2020-01-19 12:07:27 -06:00
|
|
|
val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
|
2019-12-01 15:35:42 -06:00
|
|
|
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
|
|
|
builder.addInterceptor(chuckerInterceptor)
|
|
|
|
}
|
|
|
|
|
|
|
|
builder.build()
|
|
|
|
}
|
|
|
|
val httpLazy: OkHttpClient by lazy {
|
|
|
|
http.newBuilder()
|
|
|
|
.followRedirects(false)
|
|
|
|
.followSslRedirects(false)
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
val cookieJar by lazy { PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(this)) }
|
|
|
|
|
|
|
|
/* _____ _ _
|
|
|
|
/ ____(_) | |
|
|
|
|
| (___ _ __ _ _ __ __ _| |_ _ _ _ __ ___
|
|
|
|
\___ \| |/ _` | '_ \ / _` | __| | | | '__/ _ \
|
|
|
|
____) | | (_| | | | | (_| | |_| |_| | | | __/
|
|
|
|
|_____/|_|\__, |_| |_|\__,_|\__|\__,_|_| \___|
|
|
|
|
__/ |
|
|
|
|
|__*/
|
2020-01-19 12:07:27 -06:00
|
|
|
val deviceId: String by lazy { Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID) ?: "" }
|
2019-12-01 15:35:42 -06:00
|
|
|
private var unreadBadgesAvailable = true
|
|
|
|
|
|
|
|
/* _____ _
|
|
|
|
/ ____| | |
|
|
|
|
___ _ __ | | _ __ ___ __ _| |_ ___
|
|
|
|
/ _ \| '_ \| | | '__/ _ \/ _` | __/ _ \
|
|
|
|
| (_) | | | | |____| | | __/ (_| | || __/
|
|
|
|
\___/|_| |_|\_____|_| \___|\__,_|\__\__*/
|
|
|
|
override fun onCreate() {
|
|
|
|
super.onCreate()
|
|
|
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
|
|
|
CaocConfig.Builder.create()
|
|
|
|
.backgroundMode(CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM)
|
|
|
|
.enabled(true)
|
|
|
|
.showErrorDetails(true)
|
|
|
|
.showRestartButton(true)
|
|
|
|
.logErrorOnRestart(true)
|
|
|
|
.trackActivities(true)
|
|
|
|
.minTimeBetweenCrashesMs(60*1000)
|
|
|
|
.errorDrawable(R.drawable.ic_rip)
|
|
|
|
.restartActivity(MainActivity::class.java)
|
|
|
|
.errorActivity(CrashActivity::class.java)
|
|
|
|
.apply()
|
|
|
|
Iconics.init(applicationContext)
|
|
|
|
Iconics.registerFont(SzkolnyFont)
|
2020-01-19 12:07:27 -06:00
|
|
|
App.db = AppDb(this)
|
2019-12-01 15:35:42 -06:00
|
|
|
Themes.themeInt = config.ui.theme
|
|
|
|
MHttp.instance().customOkHttpClient(http)
|
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
if (!profileLoadById(config.lastProfileId)) {
|
|
|
|
db.profileDao().firstId?.let { profileLoadById(it) }
|
|
|
|
}
|
|
|
|
|
2019-12-01 15:35:42 -06:00
|
|
|
devMode = "f054761fbdb6a238" == deviceId || BuildConfig.DEBUG
|
|
|
|
|
2019-12-14 15:56:56 -06:00
|
|
|
Signing.getCert(this)
|
2019-12-01 15:35:42 -06:00
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
launch {
|
|
|
|
withContext(Dispatchers.Default) {
|
|
|
|
config.migrate(this@App)
|
|
|
|
|
|
|
|
if (config.devModePassword != null)
|
|
|
|
checkDevModePassword()
|
|
|
|
|
|
|
|
if (config.sync.enabled)
|
|
|
|
SyncWorker.scheduleNext(this@App, false)
|
|
|
|
else
|
|
|
|
SyncWorker.cancelNext(this@App)
|
|
|
|
|
|
|
|
if (config.sync.notifyAboutUpdates)
|
|
|
|
UpdateWorker.scheduleNext(this@App, false)
|
|
|
|
else
|
|
|
|
UpdateWorker.cancelNext(this@App)
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
|
|
|
val shortcutManager = getSystemService(ShortcutManager::class.java)
|
|
|
|
|
|
|
|
val shortcutTimetable = ShortcutInfo.Builder(this@App, "item_timetable")
|
|
|
|
.setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable))
|
|
|
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_timetable))
|
|
|
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
|
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE))
|
|
|
|
.build()
|
2019-12-01 15:35:42 -06:00
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
val shortcutAgenda = ShortcutInfo.Builder(this@App, "item_agenda")
|
|
|
|
.setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda))
|
|
|
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_agenda))
|
|
|
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
|
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_AGENDA))
|
|
|
|
.build()
|
2019-12-01 15:35:42 -06:00
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
val shortcutGrades = ShortcutInfo.Builder(this@App, "item_grades")
|
|
|
|
.setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades))
|
|
|
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_grades))
|
|
|
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
|
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_GRADES))
|
|
|
|
.build()
|
2019-12-01 15:35:42 -06:00
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
val shortcutHomework = ShortcutInfo.Builder(this@App, "item_homeworks")
|
|
|
|
.setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework))
|
|
|
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_homework))
|
|
|
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
|
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOMEWORK))
|
|
|
|
.build()
|
2019-12-01 15:35:42 -06:00
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
val shortcutMessages = ShortcutInfo.Builder(this@App, "item_messages")
|
|
|
|
.setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages))
|
|
|
|
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_messages))
|
|
|
|
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
|
|
|
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_MESSAGES))
|
|
|
|
.build()
|
|
|
|
|
|
|
|
shortcutManager.dynamicShortcuts = listOf(
|
|
|
|
shortcutTimetable,
|
|
|
|
shortcutAgenda,
|
|
|
|
shortcutGrades,
|
|
|
|
shortcutHomework,
|
|
|
|
shortcutMessages
|
|
|
|
)
|
|
|
|
} // shortcuts - end
|
|
|
|
|
2020-02-16 06:42:14 -06:00
|
|
|
notificationChannelsManager.registerAllChannels()
|
2020-01-19 12:07:27 -06:00
|
|
|
|
|
|
|
|
|
|
|
if (config.appInstalledTime == 0L)
|
|
|
|
try {
|
|
|
|
config.appInstalledTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
|
|
|
|
config.appRateSnackbarTime = config.appInstalledTime + 7 * DAY * MS
|
|
|
|
} catch (e: PackageManager.NameNotFoundException) {
|
|
|
|
e.printStackTrace()
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
|
|
|
|
val pushMobidziennikApp = FirebaseApp.initializeApp(
|
|
|
|
this@App,
|
|
|
|
FirebaseOptions.Builder()
|
|
|
|
.setApiKey("AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE")
|
|
|
|
.setApplicationId("1:747285019373:android:f6341bf7b158621d")
|
|
|
|
.build(),
|
|
|
|
"Mobidziennik2"
|
|
|
|
)
|
|
|
|
|
|
|
|
val pushLibrusApp = FirebaseApp.initializeApp(
|
|
|
|
this@App,
|
|
|
|
FirebaseOptions.Builder()
|
|
|
|
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
|
|
|
|
.setApplicationId("1:513056078587:android:1e29083b760af544")
|
|
|
|
.build(),
|
|
|
|
"Librus"
|
|
|
|
)
|
|
|
|
|
|
|
|
val pushVulcanApp = FirebaseApp.initializeApp(
|
|
|
|
this@App,
|
|
|
|
FirebaseOptions.Builder()
|
|
|
|
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
|
|
|
|
.setApplicationId("1:987828170337:android:ac97431a0a4578c3")
|
|
|
|
.build(),
|
|
|
|
"Vulcan"
|
|
|
|
)
|
|
|
|
|
|
|
|
try {
|
|
|
|
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { instanceIdResult ->
|
|
|
|
val token = instanceIdResult.token
|
|
|
|
config.sync.tokenApp = token
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
FirebaseInstanceId.getInstance(pushMobidziennikApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
|
|
|
val token = instanceIdResult.token
|
|
|
|
if (token != config.sync.tokenMobidziennik) {
|
|
|
|
config.sync.tokenMobidziennik = token
|
|
|
|
config.sync.tokenMobidziennikList = listOf()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FirebaseInstanceId.getInstance(pushLibrusApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
|
|
|
val token = instanceIdResult.token
|
|
|
|
if (token != config.sync.tokenLibrus) {
|
|
|
|
config.sync.tokenLibrus = token
|
|
|
|
config.sync.tokenLibrusList = listOf()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FirebaseInstanceId.getInstance(pushVulcanApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
|
|
|
val token = instanceIdResult.token
|
|
|
|
if (token != config.sync.tokenVulcan) {
|
|
|
|
config.sync.tokenVulcan = token
|
|
|
|
config.sync.tokenVulcanList = listOf()
|
|
|
|
}
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
FirebaseMessaging.getInstance().subscribeToTopic(packageName)
|
|
|
|
} catch (e: IllegalStateException) {
|
|
|
|
e.printStackTrace()
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-19 12:07:27 -06:00
|
|
|
db.metadataDao().countUnseen().observeForever { count: Int ->
|
|
|
|
if (unreadBadgesAvailable)
|
|
|
|
unreadBadgesAvailable = ShortcutBadger.applyCount(this@App, count)
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
|
|
|
|
private fun profileLoadById(profileId: Int): Boolean {
|
|
|
|
db.profileDao().getByIdNow(profileId)?.also {
|
|
|
|
App.profile = it
|
|
|
|
App.config.lastProfileId = it.id
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
fun profileLoad(profileId: Int, onSuccess: (profile: Profile) -> Unit) {
|
2019-12-01 15:35:42 -06:00
|
|
|
launch {
|
2020-01-19 12:07:27 -06:00
|
|
|
val success = withContext(Dispatchers.Default) {
|
|
|
|
profileLoadById(profileId)
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
if (success)
|
|
|
|
onSuccess(profile)
|
|
|
|
else
|
|
|
|
profileLoadLast(onSuccess)
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
fun profileLoadLast(onSuccess: (profile: Profile) -> Unit) {
|
|
|
|
launch {
|
|
|
|
val success = withContext(Dispatchers.Default) {
|
|
|
|
profileLoadById(db.profileDao().lastId ?: return@withContext false)
|
|
|
|
}
|
|
|
|
if (!success) {
|
|
|
|
EventBus.getDefault().post(ProfileListEmptyEvent())
|
2019-12-01 15:35:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
fun profileSave() = profileSave(profile)
|
|
|
|
fun profileSave(profile: Profile) {
|
|
|
|
launch(Dispatchers.Default) {
|
|
|
|
App.db.profileDao().add(profile)
|
|
|
|
}
|
|
|
|
}
|
2019-12-01 15:35:42 -06:00
|
|
|
|
|
|
|
fun checkDevModePassword() {
|
|
|
|
devMode = try {
|
|
|
|
Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.devModePassword) == "ok here you go it's enabled now" || BuildConfig.DEBUG
|
|
|
|
} catch (e: Exception) {
|
|
|
|
e.printStackTrace()
|
|
|
|
false
|
|
|
|
}
|
2020-01-19 12:07:27 -06:00
|
|
|
}
|
2020-02-16 06:42:14 -06:00
|
|
|
}
|