This commit is contained in:
andrew
2023-08-06 22:22:39 +09:30
parent a27f81db30
commit bcf925c132
31 changed files with 176 additions and 204 deletions

View File

@@ -4,7 +4,7 @@
<application tools:node="merge">
<service
android:name="org.thoughtcrime.securesms.notifications.FirebasePushNotificationService"
android:name="org.thoughtcrime.securesms.notifications.FirebasePushService"
android:enabled="true"
android:exported="false">
<intent-filter>

View File

@@ -1,16 +0,0 @@
@file:JvmName("FcmUtils")
package org.thoughtcrime.securesms.notifications
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.iid.InstanceIdResult
import kotlinx.coroutines.*
fun getFcmInstanceId(body: (Task<InstanceIdResult>)->Unit): Job = MainScope().launch(Dispatchers.IO) {
val task = FirebaseInstanceId.getInstance().instanceId
Tasks.await(task)
if (!isActive) return@launch // don't 'complete' task if we were canceled
body(task)
}

View File

@@ -1,37 +0,0 @@
package org.thoughtcrime.securesms.notifications
import kotlinx.coroutines.Job
import org.session.libsignal.utilities.Log
import javax.inject.Inject
import javax.inject.Singleton
private const val TAG = "FirebasePushManager"
@Singleton
class FirebasePushManager @Inject constructor(
private val genericPushManager: GenericPushManager
): PushManager {
private var firebaseInstanceIdJob: Job? = null
@Synchronized
override fun refresh(force: Boolean) {
Log.d(TAG, "refresh() called with: force = $force")
firebaseInstanceIdJob?.apply {
when {
force -> cancel()
isActive -> return
}
}
firebaseInstanceIdJob = getFcmInstanceId { task ->
when {
task.isSuccessful -> try { task.result?.token?.let {
genericPushManager.refresh(it, force).get()
} } catch(e: Exception) { Log.e(TAG, "refresh() failed", e) }
else -> Log.w(TAG, "getFcmInstanceId failed." + task.exception)
}
}
}
}

View File

@@ -9,5 +9,5 @@ import dagger.hilt.components.SingletonComponent
@InstallIn(SingletonComponent::class)
abstract class FirebaseBindingModule {
@Binds
abstract fun bindPushManager(firebasePushManager: FirebasePushManager): PushManager
abstract fun bindTokenFetcher(tokenFetcher: FirebaseTokenFetcher): TokenFetcher
}

View File

@@ -9,26 +9,25 @@ import javax.inject.Inject
private const val TAG = "FirebasePushNotificationService"
@AndroidEntryPoint
class FirebasePushNotificationService : FirebaseMessagingService() {
class FirebasePushService : FirebaseMessagingService() {
@Inject lateinit var pushManager: PushManager
@Inject lateinit var pushHandler: PushHandler
@Inject lateinit var prefs: TextSecurePreferences
@Inject lateinit var pushReceiver: PushReceiver
@Inject lateinit var pushRegistry: PushRegistry
override fun onNewToken(token: String) {
super.onNewToken(token)
TextSecurePreferences.getLocalNumber(this) ?: return
if (TextSecurePreferences.getFCMToken(this) != token) {
pushManager.refresh(true)
}
if (token == prefs.getPushToken()) return
pushRegistry.refresh(token, true)
}
override fun onMessageReceived(message: RemoteMessage) {
Log.d(TAG, "Received a push notification.")
pushHandler.onPush(message.data)
pushReceiver.onPush(message.data)
}
override fun onDeletedMessages() {
Log.d(TAG, "Called onDeletedMessages.")
pushManager.refresh(true)
pushRegistry.refresh(true)
}
}

View File

@@ -0,0 +1,45 @@
package org.thoughtcrime.securesms.notifications
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.iid.InstanceIdResult
import dagger.Lazy
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import org.session.libsignal.utilities.Log
import javax.inject.Inject
import javax.inject.Singleton
private val TAG = FirebaseTokenFetcher::class.java.name
@Singleton
class FirebaseTokenFetcher @Inject constructor(
private val pushRegistry: Lazy<PushRegistry>,
): TokenFetcher {
override fun fetch(): Job = MainScope().launch(Dispatchers.IO) {
FirebaseInstanceId.getInstance().instanceId
.also(Tasks::await)
.also { if (!isActive) return@launch } // don't 'complete' task if we were canceled
.process()
}
private fun Task<InstanceIdResult>.process() {
when {
isSuccessful -> try {
result?.token?.let {
pushRegistry.get().refresh(it, force = true).get()
}
} catch (e: Exception) {
onFail(e)
}
else -> exception?.let(::onFail)
}
}
private fun onFail(e: Exception) = Log.e(TAG, "fetch failed", e)
}