mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-25 02:45:53 +03:00
Add UnifiedPush support
This commit is contained in:
parent
928183ff64
commit
04b297b261
17 changed files with 431 additions and 73 deletions
1
changelog.d/3448.feature
Normal file
1
changelog.d/3448.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Use UnifiedPush and allows user to have push without FCM.
|
|
@ -43,6 +43,7 @@ ext.libs = [
|
||||||
|
|
||||||
],
|
],
|
||||||
jetbrains : [
|
jetbrains : [
|
||||||
|
'kotlinReflect' : "org.jetbrains.kotlin:kotlin-reflect:$kotlin",
|
||||||
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
|
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
|
||||||
'coroutinesAndroid' : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines",
|
'coroutinesAndroid' : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines",
|
||||||
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
||||||
|
@ -88,6 +89,7 @@ ext.libs = [
|
||||||
],
|
],
|
||||||
squareup : [
|
squareup : [
|
||||||
'moshi' : "com.squareup.moshi:moshi:$moshi",
|
'moshi' : "com.squareup.moshi:moshi:$moshi",
|
||||||
|
'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi",
|
||||||
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
|
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
|
||||||
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
|
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
|
||||||
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
||||||
|
|
|
@ -12,6 +12,7 @@ ext.groups = [
|
||||||
'com.github.vector-im',
|
'com.github.vector-im',
|
||||||
'com.github.yalantis',
|
'com.github.yalantis',
|
||||||
'com.github.Zhuinden',
|
'com.github.Zhuinden',
|
||||||
|
'com.github.UnifiedPush',
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
jitsi : [
|
jitsi : [
|
||||||
|
|
|
@ -17,7 +17,11 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Note: pusher_http_url should have path '/_matrix/push/v1/notify' -->
|
<!-- Note: pusher_http_url should have path '/_matrix/push/v1/notify' -->
|
||||||
|
<!-- It is the push gateway for FCM embedded distributor -->
|
||||||
<string name="pusher_http_url" translatable="false">https://matrix.org/_matrix/push/v1/notify</string>
|
<string name="pusher_http_url" translatable="false">https://matrix.org/_matrix/push/v1/notify</string>
|
||||||
|
<!-- Note: default_push_gateway_http_url should have path '/_matrix/push/v1/notify' -->
|
||||||
|
<!-- It is the push gateway for UnifiedPush -->
|
||||||
|
<string name="default_push_gateway_http_url" translatable="false">https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify</string>
|
||||||
<!-- Note: pusher_app_id cannot exceed 64 chars -->
|
<!-- Note: pusher_app_id cannot exceed 64 chars -->
|
||||||
<string name="pusher_app_id" translatable="false">im.vector.app.android</string>
|
<string name="pusher_app_id" translatable="false">im.vector.app.android</string>
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ android {
|
||||||
buildConfigField "boolean", "ALLOW_FCM_USE", "true"
|
buildConfigField "boolean", "ALLOW_FCM_USE", "true"
|
||||||
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
|
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
|
||||||
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
|
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
|
||||||
|
buildConfigField "boolean", "ALLOW_EXTERNAL_UNIFIEDPUSH_DISTRIB", "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
fdroid {
|
fdroid {
|
||||||
|
@ -293,6 +294,7 @@ android {
|
||||||
buildConfigField "boolean", "ALLOW_FCM_USE", "false"
|
buildConfigField "boolean", "ALLOW_FCM_USE", "false"
|
||||||
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
|
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
|
||||||
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
|
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
|
||||||
|
buildConfigField "boolean", "ALLOW_EXTERNAL_UNIFIEDPUSH_DISTRIB", "true"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,6 +350,7 @@ dependencies {
|
||||||
implementation project(":library:multipicker")
|
implementation project(":library:multipicker")
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
|
|
||||||
|
implementation libs.jetbrains.kotlinReflect
|
||||||
implementation libs.jetbrains.coroutinesCore
|
implementation libs.jetbrains.coroutinesCore
|
||||||
implementation libs.jetbrains.coroutinesAndroid
|
implementation libs.jetbrains.coroutinesAndroid
|
||||||
|
|
||||||
|
@ -364,6 +367,7 @@ dependencies {
|
||||||
implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.10.0"
|
implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.10.0"
|
||||||
|
|
||||||
implementation libs.squareup.moshi
|
implementation libs.squareup.moshi
|
||||||
|
implementation libs.squareup.moshiKt
|
||||||
kapt libs.squareup.moshiKotlin
|
kapt libs.squareup.moshiKotlin
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
|
@ -462,8 +466,10 @@ dependencies {
|
||||||
// Analytics
|
// Analytics
|
||||||
implementation 'com.posthog.android:posthog:1.1.2'
|
implementation 'com.posthog.android:posthog:1.1.2'
|
||||||
|
|
||||||
// gplay flavor only
|
// UnifiedPush
|
||||||
gplayImplementation('com.google.firebase:firebase-messaging:23.0.0') {
|
implementation 'com.github.UnifiedPush:android-connector:2.0.0-beta2'
|
||||||
|
// UnifiedPush gplay flavor only
|
||||||
|
gplayImplementation('com.github.UnifiedPush:android-embedded_fcm_distributor:a0056aa939') {
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||||
|
|
|
@ -9,13 +9,17 @@
|
||||||
android:name="firebase_analytics_collection_deactivated"
|
android:name="firebase_analytics_collection_deactivated"
|
||||||
android:value="true" />
|
android:value="true" />
|
||||||
|
|
||||||
<service
|
<receiver
|
||||||
android:name=".gplay.push.fcm.VectorFirebaseMessagingService"
|
android:enabled="true"
|
||||||
|
android:name=".push.fcm.EmbeddedFCMDistributor"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
<action android:name="org.unifiedpush.android.distributor.REGISTER"/>
|
||||||
|
<action android:name="org.unifiedpush.android.distributor.UNREGISTER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
|
||||||
|
</receiver>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
|
@ -50,12 +50,12 @@ class TestPushFromPushGateway @Inject constructor(
|
||||||
|
|
||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||||
pushReceived = false
|
pushReceived = false
|
||||||
val fcmToken = FcmHelper.getFcmToken(context) ?: run {
|
FcmHelper.getFcmToken(context) ?: run {
|
||||||
status = TestStatus.FAILED
|
status = TestStatus.FAILED
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
action = activeSessionHolder.getActiveSession().coroutineScope.launch {
|
action = activeSessionHolder.getActiveSession().coroutineScope.launch {
|
||||||
val result = runCatching { pushersManager.testPush(fcmToken) }
|
val result = runCatching { pushersManager.testPush(context) }
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
status = result
|
status = result
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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.push.fcm
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.unifiedpush.android.embedded_fcm_distributor.EmbeddedDistributorReceiver
|
||||||
|
|
||||||
|
class EmbeddedFCMDistributor: EmbeddedDistributorReceiver() {
|
||||||
|
override fun getEndpoint(context: Context, token: String, instance: String): String {
|
||||||
|
// Here token is the FCM Token, used by the gateway (sygnal)
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,9 +98,9 @@ object FcmHelper {
|
||||||
* it doesn't, display a dialog that allows users to download the APK from
|
* 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.
|
* the Google Play Store or enable it in the device's system settings.
|
||||||
*/
|
*/
|
||||||
private fun checkPlayServices(activity: Activity): Boolean {
|
fun checkPlayServices(context: Context): Boolean {
|
||||||
val apiAvailability = GoogleApiAvailability.getInstance()
|
val apiAvailability = GoogleApiAvailability.getInstance()
|
||||||
val resultCode = apiAvailability.isGooglePlayServicesAvailable(activity)
|
val resultCode = apiAvailability.isGooglePlayServicesAvailable(context)
|
||||||
return resultCode == ConnectionResult.SUCCESS
|
return resultCode == ConnectionResult.SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -410,6 +410,17 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<!-- UnifiedPush -->
|
||||||
|
<receiver android:exported="true" android:enabled="true" android:name=".core.pushers.VectorMessagingReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.UNREGISTERED"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED"/>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<!-- Providers -->
|
<!-- Providers -->
|
||||||
|
|
||||||
<!-- Remove WorkManagerInitializer Provider because we are using on-demand initialization of WorkManager-->
|
<!-- Remove WorkManagerInitializer Provider because we are using on-demand initialization of WorkManager-->
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package im.vector.app.core.pushers
|
package im.vector.app.core.pushers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.resources.AppNameProvider
|
import im.vector.app.core.resources.AppNameProvider
|
||||||
|
@ -34,13 +35,13 @@ class PushersManager @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val appNameProvider: AppNameProvider
|
private val appNameProvider: AppNameProvider
|
||||||
) {
|
) {
|
||||||
suspend fun testPush(pushKey: String) {
|
suspend fun testPush(context: Context) {
|
||||||
val currentSession = activeSessionHolder.getActiveSession()
|
val currentSession = activeSessionHolder.getActiveSession()
|
||||||
|
|
||||||
currentSession.pushersService().testPush(
|
currentSession.pushersService().testPush(
|
||||||
stringProvider.getString(R.string.pusher_http_url),
|
UnifiedPushHelper.getPushGateway(context),
|
||||||
stringProvider.getString(R.string.pusher_app_id),
|
stringProvider.getString(R.string.pusher_app_id),
|
||||||
pushKey,
|
UnifiedPushHelper.getEndpointOrToken(context) ?: "",
|
||||||
TEST_EVENT_ID
|
TEST_EVENT_ID
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -50,19 +51,38 @@ class PushersManager @Inject constructor(
|
||||||
return currentSession.pushersService().enqueueAddHttpPusher(createHttpPusher(pushKey))
|
return currentSession.pushersService().enqueueAddHttpPusher(createHttpPusher(pushKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun enqueueRegisterPusher(
|
||||||
|
pushKey: String,
|
||||||
|
gateway: String
|
||||||
|
): UUID {
|
||||||
|
val currentSession = activeSessionHolder.getActiveSession()
|
||||||
|
return currentSession.pushersService().enqueueAddHttpPusher(createHttpPusher(pushKey, gateway))
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun registerPusherWithFcmKey(pushKey: String) {
|
suspend fun registerPusherWithFcmKey(pushKey: String) {
|
||||||
val currentSession = activeSessionHolder.getActiveSession()
|
val currentSession = activeSessionHolder.getActiveSession()
|
||||||
currentSession.pushersService().addHttpPusher(createHttpPusher(pushKey))
|
currentSession.pushersService().addHttpPusher(createHttpPusher(pushKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createHttpPusher(pushKey: String) = HttpPusher(
|
suspend fun registerPusher(
|
||||||
|
pushKey: String,
|
||||||
|
gateway: String
|
||||||
|
) {
|
||||||
|
val currentSession = activeSessionHolder.getActiveSession()
|
||||||
|
currentSession.pushersService().addHttpPusher(createHttpPusher(pushKey, gateway))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createHttpPusher(
|
||||||
|
pushKey: String,
|
||||||
|
gateway: String = stringProvider.getString(R.string.pusher_http_url)
|
||||||
|
) = HttpPusher(
|
||||||
pushKey,
|
pushKey,
|
||||||
stringProvider.getString(R.string.pusher_app_id),
|
stringProvider.getString(R.string.pusher_app_id),
|
||||||
profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()),
|
profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()),
|
||||||
localeProvider.current().language,
|
localeProvider.current().language,
|
||||||
appNameProvider.getAppName(),
|
appNameProvider.getAppName(),
|
||||||
activeSessionHolder.getActiveSession().sessionParams.deviceId ?: "MOBILE",
|
activeSessionHolder.getActiveSession().sessionParams.deviceId ?: "MOBILE",
|
||||||
stringProvider.getString(R.string.pusher_http_url),
|
gateway,
|
||||||
append = false,
|
append = false,
|
||||||
withEventIdOnly = true
|
withEventIdOnly = true
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
* 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.core.pushers
|
||||||
|
|
||||||
|
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.BuildConfig
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.di.DefaultSharedPreferences
|
||||||
|
import im.vector.app.push.fcm.FcmHelper
|
||||||
|
import org.unifiedpush.android.connector.UnifiedPush
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.net.URI
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
object UnifiedPushHelper {
|
||||||
|
private const val PREFS_ENDPOINT_OR_TOKEN = "UP_ENDPOINT_OR_TOKEN"
|
||||||
|
private const val PREFS_PUSH_GATEWAY = "PUSH_GATEWAY"
|
||||||
|
private val up = UnifiedPush
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the UnifiedPush Endpoint.
|
||||||
|
*
|
||||||
|
* @return the UnifiedPush Endpoint or null if not received
|
||||||
|
*/
|
||||||
|
fun getEndpointOrToken(context: Context): String? {
|
||||||
|
return DefaultSharedPreferences.getInstance(context).getString(PREFS_ENDPOINT_OR_TOKEN, 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_ENDPOINT_OR_TOKEN, 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 register(context: Context, force: Boolean = false, onDoneRunnable: Runnable? = null) {
|
||||||
|
if (!BuildConfig.ALLOW_EXTERNAL_UNIFIEDPUSH_DISTRIB) {
|
||||||
|
up.saveDistributor(context, context.packageName)
|
||||||
|
up.registerApp(context)
|
||||||
|
onDoneRunnable?.run()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (force) {
|
||||||
|
// Un-register first
|
||||||
|
up.unregisterApp(context)
|
||||||
|
storeUpEndpoint(context, null)
|
||||||
|
storePushGateway(context, null)
|
||||||
|
} else if (up.getDistributor(context).isNotEmpty()) {
|
||||||
|
up.registerApp(context)
|
||||||
|
onDoneRunnable?.run()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val distributors = up.getDistributors(context).toMutableList()
|
||||||
|
|
||||||
|
val internalDistributorName = if (!FcmHelper.isPushSupported()) {
|
||||||
|
// Adding packageName for background sync
|
||||||
|
distributors.add(context.packageName)
|
||||||
|
context.getString(R.string.unifiedpush_getdistributors_dialog_background_sync)
|
||||||
|
} else {
|
||||||
|
context.getString(R.string.unifiedpush_getdistributors_dialog_fcm_fallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distributors.size == 1
|
||||||
|
&& !force){
|
||||||
|
up.saveDistributor(context, distributors.first())
|
||||||
|
up.registerApp(context)
|
||||||
|
onDoneRunnable?.run()
|
||||||
|
} else {
|
||||||
|
val builder: AlertDialog.Builder = MaterialAlertDialogBuilder(context)
|
||||||
|
builder.setTitle(context.getString(R.string.unifiedpush_getdistributors_dialog_title))
|
||||||
|
|
||||||
|
val distributorsArray = distributors.toTypedArray()
|
||||||
|
val distributorsNameArray = distributorsArray.map {
|
||||||
|
if (it == context.packageName) {
|
||||||
|
internalDistributorName
|
||||||
|
} 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")
|
||||||
|
up.registerApp(context)
|
||||||
|
onDoneRunnable?.run()
|
||||||
|
}
|
||||||
|
builder.setOnDismissListener {
|
||||||
|
onDoneRunnable?.run()
|
||||||
|
}
|
||||||
|
builder.setOnCancelListener {
|
||||||
|
onDoneRunnable?.run()
|
||||||
|
}
|
||||||
|
val dialog: AlertDialog = builder.create()
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregister(context: Context) {
|
||||||
|
up.unregisterApp(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
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 distributorExists(context: Context): Boolean {
|
||||||
|
return up.getDistributor(context).isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isEmbeddedDistributor(context: Context) : Boolean {
|
||||||
|
return ( up.getDistributor(context) == context.packageName
|
||||||
|
&& FcmHelper.isPushSupported())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isBackgroundSync(context: Context) : Boolean {
|
||||||
|
return ( up.getDistributor(context) == context.packageName
|
||||||
|
&& !FcmHelper.isPushSupported())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPrivacyFriendlyUpEndpoint(context: Context): String? {
|
||||||
|
val endpoint = getEndpointOrToken(context)
|
||||||
|
if (endpoint.isNullOrEmpty()) return endpoint
|
||||||
|
if (isEmbeddedDistributor(context)) {
|
||||||
|
return endpoint
|
||||||
|
}
|
||||||
|
return try {
|
||||||
|
val parsed = URL(endpoint)
|
||||||
|
"${parsed.protocol}://${parsed.host}"
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e("Error parsing unifiedpush endpoint: $e")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2019 New Vector Ltd
|
* Copyright (c) 2022 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@ -14,27 +14,31 @@
|
||||||
* limitations under the License.
|
* 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.content.Intent
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
import com.squareup.moshi.Json
|
||||||
import com.google.firebase.messaging.RemoteMessage
|
import com.squareup.moshi.JsonClass
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
|
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.BuildConfig
|
import im.vector.app.BuildConfig
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.network.WifiDetector
|
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.NotifiableEventResolver
|
||||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||||
import im.vector.app.features.notifications.NotificationUtils
|
import im.vector.app.features.notifications.NotificationUtils
|
||||||
|
import im.vector.app.features.settings.BackgroundSyncMode
|
||||||
import im.vector.app.features.settings.VectorDataStore
|
import im.vector.app.features.settings.VectorDataStore
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.app.push.fcm.FcmHelper
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -43,18 +47,35 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.logger.LoggerTag
|
import org.matrix.android.sdk.api.logger.LoggerTag
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
import org.unifiedpush.android.connector.MessagingReceiver
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class UnifiedPushMessage(
|
||||||
|
val notification: 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()
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class Counts(
|
||||||
|
val unread: Int = 0
|
||||||
|
)
|
||||||
|
|
||||||
private val loggerTag = LoggerTag("Push", LoggerTag.SYNC)
|
private val loggerTag = LoggerTag("Push", LoggerTag.SYNC)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class extending FirebaseMessagingService.
|
* Hilt injection happen at super.onReceive().
|
||||||
*/
|
*/
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
class VectorMessagingReceiver : MessagingReceiver() {
|
||||||
|
|
||||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||||
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver
|
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver
|
||||||
@Inject lateinit var pusherManager: PushersManager
|
@Inject lateinit var pusherManager: PushersManager
|
||||||
|
@ -74,21 +95,38 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
* Called when message is received.
|
* Called when message is received.
|
||||||
*
|
*
|
||||||
* @param message the message
|
* @param message the message
|
||||||
|
* @param instance connection, for multi-account
|
||||||
*/
|
*/
|
||||||
override fun onMessageReceived(message: RemoteMessage) {
|
override fun onMessage(context: Context, message: ByteArray, instance: String) {
|
||||||
|
Timber.tag(loggerTag.value).d("## onMessage() received")
|
||||||
|
val sMessage = String(message)
|
||||||
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
|
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
|
||||||
Timber.tag(loggerTag.value).d("## onMessageReceived() %s", message.data.toString())
|
Timber.tag(loggerTag.value).d("## onMessage() %s", sMessage)
|
||||||
}
|
}
|
||||||
Timber.tag(loggerTag.value).d("## onMessageReceived() from FCM with priority %s", message.priority)
|
|
||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
vectorDataStore.incrementPushCounter()
|
vectorDataStore.incrementPushCounter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val moshi: Moshi = Moshi.Builder()
|
||||||
|
.add(KotlinJsonAdapterFactory())
|
||||||
|
.build()
|
||||||
|
lateinit var notification: Notification
|
||||||
|
|
||||||
|
if (UnifiedPushHelper.isEmbeddedDistributor(context)) {
|
||||||
|
notification = moshi.adapter(Notification::class.java)
|
||||||
|
.fromJson(sMessage) ?: return
|
||||||
|
} else {
|
||||||
|
val data = moshi.adapter(UnifiedPushMessage::class.java)
|
||||||
|
.fromJson(sMessage) ?: return
|
||||||
|
notification = data.notification
|
||||||
|
notification.unread = notification.counts.unread
|
||||||
|
}
|
||||||
|
|
||||||
// Diagnostic Push
|
// Diagnostic Push
|
||||||
if (message.data["event_id"] == PushersManager.TEST_EVENT_ID) {
|
if (notification.eventId == PushersManager.TEST_EVENT_ID) {
|
||||||
val intent = Intent(NotificationUtils.PUSH_ACTION)
|
val intent = Intent(NotificationUtils.PUSH_ACTION)
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +140,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
// we are in foreground, let the sync do the things?
|
// we are in foreground, let the sync do the things?
|
||||||
Timber.tag(loggerTag.value).d("PUSH received in a foreground state, ignore")
|
Timber.tag(loggerTag.value).d("PUSH received in a foreground state, ignore")
|
||||||
} else {
|
} else {
|
||||||
onMessageReceivedInternal(message.data)
|
onMessageReceivedInternal(context, notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,55 +151,69 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
* when the InstanceID token is initially generated, so this is where
|
* when the InstanceID token is initially generated, so this is where
|
||||||
* you retrieve the token.
|
* you retrieve the token.
|
||||||
*/
|
*/
|
||||||
override fun onNewToken(refreshedToken: String) {
|
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
||||||
Timber.tag(loggerTag.value).i("onNewToken: FCM Token has been updated")
|
Timber.tag(loggerTag.value).i("onNewEndpoint: adding $endpoint")
|
||||||
FcmHelper.storeFcmToken(this, refreshedToken)
|
|
||||||
if (vectorPreferences.areNotificationEnabledForDevice() && activeSessionHolder.hasActiveSession()) {
|
if (vectorPreferences.areNotificationEnabledForDevice() && activeSessionHolder.hasActiveSession()) {
|
||||||
pusherManager.enqueueRegisterPusherWithFcmKey(refreshedToken)
|
val gateway = UnifiedPushHelper.customOrDefaultGateway(context, endpoint)
|
||||||
|
// If the endpoint has changed
|
||||||
|
// or the gateway has changed
|
||||||
|
if (UnifiedPushHelper.getEndpointOrToken(context) != endpoint
|
||||||
|
|| UnifiedPushHelper.getPushGateway(context) != gateway) {
|
||||||
|
UnifiedPushHelper.storePushGateway(context, gateway)
|
||||||
|
UnifiedPushHelper.storeUpEndpoint(context, endpoint)
|
||||||
|
pusherManager.enqueueRegisterPusher(endpoint, gateway)
|
||||||
|
} else {
|
||||||
|
Timber.tag(loggerTag.value).i("onNewEndpoint: skipped")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED
|
||||||
|
vectorPreferences.setFdroidSyncBackgroundMode(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override fun onRegistrationFailed(context: Context, instance: String) {
|
||||||
* Called when the FCM server deletes pending messages. This may be due to:
|
Toast.makeText(context, "Push service registration failed", Toast.LENGTH_SHORT).show()
|
||||||
* - 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)
|
override fun onUnregistered(context: Context, instance: String) {
|
||||||
* sent a message to the app on that device.
|
Timber.tag(loggerTag.value).d("Unifiedpush: Unregistered")
|
||||||
*
|
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY
|
||||||
* It is recommended that the app do a full sync with the app server after receiving this call.
|
vectorPreferences.setFdroidSyncBackgroundMode(mode)
|
||||||
*/
|
runBlocking {
|
||||||
override fun onDeletedMessages() {
|
try {
|
||||||
Timber.tag(loggerTag.value).v("## onDeletedMessages()")
|
pusherManager.unregisterPusher(UnifiedPushHelper.getEndpointOrToken(context) ?: "")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.tag(loggerTag.value).d("Probably unregistering a non existant pusher")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal receive method
|
* Internal receive method
|
||||||
*
|
*
|
||||||
* @param data Data map containing message data as key/value pairs.
|
* @param notification Notification containing message data.
|
||||||
* For Set of keys use data.keySet().
|
|
||||||
*/
|
*/
|
||||||
private fun onMessageReceivedInternal(data: Map<String, String>) {
|
private fun onMessageReceivedInternal(context: Context, notification: Notification) {
|
||||||
try {
|
try {
|
||||||
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
|
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
|
||||||
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal() : $data")
|
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal() : $notification")
|
||||||
} else {
|
} else {
|
||||||
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal()")
|
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal()")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update the badge counter
|
||||||
|
BadgeProxy.updateBadgeCount(context, notification.unread)
|
||||||
|
|
||||||
val session = activeSessionHolder.getSafeActiveSession()
|
val session = activeSessionHolder.getSafeActiveSession()
|
||||||
|
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
Timber.tag(loggerTag.value).w("## Can't sync from push, no current session")
|
Timber.tag(loggerTag.value).w("## Can't sync from push, no current session")
|
||||||
} else {
|
} else {
|
||||||
val eventId = data["event_id"]
|
if (isEventAlreadyKnown(notification.eventId, notification.roomId)) {
|
||||||
val roomId = data["room_id"]
|
|
||||||
|
|
||||||
if (isEventAlreadyKnown(eventId, roomId)) {
|
|
||||||
Timber.tag(loggerTag.value).d("Ignoring push, event already known")
|
Timber.tag(loggerTag.value).d("Ignoring push, event already known")
|
||||||
} else {
|
} else {
|
||||||
// Try to get the Event content faster
|
// Try to get the Event content faster
|
||||||
Timber.tag(loggerTag.value).d("Requesting event in fast lane")
|
Timber.tag(loggerTag.value).d("Requesting event in fast lane")
|
||||||
getEventFastLane(session, roomId, eventId)
|
getEventFastLane(session, notification.roomId, notification.eventId)
|
||||||
|
|
||||||
Timber.tag(loggerTag.value).d("Requesting background sync")
|
Timber.tag(loggerTag.value).d("Requesting background sync")
|
||||||
session.syncService().requireBackgroundSync()
|
session.syncService().requireBackgroundSync()
|
|
@ -21,6 +21,7 @@ import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import im.vector.app.ActiveSessionDataSource
|
import im.vector.app.ActiveSessionDataSource
|
||||||
import im.vector.app.BuildConfig
|
import im.vector.app.BuildConfig
|
||||||
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.services.CallService
|
import im.vector.app.core.services.CallService
|
||||||
import im.vector.app.features.analytics.AnalyticsTracker
|
import im.vector.app.features.analytics.AnalyticsTracker
|
||||||
import im.vector.app.features.analytics.plan.CallEnded
|
import im.vector.app.features.analytics.plan.CallEnded
|
||||||
|
@ -32,7 +33,6 @@ import im.vector.app.features.call.lookup.CallUserMapper
|
||||||
import im.vector.app.features.call.utils.EglUtils
|
import im.vector.app.features.call.utils.EglUtils
|
||||||
import im.vector.app.features.call.vectorCallService
|
import im.vector.app.features.call.vectorCallService
|
||||||
import im.vector.app.features.session.coroutineScope
|
import im.vector.app.features.session.coroutineScope
|
||||||
import im.vector.app.push.fcm.FcmHelper
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.asCoroutineDispatcher
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
|
@ -272,7 +272,7 @@ class WebRtcCallManager @Inject constructor(
|
||||||
audioManager.setMode(CallAudioManager.Mode.DEFAULT)
|
audioManager.setMode(CallAudioManager.Mode.DEFAULT)
|
||||||
// did we start background sync? so we should stop it
|
// did we start background sync? so we should stop it
|
||||||
if (isInBackground) {
|
if (isInBackground) {
|
||||||
if (FcmHelper.isPushSupported()) {
|
if (!UnifiedPushHelper.isBackgroundSync(context)) {
|
||||||
currentSession?.syncService()?.stopAnyBackgroundSync()
|
currentSession?.syncService()?.stopAnyBackgroundSync()
|
||||||
} else {
|
} else {
|
||||||
// for fdroid we should not stop, it should continue syncing
|
// for fdroid we should not stop, it should continue syncing
|
||||||
|
@ -378,7 +378,7 @@ class WebRtcCallManager @Inject constructor(
|
||||||
// and thus won't be able to received events. For example if the call is
|
// 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
|
// accepted on an other session this device will continue ringing
|
||||||
if (isInBackground) {
|
if (isInBackground) {
|
||||||
if (FcmHelper.isPushSupported()) {
|
if (!UnifiedPushHelper.isBackgroundSync(context)) {
|
||||||
// only for push version as fdroid version is already doing it?
|
// only for push version as fdroid version is already doing it?
|
||||||
currentSession?.syncService()?.startAutomaticBackgroundSync(30, 0)
|
currentSession?.syncService()?.startAutomaticBackgroundSync(30, 0)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -44,6 +44,7 @@ import im.vector.app.core.extensions.replaceFragment
|
||||||
import im.vector.app.core.extensions.validateBackPressed
|
import im.vector.app.core.extensions.validateBackPressed
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.pushers.PushersManager
|
import im.vector.app.core.pushers.PushersManager
|
||||||
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.databinding.ActivityHomeBinding
|
import im.vector.app.databinding.ActivityHomeBinding
|
||||||
import im.vector.app.features.MainActivity
|
import im.vector.app.features.MainActivity
|
||||||
import im.vector.app.features.MainActivityArgs
|
import im.vector.app.features.MainActivityArgs
|
||||||
|
@ -187,7 +188,15 @@ class HomeActivity :
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
analyticsScreenName = MobileScreen.ScreenName.Home
|
analyticsScreenName = MobileScreen.ScreenName.Home
|
||||||
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false)
|
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false)
|
||||||
FcmHelper.ensureFcmTokenIsRetrieved(this, pushManager, vectorPreferences.areNotificationEnabledForDevice())
|
UnifiedPushHelper.register(this, onDoneRunnable = {
|
||||||
|
if (UnifiedPushHelper.isEmbeddedDistributor(this)) {
|
||||||
|
FcmHelper.ensureFcmTokenIsRetrieved(
|
||||||
|
this,
|
||||||
|
pushManager,
|
||||||
|
vectorPreferences.areNotificationEnabledForDevice()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
sharedActionViewModel = viewModelProvider.get(HomeSharedActionViewModel::class.java)
|
sharedActionViewModel = viewModelProvider.get(HomeSharedActionViewModel::class.java)
|
||||||
views.drawerLayout.addDrawerListener(drawerListener)
|
views.drawerLayout.addDrawerListener(drawerListener)
|
||||||
if (isFirstCreation()) {
|
if (isFirstCreation()) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import im.vector.app.core.preference.VectorPreference
|
||||||
import im.vector.app.core.preference.VectorPreferenceCategory
|
import im.vector.app.core.preference.VectorPreferenceCategory
|
||||||
import im.vector.app.core.preference.VectorSwitchPreference
|
import im.vector.app.core.preference.VectorSwitchPreference
|
||||||
import im.vector.app.core.pushers.PushersManager
|
import im.vector.app.core.pushers.PushersManager
|
||||||
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.services.GuardServiceStarter
|
import im.vector.app.core.services.GuardServiceStarter
|
||||||
import im.vector.app.core.utils.combineLatest
|
import im.vector.app.core.utils.combineLatest
|
||||||
import im.vector.app.core.utils.isIgnoringBatteryOptimizations
|
import im.vector.app.core.utils.isIgnoringBatteryOptimizations
|
||||||
|
@ -49,7 +50,6 @@ import im.vector.app.features.settings.BackgroundSyncModeChooserDialog
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.app.features.settings.VectorSettingsBaseFragment
|
import im.vector.app.features.settings.VectorSettingsBaseFragment
|
||||||
import im.vector.app.features.settings.VectorSettingsFragmentInteractionListener
|
import im.vector.app.features.settings.VectorSettingsFragmentInteractionListener
|
||||||
import im.vector.app.push.fcm.FcmHelper
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
@ -58,6 +58,7 @@ import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||||
import org.matrix.android.sdk.api.session.pushers.Pusher
|
import org.matrix.android.sdk.api.session.pushers.Pusher
|
||||||
import org.matrix.android.sdk.api.session.pushrules.RuleIds
|
import org.matrix.android.sdk.api.session.pushrules.RuleIds
|
||||||
import org.matrix.android.sdk.api.session.pushrules.RuleKind
|
import org.matrix.android.sdk.api.session.pushrules.RuleKind
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
// Referenced in vector_settings_preferences_root.xml
|
// Referenced in vector_settings_preferences_root.xml
|
||||||
|
@ -97,16 +98,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor(
|
||||||
|
|
||||||
findPreference<SwitchPreference>(VectorPreferences.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY)?.let {
|
findPreference<SwitchPreference>(VectorPreferences.SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY)?.let {
|
||||||
it.setTransactionalSwitchChangeListener(lifecycleScope) { isChecked ->
|
it.setTransactionalSwitchChangeListener(lifecycleScope) { isChecked ->
|
||||||
if (isChecked) {
|
updateEnabledForDevice(isChecked)
|
||||||
FcmHelper.getFcmToken(requireContext())?.let {
|
|
||||||
pushManager.registerPusherWithFcmKey(it)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
FcmHelper.getFcmToken(requireContext())?.let {
|
|
||||||
pushManager.unregisterPusher(it)
|
|
||||||
session.pushersService().refreshPushers()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +214,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
findPreference<VectorPreferenceCategory>(VectorPreferences.SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY)?.let {
|
findPreference<VectorPreferenceCategory>(VectorPreferences.SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY)?.let {
|
||||||
it.isVisible = !FcmHelper.isPushSupported()
|
it.isVisible = UnifiedPushHelper.isBackgroundSync(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
val backgroundSyncEnabled = vectorPreferences.isBackgroundSyncEnabled()
|
val backgroundSyncEnabled = vectorPreferences.isBackgroundSyncEnabled()
|
||||||
|
@ -331,7 +323,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor(
|
||||||
|
|
||||||
private fun refreshPref() {
|
private fun refreshPref() {
|
||||||
// This pref may have change from troubleshoot pref fragment
|
// This pref may have change from troubleshoot pref fragment
|
||||||
if (!FcmHelper.isPushSupported()) {
|
if (UnifiedPushHelper.isBackgroundSync(requireContext())) {
|
||||||
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_START_ON_BOOT_PREFERENCE_KEY)
|
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_START_ON_BOOT_PREFERENCE_KEY)
|
||||||
?.isChecked = vectorPreferences.autoStartOnBoot()
|
?.isChecked = vectorPreferences.autoStartOnBoot()
|
||||||
}
|
}
|
||||||
|
@ -364,6 +356,26 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun updateEnabledForDevice(enabled: Boolean) {
|
||||||
|
if (enabled) {
|
||||||
|
UnifiedPushHelper.register(requireContext())
|
||||||
|
} else {
|
||||||
|
UnifiedPushHelper.getEndpointOrToken(requireContext())?.let {
|
||||||
|
try {
|
||||||
|
pushManager.unregisterPusher(it)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.d("Probably unregistering a non existant pusher")
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
UnifiedPushHelper.unregister(requireContext())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.d("Probably unregistering to a non-saved distributor")
|
||||||
|
}
|
||||||
|
session.pushersService().refreshPushers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateEnabledForAccount(preference: Preference?) {
|
private fun updateEnabledForAccount(preference: Preference?) {
|
||||||
val pushRuleService = session.pushRuleService()
|
val pushRuleService = session.pushRuleService()
|
||||||
val switchPref = preference as SwitchPreference
|
val switchPref = preference as SwitchPreference
|
||||||
|
|
|
@ -3063,4 +3063,8 @@
|
||||||
<!-- Screen sharing -->
|
<!-- Screen sharing -->
|
||||||
<string name="screen_sharing_notification_title">${app_name} Screen Sharing</string>
|
<string name="screen_sharing_notification_title">${app_name} Screen Sharing</string>
|
||||||
<string name="screen_sharing_notification_description">Screen sharing is in progress</string>
|
<string name="screen_sharing_notification_description">Screen sharing is in progress</string>
|
||||||
|
|
||||||
|
<string name="unifiedpush_getdistributors_dialog_title">Choose how to receive notifications</string>
|
||||||
|
<string name="unifiedpush_getdistributors_dialog_fcm_fallback">Google Services</string>
|
||||||
|
<string name="unifiedpush_getdistributors_dialog_background_sync">Background synchronization</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue