Remove foreground service restart() function, in an attempt to avoid crashes
This commit is contained in:
parent
50d3e9b038
commit
d064e751c4
5 changed files with 36 additions and 21 deletions
|
|
@ -6,7 +6,14 @@ interface Connection {
|
|||
fun since(): String?
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a unique connection identifier that changes every time a
|
||||
* connection needs to be re-established.
|
||||
*/
|
||||
data class ConnectionId(
|
||||
val baseUrl: String,
|
||||
val topicsToSubscriptionIds: Map<String, Long>
|
||||
val topicsToSubscriptionIds: Map<String, Long>,
|
||||
val connectionProtocol: String,
|
||||
val credentialsHash: Int, // Hash of "username:password" or 0 if no user
|
||||
val headersHash: Int // Hash of sorted headers or 0 if none
|
||||
)
|
||||
|
|
|
|||
|
|
@ -206,9 +206,27 @@ class SubscriberService : Service() {
|
|||
val instantSubscriptions = repository.getSubscriptions()
|
||||
.filter { s -> s.instant }
|
||||
val activeConnectionIds = connections.keys().toList().toSet()
|
||||
val connectionProtocol = repository.getConnectionProtocol()
|
||||
val desiredConnectionIds = instantSubscriptions // Set<ConnectionId>
|
||||
.groupBy { s -> ConnectionId(s.baseUrl, emptyMap()) }
|
||||
.map { entry -> entry.key.copy(topicsToSubscriptionIds = entry.value.associate { s -> s.topic to s.id }) }
|
||||
.groupBy { s -> s.baseUrl }
|
||||
.map { (baseUrl, subs) ->
|
||||
// Create a unique connection ID for each base URL. Each change in the connection ID will
|
||||
// trigger a new connection, and close existing connections. We want to make sure that when the
|
||||
// connection protocol (JSON/WS), the user or the custom headers are updated, that we kill existing
|
||||
// connections and start new ones.
|
||||
val credentialsHash = repository.getUser(baseUrl)?.let { "${it.username}:${it.password}".hashCode() } ?: 0
|
||||
val headersHash = repository.getCustomHeadersForServer(baseUrl)
|
||||
.sortedBy { "${it.name}:${it.value}" }
|
||||
.joinToString(",") { "${it.name}:${it.value}" }
|
||||
.hashCode()
|
||||
ConnectionId(
|
||||
baseUrl = baseUrl,
|
||||
topicsToSubscriptionIds = subs.associate { s -> s.topic to s.id },
|
||||
connectionProtocol = connectionProtocol,
|
||||
credentialsHash = credentialsHash,
|
||||
headersHash = headersHash
|
||||
)
|
||||
}
|
||||
.toSet()
|
||||
val newConnectionIds = desiredConnectionIds.subtract(activeConnectionIds)
|
||||
val obsoleteConnectionIds = activeConnectionIds.subtract(desiredConnectionIds)
|
||||
|
|
@ -237,7 +255,7 @@ class SubscriberService : Service() {
|
|||
val since = sinceByBaseUrl[connectionId.baseUrl] ?: "none"
|
||||
val serviceActive = { isServiceStarted }
|
||||
val user = repository.getUser(connectionId.baseUrl)
|
||||
val connection = if (repository.getConnectionProtocol() == Repository.CONNECTION_PROTOCOL_WS) {
|
||||
val connection = if (connectionId.connectionProtocol == Repository.CONNECTION_PROTOCOL_WS) {
|
||||
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
|
||||
WsConnection(connectionId, repository, user, since, ::onStateChanged, ::onNotificationReceived, alarmManager)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -26,12 +26,6 @@ class SubscriberServiceManager(private val context: Context) {
|
|||
workManager.enqueueUniqueWork(WORK_NAME_ONCE, ExistingWorkPolicy.KEEP, startServiceRequest) // Unique avoids races!
|
||||
}
|
||||
|
||||
fun restart() {
|
||||
Intent(context, SubscriberService::class.java).also { intent ->
|
||||
context.stopService(intent) // Service will auto-restart
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts or stops the foreground service by figuring out how many instant delivery subscriptions
|
||||
* exist. If there's > 0, then we need a foreground service.
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ class MainActivity : AppCompatActivity(), AddFragment.SubscribeListener, Notific
|
|||
}
|
||||
wsEnableButton.setOnClickListener {
|
||||
repository.setConnectionProtocol(Repository.CONNECTION_PROTOCOL_WS)
|
||||
SubscriberServiceManager(this).restart()
|
||||
SubscriberServiceManager(this).refresh()
|
||||
wsBanner.visibility = View.GONE
|
||||
|
||||
// Maybe show WebSocketReconnectBanner
|
||||
|
|
|
|||
|
|
@ -700,7 +700,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
override fun putString(key: String?, value: String?) {
|
||||
val proto = value ?: repository.getConnectionProtocol()
|
||||
repository.setConnectionProtocol(proto)
|
||||
restartService()
|
||||
serviceManager.refresh() // Refresh to switch connections between WS and JSON stream
|
||||
}
|
||||
override fun getString(key: String?, defValue: String?): String {
|
||||
return repository.getConnectionProtocol()
|
||||
|
|
@ -737,10 +737,6 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
repository.setAutoDownloadMaxSize(autoDownloadSelectionCopy)
|
||||
}
|
||||
|
||||
private fun restartService() {
|
||||
serviceManager.restart() // Service will auto-restart
|
||||
}
|
||||
|
||||
private fun copyLogsToClipboard(scrub: Boolean) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val context = context ?: return@launch
|
||||
|
|
@ -1056,7 +1052,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
override fun onUpdateUser(dialog: DialogFragment, user: User) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
repository.updateUser(user)
|
||||
serviceManager.restart() // Editing does not change the user ID
|
||||
serviceManager.refresh()
|
||||
runOnUiThread {
|
||||
if (this@SettingsActivity::userSettingsFragment.isInitialized) {
|
||||
userSettingsFragment.reload()
|
||||
|
|
@ -1068,7 +1064,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
override fun onDeleteUser(dialog: DialogFragment, baseUrl: String) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
repository.deleteUser(baseUrl)
|
||||
serviceManager.restart()
|
||||
serviceManager.refresh()
|
||||
runOnUiThread {
|
||||
if (this@SettingsActivity::userSettingsFragment.isInitialized) {
|
||||
userSettingsFragment.reload()
|
||||
|
|
@ -1080,7 +1076,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
override fun onAddCustomHeader(dialog: DialogFragment, header: io.heckel.ntfy.db.CustomHeader) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
repository.addCustomHeader(header)
|
||||
serviceManager.restart() // Restart to apply new headers
|
||||
serviceManager.refresh() // Refresh to apply new headers
|
||||
runOnUiThread {
|
||||
if (this@SettingsActivity::customHeaderSettingsFragment.isInitialized) {
|
||||
customHeaderSettingsFragment.reload()
|
||||
|
|
@ -1092,7 +1088,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
override fun onUpdateCustomHeader(dialog: DialogFragment, oldHeader: io.heckel.ntfy.db.CustomHeader, newHeader: io.heckel.ntfy.db.CustomHeader) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
repository.updateCustomHeader(oldHeader, newHeader)
|
||||
serviceManager.restart() // Restart to apply header changes
|
||||
serviceManager.refresh() // Refresh to apply header changes
|
||||
runOnUiThread {
|
||||
if (this@SettingsActivity::customHeaderSettingsFragment.isInitialized) {
|
||||
customHeaderSettingsFragment.reload()
|
||||
|
|
@ -1104,7 +1100,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
override fun onDeleteCustomHeader(dialog: DialogFragment, header: io.heckel.ntfy.db.CustomHeader) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
repository.deleteCustomHeader(header)
|
||||
serviceManager.restart()
|
||||
serviceManager.refresh()
|
||||
runOnUiThread {
|
||||
if (this@SettingsActivity::customHeaderSettingsFragment.isInitialized) {
|
||||
customHeaderSettingsFragment.reload()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue