UnifiedPush WIP
This commit is contained in:
committed by
Benoit Marty
parent
95bafe4059
commit
80268156b5
@@ -37,7 +37,7 @@ interface PushProvider {
|
||||
/**
|
||||
* Register the pusher to the homeserver
|
||||
*/
|
||||
suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor, clientSecret: String)
|
||||
suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor)
|
||||
|
||||
/**
|
||||
* Unregister the pusher
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.element.android.libraries.push.providers.firebase
|
||||
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.asSessionId
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
@@ -41,15 +41,17 @@ class FirebaseNewTokenHandler @Inject constructor(
|
||||
suspend fun handle(firebaseToken: String) {
|
||||
firebaseStore.storeFcmToken(firebaseToken)
|
||||
// Register the pusher for all the sessions
|
||||
sessionStore.getAllSessions().toUserList().forEach { userId ->
|
||||
val userDataStore = userPushStoreFactory.create(userId)
|
||||
if (userDataStore.getPushProviderName() == FirebaseConfig.name) {
|
||||
matrixAuthenticationService.restoreSession(SessionId(userId)).getOrNull()?.use { client ->
|
||||
pusherSubscriber.registerPusher(client, firebaseToken, FirebaseConfig.pusher_http_url)
|
||||
sessionStore.getAllSessions().toUserList()
|
||||
.map { it.asSessionId() }
|
||||
.forEach { userId ->
|
||||
val userDataStore = userPushStoreFactory.create(userId)
|
||||
if (userDataStore.getPushProviderName() == FirebaseConfig.name) {
|
||||
matrixAuthenticationService.restoreSession(userId).getOrNull()?.use { client ->
|
||||
pusherSubscriber.registerPusher(client, firebaseToken, FirebaseConfig.pusher_http_url)
|
||||
}
|
||||
} else {
|
||||
Timber.tag(loggerTag.value).d("This session is not using Firebase pusher")
|
||||
}
|
||||
} else {
|
||||
Timber.tag(loggerTag.value).d("This session is not using Firebase pusher")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PushProvider
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -30,6 +31,7 @@ class FirebasePushProvider @Inject constructor(
|
||||
private val firebaseStore: FirebaseStore,
|
||||
private val firebaseTroubleshooter: FirebaseTroubleshooter,
|
||||
private val pusherSubscriber: PusherSubscriber,
|
||||
private val pushClientSecret: PushClientSecret,
|
||||
) : PushProvider {
|
||||
override val index = FirebaseConfig.index
|
||||
override val name = FirebaseConfig.name
|
||||
@@ -38,7 +40,7 @@ class FirebasePushProvider @Inject constructor(
|
||||
return listOf(Distributor("Firebase", "Firebase"))
|
||||
}
|
||||
|
||||
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor, clientSecret: String) {
|
||||
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor) {
|
||||
val pushKey = firebaseStore.getFcmToken() ?: return Unit.also {
|
||||
Timber.tag(loggerTag.value).w("Unable to register pusher, Firebase token is not known.")
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ class RegisterUnifiedPushUseCase @Inject constructor(
|
||||
val distributorValue = distributor.value
|
||||
if (distributorValue.isNotEmpty()) {
|
||||
saveAndRegisterApp(distributorValue, clientSecret)
|
||||
val endpoint = unifiedPushStore.getEndpoint() ?: return RegisterUnifiedPushResult.Error
|
||||
val gateway = unifiedPushStore.getPushGateway() ?: return RegisterUnifiedPushResult.Error
|
||||
val endpoint = unifiedPushStore.getEndpoint(clientSecret) ?: return RegisterUnifiedPushResult.Error
|
||||
val gateway = unifiedPushStore.getPushGateway(clientSecret) ?: return RegisterUnifiedPushResult.Error
|
||||
pusherSubscriber.registerPusher(matrixClient, endpoint, gateway)
|
||||
return RegisterUnifiedPushResult.Success
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.network.RetrofitFactory
|
||||
import io.element.android.libraries.push.providers.unifiedpush.network.UnifiedPushApi
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
import javax.inject.Inject
|
||||
|
||||
class UnifiedPushGatewayResolver @Inject constructor(
|
||||
private val retrofitFactory: RetrofitFactory,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
) {
|
||||
suspend fun getGateway(endpoint: String): String? {
|
||||
val gateway = UnifiedPushConfig.default_push_gateway_http_url
|
||||
val url = URL(endpoint)
|
||||
val custom = "${url.protocol}://${url.host}/_matrix/push/v1/notify"
|
||||
Timber.i("Testing $custom")
|
||||
try {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
val api = retrofitFactory.create("${url.protocol}://${url.host}")
|
||||
.create(UnifiedPushApi::class.java)
|
||||
try {
|
||||
val discoveryResponse = api.discover()
|
||||
if (discoveryResponse.unifiedpush.gateway == "matrix") {
|
||||
Timber.d("Using custom gateway")
|
||||
return@withContext custom
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag("UnifiedPushHelper").e(throwable)
|
||||
}
|
||||
return@withContext gateway
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.d(e, "Cannot try custom gateway")
|
||||
}
|
||||
return gateway
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.providers.unifiedpush
|
||||
|
||||
import android.content.Context
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.network.RetrofitFactory
|
||||
import io.element.android.libraries.push.providers.unifiedpush.network.UnifiedPushApi
|
||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
import javax.inject.Inject
|
||||
|
||||
class UnifiedPushHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val unifiedPushStore: UnifiedPushStore,
|
||||
private val stringProvider: StringProvider,
|
||||
private val retrofitFactory: RetrofitFactory,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
) {
|
||||
suspend fun storeCustomOrDefaultGateway(endpoint: String) {
|
||||
val gateway = UnifiedPushConfig.default_push_gateway_http_url
|
||||
val parsed = URL(endpoint)
|
||||
val custom = "${parsed.protocol}://${parsed.host}/_matrix/push/v1/notify"
|
||||
Timber.i("Testing $custom")
|
||||
try {
|
||||
withContext(coroutineDispatchers.io) {
|
||||
val api = retrofitFactory.create("${parsed.protocol}://${parsed.host}")
|
||||
.create(UnifiedPushApi::class.java)
|
||||
tryOrNull { api.discover() }
|
||||
?.let { discoveryResponse ->
|
||||
if (discoveryResponse.unifiedpush.gateway == "matrix") {
|
||||
Timber.d("Using custom gateway")
|
||||
unifiedPushStore.storePushGateway(custom)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
} catch (e: Throwable) {
|
||||
Timber.d(e, "Cannot try custom gateway")
|
||||
}
|
||||
unifiedPushStore.storePushGateway(gateway)
|
||||
}
|
||||
|
||||
private fun isEmbeddedDistributor() = false
|
||||
|
||||
fun getPrivacyFriendlyUpEndpoint(): String? {
|
||||
val endpoint = getEndpointOrToken()
|
||||
if (endpoint.isNullOrEmpty()) return null
|
||||
if (isEmbeddedDistributor()) {
|
||||
return endpoint
|
||||
}
|
||||
return try {
|
||||
val parsed = URL(endpoint)
|
||||
"${parsed.protocol}://${parsed.host}/***"
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error parsing unifiedpush endpoint")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getEndpointOrToken(): String? {
|
||||
// TODO
|
||||
return if (isEmbeddedDistributor()) "" // fcmHelper.getFcmToken()
|
||||
else unifiedPushStore.getEndpoint()
|
||||
}
|
||||
|
||||
fun getPushGateway(): String? {
|
||||
return if (isEmbeddedDistributor()) "" // PushConfig.pusher_http_url
|
||||
else unifiedPushStore.getPushGateway()
|
||||
}
|
||||
}
|
||||
@@ -18,11 +18,9 @@ package io.element.android.libraries.push.providers.unifiedpush
|
||||
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.api.toUserList
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -33,21 +31,22 @@ private val loggerTag = LoggerTag("UnifiedPushNewGatewayHandler")
|
||||
*/
|
||||
class UnifiedPushNewGatewayHandler @Inject constructor(
|
||||
private val pusherSubscriber: PusherSubscriber,
|
||||
private val sessionStore: SessionStore,
|
||||
private val userPushStoreFactory: UserPushStoreFactory,
|
||||
private val pushClientSecret: PushClientSecret,
|
||||
private val matrixAuthenticationService: MatrixAuthenticationService,
|
||||
) {
|
||||
suspend fun handle(endpoint: String, pushGateway: String) {
|
||||
// Register the pusher for all the sessions which are using UnifiedPush.
|
||||
sessionStore.getAllSessions().toUserList().forEach { userId ->
|
||||
val userDataStore = userPushStoreFactory.create(userId)
|
||||
if (userDataStore.getPushProviderName() == UnifiedPushConfig.name) {
|
||||
matrixAuthenticationService.restoreSession(SessionId(userId)).getOrNull()?.use { client ->
|
||||
pusherSubscriber.registerPusher(client, endpoint, pushGateway)
|
||||
}
|
||||
} else {
|
||||
Timber.tag(loggerTag.value).d("This session is not using UnifiedPush pusher")
|
||||
suspend fun handle(endpoint: String, pushGateway: String, clientSecret: String) {
|
||||
// Register the pusher for the session with this client secret, if is it using UnifiedPush.
|
||||
val userId = pushClientSecret.getUserIdFromSecret(clientSecret) ?: return Unit.also {
|
||||
Timber.w("Unable to retrieve session")
|
||||
}
|
||||
val userDataStore = userPushStoreFactory.create(userId)
|
||||
if (userDataStore.getPushProviderName() == UnifiedPushConfig.name) {
|
||||
matrixAuthenticationService.restoreSession(userId).getOrNull()?.use { client ->
|
||||
pusherSubscriber.registerPusher(client, endpoint, pushGateway)
|
||||
}
|
||||
} else {
|
||||
Timber.tag(loggerTag.value).d("This session is not using UnifiedPush pusher")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.providers.api.Distributor
|
||||
import io.element.android.libraries.push.providers.api.PushProvider
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -29,6 +30,7 @@ class UnifiedPushProvider @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
|
||||
private val unRegisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
||||
private val pushClientSecret: PushClientSecret,
|
||||
) : PushProvider {
|
||||
override val index = UnifiedPushConfig.index
|
||||
override val name = UnifiedPushConfig.name
|
||||
@@ -45,12 +47,14 @@ class UnifiedPushProvider @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor, clientSecret: String) {
|
||||
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor) {
|
||||
val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId)
|
||||
registerUnifiedPushUseCase.execute(matrixClient, distributor, clientSecret)
|
||||
}
|
||||
|
||||
override suspend fun unregister(matrixClient: MatrixClient) {
|
||||
unRegisterUnifiedPushUseCase.execute()
|
||||
val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId)
|
||||
unRegisterUnifiedPushUseCase.execute(clientSecret)
|
||||
}
|
||||
|
||||
override suspend fun troubleshoot(): Result<Unit> {
|
||||
|
||||
@@ -23,9 +23,6 @@ import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.DefaultPreferences
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* TODO EAx Store in BDD (for multisession).
|
||||
*/
|
||||
class UnifiedPushStore @Inject constructor(
|
||||
@ApplicationContext val context: Context,
|
||||
@DefaultPreferences private val defaultPrefs: SharedPreferences,
|
||||
@@ -35,8 +32,8 @@ class UnifiedPushStore @Inject constructor(
|
||||
*
|
||||
* @return the UnifiedPush Endpoint or null if not received
|
||||
*/
|
||||
fun getEndpoint(): String? {
|
||||
return defaultPrefs.getString(PREFS_ENDPOINT_OR_TOKEN, null)
|
||||
fun getEndpoint(clientSecret: String): String? {
|
||||
return defaultPrefs.getString(PREFS_ENDPOINT_OR_TOKEN + clientSecret, null)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,9 +41,9 @@ class UnifiedPushStore @Inject constructor(
|
||||
*
|
||||
* @param endpoint the endpoint to store
|
||||
*/
|
||||
fun storeUpEndpoint(endpoint: String?) {
|
||||
fun storeUpEndpoint(endpoint: String?, clientSecret: String) {
|
||||
defaultPrefs.edit {
|
||||
putString(PREFS_ENDPOINT_OR_TOKEN, endpoint)
|
||||
putString(PREFS_ENDPOINT_OR_TOKEN + clientSecret, endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +52,8 @@ class UnifiedPushStore @Inject constructor(
|
||||
*
|
||||
* @return the Push Gateway or null if not defined
|
||||
*/
|
||||
fun getPushGateway(): String? {
|
||||
return defaultPrefs.getString(PREFS_PUSH_GATEWAY, null)
|
||||
fun getPushGateway(clientSecret: String): String? {
|
||||
return defaultPrefs.getString(PREFS_PUSH_GATEWAY + clientSecret, null)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,9 +61,9 @@ class UnifiedPushStore @Inject constructor(
|
||||
*
|
||||
* @param gateway the push gateway to store
|
||||
*/
|
||||
fun storePushGateway(gateway: String?) {
|
||||
fun storePushGateway(gateway: String?, clientSecret: String) {
|
||||
defaultPrefs.edit {
|
||||
putString(PREFS_PUSH_GATEWAY, gateway)
|
||||
putString(PREFS_PUSH_GATEWAY + clientSecret, gateway)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,22 +26,22 @@ class UnregisterUnifiedPushUseCase @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
//private val pushDataStore: PushDataStore,
|
||||
private val unifiedPushStore: UnifiedPushStore,
|
||||
private val unifiedPushHelper: UnifiedPushHelper,
|
||||
private val unifiedPushGatewayResolver: UnifiedPushGatewayResolver,
|
||||
) {
|
||||
|
||||
suspend fun execute(/*pushersManager: PushersManager?*/) {
|
||||
suspend fun execute(clientSecret: String /*pushersManager: PushersManager?*/) {
|
||||
//val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
||||
//pushDataStore.setFdroidSyncBackgroundMode(mode)
|
||||
try {
|
||||
unifiedPushHelper.getEndpointOrToken()?.let {
|
||||
unifiedPushStore.getEndpoint(clientSecret)?.let {
|
||||
Timber.d("Removing $it")
|
||||
// TODO pushersManager?.unregisterPusher(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.d(e, "Probably unregistering a non existing pusher")
|
||||
}
|
||||
unifiedPushStore.storeUpEndpoint(null)
|
||||
unifiedPushStore.storePushGateway(null)
|
||||
unifiedPushStore.storeUpEndpoint(null, clientSecret)
|
||||
unifiedPushStore.storePushGateway(null, clientSecret)
|
||||
UnifiedPush.unregisterApp(context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.content.Intent
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.push.providers.api.PushHandler
|
||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -33,13 +32,10 @@ private val loggerTag = LoggerTag("VectorUnifiedPushMessagingReceiver")
|
||||
|
||||
class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||
@Inject lateinit var pushParser: UnifiedPushParser
|
||||
|
||||
// @Inject lateinit var pushDataStore: PushDataStore
|
||||
@Inject lateinit var pushHandler: PushHandler
|
||||
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
||||
@Inject lateinit var unifiedPushStore: UnifiedPushStore
|
||||
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
||||
@Inject lateinit var pusherSubscriber: PusherSubscriber
|
||||
@Inject lateinit var unifiedPushGatewayResolver: UnifiedPushGatewayResolver
|
||||
@Inject lateinit var newGatewayHandler: UnifiedPushNewGatewayHandler
|
||||
|
||||
private val coroutineScope = CoroutineScope(SupervisorJob())
|
||||
@@ -71,25 +67,23 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||
/**
|
||||
* Called when a new endpoint is to be used for sending push messages.
|
||||
* You should send the endpoint to your application server and sync for missing notifications.
|
||||
* TODO use [instance] for multi-account
|
||||
*/
|
||||
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
||||
Timber.tag(loggerTag.value).i("onNewEndpoint: adding $endpoint")
|
||||
// If the endpoint has changed
|
||||
// or the gateway has changed
|
||||
if (unifiedPushHelper.getEndpointOrToken() != endpoint) {
|
||||
unifiedPushStore.storeUpEndpoint(endpoint)
|
||||
if (unifiedPushStore.getEndpoint(instance) != endpoint) {
|
||||
unifiedPushStore.storeUpEndpoint(endpoint, instance)
|
||||
coroutineScope.launch {
|
||||
unifiedPushHelper.storeCustomOrDefaultGateway(endpoint)
|
||||
unifiedPushHelper.getPushGateway()?.let { pushGateway ->
|
||||
newGatewayHandler.handle(endpoint, pushGateway)
|
||||
val gateway = unifiedPushGatewayResolver.getGateway(endpoint)
|
||||
unifiedPushStore.storePushGateway(gateway, instance)
|
||||
gateway?.let { pushGateway ->
|
||||
newGatewayHandler.handle(endpoint, pushGateway, instance)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Timber.tag(loggerTag.value).i("onNewEndpoint: skipped")
|
||||
}
|
||||
//val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED
|
||||
//pushDataStore.setFdroidSyncBackgroundMode(mode)
|
||||
guardServiceStarter.stop()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user