From a3a946fb750b4186797cc97af7f17fbdce458496 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 1 Jun 2021 20:29:44 +0200 Subject: [PATCH 01/28] 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 From 434739ad3134f1b8197dbce985db9d74efb10512 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 2 Jun 2021 01:14:30 +0200 Subject: [PATCH 02/28] up: troubleshoot list --- ...ificationTroubleshootTestManagerFactory.kt | 29 +++++-- .../settings/troubleshoot/TestNewEndpoint.kt | 83 ------------------- ...ificationTroubleshootTestManagerFactory.kt | 31 +++++-- vector/src/main/AndroidManifest.xml | 4 + .../im/vector/app/core/pushers/UPHelper.kt | 5 ++ .../troubleshoot/TestAutoStartBoot.kt | 2 +- .../TestBackgroundRestrictions.kt | 5 +- .../troubleshoot/TestBatteryOptimization.kt | 2 +- .../settings/troubleshoot/TestNewEndpoint.kt | 45 ++++++++++ .../troubleshoot/TestPushFromPushGateway.kt | 6 +- .../troubleshoot/TestTokenRegistration.kt | 9 +- vector/src/main/res/values/strings.xml | 12 +++ 12 files changed, 122 insertions(+), 111 deletions(-) delete mode 100644 vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestNewEndpoint.kt rename vector/src/{fdroid/java/im/vector/app/fdroid => main/java/im/vector/app}/features/settings/troubleshoot/TestAutoStartBoot.kt (97%) rename vector/src/{fdroid/java/im/vector/app/fdroid => main/java/im/vector/app}/features/settings/troubleshoot/TestBackgroundRestrictions.kt (95%) rename vector/src/{fdroid/java/im/vector/app/fdroid => main/java/im/vector/app}/features/settings/troubleshoot/TestBatteryOptimization.kt (97%) create mode 100644 vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt rename vector/src/{gplay/java/im/vector/app/gplay => main/java/im/vector/app}/features/settings/troubleshoot/TestPushFromPushGateway.kt (96%) rename vector/src/{gplay/java/im/vector/app/gplay => main/java/im/vector/app}/features/settings/troubleshoot/TestTokenRegistration.kt (91%) diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index 6236aad65c..366128ff2c 100644 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -16,21 +16,29 @@ package im.vector.app.push.fcm import androidx.fragment.app.Fragment -import im.vector.app.fdroid.features.settings.troubleshoot.TestAutoStartBoot -import im.vector.app.fdroid.features.settings.troubleshoot.TestBackgroundRestrictions -import im.vector.app.fdroid.features.settings.troubleshoot.TestBatteryOptimization +import im.vector.app.core.pushers.UPHelper +import im.vector.app.features.settings.troubleshoot.TestAutoStartBoot +import im.vector.app.features.settings.troubleshoot.TestBackgroundRestrictions +import im.vector.app.features.settings.troubleshoot.TestBatteryOptimization import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TestAccountSettings import im.vector.app.features.settings.troubleshoot.TestDeviceSettings +import im.vector.app.features.settings.troubleshoot.TestNewEndpoint import im.vector.app.features.settings.troubleshoot.TestNotification +import im.vector.app.features.settings.troubleshoot.TestPushFromPushGateway import im.vector.app.features.settings.troubleshoot.TestPushRulesSettings import im.vector.app.features.settings.troubleshoot.TestSystemSettings +import im.vector.app.features.settings.troubleshoot.TestTokenRegistration import javax.inject.Inject class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testSystemSettings: TestSystemSettings, private val testAccountSettings: TestAccountSettings, private val testDeviceSettings: TestDeviceSettings, + private val testBingRulesSettings: TestPushRulesSettings, + private val testNewEndpoint: TestNewEndpoint, + private val testTokenRegistration: TestTokenRegistration, + private val testPushFromPushGateway: TestPushFromPushGateway, private val testPushRulesSettings: TestPushRulesSettings, private val testAutoStartBoot: TestAutoStartBoot, private val testBackgroundRestrictions: TestBackgroundRestrictions, @@ -43,10 +51,17 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) mgr.addTest(testDeviceSettings) - mgr.addTest(testPushRulesSettings) - mgr.addTest(testAutoStartBoot) - mgr.addTest(testBackgroundRestrictions) - mgr.addTest(testBatteryOptimization) + if (UPHelper.DistributorExists(fragment.requireContext())) { + mgr.addTest(testBingRulesSettings) + mgr.addTest(testNewEndpoint) + mgr.addTest(testTokenRegistration) + mgr.addTest(testPushFromPushGateway) + } else { + mgr.addTest(testPushRulesSettings) + mgr.addTest(testAutoStartBoot) + mgr.addTest(testBackgroundRestrictions) + mgr.addTest(testBatteryOptimization) + } mgr.addTest(testNotification) return mgr } diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestNewEndpoint.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestNewEndpoint.kt deleted file mode 100644 index 7cb0fed9f4..0000000000 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestNewEndpoint.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2018 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.gplay.features.settings.troubleshoot - -import android.content.Intent -import androidx.activity.result.ActivityResultLauncher -import androidx.appcompat.app.AppCompatActivity -import im.vector.app.R -import im.vector.app.core.resources.StringProvider -import im.vector.app.core.utils.startAddGoogleAccountIntent -import im.vector.app.features.settings.troubleshoot.TroubleshootTest -import im.vector.app.push.fcm.FcmHelper -import timber.log.Timber -import javax.inject.Inject - -/* -* Test that app can successfully retrieve a new endpoint - */ -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) { - description = "bypassed" - status = TestStatus.SUCCESS - /** - * TODO - */ - /*status = TestStatus.RUNNING - try { - FirebaseMessaging.getInstance().token - .addOnCompleteListener(context) { task -> - if (!task.isSuccessful) { - // Can't find where this constant is (not documented -or deprecated in docs- and all obfuscated) - description = when (val errorMsg = task.exception?.localizedMessage ?: "Unknown") { - "SERVICE_NOT_AVAILABLE" -> { - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg) - } - "TOO_MANY_REGISTRATIONS" -> { - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg) - } - "ACCOUNT_MISSING" -> { - quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) { - override fun doFix() { - startAddGoogleAccountIntent(context, activityResultLauncher) - } - } - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg) - } - else -> { - stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg) - } - } - status = TestStatus.FAILED - } else { - task.result?.let { token -> - val tok = token.take(8) + "********************" - description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_success, tok) - Timber.e("Retrieved FCM token success [$tok].") - // Ensure it is well store in our local storage - FcmHelper.storeFcmToken(context, token) - } - status = TestStatus.SUCCESS - } - } - } 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/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index df0b3409bc..14c0e1c48d 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 @@ -16,16 +16,20 @@ package im.vector.app.push.fcm import androidx.fragment.app.Fragment +import im.vector.app.core.pushers.UPHelper import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TestAccountSettings +import im.vector.app.features.settings.troubleshoot.TestAutoStartBoot +import im.vector.app.features.settings.troubleshoot.TestBackgroundRestrictions +import im.vector.app.features.settings.troubleshoot.TestBatteryOptimization 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.TestNewEndpoint +import im.vector.app.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 +import im.vector.app.features.settings.troubleshoot.TestPushFromPushGateway +import im.vector.app.features.settings.troubleshoot.TestTokenRegistration import javax.inject.Inject class NotificationTroubleshootTestManagerFactory @Inject constructor( @@ -37,6 +41,10 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testNewEndpoint: TestNewEndpoint, private val testTokenRegistration: TestTokenRegistration, private val testPushFromPushGateway: TestPushFromPushGateway, + private val testPushRulesSettings: TestPushRulesSettings, + private val testAutoStartBoot: TestAutoStartBoot, + private val testBackgroundRestrictions: TestBackgroundRestrictions, + private val testBatteryOptimization: TestBatteryOptimization, private val testNotification: TestNotification ) { @@ -45,11 +53,18 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) mgr.addTest(testDeviceSettings) - mgr.addTest(testBingRulesSettings) - mgr.addTest(testPlayServices) - mgr.addTest(testNewEndpoint) - mgr.addTest(testTokenRegistration) - mgr.addTest(testPushFromPushGateway) + if (UPHelper.DistributorExists(fragment.requireContext())) { + mgr.addTest(testBingRulesSettings) + mgr.addTest(testPlayServices) + mgr.addTest(testNewEndpoint) + mgr.addTest(testTokenRegistration) + mgr.addTest(testPushFromPushGateway) + } else { + mgr.addTest(testPushRulesSettings) + mgr.addTest(testAutoStartBoot) + mgr.addTest(testBackgroundRestrictions) + mgr.addTest(testBatteryOptimization) + } mgr.addTest(testNotification) return mgr } diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index ba820cc3a7..0cc1b7c178 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -357,6 +357,10 @@ android:name=".features.settings.troubleshoot.TestNotificationReceiver" android:exported="false" /> + + ) { + status = TestStatus.RUNNING + + val endpoint = UPHelper.getUpEndpoint(context) + + if (!endpoint.isNullOrEmpty()) { + status = TestStatus.SUCCESS + description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_success, endpoint) + return + } + status = TestStatus.FAILED + description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_failed) + } +} diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt similarity index 96% rename from vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt rename to vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt index a4a3507828..9d6a0cfe73 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 New Vector Ltd + * 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package im.vector.app.gplay.features.settings.troubleshoot +package im.vector.app.features.settings.troubleshoot import android.content.Intent import androidx.activity.result.ActivityResultLauncher @@ -24,7 +24,6 @@ import im.vector.app.core.error.ErrorFormatter 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.core.pushers.UPHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -46,6 +45,7 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat private var action: Job? = null private var pushReceived: Boolean = false + override fun perform(activityResultLauncher: ActivityResultLauncher) { pushReceived = false UPHelper.getUpEndpoint(context) ?: run { diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestTokenRegistration.kt similarity index 91% rename from vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt rename to vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestTokenRegistration.kt index 4d1a869768..b9ca1290ff 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestTokenRegistration.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package im.vector.app.gplay.features.settings.troubleshoot +package im.vector.app.features.settings.troubleshoot import android.content.Intent import androidx.activity.result.ActivityResultLauncher @@ -26,7 +26,6 @@ import im.vector.app.R 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.core.pushers.UPHelper import javax.inject.Inject @@ -37,7 +36,7 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc private val stringProvider: StringProvider, private val pushersManager: PushersManager, private val activeSessionHolder: ActiveSessionHolder) - : TroubleshootTest(R.string.settings_troubleshoot_test_token_registration_title) { + : TroubleshootTest(R.string.settings_troubleshoot_test_pusher_registration_title) { override fun perform(activityResultLauncher: ActivityResultLauncher) { // Check if we have a registered pusher for this token @@ -57,7 +56,7 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc it.pushKey == pushToken && it.state == PusherState.REGISTERED } if (pushers.isEmpty()) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_token_registration_failed, + description = stringProvider.getString(R.string.settings_troubleshoot_test_pusher_registration_failed, stringProvider.getString(R.string.sas_error_unknown)) quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_token_registration_quick_fix) { override fun doFix() { @@ -76,7 +75,7 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc status = TestStatus.FAILED } else { - description = stringProvider.getString(R.string.settings_troubleshoot_test_token_registration_success) + description = stringProvider.getString(R.string.settings_troubleshoot_test_pusher_registration_success) status = TestStatus.SUCCESS } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 1e3d246e64..7f1d9e1fd3 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1110,6 +1110,12 @@ ${app_name} uses Google Play Services to deliver push messages but it doesn’t seem to be configured correctly:\n%1$s Fix Play Services + + Endpoint + Endpoint successfully retrieved:\n%1$s + Failed to retrieved Endpoint. + + Firebase Token FCM token successfully retrieved:\n%1$s Failed to retrieved FCM token:\n%1$s @@ -1121,6 +1127,12 @@ [%1$s]\nThis error is out of control of ${app_name}. There is no Google account on the phone. Please open the account manager and add a Google account. Add Account + + Pusher Registration + Pusher successfully registered to HomeServer. + Failed to register pusher to HomeServer:\n%1$s + + Token Registration FCM token successfully registered to HomeServer. Failed to register FCM token to HomeServer:\n%1$s From 8a8a3750fdaa5d51ebe38cc4da727ab23ecf346a Mon Sep 17 00:00:00 2001 From: user Date: Wed, 2 Jun 2021 07:57:58 +0200 Subject: [PATCH 03/28] upReceiver: on/off background sync --- .../im/vector/app/core/pushers/VectorMessagingReceiver.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index 0180b91b87..f54c5db661 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -35,6 +35,7 @@ import im.vector.app.features.badge.BadgeProxy import im.vector.app.features.notifications.NotifiableEventResolver import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.notifications.NotificationUtils +import im.vector.app.features.settings.BackgroundSyncMode import im.vector.app.features.settings.VectorPreferences import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob @@ -152,6 +153,8 @@ val upHandler = object: MessagingReceiverHandler { UPHelper.storeUpEndpoint(context, endpoint) pusherManager.registerPusher(endpoint, gateway) } + val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED + vectorPreferences.setFdroidSyncBackgroundMode(mode) } override fun onRegistrationFailed(context: Context?, instance: String) { @@ -165,6 +168,8 @@ val upHandler = object: MessagingReceiverHandler { override fun onUnregistered(context: Context?, instance: String) { Timber.d("Unifiedpush: Unregistered") initVar(context!!) + val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY + vectorPreferences.setFdroidSyncBackgroundMode(mode) runBlocking { try { pusherManager.unregisterPusher(UPHelper.getUpEndpoint(context)!!) From 1e8d8b24fde042d755c52fff6c2d9ef1f43c7fbb Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 2 Jun 2021 08:36:00 +0200 Subject: [PATCH 04/28] 3448: newsfragment Signed-off-by: S1m --- newsfragment/3448.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 newsfragment/3448.feature diff --git a/newsfragment/3448.feature b/newsfragment/3448.feature new file mode 100644 index 0000000000..3f83f1bef5 --- /dev/null +++ b/newsfragment/3448.feature @@ -0,0 +1 @@ +Use UnifiedPush and allows user to have push without FCM. From b32fab390e72c1533c178be0e17ea4a5e8f89974 Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 2 Jun 2021 13:01:14 +0200 Subject: [PATCH 05/28] clean code --- vector/src/main/AndroidManifest.xml | 4 ---- .../app/features/settings/troubleshoot/TestAutoStartBoot.kt | 1 - .../features/settings/troubleshoot/TestBatteryOptimization.kt | 1 - .../app/features/settings/troubleshoot/TestNewEndpoint.kt | 3 ++- .../features/settings/troubleshoot/TestPushFromPushGateway.kt | 1 - 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 0cc1b7c178..ba820cc3a7 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -357,10 +357,6 @@ android:name=".features.settings.troubleshoot.TestNotificationReceiver" android:exported="false" /> - - ) { status = TestStatus.RUNNING diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt index 9d6a0cfe73..2b17694839 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -45,7 +45,6 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat private var action: Job? = null private var pushReceived: Boolean = false - override fun perform(activityResultLauncher: ActivityResultLauncher) { pushReceived = false UPHelper.getUpEndpoint(context) ?: run { From 6c80b3a14bd93425e50a54accdd8428c4713ecea Mon Sep 17 00:00:00 2001 From: S1m Date: Fri, 4 Jun 2021 01:23:15 +0200 Subject: [PATCH 06/28] embedded distrib with sygnal --- .../gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt | 5 ++--- .../src/main/java/im/vector/app/core/pushers/UPHelper.kt | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) 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 index 1e7f04f9c3..1ae67c3500 100644 --- a/vector/src/gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt @@ -1,7 +1,6 @@ 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 @@ -23,8 +22,8 @@ import org.unifiedpush.android.embedded_fcm_distributor.EmbeddedDistributorRecei 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" + // Here token is the FCM Token, used by the gateway (sygnal) + return token } } 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 index b8fa15f860..4de1afc716 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt @@ -125,6 +125,13 @@ object UPHelper { } fun customOrDefaultGateway(context: Context, endpoint: String?): String { + // if we use the embedded distributor, + // register app_id type upfcm on sygnal + // the pushkey if FCM key + val up = Registration() + if (up.getDistributor(context) == context.packageName) + return context.getString(R.string.pusher_http_url) + // else, unifiedpush, and pushkey is an endpoint val default = context.getString(R.string.default_push_gateway_http_url) endpoint?.let { val uri = URI(it) From 5f5b873414125afa348019c286dd5e38e04647e6 Mon Sep 17 00:00:00 2001 From: S1m Date: Mon, 7 Jun 2021 13:22:07 +0200 Subject: [PATCH 07/28] different Pusher AppId --- ...tificationTroubleshootTestManagerFactory.kt | 2 +- ...tificationTroubleshootTestManagerFactory.kt | 2 +- .../vector/app/core/pushers/PushersManager.kt | 18 +++++++++++++----- .../im/vector/app/core/pushers/UPHelper.kt | 8 +++++++- .../core/pushers/VectorMessagingReceiver.kt | 4 ++-- ...orSettingsNotificationPreferenceFragment.kt | 2 +- .../troubleshoot/TestTokenRegistration.kt | 2 +- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index 366128ff2c..4a73457c01 100644 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -51,7 +51,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) mgr.addTest(testDeviceSettings) - if (UPHelper.DistributorExists(fragment.requireContext())) { + if (UPHelper.distributorExists(fragment.requireContext())) { mgr.addTest(testBingRulesSettings) mgr.addTest(testNewEndpoint) mgr.addTest(testTokenRegistration) 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 14c0e1c48d..36afcb28f3 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 @@ -53,7 +53,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) mgr.addTest(testDeviceSettings) - if (UPHelper.DistributorExists(fragment.requireContext())) { + if (UPHelper.distributorExists(fragment.requireContext())) { mgr.addTest(testBingRulesSettings) mgr.addTest(testPlayServices) mgr.addTest(testNewEndpoint) 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 7c5e38c8fe..6462bcf3c8 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 @@ -39,19 +39,19 @@ class PushersManager @Inject constructor( currentSession.testPush( UPHelper.getPushGateway(context)!!, - stringProvider.getString(R.string.pusher_app_id), + getPusherAppId(context), UPHelper.getUpEndpoint(context)!!, TEST_EVENT_ID ) } - fun registerPusher(pushKey: String, gateway: String): UUID { + fun registerPusher(context: Context, pushKey: String, gateway: String): UUID { val currentSession = activeSessionHolder.getActiveSession() val profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(currentSession.myUserId.hashCode()) return currentSession.addHttpPusher( pushKey, // this is the UnifiedPush endpoint - stringProvider.getString(R.string.pusher_app_id), + getPusherAppId(context), profileTag, localeProvider.current().language, appNameProvider.getAppName(), @@ -62,9 +62,17 @@ class PushersManager @Inject constructor( ) } - suspend fun unregisterPusher(pushKey: String) { + suspend fun unregisterPusher(context: Context, pushKey: String) { val currentSession = activeSessionHolder.getSafeActiveSession() ?: return - currentSession.removeHttpPusher(pushKey, stringProvider.getString(R.string.pusher_app_id)) + currentSession.removeHttpPusher(pushKey, getPusherAppId(context)) + } + + private fun getPusherAppId(context: Context) : String { + val appId = stringProvider.getString(R.string.pusher_app_id) + return if (UPHelper.isEmbeddedDistributor(context)) { + "${appId}.fcm" + } else + "${appId}.up" } companion object { 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 index 4de1afc716..0d7e69d382 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt @@ -153,8 +153,14 @@ object UPHelper { return false } - fun DistributorExists(context: Context): Boolean { + fun distributorExists(context: Context): Boolean { val up = Registration() return up.getDistributor(context).isNotEmpty() } + + fun isEmbeddedDistributor(context: Context) : Boolean { + val up = Registration() + return up.getDistributor(context) == context.packageName + } + } diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index f54c5db661..c9fa4bfca1 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -151,7 +151,7 @@ val upHandler = object: MessagingReceiverHandler { val gateway = UPHelper.customOrDefaultGateway(context, endpoint) UPHelper.storePushGateway(context, gateway) UPHelper.storeUpEndpoint(context, endpoint) - pusherManager.registerPusher(endpoint, gateway) + pusherManager.registerPusher(context, endpoint, gateway) } val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED vectorPreferences.setFdroidSyncBackgroundMode(mode) @@ -172,7 +172,7 @@ val upHandler = object: MessagingReceiverHandler { vectorPreferences.setFdroidSyncBackgroundMode(mode) runBlocking { try { - pusherManager.unregisterPusher(UPHelper.getUpEndpoint(context)!!) + pusherManager.unregisterPusher(context, UPHelper.getUpEndpoint(context)!!) } catch (e: Exception) { Timber.d("Probably unregistering a non existant pusher") } 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 a798efc168..e4cd8db693 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 @@ -296,7 +296,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( lifecycleScope.launch { runCatching { try { - pushManager.unregisterPusher(it) + pushManager.unregisterPusher(requireContext(), it) } catch (e: Exception) { Timber.d("Probably unregistering a non existant pusher") } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestTokenRegistration.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestTokenRegistration.kt index b9ca1290ff..eb92ed00af 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestTokenRegistration.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestTokenRegistration.kt @@ -60,7 +60,7 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc 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.registerPusher(pushToken, pushGateway) + val workId = pushersManager.registerPusher(context, pushToken, pushGateway) WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo -> if (workInfo != null) { if (workInfo.state == WorkInfo.State.SUCCEEDED) { From 09b290e579d635502b9341d864aed97e94701671 Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 30 Jun 2021 08:36:29 +0200 Subject: [PATCH 08/28] UP dialog: app name --- .../im/vector/app/core/pushers/UPHelper.kt | 19 ++++++++++++++++--- vector/src/main/res/values/strings.xml | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) 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 index 0d7e69d382..e8c06ef1cc 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt @@ -16,6 +16,7 @@ package im.vector.app.core.pushers import android.content.Context +import android.content.pm.PackageManager import androidx.appcompat.app.AlertDialog import androidx.core.content.edit import im.vector.app.R @@ -95,7 +96,7 @@ object UPHelper { when (distributors.size) { 0 -> { /** - * TODO: fallback with sync service : automatic ? + * Fallback with sync service */ } 1 -> { @@ -104,10 +105,22 @@ object UPHelper { } else -> { val builder: AlertDialog.Builder = AlertDialog.Builder(context) - builder.setTitle("Choose a distributor") + builder.setTitle(context.getString(R.string.unifiedpush_getdistributors_dialog_title)) val distributorsArray = distributors.toTypedArray() - builder.setItems(distributorsArray) { _, which -> + val distributorsNameArray = distributorsArray.map { + if (it == context.packageName) { + context.getString(R.string.unifiedpush_getdistributors_dialog_fcm_fallback) + } else { + try { + val ai = context.packageManager.getApplicationInfo(it, 0) + context.packageManager.getApplicationLabel(ai) + } catch (e: PackageManager.NameNotFoundException) { + it + } as String + } + }.toTypedArray() + builder.setItems(distributorsNameArray) { _, which -> val distributor = distributorsArray[which] up.saveDistributor(context, distributor) Timber.i("Saving distributor: $distributor") diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index d82c8bead2..a3d5b3a0e4 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1115,6 +1115,10 @@ Endpoint successfully retrieved:\n%1$s Failed to retrieved Endpoint. + + Choose a distributor + FCM Fallback + Firebase Token FCM token successfully retrieved:\n%1$s From 4a8fa4a3ce5e0f4603e64ba2a8bcb85a69216ff4 Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 30 Jun 2021 19:53:24 +0200 Subject: [PATCH 09/28] embedded distrib: original gateway --- vector/build.gradle | 2 +- .../vector/app/core/pushers/PushersManager.kt | 2 +- .../core/pushers/VectorMessagingReceiver.kt | 32 +++++++++++++++---- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index f7804bb5dc..62cc8eaae7 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -435,7 +435,7 @@ dependencies { // Unifiedpush implementation 'com.github.UnifiedPush:android-connector:1.1.3' - gplayImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.0.2' + gplayImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.1.0' // OSS License, gplay flavor only gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0' 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 6462bcf3c8..6910c0ae0c 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 @@ -70,7 +70,7 @@ class PushersManager @Inject constructor( private fun getPusherAppId(context: Context) : String { val appId = stringProvider.getString(R.string.pusher_app_id) return if (UPHelper.isEmbeddedDistributor(context)) { - "${appId}.fcm" + appId } else "${appId}.up" } diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index c9fa4bfca1..a50a4b6f4e 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -94,13 +94,30 @@ val upHandler = object: MessagingReceiverHandler { lateinit var data: JSONObject lateinit var notification: JSONObject - try { - data = JSONObject(message) - notification = data.getJSONObject("notification") - } catch (e: JSONException) { - Timber.e(e) - return + if (UPHelper.isEmbeddedDistributor(context)) { + try { + notification = JSONObject(message) + } catch (e: JSONException) { + Timber.e(e) + return + } + } else { + try { + data = JSONObject(message) + notification = data.getJSONObject("notification") + } catch (e: JSONException) { + Timber.e(e) + return + } + try { + notification.put("unread", + notification.getJSONObject("count").getInt("unread")) + } catch (e: JSONException) { + Timber.i("No unread on notification") + notification.put("unread", 0) + } } + val eventId: String = try { notification.getString("event_id") } catch (e: JSONException) { @@ -108,6 +125,7 @@ val upHandler = object: MessagingReceiverHandler { notification.put("event_id", "") "" } + try { notification.getString("room_id") } catch (e: JSONException) { @@ -191,7 +209,7 @@ val upHandler = object: MessagingReceiverHandler { } // update the badge counter - val unreadCount = data.getJSONObject("counts").getInt("unread") + val unreadCount = data.getInt("unread") BadgeProxy.updateBadgeCount(context, unreadCount) val session = activeSessionHolder.getSafeActiveSession() From 4ac475586837d44a3e70b829876a43786a0b2ce6 Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 7 Jul 2021 01:49:39 +0200 Subject: [PATCH 10/28] up pr: code reviewed --- vector/build.gradle | 5 +++-- .../push/fcm/NotificationTroubleshootTestManagerFactory.kt | 4 +--- .../push/fcm/NotificationTroubleshootTestManagerFactory.kt | 4 +--- .../main/java/im/vector/app/core/pushers/PushersManager.kt | 5 +++-- .../src/main/java/im/vector/app/core/pushers/UPHelper.kt | 7 ++++--- .../app/features/settings/troubleshoot/TestNewEndpoint.kt | 6 +++--- vector/src/main/res/values/config.xml | 4 +++- 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index d270e571f8..a8a42ba83f 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -444,8 +444,9 @@ dependencies { implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" - // Unifiedpush - implementation 'com.github.UnifiedPush:android-connector:1.1.3' + // UnifiedPush + implementation 'com.github.UnifiedPush:android-connector:1.2.0' + // UnifiedPush gplay flavor only gplayImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.1.0' // OSS License, gplay flavor only diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index 4a73457c01..56c96f5b2b 100644 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -35,7 +35,6 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testSystemSettings: TestSystemSettings, private val testAccountSettings: TestAccountSettings, private val testDeviceSettings: TestDeviceSettings, - private val testBingRulesSettings: TestPushRulesSettings, private val testNewEndpoint: TestNewEndpoint, private val testTokenRegistration: TestTokenRegistration, private val testPushFromPushGateway: TestPushFromPushGateway, @@ -51,13 +50,12 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) mgr.addTest(testDeviceSettings) + mgr.addTest(testPushRulesSettings) if (UPHelper.distributorExists(fragment.requireContext())) { - mgr.addTest(testBingRulesSettings) mgr.addTest(testNewEndpoint) mgr.addTest(testTokenRegistration) mgr.addTest(testPushFromPushGateway) } else { - mgr.addTest(testPushRulesSettings) mgr.addTest(testAutoStartBoot) mgr.addTest(testBackgroundRestrictions) mgr.addTest(testBatteryOptimization) 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 36afcb28f3..673733d452 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 @@ -36,7 +36,6 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testSystemSettings: TestSystemSettings, private val testAccountSettings: TestAccountSettings, private val testDeviceSettings: TestDeviceSettings, - private val testBingRulesSettings: TestPushRulesSettings, private val testPlayServices: TestPlayServices, private val testNewEndpoint: TestNewEndpoint, private val testTokenRegistration: TestTokenRegistration, @@ -53,14 +52,13 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) mgr.addTest(testDeviceSettings) + mgr.addTest(testPushRulesSettings) if (UPHelper.distributorExists(fragment.requireContext())) { - mgr.addTest(testBingRulesSettings) mgr.addTest(testPlayServices) mgr.addTest(testNewEndpoint) mgr.addTest(testTokenRegistration) mgr.addTest(testPushFromPushGateway) } else { - mgr.addTest(testPushRulesSettings) mgr.addTest(testAutoStartBoot) mgr.addTest(testBackgroundRestrictions) mgr.addTest(testBatteryOptimization) 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 6910c0ae0c..5ebbfd5b81 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 @@ -71,8 +71,9 @@ class PushersManager @Inject constructor( val appId = stringProvider.getString(R.string.pusher_app_id) return if (UPHelper.isEmbeddedDistributor(context)) { appId - } else - "${appId}.up" + } else { + "$appId.up" + } } companion object { 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 index e8c06ef1cc..5f34ae4f3a 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/UPHelper.kt @@ -19,6 +19,7 @@ import android.content.Context import android.content.pm.PackageManager import androidx.appcompat.app.AlertDialog import androidx.core.content.edit +import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.di.DefaultSharedPreferences import im.vector.app.push.fcm.FcmHelper @@ -104,7 +105,7 @@ object UPHelper { up.registerApp(context) } else -> { - val builder: AlertDialog.Builder = AlertDialog.Builder(context) + val builder: AlertDialog.Builder = MaterialAlertDialogBuilder(context) builder.setTitle(context.getString(R.string.unifiedpush_getdistributors_dialog_title)) val distributorsArray = distributors.toTypedArray() @@ -142,8 +143,9 @@ object UPHelper { // register app_id type upfcm on sygnal // the pushkey if FCM key val up = Registration() - if (up.getDistributor(context) == context.packageName) + if (up.getDistributor(context) == context.packageName) { return context.getString(R.string.pusher_http_url) + } // else, unifiedpush, and pushkey is an endpoint val default = context.getString(R.string.default_push_gateway_http_url) endpoint?.let { @@ -175,5 +177,4 @@ object UPHelper { val up = Registration() return up.getDistributor(context) == context.packageName } - } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt index 075505fd75..cb09046628 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt @@ -38,9 +38,9 @@ class TestNewEndpoint @Inject constructor(private val context: AppCompatActivity if (!endpoint.isNullOrEmpty()) { status = TestStatus.SUCCESS description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_success, endpoint) - return + } else { + status = TestStatus.FAILED + description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_failed) } - status = TestStatus.FAILED - description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_failed) } } diff --git a/vector/src/main/res/values/config.xml b/vector/src/main/res/values/config.xml index 4616b55796..b5d92337bc 100755 --- a/vector/src/main/res/values/config.xml +++ b/vector/src/main/res/values/config.xml @@ -14,8 +14,10 @@ --> + https://matrix.org/_matrix/push/v1/notify - + + https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify im.vector.app.android From 7ead76c8caf82c297510d0b04665e2402f674e50 Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 7 Jul 2021 03:35:16 +0200 Subject: [PATCH 11/28] up: moshi to parse json --- vector/build.gradle | 2 + .../core/pushers/VectorMessagingReceiver.kt | 90 ++++++++----------- 2 files changed, 41 insertions(+), 51 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index a8a42ba83f..4ee326348b 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -337,6 +337,7 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" @@ -353,6 +354,7 @@ dependencies { implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.9.0" implementation "com.squareup.moshi:moshi-adapters:$moshi_version" + implementation "com.squareup.moshi:moshi-kotlin:$moshi_version" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index a50a4b6f4e..1b0b0fc9b2 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -27,6 +27,10 @@ import android.widget.Toast import androidx.lifecycle.Lifecycle import androidx.lifecycle.ProcessLifecycleOwner import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import im.vector.app.BuildConfig import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.vectorComponent @@ -41,16 +45,30 @@ 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.session.Session import org.unifiedpush.android.connector.MessagingReceiver import org.unifiedpush.android.connector.MessagingReceiverHandler import timber.log.Timber +data class UnifiedPushMessage ( + val notification: Notification + ) + +@JsonClass(generateAdapter = true) +data class Notification ( + @Json(name = "event_id") val eventId: String = "", + @Json(name = "room_id") val roomId: String = "", + var unread: Int = 0, + val counts: Counts = Counts() + ) + +data class Counts ( + val unread: Int = 0 + ) + /** - * Unifiedpush handler. + * UnifiedPush handler. */ val upHandler = object: MessagingReceiverHandler { @@ -92,49 +110,23 @@ val upHandler = object: MessagingReceiverHandler { } Timber.d("## onMessage() received") - lateinit var data: JSONObject - lateinit var notification: JSONObject + val moshi: Moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() + lateinit var notification: Notification + if (UPHelper.isEmbeddedDistributor(context)) { - try { - notification = JSONObject(message) - } catch (e: JSONException) { - Timber.e(e) - return - } + notification = moshi.adapter(Notification::class.java) + .fromJson(message)!! } else { - try { - data = JSONObject(message) - notification = data.getJSONObject("notification") - } catch (e: JSONException) { - Timber.e(e) - return - } - try { - notification.put("unread", - notification.getJSONObject("count").getInt("unread")) - } catch (e: JSONException) { - Timber.i("No unread on notification") - notification.put("unread", 0) - } - } - - 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", "") + val data = moshi.adapter(UnifiedPushMessage::class.java) + .fromJson(message)!! + notification = data.notification + notification.unread = notification.counts.unread } // Diagnostic Push - if (eventId == PushersManager.TEST_EVENT_ID) { + if (notification.eventId == PushersManager.TEST_EVENT_ID) { val intent = Intent(NotificationUtils.PUSH_ACTION) LocalBroadcastManager.getInstance(context).sendBroadcast(intent) return @@ -200,32 +192,28 @@ val upHandler = object: MessagingReceiverHandler { /** * Internal receive method * - * @param data Data json containing message data. + * @param notification Notification containing message data. */ - private fun onMessageReceivedInternal(context: Context, data: JSONObject) { + private fun onMessageReceivedInternal(context: Context, notification: Notification) { try { if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { - Timber.d("## onMessageReceivedInternal() : $data") + Timber.d("## onMessageReceivedInternal() : $notification") } // update the badge counter - val unreadCount = data.getInt("unread") - BadgeProxy.updateBadgeCount(context, unreadCount) + BadgeProxy.updateBadgeCount(context, notification.unread) val session = activeSessionHolder.getSafeActiveSession() if (session == null) { Timber.w("## Can't sync from push, no current session") } else { - val eventId = data.getString("event_id") - val roomId = data.getString("room_id") - - if (isEventAlreadyKnown(eventId, roomId)) { + if (isEventAlreadyKnown(notification.eventId, notification.roomId)) { Timber.d("Ignoring push, event already known") } else { // Try to get the Event content faster Timber.d("Requesting event in fast lane") - getEventFastLane(session, roomId, eventId) + getEventFastLane(session, notification.roomId, notification.eventId) Timber.d("Requesting background sync") session.requireBackgroundSync() From a223ddc48af9ccc94482af7f5c1323b47e985c8a Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 7 Jul 2021 04:02:08 +0200 Subject: [PATCH 12/28] up pr: lint --- .../im/vector/app/core/pushers/VectorMessagingReceiver.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index 1b0b0fc9b2..f400cded9d 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -51,19 +51,19 @@ import org.unifiedpush.android.connector.MessagingReceiver import org.unifiedpush.android.connector.MessagingReceiverHandler import timber.log.Timber -data class UnifiedPushMessage ( +data class UnifiedPushMessage( val notification: Notification ) @JsonClass(generateAdapter = true) -data class Notification ( +data class Notification( @Json(name = "event_id") val eventId: String = "", @Json(name = "room_id") val roomId: String = "", var unread: Int = 0, val counts: Counts = Counts() ) -data class Counts ( +data class Counts( val unread: Int = 0 ) From 15c3bb7fc355cb6281768b4c040432fc390de6b7 Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 7 Jul 2021 23:11:18 +0200 Subject: [PATCH 13/28] exclude firebase analytics --- vector/build.gradle | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index 4ee326348b..80356968b6 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -449,7 +449,11 @@ dependencies { // UnifiedPush implementation 'com.github.UnifiedPush:android-connector:1.2.0' // UnifiedPush gplay flavor only - gplayImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.1.0' + gplayImplementation('com.github.UnifiedPush:android-embedded_fcm_distributor:1.1.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' + } // OSS License, gplay flavor only gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0' From dbfa5e1fd530223e203f61d2e91de87f550cfd59 Mon Sep 17 00:00:00 2001 From: S1m Date: Mon, 12 Jul 2021 18:14:46 +0200 Subject: [PATCH 14/28] test on new endpoint --- .../app/core/pushers/VectorMessagingReceiver.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index f400cded9d..0949b2f657 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -156,12 +156,16 @@ val upHandler = object: MessagingReceiverHandler { 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()) { val gateway = UPHelper.customOrDefaultGateway(context, endpoint) - UPHelper.storePushGateway(context, gateway) - UPHelper.storeUpEndpoint(context, endpoint) - pusherManager.registerPusher(context, endpoint, gateway) + if (UPHelper.getUpEndpoint(context) != endpoint || + UPHelper.getPushGateway(context) != gateway) { + UPHelper.storePushGateway(context, gateway) + UPHelper.storeUpEndpoint(context, endpoint) + pusherManager.registerPusher(context, endpoint, gateway) + } else { + Timber.i("onNewEndpoint: skipped") + } } val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED vectorPreferences.setFdroidSyncBackgroundMode(mode) From ff0c98e8faef3d7697625ca15abae851a26efd9b Mon Sep 17 00:00:00 2001 From: S1m Date: Tue, 13 Jul 2021 08:29:05 +0200 Subject: [PATCH 15/28] lint --- .../im/vector/app/core/pushers/VectorMessagingReceiver.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index 0949b2f657..acfe22cb11 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -158,8 +158,8 @@ val upHandler = object: MessagingReceiverHandler { Timber.i("onNewEndpoint: adding $endpoint") if (vectorPreferences.areNotificationEnabledForDevice() && activeSessionHolder.hasActiveSession()) { val gateway = UPHelper.customOrDefaultGateway(context, endpoint) - if (UPHelper.getUpEndpoint(context) != endpoint || - UPHelper.getPushGateway(context) != gateway) { + if (UPHelper.getUpEndpoint(context) != endpoint + || UPHelper.getPushGateway(context) != gateway) { UPHelper.storePushGateway(context, gateway) UPHelper.storeUpEndpoint(context, endpoint) pusherManager.registerPusher(context, endpoint, gateway) From d1379377b174ce74910a7b70a095550fb76a7401 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Wed, 11 Aug 2021 19:45:00 +0200 Subject: [PATCH 16/28] Change default unifiedpush gateway Change-Id: Ib6b4947295e348283067e3996266f8207bca6440 --- vector/src/main/res/values/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values/config.xml b/vector/src/main/res/values/config.xml index 6ffb276ac9..559ac64fd3 100755 --- a/vector/src/main/res/values/config.xml +++ b/vector/src/main/res/values/config.xml @@ -18,7 +18,7 @@ https://matrix.org/_matrix/push/v1/notify - https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify + https://up.schildi.chat/_matrix/push/v1/notify im.vector.app.android From 38212b64108496ebd2b7e1386c855b5fef5ce9b7 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Wed, 11 Aug 2021 22:06:18 +0200 Subject: [PATCH 17/28] Fix some UP crashes Change-Id: I16f47f86a58c23210cc99c85081da1703bbda5ac --- .../im/vector/app/core/pushers/VectorMessagingReceiver.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index acfe22cb11..04d4cfeb0e 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -51,6 +51,7 @@ import org.unifiedpush.android.connector.MessagingReceiver import org.unifiedpush.android.connector.MessagingReceiverHandler import timber.log.Timber +@JsonClass(generateAdapter = true) data class UnifiedPushMessage( val notification: Notification ) @@ -117,10 +118,10 @@ val upHandler = object: MessagingReceiverHandler { if (UPHelper.isEmbeddedDistributor(context)) { notification = moshi.adapter(Notification::class.java) - .fromJson(message)!! + .fromJson(message) ?: return } else { val data = moshi.adapter(UnifiedPushMessage::class.java) - .fromJson(message)!! + .fromJson(message) ?: return notification = data.notification notification.unread = notification.counts.unread } From 37e722e85d242a56dc571e6e945d2ac22d9a06dc Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Thu, 12 Aug 2021 02:36:39 +0300 Subject: [PATCH 18/28] version++ --- vector/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index c3be35bb81..85fdafc7f8 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -14,7 +14,7 @@ kapt { // Note: 2 digits max for each value ext.versionMajor = 1 ext.versionMinor = 2 -ext.versionPatch = 0 +ext.versionPatch = 1 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From 3a1cb53c985a97ee737aa526d4febdc6ebd9d333 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Wed, 11 Aug 2021 22:06:18 +0200 Subject: [PATCH 19/28] Fix some UP crashes Change-Id: I16f47f86a58c23210cc99c85081da1703bbda5ac --- .../im/vector/app/core/pushers/VectorMessagingReceiver.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt index acfe22cb11..04d4cfeb0e 100755 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -51,6 +51,7 @@ import org.unifiedpush.android.connector.MessagingReceiver import org.unifiedpush.android.connector.MessagingReceiverHandler import timber.log.Timber +@JsonClass(generateAdapter = true) data class UnifiedPushMessage( val notification: Notification ) @@ -117,10 +118,10 @@ val upHandler = object: MessagingReceiverHandler { if (UPHelper.isEmbeddedDistributor(context)) { notification = moshi.adapter(Notification::class.java) - .fromJson(message)!! + .fromJson(message) ?: return } else { val data = moshi.adapter(UnifiedPushMessage::class.java) - .fromJson(message)!! + .fromJson(message) ?: return notification = data.notification notification.unread = notification.counts.unread } From 7e258282a2a83ddc875ac6f0ac7f7e09db724608 Mon Sep 17 00:00:00 2001 From: S1m Date: Mon, 16 Aug 2021 18:01:10 +0200 Subject: [PATCH 20/28] Change troubleshoot description if using FCM --- .../settings/troubleshoot/TestNewEndpoint.kt | 20 ++++++++++++++----- vector/src/main/res/values/strings.xml | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt index cb09046628..76e1b7c662 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNewEndpoint.kt @@ -35,12 +35,22 @@ class TestNewEndpoint @Inject constructor(private val context: AppCompatActivity val endpoint = UPHelper.getUpEndpoint(context) - if (!endpoint.isNullOrEmpty()) { - status = TestStatus.SUCCESS - description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_success, endpoint) + if (UPHelper.isEmbeddedDistributor(context)) { + if (!endpoint.isNullOrEmpty()) { + status = TestStatus.SUCCESS + description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_success, endpoint) + } else { + status = TestStatus.FAILED + description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed) + } } else { - status = TestStatus.FAILED - description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_failed) + if (!endpoint.isNullOrEmpty()) { + status = TestStatus.SUCCESS + description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_success, endpoint) + } else { + status = TestStatus.FAILED + description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_failed) + } } } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index bd73930f19..409fde1d01 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1132,7 +1132,7 @@ Fix Play Services - Endpoint + Endpoint/FCM Endpoint successfully retrieved:\n%1$s Failed to retrieved Endpoint. From 3cdf4f9d24924e4d101700812a00db3e5dc3f806 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Wed, 18 Aug 2021 16:20:20 +0200 Subject: [PATCH 21/28] Explicitely specify unifiedpush pusher app id We use the upstream pusher_app_id for their sygnal, but we do not need to do this for unifiedpush, so we can explicitely define the SchildiChat package here. Change-Id: Ib56fcde242a584514978ccbdd7e8b337fa7c6529 --- .../main/java/im/vector/app/core/pushers/PushersManager.kt | 5 ++--- vector/src/main/res/values/config_sc.xml | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100755 vector/src/main/res/values/config_sc.xml 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 5ebbfd5b81..21e43dddef 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 @@ -68,11 +68,10 @@ class PushersManager @Inject constructor( } private fun getPusherAppId(context: Context) : String { - val appId = stringProvider.getString(R.string.pusher_app_id) return if (UPHelper.isEmbeddedDistributor(context)) { - appId + stringProvider.getString(R.string.pusher_app_id) } else { - "$appId.up" + stringProvider.getString(R.string.up_pusher_app_id) } } diff --git a/vector/src/main/res/values/config_sc.xml b/vector/src/main/res/values/config_sc.xml new file mode 100755 index 0000000000..89af6b984f --- /dev/null +++ b/vector/src/main/res/values/config_sc.xml @@ -0,0 +1,6 @@ + + + + de.spiritcroc.riotx.up + + From 6fd5ef90947c5b2189d5f7463a2e5e9a425c1418 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Wed, 18 Aug 2021 16:46:26 +0200 Subject: [PATCH 22/28] Add unifiedpush information to rageshake Change-Id: I2434931f71a5012ba7d64c8c58ce6617cf3d2cd9 --- .../app/features/rageshake/BugReporter.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index 9c520000ea..f71605581b 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -21,6 +21,7 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.os.Build +import android.text.TextUtils import android.view.View import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentActivity @@ -29,6 +30,7 @@ import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.getAllChildFragments import im.vector.app.core.extensions.toOnOff +import im.vector.app.core.pushers.UPHelper import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.devtools.GossipingEventsSerializer @@ -55,6 +57,7 @@ import java.io.File import java.io.IOException import java.io.OutputStreamWriter import java.net.HttpURLConnection +import java.net.URL import java.util.Locale import java.util.zip.GZIPOutputStream import javax.inject.Inject @@ -275,6 +278,13 @@ class BugReporter @Inject constructor( .addFormDataPart("theme", ThemeUtils.getApplicationTheme(context)) .addFormDataPart("server_version", serverVersion) + // UnifiedPush + // Only include the UP endpoint base url to exclude private user tokens in the path or parameters + builder.addFormDataPart("unifiedpush_endpoint", strippedUrl(UPHelper.getUpEndpoint(context)).toString()) + .addFormDataPart("unifiedpush_gateway", UPHelper.getPushGateway(context)) + .addFormDataPart("unifiedpush_distributor_exists", UPHelper.distributorExists(context).toString()) + .addFormDataPart("unifiedpush_is_embedded_distributor", UPHelper.isEmbeddedDistributor(context).toString()) + val buildNumber = context.getString(R.string.build_number) if (buildNumber.isNotEmpty() && buildNumber != "0") { builder.addFormDataPart("build_number", buildNumber) @@ -450,6 +460,16 @@ class BugReporter @Inject constructor( } } + fun strippedUrl(url: String?): String? { + if (TextUtils.isEmpty(url)) return null + return try { + val parsed = URL(url) + "${parsed.protocol}://${parsed.host}" + } catch (e: Exception) { + "Malformed url" + } + } + /** * Send a bug report either with email or with Vector. */ From ba89b11097379fd0bbd8c33c25b3e817926060e7 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Wed, 18 Aug 2021 17:31:56 +0200 Subject: [PATCH 23/28] Add to rageshake whether it is a debug build or not Change-Id: I90336416c10d2f09979eb7518cc651c3e33a40fa --- .../main/java/im/vector/app/features/rageshake/BugReporter.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index f71605581b..5d5b264517 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -262,6 +262,7 @@ class BugReporter @Inject constructor( .addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent()) .addFormDataPart("user_id", userId) .addFormDataPart("can_contact", canContact.toString()) + .addFormDataPart("is_debug_build", BuildConfig.DEBUG.toString()) .addFormDataPart("device_id", deviceId) .addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false)) .addFormDataPart("branch_name", context.getString(R.string.git_branch_name)) @@ -327,6 +328,9 @@ class BugReporter @Inject constructor( builder.addFormDataPart("label", BuildConfig.FLAVOR_DESCRIPTION) builder.addFormDataPart("label", context.getString(R.string.git_branch_name)) + if (BuildConfig.DEBUG) { + builder.addFormDataPart("label", "debug_build") + } if (canContact) { builder.addFormDataPart("label", "can contact") } From 89145f8ad57acf800799a2a8d39b1fc6d5d224bf Mon Sep 17 00:00:00 2001 From: PoorPocketsMcNewHold Date: Sun, 15 Aug 2021 09:08:56 +0000 Subject: [PATCH 24/28] Translated using Weblate (French) Currently translated at 98.8% (88 of 89 strings) Translation: SchildiChat/SchildiChat-android Translate-URL: https://weblate.bubu1.eu/projects/schildichat/schildichat-android/fr/ --- vector/src/main/res/values-fr/strings_sc.xml | 37 +++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-fr/strings_sc.xml b/vector/src/main/res/values-fr/strings_sc.xml index 7533b7e19a..7d0da6488a 100644 --- a/vector/src/main/res/values-fr/strings_sc.xml +++ b/vector/src/main/res/values-fr/strings_sc.xml @@ -45,7 +45,7 @@ En-bas Inclure les discussions sans notification dans le comptage des messages par catégorie Marquer les discussions comme non lues - Autoriser de marquer les discussions comme non lues. D\'autres clients matrix ne prennent peut-être pas encore cette fonctionnaloté en charge. + Autoriser de marquer les discussions comme non lues. D’autres clients Matrix ne prennent peut-être pas encore cette fonctionnalité en charge. Prévisualisations des URL dans les discussions chiffrées Ceci fera fuiter les URL de tes messages vers votre serveur domestique ! SchildiChat Android @@ -54,4 +54,39 @@ par ex. @utilisateur:domaine.com Serveur personnalisé Compter les évènements de discussion non importants + Messages vocaux + Crée un bouton pour enregistrer ses messages + Jaune + Chair + Denim + Indigo + Lave + Bleu + Couleurs de thème + Couleur d’accentuation pour les thèmes clairs + Couleur d’accentuation pour les thèmes sombres + Notez que ces options de couleurs ne s’applique que pour les thèmes SC, et non les thèmes Element. + Citron vert + Orange + Vert clair + Vert sombre + Bleu sarcelle + Rose + Violet + Couleurs d’utilisateurs dans les conversations directes + Couleurs d’utilisateurs dans les conversations de groupe + Couleurs d’utilisateurs dans les salons publiques + Ouvrir au premier non lu + Ouvrir la discussion au premier message non lu au lieu du dernier message. + Rouge + Uniformiser + Basé sur le niveau de batterie + Basé sur l’identifiant Matrix + Paramètres de thèmes avancés + Couleurs d’utilisateur + Ambre + Bleu clair + Cyan + Or + Turquoise \ No newline at end of file From 2b93557fd12acc34c7419f825ef6140e58719812 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Thu, 19 Aug 2021 10:10:23 +0200 Subject: [PATCH 25/28] Make composer notification (not allowing to send messages) more compact Change-Id: Iba087f569d8928e844bf34d5660ea7256156ad9d --- vector/src/main/res/layout/view_notification_area.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/layout/view_notification_area.xml b/vector/src/main/res/layout/view_notification_area.xml index 488b3e1c29..11e220f9ef 100644 --- a/vector/src/main/res/layout/view_notification_area.xml +++ b/vector/src/main/res/layout/view_notification_area.xml @@ -6,13 +6,13 @@ android:background="?vctr_keys_backup_banner_accent_color" android:minHeight="48dp" android:orientation="horizontal" - android:padding="16dp"> + android:paddingHorizontal="16dp"> @@ -27,6 +27,7 @@ android:gravity="start" android:paddingStart="4dp" android:paddingEnd="0dp" + android:paddingVertical="12dp" android:textColor="?vctr_content_primary" tools:text="@string/room_do_not_have_permission_to_post" /> From 19f9de9db003ea792e66e9e8e48ac8b649886b71 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Wed, 18 Aug 2021 17:48:05 +0000 Subject: [PATCH 26/28] Translated using Weblate (Czech) Currently translated at 100.0% (90 of 90 strings) Translation: SchildiChat/SchildiChat-android Translate-URL: https://weblate.bubu1.eu/projects/schildichat/schildichat-android/cs/ --- vector/src/main/res/values-cs/strings_sc.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/res/values-cs/strings_sc.xml b/vector/src/main/res/values-cs/strings_sc.xml index 756d25f20d..550f5eb369 100644 --- a/vector/src/main/res/values-cs/strings_sc.xml +++ b/vector/src/main/res/values-cs/strings_sc.xml @@ -91,4 +91,5 @@ Džínová Hlasové zprávy Zobrazit tlačítko pro nahrávání hlasových zpráv + Abyste zvýšili viditelnost svého problému a umožnili nám vás kontaktovat, můžete se na tuto zprávu odkázat (uvedením svého matrix ID a přibližného času, kdy byla odeslána) v problému na adrese https://github.com/SchildiChat/SchildiChat-android/issues (nejprve zkontrolujte, zda pro váš problém již neexistuje, a teprve pokud ne, vytvořte nový). \ No newline at end of file From cad30d47904344785c8d3cf8b2e022a691665075 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Thu, 19 Aug 2021 10:42:34 +0200 Subject: [PATCH 27/28] Actually, we're still at 1.2.0 Got develop in by accident due to unifiedpush, but whatever Change-Id: I3d15dd820274076e4383aa17467a87dac9eebe31 --- vector/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index 2b12ce188c..c0f4ce1fbe 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -14,7 +14,7 @@ kapt { // Note: 2 digits max for each value ext.versionMajor = 1 ext.versionMinor = 2 -ext.versionPatch = 1 +ext.versionPatch = 0 ext.scVersion = 40 From 1af014a527db765529e8d6ba1c1230d114e2c8cd Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Thu, 19 Aug 2021 11:52:11 +0200 Subject: [PATCH 28/28] Work around voice message crashes on Android 5 - Catch NPE in onVisibilityChanged (happens for SDK 21 and 22) - Do not allow voice messages on SDK 21: segfaults as soon as recording stops Change-Id: I0cfc55fbb7880dc29e29df4fba14d57af1f82bba --- .../detail/composer/VoiceMessageRecorderView.kt | 13 +++++++++---- .../app/features/settings/VectorPreferences.kt | 6 ++++-- .../features/settings/VectorSettingsLabsFragment.kt | 3 +++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index 7f1c4f0759..40bc3db2f8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -90,10 +90,15 @@ class VoiceMessageRecorderView @JvmOverloads constructor( override fun onVisibilityChanged(changedView: View, visibility: Int) { super.onVisibilityChanged(changedView, visibility) - if (changedView == this && visibility == VISIBLE) { - views.voiceMessageMicButton.contentDescription = context.getString(R.string.a11y_start_voice_message) - } else { - views.voiceMessageMicButton.contentDescription = "" + // On Android 5, this can cause a NPE for some unknown reason + try { + if (changedView == this && visibility == VISIBLE) { + views.voiceMessageMicButton.contentDescription = context.getString(R.string.a11y_start_voice_message) + } else { + views.voiceMessageMicButton.contentDescription = "" + } + } catch (e: Exception) { + e.printStackTrace() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index b1b9ccfa70..15e1d366fe 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -19,6 +19,7 @@ import android.content.Context import android.content.SharedPreferences import android.media.RingtoneManager import android.net.Uri +import android.os.Build import android.provider.MediaStore import androidx.core.content.edit import com.squareup.seismic.ShakeDetector @@ -202,7 +203,7 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val SETTINGS_USER_COLOR_MODE_DEFAULT = "SETTINGS_USER_COLOR_MODE_DEFAULT" private const val SETTINGS_USER_COLOR_MODE_PUBLIC_ROOM = "SETTINGS_USER_COLOR_MODE_PUBLIC_ROOM" private const val SETTINGS_OPEN_CHATS_AT_FIRST_UNREAD = "SETTINGS_OPEN_CHATS_AT_FIRST_UNREAD" - private const val SETTINGS_VOICE_MESSAGE = "SETTINGS_VOICE_MESSAGE" + const val SETTINGS_VOICE_MESSAGE = "SETTINGS_VOICE_MESSAGE" private const val DID_ASK_TO_ENABLE_SESSION_PUSH = "DID_ASK_TO_ENABLE_SESSION_PUSH" @@ -1004,7 +1005,8 @@ class VectorPreferences @Inject constructor(private val context: Context) { // Element removed this, SC added it back (but this time, default to true) fun useVoiceMessage(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_VOICE_MESSAGE, true) + // Voice messages crash on SDK 21 + return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP && defaultPrefs.getBoolean(SETTINGS_VOICE_MESSAGE, true) } /** diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt index dc74a1fa4f..e12e9353d2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt @@ -16,6 +16,7 @@ package im.vector.app.features.settings +import android.os.Build import androidx.preference.Preference import im.vector.app.R import im.vector.app.core.preference.VectorSwitchPreference @@ -56,6 +57,8 @@ class VectorSettingsLabsFragment @Inject constructor( findPreference(VectorPreferences.SETTINGS_ALLOW_URL_PREVIEW_IN_ENCRYPTED_ROOM_KEY)?.isEnabled = vectorPreferences.showUrlPreviews() + findPreference(VectorPreferences.SETTINGS_VOICE_MESSAGE)?.isEnabled = Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP + findPreference(VectorPreferences.SETTINGS_LABS_SPACES_HOME_AS_ORPHAN)!!.let { pref -> pref.setOnPreferenceChangeListener { _, _ -> MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = false))