mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-22 16:07:30 +00:00
Refactor to accept Huawei token from getToken() and/or onNewToken()
This commit is contained in:
parent
c8dcfbf32c
commit
5a5b2f593f
@ -14,11 +14,6 @@ private val TAG = HuaweiPushService::class.java.simpleName
|
||||
|
||||
@AndroidEntryPoint
|
||||
class HuaweiPushService: HmsMessageService() {
|
||||
|
||||
init {
|
||||
Log.d(TAG, "init Huawei Service")
|
||||
}
|
||||
|
||||
@Inject lateinit var pushRegistry: PushRegistry
|
||||
@Inject lateinit var pushReceiver: PushReceiver
|
||||
|
||||
@ -32,33 +27,13 @@ class HuaweiPushService: HmsMessageService() {
|
||||
pushReceiver.onPush(message?.data?.let(Base64::decode))
|
||||
}
|
||||
|
||||
override fun onMessageSent(p0: String?) {
|
||||
Log.d(TAG, "onMessageSent() called with: p0 = $p0")
|
||||
super.onMessageSent(p0)
|
||||
}
|
||||
|
||||
override fun onSendError(p0: String?, p1: Exception?) {
|
||||
Log.d(TAG, "onSendError() called with: p0 = $p0, p1 = $p1")
|
||||
super.onSendError(p0, p1)
|
||||
}
|
||||
|
||||
override fun onMessageDelivered(p0: String?, p1: Exception?) {
|
||||
Log.d(TAG, "onMessageDelivered")
|
||||
super.onMessageDelivered(p0, p1)
|
||||
}
|
||||
|
||||
|
||||
override fun onNewToken(p0: String?) {
|
||||
Log.d(TAG, "onNewToken")
|
||||
super.onNewToken(p0)
|
||||
override fun onNewToken(token: String?) {
|
||||
pushRegistry.register(token)
|
||||
}
|
||||
|
||||
override fun onNewToken(token: String?, bundle: Bundle?) {
|
||||
Log.d(TAG, "New HCM token: $token.")
|
||||
|
||||
TextSecurePreferences.setPushToken(this, token)
|
||||
|
||||
pushRegistry.refresh(token, true)
|
||||
onNewToken(token)
|
||||
}
|
||||
|
||||
override fun onDeletedMessages() {
|
||||
|
@ -2,26 +2,28 @@ package org.thoughtcrime.securesms.notifications
|
||||
|
||||
import android.content.Context
|
||||
import com.huawei.hms.aaid.HmsInstanceId
|
||||
import dagger.Lazy
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.session.libsignal.utilities.Log
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
private const val APP_ID = "107205081"
|
||||
private const val TOKEN_SCOPE = "HCM"
|
||||
|
||||
@Singleton
|
||||
class HuaweiTokenFetcher @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
@ApplicationContext private val context: Context,
|
||||
private val pushRegistry: Lazy<PushRegistry>,
|
||||
): TokenFetcher {
|
||||
override fun fetch(): Job {
|
||||
val hmsInstanceId = HmsInstanceId.getInstance(context)
|
||||
|
||||
return MainScope().launch(Dispatchers.IO) {
|
||||
val appId = "107205081"
|
||||
val tokenScope = "HCM"
|
||||
// getToken returns an empty string, but triggers the service to initialize.
|
||||
hmsInstanceId.getToken(appId, tokenScope)
|
||||
}
|
||||
override suspend fun fetch(): String? = HmsInstanceId.getInstance(context).run {
|
||||
// https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/push-basic-capability#h2-1576218800370
|
||||
// getToken may return an empty string, if so HuaweiPushService#onNewToken will be called.
|
||||
withContext(Dispatchers.IO) { getToken(APP_ID, TOKEN_SCOPE) }
|
||||
}
|
||||
}
|
||||
|
@ -427,11 +427,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
|
||||
}
|
||||
|
||||
private static class ProviderInitializationException extends RuntimeException { }
|
||||
|
||||
public void registerForPnIfNeeded(final Boolean force) {
|
||||
pushRegistry.refresh(force);
|
||||
}
|
||||
|
||||
private void setUpPollingIfNeeded() {
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null) return;
|
||||
|
@ -75,7 +75,7 @@ class PushReceiver @Inject constructor(@ApplicationContext val context: Context)
|
||||
else -> this["ENCRYPTED_DATA"]?.let(Base64::decode)
|
||||
}
|
||||
|
||||
fun decrypt(encPayload: ByteArray): ByteArray? {
|
||||
private fun decrypt(encPayload: ByteArray): ByteArray? {
|
||||
Log.d(TAG, "decrypt() called")
|
||||
|
||||
val encKey = getOrCreateNotificationKey()
|
||||
|
@ -4,6 +4,8 @@ import android.content.Context
|
||||
import com.goterl.lazysodium.utils.KeyPair
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.combine.and
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1
|
||||
@ -22,8 +24,10 @@ private val TAG = PushRegistry::class.java.name
|
||||
class PushRegistry @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val device: Device,
|
||||
private val tokenManager: PushTokenManager,
|
||||
private val tokenManager: TokenManager,
|
||||
private val pushRegistryV2: PushRegistryV2,
|
||||
private val prefs: TextSecurePreferences,
|
||||
private val tokenFetcher: TokenFetcher,
|
||||
) {
|
||||
|
||||
private var pushRegistrationJob: Job? = null
|
||||
@ -32,42 +36,33 @@ class PushRegistry @Inject constructor(
|
||||
Log.d(TAG, "refresh() called with: force = $force")
|
||||
|
||||
pushRegistrationJob?.apply {
|
||||
if (force) cancel() else if (isActive) return
|
||||
if (force) cancel() else if (isActive || !tokenManager.hasValidRegistration) return
|
||||
}
|
||||
|
||||
pushRegistrationJob = tokenManager.fetchToken()
|
||||
pushRegistrationJob = MainScope().launch {
|
||||
register(tokenFetcher.fetch()) fail {
|
||||
Log.e(TAG, "register failed", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun refresh(token: String?, force: Boolean): Promise<*, Exception> {
|
||||
Log.d(TAG, "refresh($token, $force) called")
|
||||
fun register(token: String?): Promise<*, Exception> {
|
||||
Log.d(TAG, "refresh($token) called")
|
||||
|
||||
token ?: return emptyPromise()
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return emptyPromise()
|
||||
if (token?.isNotEmpty() != true) return emptyPromise()
|
||||
|
||||
prefs.setPushToken(token)
|
||||
|
||||
val userPublicKey = prefs.getLocalNumber() ?: return emptyPromise()
|
||||
val userEdKey = KeyPairUtilities.getUserED25519KeyPair(context) ?: return emptyPromise()
|
||||
|
||||
return when {
|
||||
tokenManager.isPushEnabled -> register(force, token, userPublicKey, userEdKey)
|
||||
tokenManager.requiresUnregister -> unregister(token, userPublicKey, userEdKey)
|
||||
prefs.isPushEnabled() -> register(token, userPublicKey, userEdKey)
|
||||
tokenManager.isRegistered -> unregister(token, userPublicKey, userEdKey)
|
||||
else -> emptyPromise()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register for push notifications if:
|
||||
* force is true
|
||||
* there is no FCM Token
|
||||
* FCM Token has expired
|
||||
*/
|
||||
private fun register(
|
||||
force: Boolean,
|
||||
token: String,
|
||||
publicKey: String,
|
||||
userEd25519Key: KeyPair,
|
||||
namespaces: List<Int> = listOf(Namespace.DEFAULT)
|
||||
): Promise<*, Exception> = if (force || tokenManager.isInvalid()) {
|
||||
register(token, publicKey, userEd25519Key, namespaces)
|
||||
} else emptyPromise()
|
||||
|
||||
/**
|
||||
* Register for push notifications.
|
||||
*/
|
||||
@ -77,7 +72,7 @@ class PushRegistry @Inject constructor(
|
||||
userEd25519Key: KeyPair,
|
||||
namespaces: List<Int> = listOf(Namespace.DEFAULT)
|
||||
): Promise<*, Exception> {
|
||||
android.util.Log.d(
|
||||
Log.d(
|
||||
TAG,
|
||||
"register() called with: token = $token, publicKey = $publicKey, userEd25519Key = $userEd25519Key, namespaces = $namespaces"
|
||||
)
|
||||
@ -97,8 +92,8 @@ class PushRegistry @Inject constructor(
|
||||
}
|
||||
|
||||
return v1 and v2 success {
|
||||
Log.d(TAG, "registerBoth success... saving token!!")
|
||||
tokenManager.fcmToken = token
|
||||
Log.d(TAG, "register v1 & v2 success")
|
||||
tokenManager.register()
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +106,6 @@ class PushRegistry @Inject constructor(
|
||||
) fail {
|
||||
Log.e(TAG, "unregisterBoth failed", it)
|
||||
} success {
|
||||
tokenManager.fcmToken = null
|
||||
tokenManager.unregister()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
package org.thoughtcrime.securesms.notifications
|
||||
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Job
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class PushTokenManager @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val tokenFetcher: TokenFetcher
|
||||
) {
|
||||
private val expiryManager = ExpiryManager(context)
|
||||
|
||||
val isPushEnabled get() = TextSecurePreferences.isPushEnabled(context)
|
||||
|
||||
var fcmToken
|
||||
get() = TextSecurePreferences.getPushToken(context)
|
||||
set(value) {
|
||||
TextSecurePreferences.setPushToken(context, value)
|
||||
if (value != null) markTime() else clearTime()
|
||||
}
|
||||
|
||||
val requiresUnregister get() = fcmToken != null
|
||||
|
||||
private fun clearTime() = expiryManager.clearTime()
|
||||
private fun markTime() = expiryManager.markTime()
|
||||
private fun isExpired() = expiryManager.isExpired()
|
||||
|
||||
fun isInvalid(): Boolean = fcmToken == null || isExpired()
|
||||
fun fetchToken(): Job = tokenFetcher.fetch()
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package org.thoughtcrime.securesms.notifications
|
||||
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
interface TokenFetcher {
|
||||
fun fetch(): Job
|
||||
suspend fun fetch(): String?
|
||||
}
|
||||
|
@ -6,17 +6,21 @@ import org.session.libsession.utilities.TextSecurePreferences
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
class ExpiryManager(
|
||||
private val context: Context,
|
||||
private val interval: Int = 12 * 60 * 60 * 1000
|
||||
) {
|
||||
fun isExpired() = currentTime() > time + interval
|
||||
private const val INTERVAL: Int = 12 * 60 * 60 * 1000
|
||||
|
||||
fun markTime() {
|
||||
@Singleton
|
||||
class TokenManager @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
) {
|
||||
val hasValidRegistration get() = isRegistered && !isExpired
|
||||
val isRegistered get() = time > 0
|
||||
private val isExpired get() = currentTime() > time + INTERVAL
|
||||
|
||||
fun register() {
|
||||
time = currentTime()
|
||||
}
|
||||
|
||||
fun clearTime() {
|
||||
fun unregister() {
|
||||
time = 0
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class FirebasePushService : FirebaseMessagingService() {
|
||||
override fun onNewToken(token: String) {
|
||||
if (token == prefs.getPushToken()) return
|
||||
|
||||
pushRegistry.refresh(token, true)
|
||||
pushRegistry.register(token)
|
||||
}
|
||||
|
||||
override fun onMessageReceived(message: RemoteMessage) {
|
||||
|
@ -1,43 +1,19 @@
|
||||
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 kotlinx.coroutines.withContext
|
||||
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) {
|
||||
class FirebaseTokenFetcher @Inject constructor(): TokenFetcher {
|
||||
override suspend fun fetch() = withContext(Dispatchers.IO) {
|
||||
FirebaseInstanceId.getInstance().instanceId
|
||||
.also(Tasks::await)
|
||||
.also { if (!isActive) return@launch } // don't 'complete' task if we were canceled
|
||||
.process()
|
||||
.takeIf { isActive } // don't 'complete' task if we were canceled
|
||||
?.run { result?.token ?: throw exception!! }
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user