Restart only if a connection has succeeded once

This commit is contained in:
sim 2023-03-22 21:20:45 +01:00
parent 254a776244
commit d4870c39ad
7 changed files with 92 additions and 9 deletions

View File

@ -9,6 +9,7 @@ import org.unifiedpush.distributor.nextpush.utils.TAG
internal const val PREF_NAME = "NextPush"
private const val PREF_DEVICE_ID = "deviceId"
private const val PREF_ACCOUNT_TYPE = "account::type"
private const val PREF_HAS_STARTED_ONCE = "account::has_started_once"
enum class AccountType {
SSO,
@ -47,6 +48,12 @@ object Account {
}.apply()
}
var Context.hasStartedOnce: Boolean
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getBoolean(PREF_HAS_STARTED_ONCE, false)
set(value) = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putBoolean(PREF_HAS_STARTED_ONCE, value).apply()
fun getAccount(context: Context, uninitialized: Boolean = false): AccountFactory? {
return account
?: run {
@ -79,6 +86,12 @@ object Account {
}
}
fun logout(context: Context) {
getAccount(context)?.logout(context)
context.deviceId = null
context.hasStartedOnce = false
}
fun Context.setTypeSSO() {
account = null
accountType = AccountType.SSO

View File

@ -10,6 +10,7 @@ import android.view.View
import android.widget.* // ktlint-disable no-wildcard-imports
import androidx.appcompat.app.AppCompatActivity
import org.unifiedpush.distributor.nextpush.R
import org.unifiedpush.distributor.nextpush.account.Account
import org.unifiedpush.distributor.nextpush.account.Account.getAccount
import org.unifiedpush.distributor.nextpush.account.Account.isConnected
import org.unifiedpush.distributor.nextpush.activities.PermissionsRequest.requestAppPermissions
@ -92,7 +93,7 @@ class MainActivity : AppCompatActivity() {
StartService.stopService()
FailureHandler.clearFails()
}
getAccount(this)?.logout(this)
Account.logout(this)
finish()
goToStartActivity(this)
}

View File

@ -7,12 +7,14 @@ import com.google.gson.Gson
import okhttp3.Response
import okhttp3.sse.EventSource
import okhttp3.sse.EventSourceListener
import org.unifiedpush.distributor.nextpush.account.Account.hasStartedOnce
import org.unifiedpush.distributor.nextpush.api.response.SSEResponse
import org.unifiedpush.distributor.nextpush.distributor.Distributor.deleteAppFromSSE
import org.unifiedpush.distributor.nextpush.distributor.Distributor.sendMessage
import org.unifiedpush.distributor.nextpush.services.FailureHandler
import org.unifiedpush.distributor.nextpush.services.RestartWorker
import org.unifiedpush.distributor.nextpush.services.StartService
import org.unifiedpush.distributor.nextpush.utils.NotificationUtils.createStartErrorNotification
import org.unifiedpush.distributor.nextpush.utils.TAG
import java.lang.Exception
import java.util.Calendar
@ -39,6 +41,7 @@ class SSEListener(val context: Context) : EventSourceListener() {
lastEventDate = Calendar.getInstance()
when (type) {
"start" -> context.hasStartedOnce = true
"keepalive" -> {
val message = Gson().fromJson(data, SSEResponse::class.java)
keepalive = message.keepalive
@ -65,21 +68,17 @@ class SSEListener(val context: Context) : EventSourceListener() {
}
override fun onClosed(eventSource: EventSource) {
eventSource.cancel()
if (!StartService.isServiceStarted) {
return
}
Log.d(TAG, "onClosed: $eventSource")
eventSource.cancel()
if (!shouldRestart()) return
FailureHandler.newFail(context, eventSource)
RestartWorker.run(context, delay = 0)
}
override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
eventSource.cancel()
if (!StartService.isServiceStarted) {
return
}
Log.d(TAG, "onFailure")
eventSource.cancel()
if (!shouldRestart()) return
t?.let {
Log.d(TAG, "An error occurred: $t")
}
@ -100,6 +99,21 @@ class SSEListener(val context: Context) : EventSourceListener() {
RestartWorker.run(context, delay = delay)
}
private fun shouldRestart(): Boolean {
if (!StartService.isServiceStarted) {
Log.d(TAG, "StartService not started")
return false
}
if (!context.hasStartedOnce) {
Log.d(TAG, "SSE event 'start' never received")
Log.d(TAG, "Stopping service")
StartService.stopService()
createStartErrorNotification(context)
return false
}
return true
}
companion object {
var lastEventDate: Calendar? = null
var keepalive = 900

View File

@ -58,5 +58,9 @@ class RestartWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params
work.build()
)
}
fun stopPeriodic(context: Context) {
WorkManager.getInstance(context).cancelAllWorkByTag(UNIQUE_PERIODIC_WORK_TAG)
}
}
}

View File

@ -52,6 +52,7 @@ class StartService : Service() {
RestartWorker.run(this, delay = 0)
} else {
networkCallback.unregister()
RestartWorker.stopPeriodic(this)
}
}

View File

@ -130,6 +130,53 @@ object NotificationUtils {
warningShown = true
}
fun createStartErrorNotification(context: Context) {
val notificationChannelId = "${context.getString(R.string.app_name)}.StartError"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(
notificationChannelId,
"Start error",
NotificationManager.IMPORTANCE_HIGH
).let {
it.description = context.getString(R.string.start_error_notif_description)
it
}
notificationManager.createNotificationChannel(channel)
}
val builder: Notification.Builder = (
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Notification.Builder(
context,
notificationChannelId
)
} else {
Notification.Builder(context)
}
).setContentTitle(context.getString(R.string.app_name))
.setContentText(context.getString(R.string.start_error_notif_content))
.setStyle(
Notification.BigTextStyle()
.bigText(context.getString(R.string.start_error_notif_content))
)
.setSmallIcon(R.drawable.ic_logo)
.setTicker(context.getString(R.string.start_error_notif_ticker))
.setPriority(Notification.PRIORITY_HIGH) // for under android 26 compatibility
with(NotificationManagerCompat.from(context)) {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
) {
notify(NOTIFICATION_ID_WARNING, builder.build())
}
}
}
fun deleteWarningNotification(context: Context) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

View File

@ -15,6 +15,9 @@
<string name="main_account_title">Account</string>
<string name="main_account_desc">You are connected as: %s</string>
<string name="action_restart">Restart Service</string>
<string name="start_error_notif_content">The service could not be started correctly. Check the configuration of your server.</string>
<string name="start_error_notif_description">The service can not start correctly</string>
<string name="start_error_notif_ticker">Error</string>
<string name="warning_notif_description">NextPush is disconnected</string>
<string name="warning_notif_ticker">Warning</string>
<string name="foreground_notif_ticker">Foreground</string>