Use Single Periodic worker to restart
This commit is contained in:
parent
062706f3ae
commit
68dc14a95a
@ -80,4 +80,5 @@ dependencies {
|
||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
implementation("io.reactivex.rxjava2:rxjava:2.2.21")
|
||||
implementation("com.google.code.gson:gson:2.9.0")
|
||||
implementation("androidx.work:work-runtime-ktx:2.6.0")
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class MainActivity : AppCompatActivity() {
|
||||
format(getString(R.string.main_account_desc), ssoAccount.name)
|
||||
showLogout = true
|
||||
invalidateOptionsMenu()
|
||||
startListener(this)
|
||||
RestartWorker.start(this)
|
||||
}
|
||||
|
||||
private fun showStart() {
|
||||
@ -130,15 +130,14 @@ class MainActivity : AppCompatActivity() {
|
||||
Log.d(TAG, "Restarting the Listener")
|
||||
val receiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(p0: Context?, p1: Intent?) {
|
||||
startListener(this@MainActivity)
|
||||
RestartWorker.start(this@MainActivity, delay = 0)
|
||||
}
|
||||
}
|
||||
val intentFilter = IntentFilter(SERVICE_STOPPED_ACTION)
|
||||
val intentFilter = IntentFilter(StartService.SERVICE_STOPPED_ACTION)
|
||||
registerReceiver(receiver, intentFilter)
|
||||
isServiceStarted = false
|
||||
StartService.isServiceStarted = false
|
||||
val serviceIntent = Intent(this, StartService::class.java)
|
||||
this.stopService(serviceIntent)
|
||||
startListener(this)
|
||||
}
|
||||
|
||||
private fun logout() {
|
||||
|
@ -3,6 +3,7 @@ package org.unifiedpush.distributor.nextpush.receivers
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.PowerManager
|
||||
import android.util.Log
|
||||
import org.unifiedpush.distributor.nextpush.account.AccountUtils.isConnected
|
||||
import org.unifiedpush.distributor.nextpush.api.ApiUtils.apiCreateApp
|
||||
@ -19,7 +20,6 @@ import org.unifiedpush.distributor.nextpush.distributor.DistributorUtils.getDb
|
||||
import org.unifiedpush.distributor.nextpush.distributor.DistributorUtils.sendEndpoint
|
||||
import org.unifiedpush.distributor.nextpush.distributor.DistributorUtils.sendRegistrationFailed
|
||||
import org.unifiedpush.distributor.nextpush.distributor.DistributorUtils.sendUnregistered
|
||||
import org.unifiedpush.distributor.nextpush.services.wakeLock
|
||||
import java.lang.Exception
|
||||
|
||||
/**
|
||||
@ -30,8 +30,16 @@ private const val TAG = "RegisterBroadcastReceiver"
|
||||
|
||||
class RegisterBroadcastReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
wakeLock?.acquire(10000L /*10 secs*/)
|
||||
companion object {
|
||||
private const val WAKE_LOCK_TAG = "NextPush:RegisterBroadcastReceiver:lock"
|
||||
private var wakeLock : PowerManager.WakeLock? = null
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
wakeLock = (context.getSystemService(Context.POWER_SERVICE) as PowerManager).run {
|
||||
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG)
|
||||
}
|
||||
wakeLock?.acquire(30000L /*30 secs*/)
|
||||
when (intent!!.action) {
|
||||
ACTION_REGISTER ->{
|
||||
Log.i(TAG,"REGISTER")
|
||||
|
@ -3,20 +3,13 @@ package org.unifiedpush.distributor.nextpush.receivers
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import org.unifiedpush.distributor.nextpush.services.StartService
|
||||
import org.unifiedpush.distributor.nextpush.services.RestartWorker
|
||||
|
||||
class StartReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
||||
Intent(context, StartService::class.java).also {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(it)
|
||||
return
|
||||
}
|
||||
context.startService(it)
|
||||
}
|
||||
RestartWorker.start(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package org.unifiedpush.distributor.nextpush.services
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.work.*
|
||||
import org.unifiedpush.distributor.nextpush.services.SSEListener.Companion.lastEventDate
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
private const val UNIQUE_WORK_TAG = "nextpush::RestartWorker::unique"
|
||||
|
||||
class RestartWorker (ctx: Context, params: WorkerParameters) : Worker(ctx, params) {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "RestartWorker"
|
||||
fun start(context: Context, delay: Long? = null) {
|
||||
val work = PeriodicWorkRequestBuilder<RestartWorker>(20, TimeUnit.MINUTES)
|
||||
if (delay != null) {
|
||||
lastEventDate = null
|
||||
work.setInitialDelay(delay, TimeUnit.SECONDS)
|
||||
}
|
||||
val workManager = WorkManager.getInstance(context)
|
||||
workManager.enqueueUniquePeriodicWork(
|
||||
UNIQUE_WORK_TAG,
|
||||
ExistingPeriodicWorkPolicy.REPLACE,
|
||||
work.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun doWork(): Result {
|
||||
Log.d(TAG, "Working")
|
||||
val currentDate = Calendar.getInstance()
|
||||
val restartDate = lastEventDate?.add(Calendar.MINUTE, 15)
|
||||
if (restartDate == null || currentDate.after(restartDate)) {
|
||||
StartService.startListener(applicationContext)
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
package org.unifiedpush.distributor.nextpush.services
|
||||
|
||||
import android.content.Context
|
||||
import android.os.CountDownTimer
|
||||
import android.os.Looper
|
||||
import android.util.Base64
|
||||
import okhttp3.sse.EventSourceListener
|
||||
import okhttp3.sse.EventSource
|
||||
@ -16,15 +14,20 @@ import org.unifiedpush.distributor.nextpush.distributor.DistributorUtils.sendMes
|
||||
import org.unifiedpush.distributor.nextpush.distributor.DistributorUtils.sendUnregistered
|
||||
import org.unifiedpush.distributor.nextpush.services.NotificationUtils.createWarningNotification
|
||||
import org.unifiedpush.distributor.nextpush.services.NotificationUtils.deleteWarningNotification
|
||||
import java.util.*
|
||||
|
||||
private const val TAG = "SSEListener"
|
||||
|
||||
class SSEListener (val context: Context) : EventSourceListener() {
|
||||
|
||||
companion object {
|
||||
var lastEventDate : Calendar? = null
|
||||
}
|
||||
|
||||
override fun onOpen(eventSource: EventSource, response: Response) {
|
||||
deleteWarningNotification(context)
|
||||
nFails = 0
|
||||
wakeLock?.let {
|
||||
StartService.nFails = 0
|
||||
StartService.wakeLock?.let {
|
||||
while (it.isHeld) {
|
||||
it.release()
|
||||
}
|
||||
@ -38,7 +41,9 @@ class SSEListener (val context: Context) : EventSourceListener() {
|
||||
|
||||
override fun onEvent(eventSource: EventSource, id: String?, type: String?, data: String) {
|
||||
Log.d(TAG, "New SSE message event=$type message=$data")
|
||||
wakeLock?.acquire(10000L /*10 secs*/)
|
||||
StartService.wakeLock?.acquire(10000L /*10 secs*/)
|
||||
lastEventDate = Calendar.getInstance()
|
||||
|
||||
when (type) {
|
||||
"warning" -> Log.d(TAG, "Warning event received.")
|
||||
"ping" -> Log.d(TAG, "SSE ping received.")
|
||||
@ -61,7 +66,7 @@ class SSEListener (val context: Context) : EventSourceListener() {
|
||||
db.unregisterApp(connectorToken)
|
||||
}
|
||||
}
|
||||
wakeLock?.let {
|
||||
StartService.wakeLock?.let {
|
||||
if (it.isHeld) {
|
||||
it.release()
|
||||
}
|
||||
@ -69,49 +74,36 @@ class SSEListener (val context: Context) : EventSourceListener() {
|
||||
}
|
||||
|
||||
override fun onClosed(eventSource: EventSource) {
|
||||
if (!isServiceStarted)
|
||||
if (!StartService.isServiceStarted)
|
||||
return
|
||||
Log.d(TAG, "onClosed: $eventSource")
|
||||
nFails += 1
|
||||
StartService.nFails += 1
|
||||
createWarningNotification(context)
|
||||
startListener(context)
|
||||
RestartWorker.start(context, delay = 0)
|
||||
}
|
||||
|
||||
override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
|
||||
if (!isServiceStarted)
|
||||
if (!StartService.isServiceStarted)
|
||||
return
|
||||
Log.d(TAG, "onFailure")
|
||||
nFails += 1
|
||||
if (nFails > 1)
|
||||
createWarningNotification(context)
|
||||
val timeStop = when (nFails) {
|
||||
1 -> 2000 // 2sec
|
||||
2 -> 20000 // 20sec
|
||||
3 -> 60000 // 1min
|
||||
4 -> 300000 // 5min
|
||||
5 -> 600000 // 10min
|
||||
else -> 1800000 // 30min
|
||||
}.toLong()
|
||||
Log.d(TAG, "Retrying in $timeStop ms")
|
||||
Looper.prepare()
|
||||
object : CountDownTimer(timeStop, timeStop) {
|
||||
|
||||
override fun onTick(millisUntilFinished: Long) {}
|
||||
|
||||
override fun onFinish() {
|
||||
if (nFails > 0)
|
||||
Log.d(TAG, "Trying to restart")
|
||||
startListener(context)
|
||||
}
|
||||
|
||||
}.start()
|
||||
Looper.loop()
|
||||
t?.let {
|
||||
Log.d(TAG, "An error occurred: $t")
|
||||
return
|
||||
}
|
||||
response?.let {
|
||||
Log.d(TAG, "onFailure: ${it.code}")
|
||||
}
|
||||
StartService.nFails += 1
|
||||
if (StartService.nFails > 1)
|
||||
createWarningNotification(context)
|
||||
val delay = when (StartService.nFails) {
|
||||
1 -> 2 // 2sec
|
||||
2 -> 20 // 20sec
|
||||
3 -> 60 // 1min
|
||||
4 -> 300 // 5min
|
||||
5 -> 600 // 10min
|
||||
else -> return // else keep the worker with its 20min
|
||||
}.toLong()
|
||||
Log.d(TAG, "Retrying in $delay s")
|
||||
RestartWorker.start(context, delay = delay)
|
||||
}
|
||||
}
|
||||
|
@ -26,26 +26,30 @@ import org.unifiedpush.distributor.nextpush.services.NotificationUtils.createFor
|
||||
import java.lang.Exception
|
||||
|
||||
private const val TAG = "StartService"
|
||||
const val WAKE_LOCK_TAG = "NextPush:StartService:lock"
|
||||
const val SERVICE_STOPPED_ACTION = "org.unifiedpush.distributor.nextpush.services.STOPPED"
|
||||
var isServiceStarted = false
|
||||
var nFails = 0
|
||||
var wakeLock: PowerManager.WakeLock? = null
|
||||
|
||||
fun startListener(context: Context){
|
||||
if (isServiceStarted && nFails == 0) return
|
||||
Log.d(TAG, "Starting the Listener")
|
||||
val serviceIntent = Intent(context, StartService::class.java)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(serviceIntent)
|
||||
}else{
|
||||
context.startService(serviceIntent)
|
||||
}
|
||||
}
|
||||
|
||||
class StartService: Service(){
|
||||
|
||||
private var isCallbackRegistered = false
|
||||
companion object {
|
||||
const val WAKE_LOCK_TAG = "NextPush:StartService:lock"
|
||||
const val SERVICE_STOPPED_ACTION = "org.unifiedpush.distributor.nextpush.services.STOPPED"
|
||||
var isServiceStarted = false
|
||||
var nFails = 0
|
||||
var wakeLock: PowerManager.WakeLock? = null
|
||||
private var isCallbackRegistered = false
|
||||
|
||||
fun startListener(context: Context){
|
||||
if (isServiceStarted && nFails == 0) return
|
||||
Log.d(TAG, "Starting the Listener")
|
||||
Log.d(TAG, "Service is started: $isServiceStarted")
|
||||
Log.d(TAG, "nFails: $nFails")
|
||||
val serviceIntent = Intent(context, StartService::class.java)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(serviceIntent)
|
||||
}else{
|
||||
context.startService(serviceIntent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
return null
|
||||
@ -59,6 +63,7 @@ class StartService: Service(){
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Log.d(TAG, "onStartCommand")
|
||||
if (!isCallbackRegistered) {
|
||||
isCallbackRegistered = true
|
||||
registerNetworkCallback()
|
||||
@ -72,7 +77,7 @@ class StartService: Service(){
|
||||
Log.d(TAG, "Destroyed")
|
||||
if (isServiceStarted) {
|
||||
apiDestroy()
|
||||
startListener(this)
|
||||
RestartWorker.start(this, delay = 0)
|
||||
} else {
|
||||
stopService()
|
||||
}
|
||||
@ -121,7 +126,9 @@ class StartService: Service(){
|
||||
private val networkCallback = object : NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
Log.d(TAG, "Network is CONNECTED")
|
||||
startListener(this@StartService)
|
||||
if (nFails > 1) {
|
||||
RestartWorker.start(this@StartService, delay = 0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCapabilitiesChanged(
|
||||
@ -129,7 +136,9 @@ class StartService: Service(){
|
||||
networkCapabilities: NetworkCapabilities
|
||||
) {
|
||||
Log.d(TAG, "Network Capabilities changed")
|
||||
startListener(this@StartService)
|
||||
if (nFails > 1) {
|
||||
RestartWorker.start(this@StartService, delay = 0)
|
||||
} // else, it retries in max 2sec
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user