Merge pull request #401 from gotify/fixes

fix: reconnecting with wrong url/credentials in the background after logout
This commit is contained in:
Jannis Mattheis
2025-02-15 12:33:33 +01:00
committed by GitHub
3 changed files with 164 additions and 135 deletions

View File

@@ -1,6 +1,7 @@
package com.github.gotify.service
import android.app.AlarmManager
import android.app.AlarmManager.OnAlarmListener
import android.os.Build
import android.os.Handler
import android.os.Looper
@@ -29,9 +30,10 @@ internal class WebSocketConnection(
private val ID = AtomicLong(0)
}
private var alarmManagerCallback: OnAlarmListener? = null
private var handlerCallback: Runnable? = null
private val client: OkHttpClient
private val reconnectHandler = Handler(Looper.getMainLooper())
private val reconnectCallback = Runnable { start() }
private var errorCount = 0
private var webSocket: WebSocket? = null
@@ -106,6 +108,13 @@ internal class WebSocketConnection(
@Synchronized
fun close() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
alarmManagerCallback?.run(alarmManager::cancel)
alarmManagerCallback = null
} else {
handlerCallback?.run(reconnectHandler::removeCallbacks)
handlerCallback = null
}
if (webSocket != null) {
webSocket?.close(1000, "")
closed()
@@ -119,8 +128,10 @@ internal class WebSocketConnection(
state = State.Disconnected
}
fun scheduleReconnectNow(seconds: Long) = scheduleReconnect(ID.get(), seconds)
@Synchronized
fun scheduleReconnect(seconds: Long) {
fun scheduleReconnect(id: Long, seconds: Long) {
if (state == State.Connecting || state == State.Connected) {
return
}
@@ -130,17 +141,23 @@ internal class WebSocketConnection(
Logger.info("WebSocket: scheduling a restart in $seconds second(s) (via alarm manager)")
val future = Calendar.getInstance()
future.add(Calendar.SECOND, seconds.toInt())
alarmManagerCallback?.run(alarmManager::cancel)
val cb = OnAlarmListener { syncExec(id) { start() } }
alarmManagerCallback = cb
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
future.timeInMillis,
"reconnect-tag",
{ start() },
cb,
null
)
} else {
Logger.info("WebSocket: scheduling a restart in $seconds second(s)")
reconnectHandler.removeCallbacks(reconnectCallback)
reconnectHandler.postDelayed(reconnectCallback, TimeUnit.SECONDS.toMillis(seconds))
handlerCallback?.run(reconnectHandler::removeCallbacks)
val cb = Runnable { syncExec(id) { start() } }
handlerCallback = cb
reconnectHandler.postDelayed(cb, TimeUnit.SECONDS.toMillis(seconds))
}
}
@@ -190,7 +207,7 @@ internal class WebSocketConnection(
val minutes = (errorCount * 2 - 1).coerceAtMost(20)
onFailure.execute(response?.message ?: "unreachable", minutes)
scheduleReconnect(TimeUnit.MINUTES.toSeconds(minutes.toLong()))
scheduleReconnect(id, TimeUnit.MINUTES.toSeconds(minutes.toLong()))
}
super.onFailure(webSocket, t, response)
}

View File

@@ -172,10 +172,7 @@ internal class WebSocketService : Service() {
}
private fun doReconnect() {
if (connection == null) {
return
}
connection!!.scheduleReconnect(15)
connection?.scheduleReconnectNow(15)
}
private fun onFailure(status: String, minutes: Int) {

View File

@@ -1,22 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
tools:openDrawer="start">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/app_bar_drawer"
layout="@layout/app_bar_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
@@ -130,8 +135,18 @@
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:textColor="@android:color/white"
android:text="@string/push_button" />
android:text="@string/push_button"
android:textColor="@android:color/white" />
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
<include
android:id="@+id/app_bar_drawer"
layout="@layout/app_bar_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.drawerlayout.widget.DrawerLayout>