Skip to content

Commit 34092c9

Browse files
p1gp1gvalldrac
authored andcommitted
UnifiedPush
1 parent aa747c0 commit 34092c9

35 files changed

Lines changed: 1211 additions & 14 deletions

app/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ android {
134134
androidTest {
135135
java.srcDirs += "$projectDir/src/testShared"
136136
}
137+
138+
main {
139+
java.srcDirs += "$projectDir/src/unifiedpush/java"
140+
}
137141
}
138142

139143
compileOptions {
@@ -448,6 +452,8 @@ dependencies {
448452
implementation libs.androidx.asynclayoutinflater.appcompat
449453
implementation libs.androidx.webkit
450454

455+
implementation 'com.github.UnifiedPush:android-connector:2.1.1'
456+
451457
gmsImplementation (libs.firebase.messaging) {
452458
exclude group: 'com.google.firebase', module: 'firebase-core'
453459
exclude group: 'com.google.firebase', module: 'firebase-analytics'

app/proguard/proguard.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
-keep class org.whispersystems.** { *; }
44
-keep class org.signal.libsignal.protocol.** { *; }
55
-keep class org.thoughtcrime.securesms.** { *; }
6+
-keep class im.molly.unifiedpush.** { *; }
67
-keepclassmembers class ** {
78
public void onEvent*(**);
89
}

app/src/main/AndroidManifest.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,15 @@
12601260
android:enabled="@bool/enable_alarm_manager"
12611261
android:exported="false"/>
12621262

1263+
<receiver android:exported="true" android:enabled="true" android:name="im.molly.unifiedpush.receiver.UnifiedPushReceiver">
1264+
<intent-filter>
1265+
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>
1266+
<action android:name="org.unifiedpush.android.connector.UNREGISTERED"/>
1267+
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT"/>
1268+
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED"/>
1269+
</intent-filter>
1270+
</receiver>
1271+
12631272
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
12641273

12651274
</application>

app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,15 @@
110110
import org.thoughtcrime.securesms.util.Util;
111111
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
112112

113+
import im.molly.unifiedpush.util.UnifiedPushHelper;
113114
import java.net.SocketException;
114115
import java.net.SocketTimeoutException;
115116
import java.security.Security;
116117
import java.util.HashMap;
117118
import java.util.Map;
118119
import java.util.concurrent.TimeUnit;
119120

121+
import im.molly.unifiedpush.jobs.UnifiedPushRefreshJob;
120122
import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException;
121123
import io.reactivex.rxjava3.exceptions.UndeliverableException;
122124
import io.reactivex.rxjava3.plugins.RxJavaPlugins;
@@ -468,14 +470,19 @@ private void initializeNetworkSettings() {
468470
}
469471
}
470472

471-
private void initializeFcmCheck() {
473+
public void initializeFcmCheck() {
472474
if (!SignalStore.account().isRegistered()) {
473475
return;
474476
}
475477

476478
PlayServicesUtil.PlayServicesStatus fcmStatus = PlayServicesUtil.getPlayServicesStatus(this);
477479

478-
if (fcmStatus == PlayServicesUtil.PlayServicesStatus.DISABLED) {
480+
if (UnifiedPushHelper.isUnifiedPushAvailable()
481+
|| fcmStatus == PlayServicesUtil.PlayServicesStatus.DISABLED) {
482+
if (!SignalStore.unifiedpush().getAirGaped()) {
483+
ApplicationDependencies.getJobManager().add(new UnifiedPushRefreshJob());
484+
}
485+
ApplicationDependencies.getJobManager().cancel(new FcmRefreshJob().getId());
479486
if (SignalStore.account().isFcmEnabled()) {
480487
Log.i(TAG, "Play Services are disabled. Disabling FCM.");
481488
SignalStore.account().setFcmEnabled(false);
@@ -490,10 +497,12 @@ private void initializeFcmCheck() {
490497
SignalStore.account().getFcmTokenLastSetTime() < 0) {
491498
Log.i(TAG, "Play Services are newly-available. Updating to use FCM.");
492499
SignalStore.account().setFcmEnabled(true);
500+
ApplicationDependencies.getJobManager().cancel(new UnifiedPushRefreshJob().getId());
493501
ApplicationDependencies.getJobManager().startChain(new FcmRefreshJob())
494502
.then(new RefreshAttributesJob())
495503
.enqueue();
496504
} else {
505+
ApplicationDependencies.getJobManager().cancel(new UnifiedPushRefreshJob().getId());
497506
long nextSetTime = SignalStore.account().getFcmTokenLastSetTime() + TimeUnit.HOURS.toMillis(6);
498507

499508
if (SignalStore.account().getFcmToken() == null || nextSetTime <= System.currentTimeMillis()) {

app/src/main/java/org/thoughtcrime/securesms/components/reminder/DozeReminder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.thoughtcrime.securesms.util.PowerManagerCompat;
1818
import org.thoughtcrime.securesms.util.TextSecurePreferences;
1919

20+
import im.molly.unifiedpush.util.UnifiedPushHelper;
21+
2022
@SuppressLint("BatteryLife")
2123
public class DozeReminder extends Reminder {
2224

@@ -34,6 +36,7 @@ public DozeReminder(@NonNull final Context context) {
3436
public static boolean isEligible(Context context) {
3537
return !SignalStore.account().isFcmEnabled() &&
3638
!TextSecurePreferences.hasPromptedOptimizeDoze(context) &&
39+
!UnifiedPushHelper.isUnifiedPushAvailable() &&
3740
!((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isIgnoringBatteryOptimizations(context.getPackageName());
3841
}
3942

app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsFragment.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.components.settings.PreferenceViewHolder
2929
import org.thoughtcrime.securesms.components.settings.RadioListPreference
3030
import org.thoughtcrime.securesms.components.settings.RadioListPreferenceViewHolder
3131
import org.thoughtcrime.securesms.components.settings.configure
32+
import org.thoughtcrime.securesms.keyvalue.SettingsValues.NotificationDeliveryMethod
3233
import org.thoughtcrime.securesms.keyvalue.SignalStore
3334
import org.thoughtcrime.securesms.notifications.NotificationChannels
3435
import org.thoughtcrime.securesms.util.RingtoneUtil
@@ -59,6 +60,11 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__
5960
private val ledBlinkValues by lazy { resources.getStringArray(R.array.pref_led_blink_pattern_values) }
6061
private val ledBlinkLabels by lazy { resources.getStringArray(R.array.pref_led_blink_pattern_entries) }
6162

63+
private val notificationMethodValues = NotificationDeliveryMethod.values().filterNot {
64+
!SignalStore.account().fcmEnabled && it == NotificationDeliveryMethod.FCM
65+
}
66+
private val notificationMethodLabels by lazy { notificationMethodValues.map { resources.getString(it.getStringId()) }.toTypedArray() }
67+
6268
private lateinit var viewModel: NotificationsSettingsViewModel
6369

6470
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@@ -259,6 +265,28 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__
259265
viewModel.setNotifyWhenContactJoinsSignal(!state.notifyWhenContactJoinsSignal)
260266
}
261267
)
268+
269+
dividerPref()
270+
271+
sectionHeaderPref(R.string.NotificationsSettingsFragment__pushStrategy)
272+
273+
radioListPref(
274+
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__deliveryMethod),
275+
listItems = notificationMethodLabels,
276+
selected = notificationMethodValues.indexOf(state.notificationDeliveryMethod),
277+
onSelected = {
278+
viewModel.setNotificationDeliveryMethod(notificationMethodValues[it])
279+
}
280+
)
281+
282+
clickPref(
283+
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__unifiedpush),
284+
summary = DSLSettingsText.from(R.string.NotificationsSettingsFragment__unifiedpushDescription),
285+
isEnabled = state.notificationDeliveryMethod == NotificationDeliveryMethod.UNIFIEDPUSH,
286+
onClick = {
287+
findNavController().safeNavigate(R.id.action_notificationsSettingsFragment_to_unifiedPushFragment)
288+
}
289+
)
262290
}
263291
}
264292

app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsState.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.thoughtcrime.securesms.components.settings.app.notifications
22

33
import android.net.Uri
4+
import org.thoughtcrime.securesms.keyvalue.SettingsValues.NotificationDeliveryMethod
45

56
data class NotificationsSettingsState(
67
val messageNotificationsState: MessageNotificationsState,
78
val callNotificationsState: CallNotificationsState,
8-
val notifyWhenContactJoinsSignal: Boolean
9+
val notifyWhenContactJoinsSignal: Boolean,
10+
val notificationDeliveryMethod: NotificationDeliveryMethod
911
)
1012

1113
data class MessageNotificationsState(

app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/NotificationsSettingsViewModel.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@ import android.net.Uri
55
import androidx.lifecycle.LiveData
66
import androidx.lifecycle.ViewModel
77
import androidx.lifecycle.ViewModelProvider
8+
9+
import im.molly.unifiedpush.util.UnifiedPushHelper
10+
import org.signal.core.util.concurrent.SignalExecutors
11+
import org.thoughtcrime.securesms.ApplicationContext
812
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
13+
import org.thoughtcrime.securesms.keyvalue.SettingsValues.NotificationDeliveryMethod
914
import org.thoughtcrime.securesms.keyvalue.SignalStore
1015
import org.thoughtcrime.securesms.notifications.NotificationChannels
1116
import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference
1217
import org.thoughtcrime.securesms.util.TextSecurePreferences
18+
import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor
1319
import org.thoughtcrime.securesms.util.livedata.Store
20+
import org.unifiedpush.android.connector.UnifiedPush
1421

1522
class NotificationsSettingsViewModel(private val sharedPreferences: SharedPreferences) : ViewModel() {
1623

@@ -24,6 +31,7 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer
2431
private val store = Store(getState())
2532

2633
val state: LiveData<NotificationsSettingsState> = store.stateLiveData
34+
private val EXECUTOR = SerialMonoLifoExecutor(SignalExecutors.UNBOUNDED)
2735

2836
fun setMessageNotificationsEnabled(enabled: Boolean) {
2937
SignalStore.settings().isMessageNotificationsEnabled = enabled
@@ -94,6 +102,29 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer
94102
store.update { getState() }
95103
}
96104

105+
fun setNotificationDeliveryMethod(method: NotificationDeliveryMethod) {
106+
SignalStore.settings().notificationDeliveryMethod = method
107+
SignalStore.unifiedpush().enabled = method == NotificationDeliveryMethod.UNIFIEDPUSH
108+
SignalStore.internalValues().isWebsocketModeForced = method == NotificationDeliveryMethod.WEBSOCKET
109+
val context = ApplicationContext.getInstance()
110+
if (method == NotificationDeliveryMethod.UNIFIEDPUSH) {
111+
UnifiedPush.getDistributors(context).getOrNull(0)?.let {
112+
store.update { getState() }
113+
EXECUTOR.enqueue {
114+
UnifiedPush.saveDistributor(context, it)
115+
UnifiedPush.registerApp(context)
116+
UnifiedPushHelper.initializeMollySocketLinkedDevice(context)
117+
}
118+
// Do not enable if there is no distributor
119+
} ?: return
120+
} else {
121+
UnifiedPush.unregisterApp(context)
122+
SignalStore.unifiedpush().airGaped = false
123+
SignalStore.unifiedpush().mollySocketUrl = null
124+
}
125+
store.update { getState() }
126+
}
127+
97128
private fun getState(): NotificationsSettingsState = NotificationsSettingsState(
98129
messageNotificationsState = MessageNotificationsState(
99130
notificationsEnabled = SignalStore.settings().isMessageNotificationsEnabled,
@@ -111,7 +142,8 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer
111142
ringtone = SignalStore.settings().callRingtone,
112143
vibrateEnabled = SignalStore.settings().isCallVibrateEnabled
113144
),
114-
notifyWhenContactJoinsSignal = SignalStore.settings().isNotifyWhenContactJoinsSignal
145+
notifyWhenContactJoinsSignal = SignalStore.settings().isNotifyWhenContactJoinsSignal,
146+
notificationDeliveryMethod = SignalStore.settings().notificationDeliveryMethod
115147
)
116148

117149
class Factory(private val sharedPreferences: SharedPreferences) : ViewModelProvider.Factory {

app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
import java.util.concurrent.TimeUnit;
100100
import java.util.function.Supplier;
101101

102+
import im.molly.unifiedpush.util.UnifiedPushHelper;
103+
102104
/**
103105
* Implementation of {@link ApplicationDependencies.Provider} that provides real app dependencies.
104106
*/
@@ -285,7 +287,7 @@ public ApplicationDependencyProvider(@NonNull Application context) {
285287

286288
@Override
287289
public @NonNull SignalWebSocket provideSignalWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier) {
288-
SleepTimer sleepTimer = !SignalStore.account().isFcmEnabled() || SignalStore.internalValues().isWebsocketModeForced() ? new AlarmSleepTimer(context) : new UptimeSleepTimer() ;
290+
SleepTimer sleepTimer = !UnifiedPushHelper.isPushAvailable() || SignalStore.internalValues().isWebsocketModeForced() ? new AlarmSleepTimer(context) : new UptimeSleepTimer() ;
289291
SignalWebSocketHealthMonitor healthMonitor = new SignalWebSocketHealthMonitor(context, sleepTimer);
290292
SignalWebSocket signalWebSocket = new SignalWebSocket(provideWebSocketFactory(signalServiceConfigurationSupplier, healthMonitor));
291293

app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public void onSendError(@NonNull String s, @NonNull Exception e) {
8888
Log.w(TAG, "onSendError()", e);
8989
}
9090

91-
private static void handleReceivedNotification(Context context, @Nullable RemoteMessage remoteMessage) {
91+
public static void handleReceivedNotification(Context context, @Nullable RemoteMessage remoteMessage) {
9292
boolean highPriority = remoteMessage != null && remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH;
9393
try {
9494
Log.d(TAG, String.format(Locale.US, "[handleReceivedNotification] API: %s, RemoteMessagePriority: %s", Build.VERSION.SDK_INT, remoteMessage != null ? remoteMessage.getPriority() : "n/a"));

0 commit comments

Comments
 (0)