Skip to content

Commit

Permalink
unifiedpush notification
Browse files Browse the repository at this point in the history
  • Loading branch information
p1gp1g committed Jun 1, 2021
1 parent d2fd652 commit a3a946f
Show file tree
Hide file tree
Showing 24 changed files with 403 additions and 342 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ allprojects {
includeGroupByRegex 'com\\.github\\.chrisbanes'
// PFLockScreen-Android
includeGroupByRegex 'com\\.github\\.vector-im'
// UnifiedPush
includeGroupByRegex 'com\\.github\\.UnifiedPush'

// Chat effects
includeGroupByRegex 'com\\.github\\.jetradarmobile'
Expand Down
13 changes: 7 additions & 6 deletions vector/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ android {
buildFeatures {
viewBinding true
}

packagingOptions {
exclude 'META-INF/lib_release.kotlin_module'
}
}

dependencies {
Expand Down Expand Up @@ -429,12 +433,9 @@ dependencies {
implementation "com.google.dagger:dagger:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"

// gplay flavor only
gplayImplementation('com.google.firebase:firebase-messaging:22.0.0') {
exclude group: 'com.google.firebase', module: 'firebase-core'
exclude group: 'com.google.firebase', module: 'firebase-analytics'
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
}
// Unifiedpush
implementation 'com.github.UnifiedPush:android-connector:1.1.3'
gplayImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.0.2'

// OSS License, gplay flavor only
gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
Expand Down
29 changes: 0 additions & 29 deletions vector/src/fdroid/AndroidManifest.xml

This file was deleted.

47 changes: 2 additions & 45 deletions vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,56 +17,13 @@

package im.vector.app.push.fcm

import android.app.Activity
import android.content.Context
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.pushers.PushersManager
import im.vector.app.fdroid.BackgroundSyncStarter
import im.vector.app.fdroid.receiver.AlarmSyncBroadcastReceiver
import im.vector.app.features.settings.VectorPreferences

/**
* This class has an alter ego in the gplay variant.
*/
object FcmHelper {

fun isPushSupported(): Boolean = false

/**
* Retrieves the FCM registration token.
*
* @return the FCM token or null if not received from FCM
*/
fun getFcmToken(context: Context): String? {
return null
}

/**
* Store FCM token to the SharedPrefs
*
* @param context android context
* @param token the token to store
*/
fun storeFcmToken(context: Context, token: String?) {
// No op
}

/**
* onNewToken may not be called on application upgrade, so ensure my shared pref is set
*
* @param activity the first launch Activity
*/
fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) {
// No op
}

fun onEnterForeground(context: Context, activeSessionHolder: ActiveSessionHolder) {
// try to stop all regardless of background mode
activeSessionHolder.getSafeActiveSession()?.stopAnyBackgroundSync()
AlarmSyncBroadcastReceiver.cancelAlarm(context)
}

fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) {
BackgroundSyncStarter.start(context, vectorPreferences, activeSessionHolder)
fun isPlayServicesAvailable(context: Context): Boolean {
return false
}
}
16 changes: 5 additions & 11 deletions vector/src/gplay/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@
package="im.vector.app">

<application>

<!-- Firebase components -->
<meta-data
android:name="firebase_analytics_collection_deactivated"
android:value="true" />

<service android:name=".gplay.push.fcm.VectorFirebaseMessagingService">
<receiver android:enabled="true" android:name=".push.fcm.EmbeddedDistrib" android:exported="false">
<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>
</service>

</receiver>
</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package im.vector.app.gplay.features.settings.troubleshoot
import android.content.Intent
import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.messaging.FirebaseMessaging
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.startAddGoogleAccountIntent
Expand All @@ -28,13 +27,18 @@ import timber.log.Timber
import javax.inject.Inject

/*
* Test that app can successfully retrieve a token via firebase
* Test that app can successfully retrieve a new endpoint
*/
class TestFirebaseToken @Inject constructor(private val context: AppCompatActivity,
class TestNewEndpoint @Inject constructor(private val context: AppCompatActivity,
private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) {

override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
status = TestStatus.RUNNING
description = "bypassed"
status = TestStatus.SUCCESS
/**
* TODO
*/
/*status = TestStatus.RUNNING
try {
FirebaseMessaging.getInstance().token
.addOnCompleteListener(context) { task ->
Expand Down Expand Up @@ -74,6 +78,6 @@ class TestFirebaseToken @Inject constructor(private val context: AppCompatActivi
} catch (e: Throwable) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, e.localizedMessage)
status = TestStatus.FAILED
}
}*/
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ 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 im.vector.app.core.pushers.UPHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
Expand All @@ -48,12 +48,12 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat

override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
pushReceived = false
val fcmToken = FcmHelper.getFcmToken(context) ?: run {
UPHelper.getUpEndpoint(context) ?: run {
status = TestStatus.FAILED
return
}
action = activeSessionHolder.getActiveSession().coroutineScope.launch {
val result = runCatching { pushersManager.testPush(fcmToken) }
val result = runCatching { pushersManager.testPush(context) }

withContext(Dispatchers.Main) {
status = result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.settings.troubleshoot.TroubleshootTest
import im.vector.app.push.fcm.FcmHelper
import im.vector.app.core.pushers.UPHelper
import javax.inject.Inject

/**
Expand All @@ -41,7 +41,11 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc

override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
// Check if we have a registered pusher for this token
val fcmToken = FcmHelper.getFcmToken(context) ?: run {
val pushToken = UPHelper.getUpEndpoint(context) ?: run {
status = TestStatus.FAILED
return
}
val pushGateway = UPHelper.getPushGateway(context) ?: run {
status = TestStatus.FAILED
return
}
Expand All @@ -50,14 +54,14 @@ class TestTokenRegistration @Inject constructor(private val context: AppCompatAc
return
}
val pushers = session.getPushers().filter {
it.pushKey == fcmToken && it.state == PusherState.REGISTERED
it.pushKey == pushToken && it.state == PusherState.REGISTERED
}
if (pushers.isEmpty()) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_token_registration_failed,
stringProvider.getString(R.string.sas_error_unknown))
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_token_registration_quick_fix) {
override fun doFix() {
val workId = pushersManager.registerPusherWithFcmKey(fcmToken)
val workId = pushersManager.registerPusher(pushToken, pushGateway)
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
if (workInfo != null) {
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
Expand Down
31 changes: 31 additions & 0 deletions vector/src/gplay/java/im/vector/app/push/fcm/EmbeddedDistrib.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package im.vector.app.push.fcm

import android.content.Context
import im.vector.app.R
import org.unifiedpush.android.embedded_fcm_distributor.GetEndpointHandler
import org.unifiedpush.android.embedded_fcm_distributor.EmbeddedDistributorReceiver

/*
* Copyright (c) 2021 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.
*/

val handlerFCM = object: GetEndpointHandler {
override fun getEndpoint(context: Context?, token: String, instance: String): String {
// This returns the endpoint of your FCM Rewrite-Proxy
return "${context!!.getString(R.string.pusher_http_url)}/FCM?instance=$instance&token=$token"
}
}

class EmbeddedDistrib: EmbeddedDistributorReceiver(handlerFCM)
84 changes: 3 additions & 81 deletions vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,99 +15,21 @@
*/
package im.vector.app.push.fcm

import android.app.Activity
import android.content.Context
import android.widget.Toast
import androidx.core.content.edit
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.messaging.FirebaseMessaging
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.DefaultSharedPreferences
import im.vector.app.core.pushers.PushersManager
import im.vector.app.features.settings.VectorPreferences
import timber.log.Timber

/**
* This class store the FCM token in SharedPrefs and ensure this token is retrieved.
* It has an alter ego in the fdroid variant.
*/
object FcmHelper {
private val PREFS_KEY_FCM_TOKEN = "FCM_TOKEN"

fun isPushSupported(): Boolean = true

/**
* Retrieves the FCM registration token.
*
* @return the FCM token or null if not received from FCM
*/
fun getFcmToken(context: Context): String? {
return DefaultSharedPreferences.getInstance(context).getString(PREFS_KEY_FCM_TOKEN, null)
}

/**
* Store FCM token to the SharedPrefs
* TODO Store in realm
*
* @param context android context
* @param token the token to store
*/
fun storeFcmToken(context: Context,
token: String?) {
DefaultSharedPreferences.getInstance(context).edit {
putString(PREFS_KEY_FCM_TOKEN, token)
}
}

/**
* onNewToken may not be called on application upgrade, so ensure my shared pref is set
*
* @param activity the first launch Activity
*/
fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) {
// if (TextUtils.isEmpty(getFcmToken(activity))) {
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
if (checkPlayServices(activity)) {
try {
FirebaseMessaging.getInstance().token
.addOnSuccessListener { token ->
storeFcmToken(activity, token)
if (registerPusher) {
pushersManager.registerPusherWithFcmKey(token)
}
}
.addOnFailureListener { e ->
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
}
} catch (e: Throwable) {
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
}
} else {
Toast.makeText(activity, R.string.no_valid_google_play_services_apk, 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.
* Check the device to make sure it has the Google Play Services APK.
*/
private fun checkPlayServices(activity: Activity): Boolean {
fun isPlayServicesAvailable(context: Context): Boolean {
val apiAvailability = GoogleApiAvailability.getInstance()
val resultCode = apiAvailability.isGooglePlayServicesAvailable(activity)
val resultCode = apiAvailability.isGooglePlayServicesAvailable(context)
return resultCode == ConnectionResult.SUCCESS
}

@Suppress("UNUSED_PARAMETER")
fun onEnterForeground(context: Context, activeSessionHolder: ActiveSessionHolder) {
// No op
}

@Suppress("UNUSED_PARAMETER")
fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) {
// TODO FCM fallback
}
}
Loading

0 comments on commit a3a946f

Please sign in to comment.