Skip to content

Commit 648429b

Browse files
authored
Merge pull request #401 from gotify/fixes
fix: reconnecting with wrong url/credentials in the background after logout
2 parents a82d985 + 6968a65 commit 648429b

3 files changed

Lines changed: 163 additions & 134 deletions

File tree

app/src/main/kotlin/com/github/gotify/service/WebSocketConnection.kt

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.gotify.service
22

33
import android.app.AlarmManager
4+
import android.app.AlarmManager.OnAlarmListener
45
import android.os.Build
56
import android.os.Handler
67
import android.os.Looper
@@ -29,9 +30,10 @@ internal class WebSocketConnection(
2930
private val ID = AtomicLong(0)
3031
}
3132

33+
private var alarmManagerCallback: OnAlarmListener? = null
34+
private var handlerCallback: Runnable? = null
3235
private val client: OkHttpClient
3336
private val reconnectHandler = Handler(Looper.getMainLooper())
34-
private val reconnectCallback = Runnable { start() }
3537
private var errorCount = 0
3638

3739
private var webSocket: WebSocket? = null
@@ -106,6 +108,13 @@ internal class WebSocketConnection(
106108

107109
@Synchronized
108110
fun close() {
111+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
112+
alarmManagerCallback?.run(alarmManager::cancel)
113+
alarmManagerCallback = null
114+
} else {
115+
handlerCallback?.run(reconnectHandler::removeCallbacks)
116+
handlerCallback = null
117+
}
109118
if (webSocket != null) {
110119
webSocket?.close(1000, "")
111120
closed()
@@ -119,8 +128,10 @@ internal class WebSocketConnection(
119128
state = State.Disconnected
120129
}
121130

131+
fun scheduleReconnectNow(seconds: Long) = scheduleReconnect(ID.get(), seconds)
132+
122133
@Synchronized
123-
fun scheduleReconnect(seconds: Long) {
134+
fun scheduleReconnect(id: Long, seconds: Long) {
124135
if (state == State.Connecting || state == State.Connected) {
125136
return
126137
}
@@ -130,17 +141,23 @@ internal class WebSocketConnection(
130141
Logger.info("WebSocket: scheduling a restart in $seconds second(s) (via alarm manager)")
131142
val future = Calendar.getInstance()
132143
future.add(Calendar.SECOND, seconds.toInt())
144+
145+
alarmManagerCallback?.run(alarmManager::cancel)
146+
val cb = OnAlarmListener { syncExec(id) { start() } }
147+
alarmManagerCallback = cb
133148
alarmManager.setExact(
134149
AlarmManager.RTC_WAKEUP,
135150
future.timeInMillis,
136151
"reconnect-tag",
137-
{ start() },
152+
cb,
138153
null
139154
)
140155
} else {
141156
Logger.info("WebSocket: scheduling a restart in $seconds second(s)")
142-
reconnectHandler.removeCallbacks(reconnectCallback)
143-
reconnectHandler.postDelayed(reconnectCallback, TimeUnit.SECONDS.toMillis(seconds))
157+
handlerCallback?.run(reconnectHandler::removeCallbacks)
158+
val cb = Runnable { syncExec(id) { start() } }
159+
handlerCallback = cb
160+
reconnectHandler.postDelayed(cb, TimeUnit.SECONDS.toMillis(seconds))
144161
}
145162
}
146163

@@ -190,7 +207,7 @@ internal class WebSocketConnection(
190207
val minutes = (errorCount * 2 - 1).coerceAtMost(20)
191208

192209
onFailure.execute(response?.message ?: "unreachable", minutes)
193-
scheduleReconnect(TimeUnit.MINUTES.toSeconds(minutes.toLong()))
210+
scheduleReconnect(id, TimeUnit.MINUTES.toSeconds(minutes.toLong()))
194211
}
195212
super.onFailure(webSocket, t, response)
196213
}

app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,7 @@ internal class WebSocketService : Service() {
172172
}
173173

174174
private fun doReconnect() {
175-
if (connection == null) {
176-
return
177-
}
178-
connection!!.scheduleReconnect(15)
175+
connection?.scheduleReconnectNow(15)
179176
}
180177

181178
private fun onFailure(status: String, minutes: Int) {
Lines changed: 139 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,152 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<ScrollView
3-
xmlns:android="http://schemas.android.com/apk/res/android"
2+
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
43
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:id="@+id/drawer_layout"
56
android:layout_width="match_parent"
67
android:layout_height="match_parent"
7-
android:fitsSystemWindows="true">
8+
android:fitsSystemWindows="true"
9+
tools:openDrawer="start">
810

9-
<LinearLayout
11+
<androidx.coordinatorlayout.widget.CoordinatorLayout
1012
android:layout_width="match_parent"
11-
android:layout_height="wrap_content"
12-
android:orientation="vertical">
13+
android:layout_height="match_parent">
1314

14-
<include
15-
android:id="@+id/app_bar_drawer"
16-
layout="@layout/app_bar_drawer"
17-
android:layout_width="match_parent"
18-
android:layout_height="wrap_content" />
19-
20-
<com.google.android.material.textfield.TextInputLayout
21-
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
15+
<androidx.core.widget.NestedScrollView
2216
android:layout_width="match_parent"
23-
android:layout_height="wrap_content"
24-
android:layout_margin="20dp">
17+
android:layout_height="match_parent"
18+
app:layout_behavior="@string/appbar_scrolling_view_behavior">
2519

26-
<com.google.android.material.textfield.TextInputEditText
27-
android:id="@+id/title"
20+
<LinearLayout
2821
android:layout_width="match_parent"
2922
android:layout_height="wrap_content"
30-
android:ems="10"
31-
android:hint="@string/push_title_hint"
32-
android:inputType="text"
33-
android:singleLine="true" />
34-
</com.google.android.material.textfield.TextInputLayout>
35-
36-
<com.google.android.material.textfield.TextInputLayout
37-
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
38-
android:layout_width="match_parent"
39-
android:layout_height="wrap_content"
40-
android:layout_marginHorizontal="20dp"
41-
android:layout_marginBottom="20dp">
42-
43-
<com.google.android.material.textfield.TextInputEditText
44-
android:id="@+id/content"
45-
android:layout_width="match_parent"
46-
android:layout_height="wrap_content"
47-
android:hint="@string/push_content_hint"
48-
android:inputType="textCapSentences|textMultiLine"
49-
android:maxLength="2000"
50-
android:maxLines="10" />
51-
</com.google.android.material.textfield.TextInputLayout>
52-
53-
<com.google.android.material.textfield.TextInputLayout
54-
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
55-
android:layout_width="match_parent"
56-
android:layout_height="wrap_content"
57-
android:layout_marginHorizontal="20dp"
58-
android:layout_marginBottom="20dp">
23+
android:orientation="vertical">
24+
25+
<com.google.android.material.textfield.TextInputLayout
26+
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
27+
android:layout_width="match_parent"
28+
android:layout_height="wrap_content"
29+
android:layout_margin="20dp">
30+
31+
<com.google.android.material.textfield.TextInputEditText
32+
android:id="@+id/title"
33+
android:layout_width="match_parent"
34+
android:layout_height="wrap_content"
35+
android:ems="10"
36+
android:hint="@string/push_title_hint"
37+
android:inputType="text"
38+
android:singleLine="true" />
39+
</com.google.android.material.textfield.TextInputLayout>
40+
41+
<com.google.android.material.textfield.TextInputLayout
42+
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
43+
android:layout_width="match_parent"
44+
android:layout_height="wrap_content"
45+
android:layout_marginHorizontal="20dp"
46+
android:layout_marginBottom="20dp">
47+
48+
<com.google.android.material.textfield.TextInputEditText
49+
android:id="@+id/content"
50+
android:layout_width="match_parent"
51+
android:layout_height="wrap_content"
52+
android:hint="@string/push_content_hint"
53+
android:inputType="textCapSentences|textMultiLine"
54+
android:maxLength="2000"
55+
android:maxLines="10" />
56+
</com.google.android.material.textfield.TextInputLayout>
57+
58+
<com.google.android.material.textfield.TextInputLayout
59+
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
60+
android:layout_width="match_parent"
61+
android:layout_height="wrap_content"
62+
android:layout_marginHorizontal="20dp"
63+
android:layout_marginBottom="20dp">
64+
65+
<com.google.android.material.textfield.TextInputEditText
66+
android:id="@+id/edtTxtPriority"
67+
android:layout_width="match_parent"
68+
android:layout_height="wrap_content"
69+
android:digits="0123456789"
70+
android:hint="@string/push_priority_hint"
71+
android:imeOptions="actionDone"
72+
android:inputType="numberSigned"
73+
android:maxLength="3"
74+
android:text="0" />
75+
</com.google.android.material.textfield.TextInputLayout>
76+
77+
<LinearLayout
78+
android:layout_width="match_parent"
79+
android:layout_height="wrap_content"
80+
android:layout_marginHorizontal="20dp"
81+
android:layout_marginBottom="20dp">
82+
83+
<com.google.android.material.textview.MaterialTextView
84+
android:id="@+id/txtAppListDesc"
85+
android:layout_width="wrap_content"
86+
android:layout_height="wrap_content"
87+
android:text="@string/appListDescription" />
88+
89+
<Spinner
90+
android:id="@+id/appSpinner"
91+
android:layout_width="wrap_content"
92+
android:layout_height="50dp"
93+
android:spinnerMode="dropdown"
94+
android:textSize="18sp" />
95+
</LinearLayout>
96+
97+
<LinearLayout
98+
android:id="@+id/missingAppsContainer"
99+
android:layout_width="match_parent"
100+
android:layout_height="wrap_content"
101+
android:layout_marginHorizontal="20dp"
102+
android:layout_marginBottom="20dp"
103+
android:gravity="center"
104+
android:orientation="horizontal"
105+
android:paddingStart="10dp"
106+
android:paddingEnd="10dp"
107+
android:visibility="gone">
108+
109+
<ImageView
110+
android:id="@+id/missingAppsIcon"
111+
android:layout_width="40dp"
112+
android:layout_height="match_parent"
113+
android:layout_weight="0"
114+
app:srcCompat="@drawable/ic_info" />
115+
116+
<Space
117+
android:layout_width="10dp"
118+
android:layout_height="match_parent"
119+
android:layout_weight="0" />
120+
121+
<com.google.android.material.textview.MaterialTextView
122+
android:id="@+id/missingAppsText"
123+
android:layout_width="wrap_content"
124+
android:layout_height="match_parent"
125+
android:layout_weight="0"
126+
android:text="@string/push_missing_app_info"
127+
android:textAlignment="center"
128+
android:visibility="visible" />
129+
</LinearLayout>
130+
131+
<com.google.android.material.button.MaterialButton
132+
android:id="@+id/push_button"
133+
android:layout_width="match_parent"
134+
android:layout_height="wrap_content"
135+
android:layout_gravity="center_vertical|center_horizontal"
136+
android:layout_marginHorizontal="20dp"
137+
android:layout_marginBottom="20dp"
138+
android:text="@string/push_button"
139+
android:textColor="@android:color/white" />
140+
141+
</LinearLayout>
142+
143+
144+
</androidx.core.widget.NestedScrollView>
59145

60-
<com.google.android.material.textfield.TextInputEditText
61-
android:id="@+id/edtTxtPriority"
62-
android:layout_width="match_parent"
63-
android:layout_height="wrap_content"
64-
android:digits="0123456789"
65-
android:hint="@string/push_priority_hint"
66-
android:imeOptions="actionDone"
67-
android:inputType="numberSigned"
68-
android:maxLength="3"
69-
android:text="0" />
70-
</com.google.android.material.textfield.TextInputLayout>
71-
72-
<LinearLayout
73-
android:layout_width="match_parent"
74-
android:layout_height="wrap_content"
75-
android:layout_marginHorizontal="20dp"
76-
android:layout_marginBottom="20dp">
77-
78-
<com.google.android.material.textview.MaterialTextView
79-
android:id="@+id/txtAppListDesc"
80-
android:layout_width="wrap_content"
81-
android:layout_height="wrap_content"
82-
android:text="@string/appListDescription" />
83-
84-
<Spinner
85-
android:id="@+id/appSpinner"
86-
android:layout_width="wrap_content"
87-
android:layout_height="50dp"
88-
android:spinnerMode="dropdown"
89-
android:textSize="18sp" />
90-
</LinearLayout>
91-
92-
<LinearLayout
93-
android:id="@+id/missingAppsContainer"
94-
android:layout_width="match_parent"
95-
android:layout_height="wrap_content"
96-
android:layout_marginHorizontal="20dp"
97-
android:layout_marginBottom="20dp"
98-
android:gravity="center"
99-
android:orientation="horizontal"
100-
android:paddingStart="10dp"
101-
android:paddingEnd="10dp"
102-
android:visibility="gone">
103-
104-
<ImageView
105-
android:id="@+id/missingAppsIcon"
106-
android:layout_width="40dp"
107-
android:layout_height="match_parent"
108-
android:layout_weight="0"
109-
app:srcCompat="@drawable/ic_info" />
110-
111-
<Space
112-
android:layout_width="10dp"
113-
android:layout_height="match_parent"
114-
android:layout_weight="0" />
115-
116-
<com.google.android.material.textview.MaterialTextView
117-
android:id="@+id/missingAppsText"
118-
android:layout_width="wrap_content"
119-
android:layout_height="match_parent"
120-
android:layout_weight="0"
121-
android:text="@string/push_missing_app_info"
122-
android:textAlignment="center"
123-
android:visibility="visible" />
124-
</LinearLayout>
125-
126-
<com.google.android.material.button.MaterialButton
127-
android:id="@+id/push_button"
146+
<include
147+
android:id="@+id/app_bar_drawer"
148+
layout="@layout/app_bar_drawer"
128149
android:layout_width="match_parent"
129-
android:layout_height="wrap_content"
130-
android:layout_gravity="center_vertical|center_horizontal"
131-
android:layout_marginHorizontal="20dp"
132-
android:layout_marginBottom="20dp"
133-
android:textColor="@android:color/white"
134-
android:text="@string/push_button" />
135-
136-
</LinearLayout>
137-
</ScrollView>
150+
android:layout_height="wrap_content" />
151+
</androidx.coordinatorlayout.widget.CoordinatorLayout>
152+
</androidx.drawerlayout.widget.DrawerLayout>

0 commit comments

Comments
 (0)