2019-01-18 10:12:08 +00:00
|
|
|
/*
|
2019-01-25 13:04:59 +00:00
|
|
|
* Copyright 2019 New Vector Ltd
|
2019-01-18 10:12:08 +00:00
|
|
|
*
|
2019-01-25 13:04:59 +00:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2019-01-18 10:12:08 +00:00
|
|
|
*
|
2019-01-25 13:04:59 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2019-01-18 10:12:08 +00:00
|
|
|
*/
|
|
|
|
|
2018-10-03 15:56:33 +00:00
|
|
|
package im.vector.riotredesign
|
|
|
|
|
2019-06-19 08:46:59 +00:00
|
|
|
import android.app.AlarmManager
|
2018-10-03 15:56:33 +00:00
|
|
|
import android.app.Application
|
2019-06-19 08:46:59 +00:00
|
|
|
import android.app.PendingIntent
|
|
|
|
import android.content.ComponentName
|
2019-01-24 15:30:05 +00:00
|
|
|
import android.content.Context
|
2019-06-19 08:46:59 +00:00
|
|
|
import android.content.Intent
|
|
|
|
import android.content.ServiceConnection
|
2019-06-12 11:09:32 +00:00
|
|
|
import android.content.res.Configuration
|
2019-06-04 15:16:02 +00:00
|
|
|
import android.os.Handler
|
|
|
|
import android.os.HandlerThread
|
2019-06-19 08:46:59 +00:00
|
|
|
import android.os.IBinder
|
2019-06-04 15:16:02 +00:00
|
|
|
import androidx.core.provider.FontRequest
|
|
|
|
import androidx.core.provider.FontsContractCompat
|
2019-06-19 08:46:59 +00:00
|
|
|
import androidx.lifecycle.Lifecycle
|
|
|
|
import androidx.lifecycle.LifecycleObserver
|
|
|
|
import androidx.lifecycle.OnLifecycleEvent
|
|
|
|
import androidx.lifecycle.ProcessLifecycleOwner
|
2019-01-24 15:30:05 +00:00
|
|
|
import androidx.multidex.MultiDex
|
2019-06-19 08:46:59 +00:00
|
|
|
import androidx.work.*
|
2019-03-19 18:45:32 +00:00
|
|
|
import com.airbnb.epoxy.EpoxyAsyncUtil
|
|
|
|
import com.airbnb.epoxy.EpoxyController
|
2019-02-19 16:40:38 +00:00
|
|
|
import com.facebook.stetho.Stetho
|
2019-03-12 07:29:49 +00:00
|
|
|
import com.github.piasy.biv.BigImageViewer
|
|
|
|
import com.github.piasy.biv.loader.glide.GlideImageLoader
|
2018-10-31 15:11:59 +00:00
|
|
|
import com.jakewharton.threetenabp.AndroidThreeTen
|
2019-03-19 11:29:45 +00:00
|
|
|
import im.vector.matrix.android.api.Matrix
|
2019-06-19 08:46:59 +00:00
|
|
|
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
|
|
|
import im.vector.matrix.android.internal.session.sync.job.SyncWorker
|
2018-10-04 13:19:03 +00:00
|
|
|
import im.vector.riotredesign.core.di.AppModule
|
2019-06-19 08:46:59 +00:00
|
|
|
import im.vector.riotredesign.core.services.RestartBroadcastReceiver
|
|
|
|
import im.vector.riotredesign.core.services.VectorSyncService
|
2019-06-06 16:34:14 +00:00
|
|
|
import im.vector.riotredesign.features.configuration.VectorConfiguration
|
2019-06-12 11:09:32 +00:00
|
|
|
import im.vector.riotredesign.features.crypto.keysbackup.KeysBackupModule
|
2019-02-28 17:50:30 +00:00
|
|
|
import im.vector.riotredesign.features.home.HomeModule
|
2019-05-16 08:23:57 +00:00
|
|
|
import im.vector.riotredesign.features.lifecycle.VectorActivityLifecycleCallbacks
|
2019-06-19 08:46:59 +00:00
|
|
|
import im.vector.riotredesign.features.notifications.NotificationUtils
|
|
|
|
import im.vector.riotredesign.features.notifications.PushRuleTriggerListener
|
2019-03-28 16:28:20 +00:00
|
|
|
import im.vector.riotredesign.features.rageshake.VectorFileLogger
|
|
|
|
import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
|
2019-05-24 20:27:26 +00:00
|
|
|
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
|
2019-06-21 09:13:16 +00:00
|
|
|
import im.vector.riotredesign.features.version.getVersion
|
2019-06-19 08:46:59 +00:00
|
|
|
import org.koin.android.ext.android.get
|
2019-06-06 16:34:14 +00:00
|
|
|
import org.koin.android.ext.android.inject
|
2018-10-23 16:25:28 +00:00
|
|
|
import org.koin.log.EmptyLogger
|
2018-10-03 15:56:33 +00:00
|
|
|
import org.koin.standalone.StandAloneContext.startKoin
|
2018-10-16 13:52:30 +00:00
|
|
|
import timber.log.Timber
|
2019-06-21 09:13:16 +00:00
|
|
|
import java.text.SimpleDateFormat
|
|
|
|
import java.util.*
|
2019-06-19 08:46:59 +00:00
|
|
|
import java.util.concurrent.TimeUnit
|
2018-10-03 15:56:33 +00:00
|
|
|
|
2019-06-19 08:46:59 +00:00
|
|
|
class VectorApplication : Application(), SyncService.SyncListener {
|
2019-01-24 15:30:05 +00:00
|
|
|
|
2018-10-03 15:56:33 +00:00
|
|
|
|
2019-05-16 08:23:57 +00:00
|
|
|
lateinit var appContext: Context
|
2019-06-04 15:16:02 +00:00
|
|
|
//font thread handler
|
|
|
|
private var mFontThreadHandler: Handler? = null
|
|
|
|
|
2019-06-06 16:34:14 +00:00
|
|
|
val vectorConfiguration: VectorConfiguration by inject()
|
2019-05-16 08:23:57 +00:00
|
|
|
|
2019-06-19 08:46:59 +00:00
|
|
|
private var mBinder: SyncService.LocalBinder? = null
|
|
|
|
|
|
|
|
private val connection = object : ServiceConnection {
|
|
|
|
override fun onServiceDisconnected(name: ComponentName?) {
|
|
|
|
Timber.v("Service unbounded")
|
|
|
|
mBinder?.removeListener(this@VectorApplication)
|
|
|
|
mBinder = null
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
|
|
Timber.v("Service bounded")
|
|
|
|
mBinder = service as SyncService.LocalBinder
|
|
|
|
mBinder?.addListener(this@VectorApplication)
|
|
|
|
mBinder?.getService()?.nextBatchDelay = 0
|
|
|
|
mBinder?.getService()?.timeout = 10_000L
|
|
|
|
mBinder?.getService()?.doSync()
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// var slowMode = false
|
|
|
|
|
|
|
|
|
2018-10-03 15:56:33 +00:00
|
|
|
override fun onCreate() {
|
|
|
|
super.onCreate()
|
2019-05-16 08:23:57 +00:00
|
|
|
appContext = this
|
|
|
|
|
2019-06-21 09:13:16 +00:00
|
|
|
logInfo()
|
|
|
|
|
2019-03-28 16:28:20 +00:00
|
|
|
VectorUncaughtExceptionHandler.activate(this)
|
|
|
|
|
|
|
|
// Log
|
|
|
|
VectorFileLogger.init(this)
|
|
|
|
Timber.plant(Timber.DebugTree(), VectorFileLogger)
|
|
|
|
|
2018-10-16 13:52:30 +00:00
|
|
|
if (BuildConfig.DEBUG) {
|
2019-02-19 16:40:38 +00:00
|
|
|
Stetho.initializeWithDefaults(this)
|
2018-10-16 13:52:30 +00:00
|
|
|
}
|
2019-03-28 16:28:20 +00:00
|
|
|
|
2018-10-31 15:11:59 +00:00
|
|
|
AndroidThreeTen.init(this)
|
2019-03-12 07:29:49 +00:00
|
|
|
BigImageViewer.initialize(GlideImageLoader.with(applicationContext))
|
2019-03-19 18:45:32 +00:00
|
|
|
EpoxyController.defaultDiffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
|
|
|
|
EpoxyController.defaultModelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
|
2019-02-28 17:50:30 +00:00
|
|
|
val appModule = AppModule(applicationContext).definition
|
2019-03-01 20:44:26 +00:00
|
|
|
val homeModule = HomeModule().definition
|
2019-05-24 20:27:26 +00:00
|
|
|
val roomDirectoryModule = RoomDirectoryModule().definition
|
2019-06-12 11:09:32 +00:00
|
|
|
val keysBackupModule = KeysBackupModule().definition
|
|
|
|
val koin = startKoin(listOf(appModule, homeModule, roomDirectoryModule, keysBackupModule), logger = EmptyLogger())
|
2019-03-19 11:29:45 +00:00
|
|
|
Matrix.getInstance().setApplicationFlavor(BuildConfig.FLAVOR_DESCRIPTION)
|
2019-05-16 08:23:57 +00:00
|
|
|
registerActivityLifecycleCallbacks(VectorActivityLifecycleCallbacks())
|
2019-06-06 16:34:14 +00:00
|
|
|
|
2019-06-04 15:16:02 +00:00
|
|
|
val fontRequest = FontRequest(
|
|
|
|
"com.google.android.gms.fonts",
|
|
|
|
"com.google.android.gms",
|
|
|
|
"Noto Color Emoji Compat",
|
|
|
|
R.array.com_google_android_gms_fonts_certs
|
|
|
|
)
|
|
|
|
|
|
|
|
FontsContractCompat.requestFont(this, fontRequest, koin.koinContext.get<EmojiCompatFontProvider>(), getFontThreadHandler())
|
|
|
|
|
2019-06-06 16:34:14 +00:00
|
|
|
vectorConfiguration.initConfiguration()
|
2019-06-19 08:46:59 +00:00
|
|
|
|
|
|
|
NotificationUtils.createNotificationChannels(applicationContext)
|
|
|
|
|
|
|
|
ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleObserver {
|
|
|
|
|
|
|
|
fun cancelAlarm() {
|
|
|
|
val intent = Intent(applicationContext, RestartBroadcastReceiver::class.java)
|
|
|
|
val pIntent = PendingIntent.getBroadcast(applicationContext, RestartBroadcastReceiver.REQUEST_CODE,
|
|
|
|
intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
|
|
|
val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
|
|
|
alarm.cancel(pIntent)
|
|
|
|
}
|
|
|
|
|
|
|
|
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
|
|
|
fun entersForeground() {
|
|
|
|
// HttpLongPoolingSyncService.startService(applicationContext)
|
|
|
|
// cancelAlarm()
|
|
|
|
if (Matrix.getInstance().currentSession == null) return
|
|
|
|
WorkManager.getInstance().cancelAllWorkByTag("BG_SYNC")
|
|
|
|
Intent(applicationContext, VectorSyncService::class.java).also { intent ->
|
|
|
|
// intent.action = "NORMAL"
|
|
|
|
// try {
|
|
|
|
// startService(intent)
|
|
|
|
// } catch (e: Throwable) {
|
|
|
|
// Timber.e("Failed to launch sync service")
|
|
|
|
// }
|
|
|
|
bindService(intent, connection, Context.BIND_AUTO_CREATE)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var isPushAvailable = true
|
|
|
|
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
|
|
|
fun entersBackground() {
|
|
|
|
Timber.i("App entered background")
|
|
|
|
//we have here 3 modes
|
|
|
|
|
|
|
|
if (isPushAvailable) {
|
|
|
|
// PUSH IS AVAILABLE:
|
|
|
|
// Just stop the service, we will sync when a notification is received
|
|
|
|
try {
|
|
|
|
unbindService(connection)
|
|
|
|
mBinder?.getService()?.stopMe()
|
|
|
|
mBinder = null
|
|
|
|
} catch (t: Throwable) {
|
|
|
|
Timber.e(t)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// NO PUSH, and don't care about battery
|
|
|
|
// unbindService(connection)
|
|
|
|
// mBinder?.getService()?.stopMe()// kill also
|
|
|
|
// mBinder = null
|
|
|
|
//In this case we will keep a permanent
|
|
|
|
|
|
|
|
//TODO if no push schedule reccuring alarm
|
|
|
|
|
|
|
|
// val workRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.MINUTES)
|
|
|
|
// .setConstraints(Constraints.Builder()
|
|
|
|
// .setRequiredNetworkType(NetworkType.CONNECTED)
|
|
|
|
// .build())
|
|
|
|
// .setBackoffCriteria(BackoffPolicy.LINEAR, 10_000, TimeUnit.MILLISECONDS)
|
|
|
|
// .build()
|
|
|
|
// WorkManager.getInstance().enqueueUniquePeriodicWork(
|
|
|
|
// "BG_SYNC",
|
|
|
|
// ExistingPeriodicWorkPolicy.KEEP,
|
|
|
|
// workRequest)
|
|
|
|
val workRequest = OneTimeWorkRequestBuilder<SyncWorker>()
|
|
|
|
// .setInitialDelay(30_000, TimeUnit.MILLISECONDS)
|
|
|
|
.setInputData(Data.Builder().put("timeout", 0L).build())
|
|
|
|
.setConstraints(Constraints.Builder()
|
|
|
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
|
|
|
.build())
|
|
|
|
.setBackoffCriteria(BackoffPolicy.LINEAR, 10_000, TimeUnit.MILLISECONDS)
|
|
|
|
.build()
|
|
|
|
WorkManager.getInstance().enqueueUniqueWork("BG_SYNCP", ExistingWorkPolicy.REPLACE, workRequest)
|
|
|
|
|
|
|
|
// val intent = Intent(applicationContext, RestartBroadcastReceiver::class.java)
|
|
|
|
// // Create a PendingIntent to be triggered when the alarm goes off
|
|
|
|
// val pIntent = PendingIntent.getBroadcast(applicationContext, RestartBroadcastReceiver.REQUEST_CODE,
|
|
|
|
// intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
// // Setup periodic alarm every every half hour from this point onwards
|
|
|
|
// val firstMillis = System.currentTimeMillis(); // alarm is set right away
|
|
|
|
// val alarmMgr = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
|
|
|
// // First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
|
|
|
|
// // Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
|
|
|
|
//// alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
|
|
|
|
//// 30_000L, pIntent)
|
|
|
|
// alarmMgr.set(AlarmManager.RTC_WAKEUP, firstMillis, pIntent);
|
|
|
|
|
|
|
|
Timber.i("Alarm scheduled to restart service")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
Matrix.getInstance().currentSession?.let {
|
|
|
|
it.refreshPushers()
|
|
|
|
//bind to the sync service
|
|
|
|
get<PushRuleTriggerListener>().startWithSession(it)
|
|
|
|
}
|
2018-10-03 15:56:33 +00:00
|
|
|
}
|
|
|
|
|
2019-06-21 09:13:16 +00:00
|
|
|
private fun logInfo() {
|
|
|
|
val appVersion = getVersion(longFormat = true, useBuildNumber = true)
|
|
|
|
val sdkVersion = Matrix.getSdkVersion()
|
|
|
|
val date = SimpleDateFormat("MM-dd HH:mm:ss.SSSZ", Locale.US).format(Date())
|
|
|
|
|
|
|
|
Timber.v("----------------------------------------------------------------")
|
|
|
|
Timber.v("----------------------------------------------------------------")
|
|
|
|
Timber.v(" Application version: $appVersion")
|
|
|
|
Timber.v(" SDK version: $sdkVersion")
|
|
|
|
Timber.v(" Local time: $date")
|
|
|
|
Timber.v("----------------------------------------------------------------")
|
|
|
|
Timber.v("----------------------------------------------------------------\n\n\n\n")
|
|
|
|
}
|
|
|
|
|
2019-01-24 15:30:05 +00:00
|
|
|
override fun attachBaseContext(base: Context) {
|
|
|
|
super.attachBaseContext(base)
|
|
|
|
MultiDex.install(this)
|
|
|
|
}
|
|
|
|
|
2019-06-06 16:34:14 +00:00
|
|
|
override fun onConfigurationChanged(newConfig: Configuration?) {
|
|
|
|
super.onConfigurationChanged(newConfig)
|
|
|
|
vectorConfiguration.onConfigurationChanged(newConfig)
|
|
|
|
}
|
|
|
|
|
2019-06-04 15:16:02 +00:00
|
|
|
private fun getFontThreadHandler(): Handler {
|
|
|
|
if (mFontThreadHandler == null) {
|
|
|
|
val handlerThread = HandlerThread("fonts")
|
|
|
|
handlerThread.start()
|
|
|
|
mFontThreadHandler = Handler(handlerThread.looper)
|
|
|
|
}
|
|
|
|
return mFontThreadHandler!!
|
|
|
|
}
|
|
|
|
|
2019-06-19 08:46:59 +00:00
|
|
|
override fun onSyncFinsh() {
|
|
|
|
//in foreground sync right now!!
|
|
|
|
Timber.v("Sync just finished")
|
|
|
|
// mBinder?.getService()?.doSync()
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun networkNotAvailable() {
|
|
|
|
//we then want to retry in 10s?
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onFailed(failure: Throwable) {
|
|
|
|
//stop it also?
|
|
|
|
// if (failure is Failure.NetworkConnection
|
|
|
|
// && failure.cause is SocketTimeoutException) {
|
|
|
|
// // Timeout are not critical just retry?
|
|
|
|
// //TODO
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (failure !is Failure.NetworkConnection
|
|
|
|
// || failure.cause is JsonEncodingException) {
|
|
|
|
// //TODO Retry in 10S?
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (failure is Failure.ServerError
|
|
|
|
// && (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
|
|
|
|
// // No token or invalid token, stop the thread
|
|
|
|
// mBinder?.getService()?.unbindService(connection)
|
|
|
|
// mBinder?.getService()?.stopMe()
|
|
|
|
// }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-03 15:56:33 +00:00
|
|
|
}
|