Browse Source

Split GoogleFcmHelper

test/jme/compound-poc
Benoit Marty 1 year ago committed by Benoit Marty
parent
commit
0126c7ddc1
  1. 5
      libraries/pushproviders/api/src/main/kotlin/io/element/android/libraries/push/providers/api/PushProvider.kt
  2. 12
      libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebaseNewTokenHandler.kt
  3. 9
      libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebasePushProvider.kt
  4. 43
      libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebaseStore.kt
  5. 79
      libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebaseTroubleshooter.kt
  6. 98
      libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/GoogleFcmHelper.kt
  7. 6
      libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/VectorFirebaseMessagingService.kt
  8. 4
      libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/push/providers/unifiedpush/UnifiedPushProvider.kt

5
libraries/pushproviders/api/src/main/kotlin/io/element/android/libraries/push/providers/api/PushProvider.kt

@ -28,4 +28,9 @@ interface PushProvider { @@ -28,4 +28,9 @@ interface PushProvider {
val index: Int
fun getDistributorNames(): List<String>
suspend fun registerWith(matrixClient: MatrixClient, distributorName: String)
/**
* Attempt to troubleshoot the push provider
*/
suspend fun troubleshoot(): Result<Unit>
}

12
libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebaseSetPusher.kt → libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebaseNewTokenHandler.kt

@ -26,16 +26,20 @@ import io.element.android.libraries.sessionstorage.api.toUserList @@ -26,16 +26,20 @@ import io.element.android.libraries.sessionstorage.api.toUserList
import timber.log.Timber
import javax.inject.Inject
private val loggerTag = LoggerTag("FirebaseSetPusher")
private val loggerTag = LoggerTag("FirebaseNewTokenHandler")
// TODO Rename
class FirebaseSetPusher @Inject constructor(
/**
* Handle new token receive from Firebase. Will update all the sessions which are using Firebase as a push provider.
*/
class FirebaseNewTokenHandler @Inject constructor(
private val pusherSubscriber: PusherSubscriber,
private val sessionStore: SessionStore,
private val userPushStoreFactory: UserPushStoreFactory,
private val matrixAuthenticationService: MatrixAuthenticationService,
private val firebaseStore: FirebaseStore,
) {
suspend fun onNewFirebaseToken(firebaseToken: String) {
suspend fun handle(firebaseToken: String) {
firebaseStore.storeFcmToken(firebaseToken)
// Register the pusher for all the sessions
sessionStore.getAllSessions().toUserList().forEach { userId ->
val userDataStore = userPushStoreFactory.create(userId)

9
libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebasePushProvider.kt

@ -26,7 +26,8 @@ import javax.inject.Inject @@ -26,7 +26,8 @@ import javax.inject.Inject
private val loggerTag = LoggerTag("FirebasePushProvider")
class FirebasePushProvider @Inject constructor(
private val googleFcmHelper: GoogleFcmHelper,
private val firebaseStore: FirebaseStore,
private val firebaseTroubleshooter: FirebaseTroubleshooter,
private val pusherSubscriber: PusherSubscriber,
) : PushProvider {
override val index = 0
@ -37,9 +38,13 @@ class FirebasePushProvider @Inject constructor( @@ -37,9 +38,13 @@ class FirebasePushProvider @Inject constructor(
}
override suspend fun registerWith(matrixClient: MatrixClient, distributorName: String) {
val pushKey = googleFcmHelper.getFcmToken() ?: return Unit.also {
val pushKey = firebaseStore.getFcmToken() ?: return Unit.also {
Timber.tag(loggerTag.value).w("Unable to register pusher, Firebase token is not known.")
}
pusherSubscriber.registerPusher(matrixClient, pushKey, FirebaseConfig.pusher_http_url)
}
override suspend fun troubleshoot(): Result<Unit> {
return firebaseTroubleshooter.troubleshoot()
}
}

43
libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebaseStore.kt

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.providers.firebase
import android.content.SharedPreferences
import androidx.core.content.edit
import io.element.android.libraries.di.DefaultPreferences
import javax.inject.Inject
/**
* This class store the Firebase token in SharedPrefs.
*/
class FirebaseStore @Inject constructor(
@DefaultPreferences private val sharedPrefs: SharedPreferences,
) {
fun getFcmToken(): String? {
return sharedPrefs.getString(PREFS_KEY_FCM_TOKEN, null)
}
fun storeFcmToken(token: String?) {
sharedPrefs.edit {
putString(PREFS_KEY_FCM_TOKEN, token)
}
}
companion object {
private const val PREFS_KEY_FCM_TOKEN = "FCM_TOKEN"
}
}

79
libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/FirebaseTroubleshooter.kt

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.providers.firebase
import android.content.Context
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.messaging.FirebaseMessaging
import io.element.android.libraries.di.ApplicationContext
import timber.log.Timber
import javax.inject.Inject
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
/**
* This class force retrieving and storage of the Firebase token.
*/
class FirebaseTroubleshooter @Inject constructor(
@ApplicationContext private val context: Context,
private val newTokenHandler: FirebaseNewTokenHandler,
) {
suspend fun troubleshoot(): Result<Unit> {
return runCatching {
val token = retrievedFirebaseToken()
newTokenHandler.handle(token)
}
}
private suspend fun retrievedFirebaseToken(): String {
return suspendCoroutine { continuation ->
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
if (checkPlayServices(context)) {
try {
FirebaseMessaging.getInstance().token
.addOnSuccessListener { token ->
continuation.resume(token)
}
.addOnFailureListener { e ->
Timber.e(e, "## retrievedFirebaseToken() : failed")
continuation.resumeWithException(e)
}
} catch (e: Throwable) {
Timber.e(e, "## retrievedFirebaseToken() : failed")
continuation.resumeWithException(e)
}
} else {
val e = Exception("No valid Google Play Services found. Cannot use FCM.")
Timber.e(e)
continuation.resumeWithException(e)
}
}
}
/**
* 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(context: Context): Boolean {
val apiAvailability = GoogleApiAvailability.getInstance()
val resultCode = apiAvailability.isGooglePlayServicesAvailable(context)
return resultCode == ConnectionResult.SUCCESS
}
}

98
libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/GoogleFcmHelper.kt

@ -1,98 +0,0 @@ @@ -1,98 +0,0 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.providers.firebase
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.DefaultPreferences
import javax.inject.Inject
/**
* This class store the FCM token in SharedPrefs and ensure this token is retrieved.
* It has an alter ego in the fdroid variant.
*/
// TODO Rename to store?
class GoogleFcmHelper @Inject constructor(
@ApplicationContext private val context: Context,
@DefaultPreferences private val sharedPrefs: SharedPreferences,
) {
fun getFcmToken(): String? {
return sharedPrefs.getString(PREFS_KEY_FCM_TOKEN, null)
}
fun storeFcmToken(token: String?) {
sharedPrefs.edit {
putString(PREFS_KEY_FCM_TOKEN, token)
}
}
/*
override fun ensureFcmTokenIsRetrieved(pushersManager: PushersManager, registerPusher: Boolean) {
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
if (checkPlayServices(context)) {
try {
FirebaseMessaging.getInstance().token
.addOnSuccessListener { token ->
storeFcmToken(token)
if (registerPusher) {
runBlocking {// TODO
pushersManager.enqueueRegisterPusherWithFcmKey(token)
}
}
}
.addOnFailureListener { e ->
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
}
} catch (e: Throwable) {
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
}
} else {
Toast.makeText(context, R.string.push_no_valid_google_play_services_apk_android, 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(context: Context): Boolean {
val apiAvailability = GoogleApiAvailability.getInstance()
val resultCode = apiAvailability.isGooglePlayServicesAvailable(context)
return resultCode == ConnectionResult.SUCCESS
}
/*
override fun onEnterForeground(activeSessionHolder: ActiveSessionHolder) {
// No op
}
override fun onEnterBackground(activeSessionHolder: ActiveSessionHolder) {
// No op
}
*/
companion object {
private const val PREFS_KEY_FCM_TOKEN = "FCM_TOKEN"
}
}

6
libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/push/providers/firebase/VectorFirebaseMessagingService.kt

@ -30,10 +30,9 @@ import javax.inject.Inject @@ -30,10 +30,9 @@ import javax.inject.Inject
private val loggerTag = LoggerTag("Firebase")
class VectorFirebaseMessagingService : FirebaseMessagingService() {
@Inject lateinit var firebaseSetPusher: FirebaseSetPusher
@Inject lateinit var firebaseNewTokenHandler: FirebaseNewTokenHandler
@Inject lateinit var pushParser: FirebasePushParser
@Inject lateinit var pushHandler: PushHandler
@Inject lateinit var googleFcmHelper: GoogleFcmHelper
private val coroutineScope = CoroutineScope(SupervisorJob())
@ -44,9 +43,8 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { @@ -44,9 +43,8 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
Timber.tag(loggerTag.value).d("New Firebase token")
googleFcmHelper.storeFcmToken(token)
coroutineScope.launch {
firebaseSetPusher.onNewFirebaseToken(token)
firebaseNewTokenHandler.handle(token)
}
}

4
libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/push/providers/unifiedpush/UnifiedPushProvider.kt

@ -30,4 +30,8 @@ class UnifiedPushProvider @Inject constructor() : PushProvider { @@ -30,4 +30,8 @@ class UnifiedPushProvider @Inject constructor() : PushProvider {
override suspend fun registerWith(matrixClient: MatrixClient, distributorName: String) {
TODO("Not yet implemented")
}
override suspend fun troubleshoot(): Result<Unit> {
TODO("Not yet implemented")
}
}

Loading…
Cancel
Save