Skip to content

Commit d11b66f

Browse files
authored
Merge pull request #5884 from p1gp1g/foss_fcm
Add Push Notification with Play Service on generic flavor (full FLOSS)
2 parents bbf8d3f + 7415fec commit d11b66f

9 files changed

Lines changed: 90 additions & 20 deletions

File tree

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ dependencies {
339339
"gplayImplementation"("com.google.firebase:firebase-messaging:25.1.0")
340340

341341
implementation("org.unifiedpush.android:connector:3.3.3")
342+
"genericImplementation"("org.unifiedpush.android:embedded-fcm-distributor:3.1.0")
342343

343344
// compose
344345
implementation(platform("androidx.compose:compose-bom:2026.05.01"))

app/src/main/java/com/nextcloud/talk/account/AccountVerificationActivity.kt

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ import io.reactivex.disposables.Disposable
6060
import io.reactivex.schedulers.Schedulers
6161
import org.greenrobot.eventbus.Subscribe
6262
import org.greenrobot.eventbus.ThreadMode
63-
import org.unifiedpush.android.connector.UnifiedPush
6463
import java.net.CookieManager
6564
import javax.inject.Inject
6665

@@ -408,15 +407,21 @@ class AccountVerificationActivity : BaseActivity() {
408407
// - By default, use the Play Services if available
409408
// - If this is a first user, and we have an External UnifiedPush distributor,
410409
// and the server supports it: we use it
410+
// - Else if there is an embedded distributor (so this is a generic flavor, and the
411+
// Play services are installed) => we use it for all accounts that support web push
411412
// - Else we skip push registrations
412413
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
413414
ClosedInterfaceImpl().setUpPushTokenRegistration()
414415
eventBus.post(EventStatus(internalAccountId, EventStatus.EventType.PUSH_REGISTRATION, true))
415416
} else if (userManager.users.blockingGet().size == 1 &&
416-
UnifiedPush.getDistributors(context).isNotEmpty() &&
417+
UnifiedPushUtils.getExternalDistributors(context).isNotEmpty() &&
417418
userManager.getUserWithId(internalAccountId).blockingGet().hasWebPushCapability
418419
) {
419420
useUnifiedPushIntroduced()
421+
} else if (UnifiedPushUtils.hasEmbeddedDistributor(context) &&
422+
userManager.users.blockingGet().any { it.hasWebPushCapability }
423+
) {
424+
useEmbeddedUnifiedPush()
420425
} else {
421426
Log.w(TAG, "Skipping push registration.")
422427
eventBus.post(EventStatus(internalAccountId, EventStatus.EventType.PUSH_REGISTRATION, false))
@@ -434,13 +439,33 @@ class AccountVerificationActivity : BaseActivity() {
434439
dialogForUnifiedPush { res ->
435440
if (res) {
436441
useUnifiedPush()
442+
} else {
443+
fallbackToEmbeddedUnifiedPush()
437444
}
438445
}
439446
} else {
440447
useUnifiedPush()
441448
}
442449
}
443450

451+
/**
452+
* Check if there is an embedded distributor, and use it if present,
453+
* else, send EventStatus PUSH_REGISTRATION with success=false
454+
*/
455+
private fun fallbackToEmbeddedUnifiedPush() {
456+
if (UnifiedPushUtils.hasEmbeddedDistributor(context)) {
457+
useEmbeddedUnifiedPush()
458+
} else {
459+
eventBus.post(EventStatus(internalAccountId, EventStatus.EventType.PUSH_REGISTRATION, false))
460+
}
461+
}
462+
463+
private fun useEmbeddedUnifiedPush() {
464+
UnifiedPushUtils.useEmbeddedDistributor(context)
465+
UnifiedPushUtils.registerWithCurrentDistributor(context)
466+
eventBus.post(EventStatus(internalAccountId, EventStatus.EventType.PUSH_REGISTRATION, true))
467+
}
468+
444469
private fun useUnifiedPush() {
445470
UnifiedPushUtils.useDefaultDistributor(this) { distrib ->
446471
distrib?.let {
@@ -449,7 +474,7 @@ class AccountVerificationActivity : BaseActivity() {
449474
eventBus.post(EventStatus(internalAccountId, EventStatus.EventType.PUSH_REGISTRATION, true))
450475
} ?: run {
451476
Log.d(TAG, "No UnifiedPush distrib selected")
452-
eventBus.post(EventStatus(internalAccountId, EventStatus.EventType.PUSH_REGISTRATION, false))
477+
fallbackToEmbeddedUnifiedPush()
453478
}
454479
}
455480
}

app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import com.nextcloud.talk.utils.ParticipantPermissions
8989
import com.nextcloud.talk.utils.ShareUtils
9090
import com.nextcloud.talk.utils.ShortcutManagerHelper
9191
import com.nextcloud.talk.utils.SpreedFeatures
92+
import com.nextcloud.talk.utils.UnifiedPushUtils
9293
import com.nextcloud.talk.utils.UserIdUtils
9394
import com.nextcloud.talk.utils.bundle.BundleKeys
9495
import com.nextcloud.talk.utils.bundle.BundleKeys.ADD_ADDITIONAL_ACCOUNT
@@ -363,7 +364,8 @@ class ConversationsListActivity : BaseActivity() {
363364
!platformPermissionUtil.isPostNotificationsPermissionGranted() &&
364365
(
365366
ClosedInterfaceImpl().isGooglePlayServicesAvailable ||
366-
appPreferences.useUnifiedPush
367+
appPreferences.useUnifiedPush ||
368+
UnifiedPushUtils.hasEmbeddedDistributor(context)
367369
)
368370
) {
369371
requestPermissions(

app/src/main/java/com/nextcloud/talk/diagnosis/DiagnosisActivity.kt

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import com.nextcloud.talk.utils.DisplayUtils
5050
import com.nextcloud.talk.utils.NotificationUtils
5151
import com.nextcloud.talk.utils.PushUtils.Companion.LATEST_PUSH_REGISTRATION_AT_PUSH_PROXY
5252
import com.nextcloud.talk.utils.PushUtils.Companion.LATEST_PUSH_REGISTRATION_AT_SERVER
53+
import com.nextcloud.talk.utils.UnifiedPushUtils
5354
import com.nextcloud.talk.utils.UserIdUtils
5455
import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
5556
import com.nextcloud.talk.utils.power.PowerManagerUtils
@@ -79,6 +80,7 @@ class DiagnosisActivity : BaseActivity() {
7980
lateinit var platformPermissionUtil: PlatformPermissionUtil
8081

8182
private var isGooglePlayServicesAvailable: Boolean = false
83+
private var useEmbeddedDistrib: Boolean = false
8284

8385
private var nUnifiedPushServices = 0
8486
private var offerUnifiedPush: Boolean = false
@@ -103,10 +105,11 @@ class DiagnosisActivity : BaseActivity() {
103105

104106
val colorScheme = viewThemeUtils.getColorScheme(this)
105107
isGooglePlayServicesAvailable = ClosedInterfaceImpl().isGooglePlayServicesAvailable
106-
nUnifiedPushServices = UnifiedPush.getDistributors(this).size
108+
nUnifiedPushServices = UnifiedPushUtils.getExternalDistributors(this).size
107109
offerUnifiedPush = nUnifiedPushServices > 0 &&
108110
userManager.users.blockingGet().all { it.hasWebPushCapability }
109111
useUnifiedPush = appPreferences.useUnifiedPush
112+
useEmbeddedDistrib = UnifiedPushUtils.hasEmbeddedDistributor(context) && !useUnifiedPush
110113
unifiedPushService = UnifiedPush.getAckDistributor(this) ?: "N/A"
111114

112115
setContent {
@@ -160,7 +163,9 @@ class DiagnosisActivity : BaseActivity() {
160163
viewState = viewState,
161164
onTestPushClick = { diagnosisViewModel.fetchTestPushResult() },
162165
onDismissDialog = { diagnosisViewModel.dismissDialog() },
163-
showTestPushButton = isGooglePlayServicesAvailable || useUnifiedPush,
166+
showTestPushButton = isGooglePlayServicesAvailable ||
167+
useUnifiedPush ||
168+
useEmbeddedDistrib,
164169
isOnline = isOnline
165170
)
166171
}
@@ -254,17 +259,27 @@ class DiagnosisActivity : BaseActivity() {
254259
value = Build.VERSION.SDK_INT.toString()
255260
)
256261

257-
if (isGooglePlayServicesAvailable) {
258-
addDiagnosisEntry(
259-
key = context.resources.getString(R.string.nc_diagnosis_gplay_available_title),
260-
value = context.resources.getString(R.string.nc_diagnosis_gplay_available_yes)
261-
)
262-
} else {
263-
addDiagnosisEntry(
264-
key = context.resources.getString(R.string.nc_diagnosis_gplay_available_title),
265-
value = context.resources.getString(R.string.nc_diagnosis_gplay_available_no_short)
266-
)
262+
when (true) {
263+
isGooglePlayServicesAvailable -> {
264+
addDiagnosisEntry(
265+
key = context.resources.getString(R.string.nc_diagnosis_gplay_available_title),
266+
value = context.resources.getString(R.string.nc_diagnosis_gplay_available_yes)
267+
)
268+
}
269+
useEmbeddedDistrib -> {
270+
addDiagnosisEntry(
271+
key = context.resources.getString(R.string.nc_diagnosis_gplay_available_title),
272+
value = context.resources.getString(R.string.nc_diagnosis_gplay_available_yes_up)
273+
)
274+
}
275+
else -> {
276+
addDiagnosisEntry(
277+
key = context.resources.getString(R.string.nc_diagnosis_gplay_available_title),
278+
value = context.resources.getString(R.string.nc_diagnosis_gplay_available_no_short)
279+
)
280+
}
267281
}
282+
268283
addDiagnosisEntry(
269284
key = getString(R.string.nc_diagnosis_unifiedpush_available_title),
270285
value = context.resources.getQuantityString(
@@ -305,7 +320,7 @@ class DiagnosisActivity : BaseActivity() {
305320
value = getStringForBoolean(useUnifiedPush)
306321
)
307322

308-
if (useUnifiedPush) {
323+
if (useUnifiedPush || useEmbeddedDistrib) {
309324
setupAppValuesForPush()
310325
setupAppValuesForUnifiedPush()
311326
} else if (isGooglePlayServicesAvailable) {

app/src/main/java/com/nextcloud/talk/jobs/PushRegistrationWorker.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class PushRegistrationWorker(context: Context, workerParams: WorkerParameters) :
102102
} else if (useUnifiedPush) {
103103
Log.d(TAG, "PushRegistrationWorker called via $origin (unifiedPushWork)")
104104
unifiedPushWork()
105+
} else if (UnifiedPushUtils.hasEmbeddedDistributor(applicationContext)) {
106+
Log.d(TAG, "PushRegistrationWorker called via $origin (unifiedPushWork#embeddedDistrib)")
107+
UnifiedPushUtils.useEmbeddedDistributor(applicationContext)
108+
unifiedPushWork()
105109
} else {
106110
Log.d(TAG, "PushRegistrationWorker called via $origin (proxyPushWork)")
107111
proxyPushWork()

app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ class SettingsActivity :
328328
}
329329

330330
private fun showUnifiedPushToggle(): Boolean =
331-
UnifiedPush.getDistributors(this).isNotEmpty() &&
331+
UnifiedPushUtils.getExternalDistributors(this).isNotEmpty() &&
332332
userManager.users.blockingGet().all { it.hasWebPushCapability }
333333

334334
private fun setupUnifiedPushSettings() {
@@ -342,7 +342,7 @@ class SettingsActivity :
342342
binding.settingsUnifiedpush.visibility = View.GONE
343343
binding.settingsUnifiedpushService.visibility = View.GONE
344344
} else {
345-
val nDistrib = UnifiedPush.getDistributors(context).size
345+
val nDistrib = UnifiedPushUtils.getExternalDistributors(context).size
346346
binding.settingsUnifiedpush.visibility = View.VISIBLE
347347
binding.settingsUnifiedpushSwitch.isChecked = appPreferences.useUnifiedPush
348348
binding.settingsUnifiedpush.setOnClickListener {
@@ -388,7 +388,10 @@ class SettingsActivity :
388388
@SuppressLint("StringFormatInvalid")
389389
@Suppress("LongMethod")
390390
private fun setupNotificationPermissionSettings() {
391-
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable || appPreferences.useUnifiedPush) {
391+
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable ||
392+
appPreferences.useUnifiedPush ||
393+
UnifiedPushUtils.hasEmbeddedDistributor(context)
394+
) {
392395
binding.settingsPushOnlyWrapper.visibility = View.VISIBLE
393396
binding.settingsGplayNotAvailable.visibility = View.GONE
394397
binding.settingsPushNotAvailable.visibility = View.GONE

app/src/main/java/com/nextcloud/talk/utils/UnifiedPushUtils.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ object UnifiedPushUtils {
9797
enqueuePushWorker(context, false, "disableExternalUnifiedPush")
9898
}
9999

100+
/**
101+
* Check if we have a FCM embedded distributor, to get push notifications,
102+
* using the Play services, using Web Push
103+
*
104+
* Available on the generic flavor only
105+
*/
106+
@JvmStatic
107+
fun hasEmbeddedDistributor(context: Context) = context.packageName in UnifiedPush.getDistributors(context)
108+
109+
@JvmStatic
110+
fun useEmbeddedDistributor(context: Context) = UnifiedPush.saveDistributor(context, context.packageName)
111+
112+
@JvmStatic
113+
fun getExternalDistributors(context: Context) =
114+
UnifiedPush.getDistributors(context).filter {
115+
it != context.packageName
116+
}
117+
100118
private fun enqueuePushWorker(context: Context, useUnifiedPush: Boolean, origin: String) {
101119
val data = Data.Builder()
102120
.putString(PushRegistrationWorker.ORIGIN, "UnifiedPushUtils#$origin")

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ How to translate with transifex:
236236
<string name="nc_diagnosis_app_users_amount" translatable="false">Registered users</string>
237237
<string name="nc_diagnosis_gplay_available_title" translatable="false">Google Play services</string>
238238
<string name="nc_diagnosis_gplay_available_yes" translatable="false">Google Play services are available</string>
239+
<string name="nc_diagnosis_gplay_available_yes_up" translatable="false">Google Play services are available, with the embedded distributor</string>
239240
<string name="nc_diagnosis_gplay_available_no" translatable="false">Google Play services are not available. Notifications are not supported</string>
240241
<string name="nc_diagnosis_gplay_available_no_short" translatable="false">Google Play services are not available.</string>
241242
<string name="nc_diagnosis_unifiedpush_available_title" translatable="false">UnifiedPush services</string>

gradle/verification-metadata.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@
278278
<trusted-key id="7F0C6700F82B97092092AFF84DA93C0B57A98B11">
279279
<trusting group="org.unifiedpush.android" name="connector" version="3.3.2"/>
280280
<trusting group="org.unifiedpush.android" name="connector" version="3.3.3"/>
281+
<trusting group="org.unifiedpush.android" name="embedded-fcm-distributor" version="3.1.0"/>
281282
</trusted-key>
282283
<trusted-key id="7F36E793AE3252E5D9E9B98FEE9E7DC9D92FC896" group="com.google.errorprone"/>
283284
<trusted-key id="8461EFA0E74ABAE010DE66994EB27DB2A3B88B8B">

0 commit comments

Comments
 (0)