Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ internal class WebSocketConnection(
private val baseUrl: String,
settings: SSLSettings,
private val token: String?,
private val alarmManager: AlarmManager
private val alarmManager: AlarmManager,
private val reconnectInterval: Int,
private val disableBackoff: Boolean
) {
companion object {
private val ID = AtomicLong(0)
Expand Down Expand Up @@ -204,10 +206,16 @@ internal class WebSocketConnection(
closed()

errorCount++
val minutes = (errorCount * 2 - 1).coerceAtMost(20)
val seconds = if (disableBackoff) {
reconnectInterval
} else {
((errorCount * 2 - 1) * reconnectInterval)
.coerceAtMost(TimeUnit.MINUTES.toSeconds(20).toInt())
}

onFailure.execute(response?.message ?: "unreachable", minutes)
scheduleReconnect(id, TimeUnit.MINUTES.toSeconds(minutes.toLong()))
val rounded = seconds.coerceAtLeast(5)
onFailure.execute(response?.message ?: "unreachable", rounded)
scheduleReconnect(id, rounded.toLong())
}
super.onFailure(webSocket, t, response)
}
Expand All @@ -221,7 +229,7 @@ internal class WebSocketConnection(
}

internal fun interface OnNetworkFailureRunnable {
fun execute(status: String, minutes: Int)
fun execute(status: String, seconds: Int)
}

internal enum class State {
Expand Down
28 changes: 23 additions & 5 deletions app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,30 @@ internal class WebSocketService : Service() {

val cm = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
var reconnectInterval = sharedPreferences
.getString(getString(R.string.setting_key_reconnect_interval), "60")
?.trim()
?.toIntOrNull() ?: 60

reconnectInterval = reconnectInterval.coerceIn(5, 60)

val disableBackoff = sharedPreferences.getBoolean(
getString(R.string.setting_key_backoff),
false
)

connection = WebSocketConnection(
settings.url,
settings.sslSettings(),
settings.token,
alarmManager
alarmManager,
reconnectInterval,
disableBackoff
)
.onOpen { onOpen() }
.onClose { onClose() }
.onFailure { status, minutes -> onFailure(status, minutes) }
.onFailure { status, seconds -> onFailure(status, seconds) }
.onMessage { message -> onMessage(message) }
.onReconnected { notifyMissedNotifications() }
.start()
Expand Down Expand Up @@ -183,10 +197,14 @@ internal class WebSocketService : Service() {
connection?.scheduleReconnectNow(15)
}

private fun onFailure(status: String, minutes: Int) {
private fun onFailure(status: String, seconds: Int) {
val title = getString(R.string.websocket_error, status)
val intervalUnit = resources
.getQuantityString(R.plurals.websocket_retry_interval, minutes, minutes)
val intervalUnit = if (seconds >= 60) {
val minutes = seconds / 60
resources.getQuantityString(R.plurals.websocket_retry_interval, minutes, minutes)
} else {
resources.getQuantityString(R.plurals.websocket_retry_interval_seconds, seconds, seconds)
}
showForegroundNotification(
title,
"${getString(R.string.websocket_reconnect)} $intervalUnit"
Expand Down
30 changes: 30 additions & 0 deletions app/src/main/kotlin/com/github/gotify/settings/SettingsActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,36 @@ internal class SettingsActivity :
getString(R.string.setting_key_notification_channels)
)?.isEnabled = true
}
findPreference<androidx.preference.EditTextPreference>(
getString(R.string.setting_key_reconnect_interval)
)?.let {
it.setOnBindEditTextListener { editText ->
editText.inputType = android.text.InputType.TYPE_CLASS_NUMBER
}
it.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, newValue ->
val value = (newValue as String).trim().toIntOrNull() ?: 60
if (value < 5 || value > 60) {
Utils.showSnackBar(requireActivity(), "Please enter a value between 5 and 60")
return@OnPreferenceChangeListener false
}

requestWebSocketRestart()
true
}
}
findPreference<SwitchPreferenceCompat>(
getString(R.string.setting_key_backoff)
)?.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, _ ->
requestWebSocketRestart()
true
}
}

private fun requestWebSocketRestart() {
val intent = Intent(requireContext(), com.github.gotify.service.WebSocketService::class.java)
requireContext().startService(intent)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
</string-array>
<string name="time_format_value_absolute">time_format_absolute</string>
<string name="time_format_value_relative">time_format_relative</string>

<bool name="notification_channels">false</bool>
<bool name="exclude_from_recent">false</bool>
<bool name="prompt_onreceive_intent">true</bool>
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@
<item quantity="one">in %d minute</item>
<item quantity="other">in %d minutes</item>
</plurals>
<plurals name="websocket_retry_interval_seconds">
<item quantity="one">in %d second</item>
<item quantity="other">in %d seconds</item>
</plurals>
<string name="setting_reconnect_interval">Reconnect Interval (Seconds)</string>
<string name="setting_key_reconnect_interval">reconnect_interval</string>
<string name="setting_connection">Connection</string>
<string name="reconnect_interval_10_seconds">10 seconds</string>
<string name="reconnect_interval_30_seconds">30 seconds</string>
<string name="reconnect_interval_1_minute">1 minute (Default)</string>
<string name="reconnect_interval_5_minutes">5 minutes</string>
<string name="setting_reconnect_interval_summary">Wait time between connection attempts</string>
<string name="setting_backoff_title">Constant Retry Interval</string>
<string name="setting_backoff_summary">Do not increase wait time between retries</string>
<string name="setting_key_backoff">reconnect_backoff</string>

<string name="notification_channel_title_foreground">Gotify foreground notification</string>
<string name="notification_channel_title_min">Min priority messages (&lt;1)</string>
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/xml/root_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,17 @@
android:summary="@string/setting_summary_prompt_onreceive_intent" />
</PreferenceCategory>

<PreferenceCategory app:title="@string/setting_connection">
<EditTextPreference
android:defaultValue="60"
android:key="@string/setting_key_reconnect_interval"
android:title="@string/setting_reconnect_interval"
android:summary="@string/setting_reconnect_interval_summary" />
<SwitchPreferenceCompat
android:key="@string/setting_key_backoff"
android:title="@string/setting_backoff_title"
android:summary="@string/setting_backoff_summary"
android:defaultValue="false" />
</PreferenceCategory>

</PreferenceScreen>