diff --git a/vector/src/fdroid/AndroidManifest.xml b/vector/src/fdroid/AndroidManifest.xml index ea9fa023ab..ca008043c2 100644 --- a/vector/src/fdroid/AndroidManifest.xml +++ b/vector/src/fdroid/AndroidManifest.xml @@ -28,6 +28,19 @@ android:enabled="true" android:exported="false" /> + + + + + + + { + val distributors = up.getDistributors(context).toMutableList() + distributors.remove(context.packageName) + return distributors + } + + fun getCurrentDistributorName(context: Context): String { + if (isEmbeddedDistributor(context)) { + return context.getString(R.string.unifiedpush_distributor_fcm_fallback) + } + if (isBackgroundSync(context)) { + return context.getString(R.string.unifiedpush_distributor_background_sync) + } + val distributor = up.getDistributor(context) + return try { + val ai = context.packageManager.getApplicationInfo(distributor, 0) + context.packageManager.getApplicationLabel(ai) + } catch (e: PackageManager.NameNotFoundException) { + distributor + } as String } fun isEmbeddedDistributor(context: Context) : Boolean { @@ -222,7 +257,7 @@ object UnifiedPushHelper { } return try { val parsed = URL(endpoint) - "${parsed.protocol}://${parsed.host}" + "${parsed.protocol}://${parsed.host}/***" } catch (e: Exception) { Timber.e("Error parsing unifiedpush endpoint: $e") null 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 57953c1ca7..a9d3845bba 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt @@ -32,6 +32,7 @@ import dagger.hilt.android.AndroidEntryPoint import im.vector.app.BuildConfig import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.network.WifiDetector +import im.vector.app.core.services.GuardServiceStarter import im.vector.app.features.badge.BadgeProxy import im.vector.app.features.notifications.NotifiableEventResolver import im.vector.app.features.notifications.NotificationDrawerManager @@ -78,11 +79,12 @@ private val loggerTag = LoggerTag("Push", LoggerTag.SYNC) class VectorMessagingReceiver : MessagingReceiver() { @Inject lateinit var notificationDrawerManager: NotificationDrawerManager @Inject lateinit var notifiableEventResolver: NotifiableEventResolver - @Inject lateinit var pusherManager: PushersManager + @Inject lateinit var pushersManager: PushersManager @Inject lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var vectorDataStore: VectorDataStore @Inject lateinit var wifiDetector: WifiDetector + @Inject lateinit var guardServiceStarter: GuardServiceStarter private val coroutineScope = CoroutineScope(SupervisorJob()) @@ -161,26 +163,31 @@ class VectorMessagingReceiver : MessagingReceiver() { || UnifiedPushHelper.getPushGateway(context) != gateway) { UnifiedPushHelper.storePushGateway(context, gateway) UnifiedPushHelper.storeUpEndpoint(context, endpoint) - pusherManager.enqueueRegisterPusher(endpoint, gateway) + pushersManager.enqueueRegisterPusher(endpoint, gateway) } else { Timber.tag(loggerTag.value).i("onNewEndpoint: skipped") } } val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED vectorPreferences.setFdroidSyncBackgroundMode(mode) + guardServiceStarter.stop() } override fun onRegistrationFailed(context: Context, instance: String) { Toast.makeText(context, "Push service registration failed", Toast.LENGTH_SHORT).show() + val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME + vectorPreferences.setFdroidSyncBackgroundMode(mode) + guardServiceStarter.start() } override fun onUnregistered(context: Context, instance: String) { Timber.tag(loggerTag.value).d("Unifiedpush: Unregistered") val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME vectorPreferences.setFdroidSyncBackgroundMode(mode) + guardServiceStarter.start() runBlocking { try { - pusherManager.unregisterPusher(UnifiedPushHelper.getEndpointOrToken(context) ?: "") + pushersManager.unregisterPusher(UnifiedPushHelper.getEndpointOrToken(context) ?: "") } catch (e: Exception) { Timber.tag(loggerTag.value).d("Probably unregistering a non existant pusher") } 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 24831a67e3..d1d1e2e4ce 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 @@ -188,7 +188,7 @@ class HomeActivity : super.onCreate(savedInstanceState) analyticsScreenName = MobileScreen.ScreenName.Home supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false) - UnifiedPushHelper.register(this, onDoneRunnable = { + UnifiedPushHelper.register(this) { if (UnifiedPushHelper.isEmbeddedDistributor(this)) { FcmHelper.ensureFcmTokenIsRetrieved( this, @@ -196,7 +196,7 @@ class HomeActivity : vectorPreferences.areNotificationEnabledForDevice() ) } - }) + } sharedActionViewModel = viewModelProvider.get(HomeSharedActionViewModel::class.java) views.drawerLayout.addDrawerListener(drawerListener) if (isFirstCreation()) { diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt index 216b645726..282e62d43d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt @@ -63,7 +63,7 @@ import javax.inject.Inject // Referenced in vector_settings_preferences_root.xml class VectorSettingsNotificationPreferenceFragment @Inject constructor( - private val pushManager: PushersManager, + private val pushersManager: PushersManager, private val activeSessionHolder: ActiveSessionHolder, private val vectorPreferences: VectorPreferences, private val guardServiceStarter: GuardServiceStarter @@ -103,7 +103,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( } else { UnifiedPushHelper.unregister( requireContext(), - pushManager, + pushersManager, vectorPreferences ) session.pushersService().refreshPushers() @@ -152,14 +152,16 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( findPreference(VectorPreferences.SETTINGS_UNIFIED_PUSH_RE_REGISTER_KEY)?.let { if (BuildConfig.ALLOW_EXTERNAL_UNIFIEDPUSH_DISTRIB) { it.onPreferenceClickListener = Preference.OnPreferenceClickListener { - UnifiedPushHelper.register( + UnifiedPushHelper.reRegister( requireContext(), - force = true, - pushManager - ) + pushersManager, + vectorPreferences + ) { + session.pushersService().refreshPushers() + refreshBackgroundSyncPrefs() + } true } - session.pushersService().refreshPushers() } else { it.isVisible = false } @@ -199,9 +201,9 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( pref.isChecked = isEnabled pref.setTransactionalSwitchChangeListener(lifecycleScope) { isChecked -> if (isChecked) { - pushManager.registerEmailForPush(emailPid.email) + pushersManager.registerEmailForPush(emailPid.email) } else { - pushManager.unregisterEmailPusher(emailPid.email) + pushersManager.unregisterEmailPusher(emailPid.email) } } category.addPreference(pref) diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAvailableUnifiedPushDistributors.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAvailableUnifiedPushDistributors.kt new file mode 100644 index 0000000000..9e25b27d0f --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAvailableUnifiedPushDistributors.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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.features.settings.troubleshoot + +import android.content.Intent +import androidx.activity.result.ActivityResultLauncher +import androidx.fragment.app.FragmentActivity +import im.vector.app.R +import im.vector.app.core.pushers.UnifiedPushHelper +import im.vector.app.core.resources.StringProvider +import im.vector.app.push.fcm.FcmHelper +import javax.inject.Inject + +class TestAvailableUnifiedPushDistributors @Inject constructor(private val context: FragmentActivity, + private val stringProvider: StringProvider) : + TroubleshootTest(R.string.settings_troubleshoot_test_distributors_title) { + + override fun perform(activityResultLauncher: ActivityResultLauncher) { + val distributors = UnifiedPushHelper.getExternalDistributors(context) + if (distributors.isEmpty()) { + description = if (FcmHelper.isPushSupported()) { + stringProvider.getString(R.string.settings_troubleshoot_test_distributors_gplay) + } else { + stringProvider.getString(R.string.settings_troubleshoot_test_distributors_fdroid) + } + status = TestStatus.SUCCESS + } else { + description = stringProvider.getString(R.string.settings_troubleshoot_test_distributors_many, + distributors.size + 1) + status = TestStatus.SUCCESS + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestCurrentUnifiedPushDistributor.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestCurrentUnifiedPushDistributor.kt new file mode 100644 index 0000000000..5eda48ffdc --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestCurrentUnifiedPushDistributor.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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.features.settings.troubleshoot + +import android.content.Intent +import androidx.activity.result.ActivityResultLauncher +import androidx.fragment.app.FragmentActivity +import im.vector.app.R +import im.vector.app.core.pushers.UnifiedPushHelper +import im.vector.app.core.resources.StringProvider +import javax.inject.Inject + +class TestCurrentUnifiedPushDistributor @Inject constructor(private val context: FragmentActivity, + private val stringProvider: StringProvider) : + TroubleshootTest(R.string.settings_troubleshoot_test_current_distributor_title) { + + override fun perform(activityResultLauncher: ActivityResultLauncher) { + description = stringProvider.getString(R.string.settings_troubleshoot_test_current_distributor, + UnifiedPushHelper.getCurrentDistributorName(context)) + status = TestStatus.SUCCESS + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt new file mode 100644 index 0000000000..558b0e4fd9 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestEndpointAsTokenRegistration.kt @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022 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.features.settings.troubleshoot + +import android.content.Intent +import androidx.activity.result.ActivityResultLauncher +import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.Observer +import androidx.work.WorkInfo +import androidx.work.WorkManager +import im.vector.app.R +import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.pushers.PushersManager +import im.vector.app.core.pushers.UnifiedPushHelper +import im.vector.app.core.resources.StringProvider +import im.vector.app.features.settings.VectorPreferences +import org.matrix.android.sdk.api.session.pushers.PusherState +import javax.inject.Inject + +class TestEndpointAsTokenRegistration @Inject constructor(private val context: FragmentActivity, + private val stringProvider: StringProvider, + private val pushersManager: PushersManager, + private val vectorPreferences: VectorPreferences, + private val activeSessionHolder: ActiveSessionHolder) : + TroubleshootTest(R.string.settings_troubleshoot_test_endpoint_registration_title) { + + override fun perform(activityResultLauncher: ActivityResultLauncher) { + // Check if we have a registered pusher for this token + val endpoint = UnifiedPushHelper.getEndpointOrToken(context) ?: run { + status = TestStatus.FAILED + return + } + val session = activeSessionHolder.getSafeActiveSession() ?: run { + status = TestStatus.FAILED + return + } + val pushers = session.pushersService().getPushers().filter { + it.pushKey == endpoint && it.state == PusherState.REGISTERED + } + if (pushers.isEmpty()) { + description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_registration_failed, + stringProvider.getString(R.string.sas_error_unknown)) + quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_endpoint_registration_quick_fix) { + override fun doFix() { + UnifiedPushHelper.reRegister( + context, + pushersManager, + vectorPreferences + ) + val workId = pushersManager.enqueueRegisterPusherWithFcmKey(endpoint) + WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo -> + if (workInfo != null) { + if (workInfo.state == WorkInfo.State.SUCCEEDED) { + manager?.retry(activityResultLauncher) + } else if (workInfo.state == WorkInfo.State.FAILED) { + manager?.retry(activityResultLauncher) + } + } + }) + } + } + + status = TestStatus.FAILED + } else { + description = stringProvider.getString(R.string.settings_troubleshoot_test_endpoint_registration_success) + status = TestStatus.SUCCESS + } + } +} 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 85% 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 3fd80ad1c5..da26200df2 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 @@ -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,8 +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.push.fcm.FcmHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch @@ -36,13 +34,11 @@ import javax.inject.Inject /** * Test Push by asking the Push Gateway to send a Push back */ -class TestPushFromPushGateway @Inject constructor( - private val context: FragmentActivity, - private val stringProvider: StringProvider, - private val errorFormatter: ErrorFormatter, - private val pushersManager: PushersManager, - private val activeSessionHolder: ActiveSessionHolder -) : +class TestPushFromPushGateway @Inject constructor(private val context: FragmentActivity, + private val stringProvider: StringProvider, + private val errorFormatter: ErrorFormatter, + private val pushersManager: PushersManager, + private val activeSessionHolder: ActiveSessionHolder) : TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) { private var action: Job? = null @@ -50,10 +46,6 @@ class TestPushFromPushGateway @Inject constructor( override fun perform(activityResultLauncher: ActivityResultLauncher) { pushReceived = false - FcmHelper.getFcmToken(context) ?: run { - status = TestStatus.FAILED - return - } action = activeSessionHolder.getActiveSession().coroutineScope.launch { val result = runCatching { pushersManager.testPush(context) } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushEndpoint.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushEndpoint.kt new file mode 100644 index 0000000000..ab4e3dd7c2 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushEndpoint.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 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.features.settings.troubleshoot + +import android.content.Intent +import androidx.activity.result.ActivityResultLauncher +import androidx.fragment.app.FragmentActivity +import im.vector.app.R +import im.vector.app.core.pushers.UnifiedPushHelper +import im.vector.app.core.resources.StringProvider +import javax.inject.Inject + +class TestUnifiedPushEndpoint @Inject constructor(private val context: FragmentActivity, + private val stringProvider: StringProvider) : + TroubleshootTest(R.string.settings_troubleshoot_test_current_endpoint_title) { + + override fun perform(activityResultLauncher: ActivityResultLauncher) { + val endpoint = UnifiedPushHelper.getPrivacyFriendlyUpEndpoint(context) + endpoint?.let { + description = stringProvider.getString(R.string.settings_troubleshoot_test_current_endpoint_success, + UnifiedPushHelper.getPrivacyFriendlyUpEndpoint(context)) + status = TestStatus.SUCCESS + } ?: run { + description = stringProvider.getString(R.string.settings_troubleshoot_test_current_endpoint_failed) + status = TestStatus.FAILED + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushGateway.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushGateway.kt new file mode 100644 index 0000000000..75e8962c84 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestUnifiedPushGateway.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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.features.settings.troubleshoot + +import android.content.Intent +import androidx.activity.result.ActivityResultLauncher +import androidx.fragment.app.FragmentActivity +import im.vector.app.R +import im.vector.app.core.pushers.UnifiedPushHelper +import im.vector.app.core.resources.StringProvider +import javax.inject.Inject + +class TestUnifiedPushGateway @Inject constructor(private val context: FragmentActivity, + private val stringProvider: StringProvider) : + TroubleshootTest(R.string.settings_troubleshoot_test_current_gateway_title) { + + override fun perform(activityResultLauncher: ActivityResultLauncher) { + description = stringProvider.getString(R.string.settings_troubleshoot_test_current_gateway, + UnifiedPushHelper.getPushGateway(context)) + status = TestStatus.SUCCESS + } +} diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 412156be2a..89cbefd859 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -855,6 +855,10 @@ FCM token successfully registered to homeserver. Failed to register FCM token to homeserver:\n%1$s + Endpoint Registration + Endpoint successfully registered to homeserver. + Failed to register endpoint token to homeserver:\n%1$s + Test Push The application is waiting for the PUSH The application is receiving PUSH @@ -1665,6 +1669,8 @@ Register token + Reset notification method + Make a suggestion Please write your suggestion below. Describe your suggestion here @@ -3065,7 +3071,18 @@ Screen sharing is in progress Choose how to receive notifications - Google Services - Background synchronization + Google Services + Background synchronization Notification method + Available methods + No other method than Google Play Service found. + No other method than background synchronization found. + Found %d methods. + Method + Currently using %s. + Endpoint + Current endpoint: %s + Cannot find the endpoint. + Gateway + Current gateway: %s