From a3a946fb750b4186797cc97af7f17fbdce458496 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 1 Jun 2021 20:29:44 +0200 Subject: [PATCH] unifiedpush notification --- build.gradle | 2 + vector/build.gradle | 13 +- vector/src/fdroid/AndroidManifest.xml | 29 --- .../java/im/vector/app/push/fcm/FcmHelper.kt | 47 +--- vector/src/gplay/AndroidManifest.xml | 16 +- ...estFirebaseToken.kt => TestNewEndpoint.kt} | 14 +- .../troubleshoot/TestPushFromPushGateway.kt | 6 +- .../troubleshoot/TestTokenRegistration.kt | 12 +- .../im/vector/app/push/fcm/EmbeddedDistrib.kt | 31 +++ .../java/im/vector/app/push/fcm/FcmHelper.kt | 84 +------ ...ificationTroubleshootTestManagerFactory.kt | 6 +- vector/src/main/AndroidManifest.xml | 32 +++ .../java/im/vector/app/VectorApplication.kt | 6 +- .../vector/app/core/pushers/PushersManager.kt | 13 +- .../im/vector/app/core/pushers/StateHelper.kt | 35 +++ .../im/vector/app/core/pushers/UPHelper.kt | 148 +++++++++++++ .../core/pushers/VectorMessagingReceiver.kt} | 205 +++++++----------- .../receiver/AlarmSyncBroadcastReceiver.kt | 2 +- .../core/receiver}/BackgroundSyncStarter.kt | 3 +- .../OnApplicationUpgradeOrRebootReceiver.kt | 3 +- .../features/call/webrtc/WebRtcCallManager.kt | 6 +- .../vector/app/features/home/HomeActivity.kt | 4 +- ...rSettingsNotificationPreferenceFragment.kt | 26 ++- vector/src/main/res/values/config.xml | 2 + 24 files changed, 403 insertions(+), 342 deletions(-) delete mode 100644 vector/src/fdroid/AndroidManifest.xml rename vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/{TestFirebaseToken.kt => TestNewEndpoint.kt} (93%) create mode 100644 vector/src/gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt create mode 100644 vector/src/main/java/im/vector/app/core/pushers/StateHelper.kt create mode 100644 vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt rename vector/src/{gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt => main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt} (52%) rename vector/src/{fdroid/java/im/vector/app/fdroid => main/java/im/vector/app/core}/receiver/AlarmSyncBroadcastReceiver.kt (99%) rename vector/src/{fdroid/java/im/vector/app/fdroid => main/java/im/vector/app/core/receiver}/BackgroundSyncStarter.kt (96%) rename vector/src/{fdroid/java/im/vector/app/fdroid => main/java/im/vector/app/core}/receiver/OnApplicationUpgradeOrRebootReceiver.kt (94%) diff --git a/build.gradle b/build.gradle index 881cd340f1..d61f17f40f 100644 --- a/build.gradle +++ b/build.gradle @@ -44,6 +44,8 @@ allprojects { includeGroupByRegex 'com\\.github\\.chrisbanes' // PFLockScreen-Android includeGroupByRegex 'com\\.github\\.vector-im' + // UnifiedPush + includeGroupByRegex 'com\\.github\\.UnifiedPush' // Chat effects includeGroupByRegex 'com\\.github\\.jetradarmobile' diff --git a/vector/build.gradle b/vector/build.gradle index 8af6e80479..f7804bb5dc 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -291,6 +291,10 @@ android { buildFeatures { viewBinding true } + + packagingOptions { + exclude 'META-INF/lib_release.kotlin_module' + } } dependencies { @@ -429,12 +433,9 @@ dependencies { implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" - // gplay flavor only - gplayImplementation('com.google.firebase:firebase-messaging:22.0.0') { - exclude group: 'com.google.firebase', module: 'firebase-core' - exclude group: 'com.google.firebase', module: 'firebase-analytics' - exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' - } + // Unifiedpush + implementation 'com.github.UnifiedPush:android-connector:1.1.3' + gplayImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.0.2' // OSS License, gplay flavor only gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0' diff --git a/vector/src/fdroid/AndroidManifest.xml b/vector/src/fdroid/AndroidManifest.xml deleted file mode 100644 index 3a7c107138..0000000000 --- a/vector/src/fdroid/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt index 7603e738d7..45dfa30f4a 100755 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt @@ -17,56 +17,13 @@ package im.vector.app.push.fcm -import android.app.Activity import android.content.Context -import im.vector.app.core.di.ActiveSessionHolder -import im.vector.app.core.pushers.PushersManager -import im.vector.app.fdroid.BackgroundSyncStarter -import im.vector.app.fdroid.receiver.AlarmSyncBroadcastReceiver -import im.vector.app.features.settings.VectorPreferences /** * This class has an alter ego in the gplay variant. */ object FcmHelper { - - fun isPushSupported(): Boolean = false - - /** - * Retrieves the FCM registration token. - * - * @return the FCM token or null if not received from FCM - */ - fun getFcmToken(context: Context): String? { - return null - } - - /** - * Store FCM token to the SharedPrefs - * - * @param context android context - * @param token the token to store - */ - fun storeFcmToken(context: Context, token: String?) { - // No op - } - - /** - * onNewToken may not be called on application upgrade, so ensure my shared pref is set - * - * @param activity the first launch Activity - */ - fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { - // No op - } - - fun onEnterForeground(context: Context, activeSessionHolder: ActiveSessionHolder) { - // try to stop all regardless of background mode - activeSessionHolder.getSafeActiveSession()?.stopAnyBackgroundSync() - AlarmSyncBroadcastReceiver.cancelAlarm(context) - } - - fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) { - BackgroundSyncStarter.start(context, vectorPreferences, activeSessionHolder) + fun isPlayServicesAvailable(context: Context): Boolean { + return false } } diff --git a/vector/src/gplay/AndroidManifest.xml b/vector/src/gplay/AndroidManifest.xml index d849d5fb2d..5109ab90da 100755 --- a/vector/src/gplay/AndroidManifest.xml +++ b/vector/src/gplay/AndroidManifest.xml @@ -3,18 +3,12 @@ package="im.vector.app"> - - - - - + - + + - - + - + \ No newline at end of file diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestNewEndpoint.kt similarity index 93% rename from vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt rename to vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestNewEndpoint.kt index 1107737888..7cb0fed9f4 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestNewEndpoint.kt @@ -18,7 +18,6 @@ package im.vector.app.gplay.features.settings.troubleshoot import android.content.Intent import androidx.activity.result.ActivityResultLauncher import androidx.appcompat.app.AppCompatActivity -import com.google.firebase.messaging.FirebaseMessaging import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.startAddGoogleAccountIntent @@ -28,13 +27,18 @@ import timber.log.Timber import javax.inject.Inject /* -* Test that app can successfully retrieve a token via firebase +* Test that app can successfully retrieve a new endpoint */ -class TestFirebaseToken @Inject constructor(private val context: AppCompatActivity, +class TestNewEndpoint @Inject constructor(private val context: AppCompatActivity, private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) { override fun perform(activityResultLauncher: ActivityResultLauncher) { - status = TestStatus.RUNNING + description = "bypassed" + status = TestStatus.SUCCESS + /** + * TODO + */ + /*status = TestStatus.RUNNING try { FirebaseMessaging.getInstance().token .addOnCompleteListener(context) { task -> @@ -74,6 +78,6 @@ class TestFirebaseToken @Inject constructor(private val context: AppCompatActivi } catch (e: Throwable) { description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, e.localizedMessage) status = TestStatus.FAILED - } + }*/ } } diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt index d429b293b2..a4a3507828 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -25,7 +25,7 @@ import im.vector.app.core.pushers.PushersManager import im.vector.app.core.resources.StringProvider import im.vector.app.features.session.coroutineScope import im.vector.app.features.settings.troubleshoot.TroubleshootTest -import im.vector.app.push.fcm.FcmHelper +import im.vector.app.core.pushers.UPHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch @@ -48,12 +48,12 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat override fun perform(activityResultLauncher: ActivityResultLauncher) { pushReceived = false - val fcmToken = FcmHelper.getFcmToken(context) ?: run { + UPHelper.getUpEndpoint(context) ?: run { status = TestStatus.FAILED return } action = activeSessionHolder.getActiveSession().coroutineScope.launch { - val result = runCatching { pushersManager.testPush(fcmToken) } + val result = runCatching { pushersManager.testPush(context) } withContext(Dispatchers.Main) { status = result diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt index f400c17d46..4d1a869768 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt @@ -27,7 +27,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.pushers.PushersManager import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.troubleshoot.TroubleshootTest -import im.vector.app.push.fcm.FcmHelper +import im.vector.app.core.pushers.UPHelper import javax.inject.Inject /** @@ -41,7 +41,11 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc override fun perform(activityResultLauncher: ActivityResultLauncher) { // Check if we have a registered pusher for this token - val fcmToken = FcmHelper.getFcmToken(context) ?: run { + val pushToken = UPHelper.getUpEndpoint(context) ?: run { + status = TestStatus.FAILED + return + } + val pushGateway = UPHelper.getPushGateway(context) ?: run { status = TestStatus.FAILED return } @@ -50,14 +54,14 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc return } val pushers = session.getPushers().filter { - it.pushKey == fcmToken && it.state == PusherState.REGISTERED + it.pushKey == pushToken && it.state == PusherState.REGISTERED } if (pushers.isEmpty()) { description = stringProvider.getString(R.string.settings_troubleshoot_test_token_registration_failed, stringProvider.getString(R.string.sas_error_unknown)) quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_token_registration_quick_fix) { override fun doFix() { - val workId = pushersManager.registerPusherWithFcmKey(fcmToken) + val workId = pushersManager.registerPusher(pushToken, pushGateway) WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo -> if (workInfo != null) { if (workInfo.state == WorkInfo.State.SUCCEEDED) { diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt b/vector/src/gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt new file mode 100644 index 0000000000..1e7f04f9c3 --- /dev/null +++ b/vector/src/gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt @@ -0,0 +1,31 @@ +package im.vector.app.push.fcm + +import android.content.Context +import im.vector.app.R +import org.unifiedpush.android.embedded_fcm_distributor.GetEndpointHandler +import org.unifiedpush.android.embedded_fcm_distributor.EmbeddedDistributorReceiver + +/* + * Copyright (c) 2021 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. + */ + +val handlerFCM = object: GetEndpointHandler { + override fun getEndpoint(context: Context?, token: String, instance: String): String { + // This returns the endpoint of your FCM Rewrite-Proxy + return "${context!!.getString(R.string.pusher_http_url)}/FCM?instance=$instance&token=$token" + } +} + +class EmbeddedDistrib: EmbeddedDistributorReceiver(handlerFCM) diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt b/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt index f3bdcafb1c..4146059cdd 100755 --- a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt @@ -15,99 +15,21 @@ */ package im.vector.app.push.fcm -import android.app.Activity import android.content.Context -import android.widget.Toast -import androidx.core.content.edit import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailability -import com.google.firebase.messaging.FirebaseMessaging -import im.vector.app.R -import im.vector.app.core.di.ActiveSessionHolder -import im.vector.app.core.di.DefaultSharedPreferences -import im.vector.app.core.pushers.PushersManager -import im.vector.app.features.settings.VectorPreferences -import timber.log.Timber /** * This class store the FCM token in SharedPrefs and ensure this token is retrieved. * It has an alter ego in the fdroid variant. */ object FcmHelper { - private val PREFS_KEY_FCM_TOKEN = "FCM_TOKEN" - - fun isPushSupported(): Boolean = true - /** - * Retrieves the FCM registration token. - * - * @return the FCM token or null if not received from FCM + * Check the device to make sure it has the Google Play Services APK. */ - fun getFcmToken(context: Context): String? { - return DefaultSharedPreferences.getInstance(context).getString(PREFS_KEY_FCM_TOKEN, null) - } - - /** - * Store FCM token to the SharedPrefs - * TODO Store in realm - * - * @param context android context - * @param token the token to store - */ - fun storeFcmToken(context: Context, - token: String?) { - DefaultSharedPreferences.getInstance(context).edit { - putString(PREFS_KEY_FCM_TOKEN, token) - } - } - - /** - * onNewToken may not be called on application upgrade, so ensure my shared pref is set - * - * @param activity the first launch Activity - */ - fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { - // if (TextUtils.isEmpty(getFcmToken(activity))) { - // 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features' - if (checkPlayServices(activity)) { - try { - FirebaseMessaging.getInstance().token - .addOnSuccessListener { token -> - storeFcmToken(activity, token) - if (registerPusher) { - pushersManager.registerPusherWithFcmKey(token) - } - } - .addOnFailureListener { e -> - Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed") - } - } catch (e: Throwable) { - Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed") - } - } else { - Toast.makeText(activity, R.string.no_valid_google_play_services_apk, Toast.LENGTH_SHORT).show() - Timber.e("No valid Google Play Services found. Cannot use FCM.") - } - } - - /** - * Check the device to make sure it has the Google Play Services APK. If - * it doesn't, display a dialog that allows users to download the APK from - * the Google Play Store or enable it in the device's system settings. - */ - private fun checkPlayServices(activity: Activity): Boolean { + fun isPlayServicesAvailable(context: Context): Boolean { val apiAvailability = GoogleApiAvailability.getInstance() - val resultCode = apiAvailability.isGooglePlayServicesAvailable(activity) + val resultCode = apiAvailability.isGooglePlayServicesAvailable(context) return resultCode == ConnectionResult.SUCCESS } - - @Suppress("UNUSED_PARAMETER") - fun onEnterForeground(context: Context, activeSessionHolder: ActiveSessionHolder) { - // No op - } - - @Suppress("UNUSED_PARAMETER") - fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) { - // TODO FCM fallback - } } diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index e96c603e60..df0b3409bc 100644 --- a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -22,7 +22,7 @@ import im.vector.app.features.settings.troubleshoot.TestDeviceSettings import im.vector.app.features.settings.troubleshoot.TestNotification import im.vector.app.features.settings.troubleshoot.TestPushRulesSettings import im.vector.app.features.settings.troubleshoot.TestSystemSettings -import im.vector.app.gplay.features.settings.troubleshoot.TestFirebaseToken +import im.vector.app.gplay.features.settings.troubleshoot.TestNewEndpoint import im.vector.app.gplay.features.settings.troubleshoot.TestPlayServices import im.vector.app.gplay.features.settings.troubleshoot.TestPushFromPushGateway import im.vector.app.gplay.features.settings.troubleshoot.TestTokenRegistration @@ -34,7 +34,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testDeviceSettings: TestDeviceSettings, private val testBingRulesSettings: TestPushRulesSettings, private val testPlayServices: TestPlayServices, - private val testFirebaseToken: TestFirebaseToken, + private val testNewEndpoint: TestNewEndpoint, private val testTokenRegistration: TestTokenRegistration, private val testPushFromPushGateway: TestPushFromPushGateway, private val testNotification: TestNotification @@ -47,7 +47,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testDeviceSettings) mgr.addTest(testBingRulesSettings) mgr.addTest(testPlayServices) - mgr.addTest(testFirebaseToken) + mgr.addTest(testNewEndpoint) mgr.addTest(testTokenRegistration) mgr.addTest(testPushFromPushGateway) mgr.addTest(testNotification) diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index f601dc88dd..ba820cc3a7 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -39,6 +39,14 @@ android:name="android.permission.WRITE_CALENDAR" tools:node="remove" /> + + + + + @@ -382,6 +390,30 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/sdk_provider_paths" /> + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index f3e2f8740e..0f6fa5ca27 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -58,7 +58,7 @@ import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.version.VersionProvider -import im.vector.app.push.fcm.FcmHelper +import im.vector.app.core.pushers.StateHelper import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.MatrixConfiguration @@ -169,7 +169,7 @@ class VectorApplication : @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun entersForeground() { Timber.i("App entered foreground") - FcmHelper.onEnterForeground(appContext, activeSessionHolder) + StateHelper.onEnterForeground(appContext, activeSessionHolder) activeSessionHolder.getSafeActiveSession()?.also { it.stopAnyBackgroundSync() } @@ -179,7 +179,7 @@ class VectorApplication : fun entersBackground() { Timber.i("App entered background") // call persistInfo notificationDrawerManager.persistInfo() - FcmHelper.onEnterBackground(appContext, vectorPreferences, activeSessionHolder) + StateHelper.onEnterBackground(appContext, vectorPreferences, activeSessionHolder) } }) ProcessLifecycleOwner.get().lifecycle.addObserver(appStateHandler) diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt index 5896122393..7c5e38c8fe 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt @@ -16,6 +16,7 @@ package im.vector.app.core.pushers +import android.content.Context import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.AppNameProvider @@ -33,29 +34,29 @@ class PushersManager @Inject constructor( private val stringProvider: StringProvider, private val appNameProvider: AppNameProvider ) { - suspend fun testPush(pushKey: String) { + suspend fun testPush(context: Context) { val currentSession = activeSessionHolder.getActiveSession() currentSession.testPush( - stringProvider.getString(R.string.pusher_http_url), + UPHelper.getPushGateway(context)!!, stringProvider.getString(R.string.pusher_app_id), - pushKey, + UPHelper.getUpEndpoint(context)!!, TEST_EVENT_ID ) } - fun registerPusherWithFcmKey(pushKey: String): UUID { + fun registerPusher(pushKey: String, gateway: String): UUID { val currentSession = activeSessionHolder.getActiveSession() val profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(currentSession.myUserId.hashCode()) return currentSession.addHttpPusher( - pushKey, + pushKey, // this is the UnifiedPush endpoint stringProvider.getString(R.string.pusher_app_id), profileTag, localeProvider.current().language, appNameProvider.getAppName(), currentSession.sessionParams.deviceId ?: "MOBILE", - stringProvider.getString(R.string.pusher_http_url), + gateway, append = false, withEventIdOnly = true ) diff --git a/vector/src/main/java/im/vector/app/core/pushers/StateHelper.kt b/vector/src/main/java/im/vector/app/core/pushers/StateHelper.kt new file mode 100644 index 0000000000..97bbdd279b --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/pushers/StateHelper.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 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 im.vector.app.core.pushers + +import android.content.Context +import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.receiver.AlarmSyncBroadcastReceiver +import im.vector.app.core.receiver.BackgroundSyncStarter +import im.vector.app.features.settings.VectorPreferences + +object StateHelper { + fun onEnterForeground(context: Context, activeSessionHolder: ActiveSessionHolder) { + // try to stop all regardless of background mode + activeSessionHolder.getSafeActiveSession()?.stopAnyBackgroundSync() + AlarmSyncBroadcastReceiver.cancelAlarm(context) + } + + fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) { + BackgroundSyncStarter.start(context, vectorPreferences, activeSessionHolder) + } +} diff --git a/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt b/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt new file mode 100644 index 0000000000..ad6f6ab0e6 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021 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 im.vector.app.core.pushers + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import androidx.core.content.edit +import im.vector.app.R +import im.vector.app.core.di.DefaultSharedPreferences +import im.vector.app.push.fcm.FcmHelper +import org.unifiedpush.android.connector.Registration +import timber.log.Timber +import java.net.URI + +/** + * This class store the UnifiedPush Endpoint in SharedPrefs and ensure this token is retrieved. + * It has an alter ego in the fdroid variant. + */ +object UPHelper { + private const val PREFS_UP_ENDPOINT = "UP_ENDPOINT" + private const val PREFS_PUSH_GATEWAY = "PUSH_GATEWAY" + + /** + * Retrieves the UnifiedPush Endpoint. + * + * @return the UnifiedPush Endpoint or null if not received + */ + fun getUpEndpoint(context: Context): String? { + return DefaultSharedPreferences.getInstance(context).getString(PREFS_UP_ENDPOINT, null) + } + + /** + * Store UnifiedPush Endpoint to the SharedPrefs + * TODO Store in realm + * + * @param context android context + * @param endpoint the endpoint to store + */ + fun storeUpEndpoint(context: Context, + endpoint: String?) { + DefaultSharedPreferences.getInstance(context).edit { + putString(PREFS_UP_ENDPOINT, endpoint) + } + } + + /** + * Retrieves the Push Gateway. + * + * @return the Push Gateway or null if not defined + */ + fun getPushGateway(context: Context): String? { + return DefaultSharedPreferences.getInstance(context).getString(PREFS_PUSH_GATEWAY, null) + } + + /** + * Store Push Gateway to the SharedPrefs + * TODO Store in realm + * + * @param context android context + * @param gateway the push gateway to store + */ + fun storePushGateway(context: Context, + gateway: String?) { + DefaultSharedPreferences.getInstance(context).edit { + putString(PREFS_PUSH_GATEWAY, gateway) + } + } + + fun registerUnifiedPush(context: Context) { + val up = Registration() + if (up.getDistributor(context).isNotEmpty()) { + up.registerApp(context) + return + } + val distributors = up.getDistributors(context).toMutableList() + /** + * Check if it is the gplay flavour AND GServices are not available + */ + if (!FcmHelper.isPlayServicesAvailable(context)) { + distributors.remove(context.packageName) + } + when (distributors.size) { + 0 -> { + /** + * TODO: fallback with sync service : automatic ? + */ + } + 1 -> { + up.saveDistributor(context, distributors.first()) + up.registerApp(context) + } + else -> { + val builder: AlertDialog.Builder = AlertDialog.Builder(context) + builder.setTitle("Choose a distributor") + + val distributorsArray = distributors.toTypedArray() + builder.setItems(distributorsArray) { _, which -> + val distributor = distributorsArray[which] + up.saveDistributor(context, distributor) + Timber.i("Saving distributor: $distributor") + up.registerApp(context) + } + val dialog: AlertDialog = builder.create() + dialog.show() + } + } + } + + fun unregister(context: Context) { + val up = Registration() + up.unregisterApp(context) + } + + fun customOrDefaultGateway(context: Context, endpoint: String?): String { + val default = context.getString(R.string.default_push_gateway_http_url) + endpoint?.let { + val uri = URI(it) + val custom = "${it.split(uri.rawPath)[0]}/_matrix/push/v1/notify" + Timber.i("Testing $custom") + /** + * TODO: + * if GET custom returns """{"unifiedpush":{"gateway":"matrix"}}""" + * return custom + */ + } + return default + } + + fun hasEndpoint(context: Context): Boolean { + getUpEndpoint(context)?.let { + return true + } + return false + } +} diff --git a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt similarity index 52% rename from vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt rename to vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index 4cefeadb62..0180b91b87 100755 --- a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -17,43 +17,41 @@ * limitations under the License. */ -package im.vector.app.gplay.push.fcm +package im.vector.app.core.pushers +import android.content.Context import android.content.Intent import android.os.Handler import android.os.Looper +import android.widget.Toast import androidx.lifecycle.Lifecycle import androidx.lifecycle.ProcessLifecycleOwner import androidx.localbroadcastmanager.content.LocalBroadcastManager -import com.google.firebase.messaging.FirebaseMessagingService -import com.google.firebase.messaging.RemoteMessage import im.vector.app.BuildConfig -import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.vectorComponent import im.vector.app.core.network.WifiDetector -import im.vector.app.core.pushers.PushersManager import im.vector.app.features.badge.BadgeProxy import im.vector.app.features.notifications.NotifiableEventResolver -import im.vector.app.features.notifications.NotifiableMessageEvent import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.notifications.NotificationUtils -import im.vector.app.features.notifications.SimpleNotifiableEvent import im.vector.app.features.settings.VectorPreferences -import im.vector.app.push.fcm.FcmHelper import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import org.json.JSONException +import org.json.JSONObject import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.pushrules.Action import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.events.model.Event +import org.unifiedpush.android.connector.MessagingReceiver +import org.unifiedpush.android.connector.MessagingReceiverHandler import timber.log.Timber /** - * Class extending FirebaseMessagingService. + * Unifiedpush handler. */ -class VectorFirebaseMessagingService : FirebaseMessagingService() { +val upHandler = object: MessagingReceiverHandler { private lateinit var notificationDrawerManager: NotificationDrawerManager private lateinit var notifiableEventResolver: NotifiableEventResolver @@ -69,9 +67,8 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { Handler(Looper.getMainLooper()) } - override fun onCreate() { - super.onCreate() - with(vectorComponent()) { + fun initVar(context: Context) { + with(context.vectorComponent()) { notificationDrawerManager = notificationDrawerManager() notifiableEventResolver = notifiableEventResolver() pusherManager = pusherManager() @@ -85,17 +82,42 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { * Called when message is received. * * @param message the message + * @param instance connection, for multi-account */ - override fun onMessageReceived(message: RemoteMessage) { + override fun onMessage(context: Context?, message: String, instance: String) { + initVar(context!!) if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { - Timber.d("## onMessageReceived() %s", message.data.toString()) + Timber.d("## onMessageReceived() %s", message) + } + Timber.d("## onMessage() received") + + lateinit var data: JSONObject + lateinit var notification: JSONObject + try { + data = JSONObject(message) + notification = data.getJSONObject("notification") + } catch (e: JSONException) { + Timber.e(e) + return + } + val eventId: String = try { + notification.getString("event_id") + } catch (e: JSONException) { + Timber.i("No event_id on notification") + notification.put("event_id", "") + "" + } + try { + notification.getString("room_id") + } catch (e: JSONException) { + Timber.i("No room_id on notification") + notification.put("room_id", "") } - Timber.d("## onMessageReceived() from FCM with priority %s", message.priority) // Diagnostic Push - if (message.data["event_id"] == PushersManager.TEST_EVENT_ID) { + if (eventId == PushersManager.TEST_EVENT_ID) { val intent = Intent(NotificationUtils.PUSH_ACTION) - LocalBroadcastManager.getInstance(this).sendBroadcast(intent) + LocalBroadcastManager.getInstance(context).sendBroadcast(intent) return } @@ -109,7 +131,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { // we are in foreground, let the sync do the things? Timber.d("PUSH received in a foreground state, ignore") } else { - onMessageReceivedInternal(message.data) + onMessageReceivedInternal(context, notification) } } } @@ -120,52 +142,60 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { * when the InstanceID token is initially generated, so this is where * you retrieve the token. */ - override fun onNewToken(refreshedToken: String) { - Timber.i("onNewToken: FCM Token has been updated") - FcmHelper.storeFcmToken(this, refreshedToken) + override fun onNewEndpoint(context: Context?, endpoint: String, instance: String) { + initVar(context!!) + Timber.i("onNewEndpoint: adding $endpoint") + UPHelper.storeUpEndpoint(context, endpoint) if (vectorPreferences.areNotificationEnabledForDevice() && activeSessionHolder.hasActiveSession()) { - pusherManager.registerPusherWithFcmKey(refreshedToken) + val gateway = UPHelper.customOrDefaultGateway(context, endpoint) + UPHelper.storePushGateway(context, gateway) + UPHelper.storeUpEndpoint(context, endpoint) + pusherManager.registerPusher(endpoint, gateway) } } - /** - * Called when the FCM server deletes pending messages. This may be due to: - * - Too many messages stored on the FCM server. - * This can occur when an app's servers send a bunch of non-collapsible messages to FCM servers while the device is offline. - * - The device hasn't connected in a long time and the app server has recently (within the last 4 weeks) - * sent a message to the app on that device. - * - * It is recommended that the app do a full sync with the app server after receiving this call. - */ - override fun onDeletedMessages() { - Timber.v("## onDeletedMessages()") + override fun onRegistrationFailed(context: Context?, instance: String) { + Toast.makeText(context, "Push service registration failed", Toast.LENGTH_SHORT).show() + } + + override fun onRegistrationRefused(context: Context?, instance: String) { + Toast.makeText(context, "Push service registration refused by server", Toast.LENGTH_LONG).show() + } + + override fun onUnregistered(context: Context?, instance: String) { + Timber.d("Unifiedpush: Unregistered") + initVar(context!!) + runBlocking { + try { + pusherManager.unregisterPusher(UPHelper.getUpEndpoint(context)!!) + } catch (e: Exception) { + Timber.d("Probably unregistering a non existant pusher") + } + } } /** * Internal receive method * - * @param data Data map containing message data as key/value pairs. - * For Set of keys use data.keySet(). + * @param data Data json containing message data. */ - private fun onMessageReceivedInternal(data: Map) { + private fun onMessageReceivedInternal(context: Context, data: JSONObject) { try { if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { Timber.d("## onMessageReceivedInternal() : $data") - } else { - Timber.d("## onMessageReceivedInternal() : $data") } // update the badge counter - val unreadCount = data["unread"]?.let { Integer.parseInt(it) } ?: 0 - BadgeProxy.updateBadgeCount(applicationContext, unreadCount) + val unreadCount = data.getJSONObject("counts").getInt("unread") + BadgeProxy.updateBadgeCount(context, unreadCount) val session = activeSessionHolder.getSafeActiveSession() if (session == null) { Timber.w("## Can't sync from push, no current session") } else { - val eventId = data["event_id"] - val roomId = data["room_id"] + val eventId = data.getString("event_id") + val roomId = data.getString("room_id") if (isEventAlreadyKnown(eventId, roomId)) { Timber.d("Ignoring push, event already known") @@ -227,87 +257,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { } return false } - - private fun handleNotificationWithoutSyncingMode(data: Map, session: Session?) { - if (session == null) { - Timber.e("## handleNotificationWithoutSyncingMode cannot find session") - return - } - - // The Matrix event ID of the event being notified about. - // This is required if the notification is about a particular Matrix event. - // It may be omitted for notifications that only contain updated badge counts. - // This ID can and should be used to detect duplicate notification requests. - val eventId = data["event_id"] ?: return // Just ignore - - val eventType = data["type"] - if (eventType == null) { - // Just add a generic unknown event - val simpleNotifiableEvent = SimpleNotifiableEvent( - session.myUserId, - eventId, - null, - true, // It's an issue in this case, all event will bing even if expected to be silent. - title = getString(R.string.notification_unknown_new_event), - description = "", - type = null, - timestamp = System.currentTimeMillis(), - soundName = Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT, - isPushGatewayEvent = true - ) - notificationDrawerManager.onNotifiableEventReceived(simpleNotifiableEvent) - notificationDrawerManager.refreshNotificationDrawer() - } else { - val event = parseEvent(data) ?: return - - val notifiableEvent = notifiableEventResolver.resolveEvent(event, session) - - if (notifiableEvent == null) { - Timber.e("Unsupported notifiable event $eventId") - if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { - Timber.e("--> $event") - } - } else { - if (notifiableEvent is NotifiableMessageEvent) { - if (notifiableEvent.senderName.isNullOrEmpty()) { - notifiableEvent.senderName = data["sender_display_name"] ?: data["sender"] ?: "" - } - if (notifiableEvent.roomName.isNullOrEmpty()) { - notifiableEvent.roomName = findRoomNameBestEffort(data, session) ?: "" - } - } - - notifiableEvent.isPushGatewayEvent = true - notifiableEvent.matrixID = session.myUserId - notificationDrawerManager.onNotifiableEventReceived(notifiableEvent) - notificationDrawerManager.refreshNotificationDrawer() - } - } - } - - private fun findRoomNameBestEffort(data: Map, session: Session?): String? { - var roomName: String? = data["room_name"] - val roomId = data["room_id"] - if (null == roomName && null != roomId) { - // Try to get the room name from our store - roomName = session?.getRoom(roomId)?.roomSummary()?.displayName - } - return roomName - } - - /** - * Try to create an event from the FCM data - * - * @param data the FCM data - * @return the event or null if required data are missing - */ - private fun parseEvent(data: Map?): Event? { - return Event( - eventId = data?.get("event_id") ?: return null, - senderId = data["sender"], - roomId = data["room_id"] ?: return null, - type = data["type"] ?: return null, - originServerTs = System.currentTimeMillis() - ) - } } + +class VectorMessagingReceiver : MessagingReceiver(upHandler) diff --git a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt b/vector/src/main/java/im/vector/app/core/receiver/AlarmSyncBroadcastReceiver.kt similarity index 99% rename from vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt rename to vector/src/main/java/im/vector/app/core/receiver/AlarmSyncBroadcastReceiver.kt index b94e99208b..37a10cccda 100644 --- a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/receiver/AlarmSyncBroadcastReceiver.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.fdroid.receiver +package im.vector.app.core.receiver import android.app.AlarmManager import android.app.PendingIntent diff --git a/vector/src/fdroid/java/im/vector/app/fdroid/BackgroundSyncStarter.kt b/vector/src/main/java/im/vector/app/core/receiver/BackgroundSyncStarter.kt similarity index 96% rename from vector/src/fdroid/java/im/vector/app/fdroid/BackgroundSyncStarter.kt rename to vector/src/main/java/im/vector/app/core/receiver/BackgroundSyncStarter.kt index 7221e2b065..b3789ef6df 100644 --- a/vector/src/fdroid/java/im/vector/app/fdroid/BackgroundSyncStarter.kt +++ b/vector/src/main/java/im/vector/app/core/receiver/BackgroundSyncStarter.kt @@ -14,11 +14,10 @@ * limitations under the License. */ -package im.vector.app.fdroid +package im.vector.app.core.receiver import android.content.Context import im.vector.app.core.di.ActiveSessionHolder -import im.vector.app.fdroid.receiver.AlarmSyncBroadcastReceiver import im.vector.app.features.settings.BackgroundSyncMode import im.vector.app.features.settings.VectorPreferences import timber.log.Timber diff --git a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/OnApplicationUpgradeOrRebootReceiver.kt b/vector/src/main/java/im/vector/app/core/receiver/OnApplicationUpgradeOrRebootReceiver.kt similarity index 94% rename from vector/src/fdroid/java/im/vector/app/fdroid/receiver/OnApplicationUpgradeOrRebootReceiver.kt rename to vector/src/main/java/im/vector/app/core/receiver/OnApplicationUpgradeOrRebootReceiver.kt index 797b5734a2..b1989eaab7 100644 --- a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/OnApplicationUpgradeOrRebootReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/receiver/OnApplicationUpgradeOrRebootReceiver.kt @@ -15,14 +15,13 @@ * limitations under the License. */ -package im.vector.app.fdroid.receiver +package im.vector.app.core.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import im.vector.app.core.di.HasVectorInjector import im.vector.app.core.extensions.vectorComponent -import im.vector.app.fdroid.BackgroundSyncStarter import timber.log.Timber class OnApplicationUpgradeOrRebootReceiver : BroadcastReceiver() { diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt index 253b1ac33d..687c86d8f5 100644 --- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt +++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt @@ -28,7 +28,7 @@ import im.vector.app.features.call.lookup.CallProtocolsChecker import im.vector.app.features.call.lookup.CallUserMapper import im.vector.app.features.call.utils.EglUtils import im.vector.app.features.call.vectorCallService -import im.vector.app.push.fcm.FcmHelper +import im.vector.app.core.pushers.UPHelper import kotlinx.coroutines.asCoroutineDispatcher import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull @@ -243,7 +243,7 @@ class WebRtcCallManager @Inject constructor( audioManager.setMode(CallAudioManager.Mode.DEFAULT) // did we start background sync? so we should stop it if (isInBackground) { - if (FcmHelper.isPushSupported()) { + if (UPHelper.hasEndpoint(context)) { currentSession?.stopAnyBackgroundSync() } else { // for fdroid we should not stop, it should continue syncing @@ -348,7 +348,7 @@ class WebRtcCallManager @Inject constructor( // and thus won't be able to received events. For example if the call is // accepted on an other session this device will continue ringing if (isInBackground) { - if (FcmHelper.isPushSupported()) { + if (UPHelper.hasEndpoint(context)) { // only for push version as fdroid version is already doing it? currentSession?.startAutomaticBackgroundSync(30, 0) } else { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 7714a69196..b08cf13f6c 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -67,7 +67,7 @@ import im.vector.app.features.spaces.share.ShareSpaceBottomSheet import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.workers.signout.ServerBackupStatusViewModel import im.vector.app.features.workers.signout.ServerBackupStatusViewState -import im.vector.app.push.fcm.FcmHelper +import im.vector.app.core.pushers.UPHelper import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.initsync.InitialSyncProgressService @@ -164,7 +164,7 @@ class HomeActivity : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - FcmHelper.ensureFcmTokenIsRetrieved(this, pushManager, vectorPreferences.areNotificationEnabledForDevice()) + UPHelper.registerUnifiedPush(this) sharedActionViewModel = viewModelProvider.get(HomeSharedActionViewModel::class.java) views.drawerLayout.addDrawerListener(drawerListener) if (isFirstCreation()) { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationPreferenceFragment.kt index fd1f406bcb..a798efc168 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationPreferenceFragment.kt @@ -37,11 +37,12 @@ import im.vector.app.core.pushers.PushersManager import im.vector.app.core.utils.isIgnoringBatteryOptimizations import im.vector.app.core.utils.requestDisablingBatteryOptimization import im.vector.app.features.notifications.NotificationUtils -import im.vector.app.push.fcm.FcmHelper +import im.vector.app.core.pushers.UPHelper import kotlinx.coroutines.launch import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.pushrules.RuleIds import org.matrix.android.sdk.api.pushrules.RuleKind +import timber.log.Timber import javax.inject.Inject // Referenced in vector_settings_preferences_root.xml @@ -145,7 +146,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( } findPreference(VectorPreferences.SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY)?.let { - it.isVisible = !FcmHelper.isPushSupported() + it.isVisible = !UPHelper.hasEndpoint(requireContext()) } findPreference(VectorPreferences.SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY)?.let { @@ -249,7 +250,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( private fun refreshPref() { // This pref may have change from troubleshoot pref fragment - if (!FcmHelper.isPushSupported()) { + if (!UPHelper.hasEndpoint(requireContext())) { findPreference(VectorPreferences.SETTINGS_START_ON_BOOT_PREFERENCE_KEY) ?.isChecked = vectorPreferences.autoStartOnBoot() } @@ -289,13 +290,22 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( private fun updateEnabledForDevice(preference: Preference?) { val switchPref = preference as SwitchPreference if (switchPref.isChecked) { - FcmHelper.getFcmToken(requireContext())?.let { - pushManager.registerPusherWithFcmKey(it) - } + UPHelper.registerUnifiedPush(requireContext()) } else { - FcmHelper.getFcmToken(requireContext())?.let { + UPHelper.getUpEndpoint(requireContext())?.let { lifecycleScope.launch { - runCatching { pushManager.unregisterPusher(it) } + runCatching { + try { + pushManager.unregisterPusher(it) + } catch (e: Exception) { + Timber.d("Probably unregistering a non existant pusher") + } + try { + UPHelper.unregister(requireContext()) + } catch (e: Exception) { + Timber.d("Probably unregistering to a non-saved distributor") + } + } .fold( { session.refreshPushers() }, { diff --git a/vector/src/main/res/values/config.xml b/vector/src/main/res/values/config.xml index 2b22b1c49b..eb0cfdb4f4 100755 --- a/vector/src/main/res/values/config.xml +++ b/vector/src/main/res/values/config.xml @@ -15,6 +15,8 @@ https://matrix.org/_matrix/push/v1/notify + + https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify im.vector.app.android