Use foreground services to process notification when appropriate.
Right now, the only condition is once every 3 minutes on Android 12. This is ok because Android 12 will allow us (once every 2 minutes or so) to start a foreground service, and it won't show it for the first 10 seconds. So we can kind of do it without any visual penalty.
This commit is contained in:
parent
8cfc013960
commit
e09ce4c820
4 changed files with 54 additions and 6 deletions
|
@ -1,5 +1,6 @@
|
|||
package org.thoughtcrime.securesms.gcm;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -8,15 +9,21 @@ import android.os.IBinder;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.MainActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
|
||||
import org.thoughtcrime.securesms.messages.BackgroundMessageRetriever;
|
||||
import org.thoughtcrime.securesms.messages.RestStrategy;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationIds;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -43,10 +50,18 @@ public class FcmFetchService extends Service {
|
|||
|
||||
private static final String TAG = Log.tag(FcmFetchService.class);
|
||||
|
||||
static final String KEY_FOREGROUND = "is_foreground";
|
||||
|
||||
private static final SerialMonoLifoExecutor EXECUTOR = new SerialMonoLifoExecutor(SignalExecutors.UNBOUNDED);
|
||||
|
||||
private final AtomicInteger activeCount = new AtomicInteger(0);
|
||||
|
||||
public static @NonNull Intent buildIntent(@NonNull Context context, boolean foreground) {
|
||||
Intent intent = new Intent(context, FcmFetchService.class);
|
||||
intent.putExtra(KEY_FOREGROUND, foreground);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
boolean performedReplace = EXECUTOR.enqueue(this::fetch);
|
||||
|
@ -58,6 +73,18 @@ public class FcmFetchService extends Service {
|
|||
Log.i(TAG, "Incrementing active count to " + count);
|
||||
}
|
||||
|
||||
if (intent.getBooleanExtra(KEY_FOREGROUND, false)) {
|
||||
Log.i(TAG, "Launching in the foreground.");
|
||||
startForeground(NotificationIds.FCM_FETCH, new NotificationCompat.Builder(this, NotificationChannels.OTHER)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle(getString(R.string.BackgroundMessageRetriever_checking_for_messages))
|
||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
.setProgress(0, 0, true)
|
||||
.setContentIntent(PendingIntent.getActivity(this, 0, MainActivity.clearTop(this), 0))
|
||||
.setVibrate(new long[] { 0 })
|
||||
.build());
|
||||
}
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,11 @@ package org.thoughtcrime.securesms.gcm;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
|
@ -16,11 +19,13 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
|||
import org.thoughtcrime.securesms.registration.PushChallengeRequest;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class FcmReceiveService extends FirebaseMessagingService {
|
||||
|
||||
private static final String TAG = Log.tag(FcmReceiveService.class);
|
||||
|
||||
private static final long FCM_FOREGROUND_INTERVAL = TimeUnit.MINUTES.toMillis(3);
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
|
@ -38,15 +43,15 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
|||
handleRegistrationPushChallenge(registrationChallenge);
|
||||
} else if (rateLimitChallenge != null) {
|
||||
handleRateLimitPushChallenge(rateLimitChallenge);
|
||||
}else {
|
||||
handleReceivedNotification(ApplicationDependencies.getApplication());
|
||||
} else {
|
||||
handleReceivedNotification(ApplicationDependencies.getApplication(), remoteMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeletedMessages() {
|
||||
Log.w(TAG, "onDeleteMessages() -- Messages may have been dropped. Doing a normal message fetch.");
|
||||
handleReceivedNotification(ApplicationDependencies.getApplication());
|
||||
handleReceivedNotification(ApplicationDependencies.getApplication(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,11 +76,17 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
|||
Log.w(TAG, "onSendError()", e);
|
||||
}
|
||||
|
||||
private static void handleReceivedNotification(Context context) {
|
||||
private static void handleReceivedNotification(Context context, @Nullable RemoteMessage remoteMessage) {
|
||||
try {
|
||||
context.startService(new Intent(context, FcmFetchService.class));
|
||||
long timeSinceLastRefresh = System.currentTimeMillis() - SignalStore.misc().getLastFcmForegroundServiceTime();
|
||||
if (Build.VERSION.SDK_INT >= 31 && remoteMessage != null && remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH && timeSinceLastRefresh > FCM_FOREGROUND_INTERVAL) {
|
||||
ContextCompat.startForegroundService(context, FcmFetchService.buildIntent(context, true));
|
||||
SignalStore.misc().setLastFcmForegroundServiceTime(System.currentTimeMillis());
|
||||
} else {
|
||||
context.startService(FcmFetchService.buildIntent(context, false));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Failed to start service. Falling back to legacy approach.");
|
||||
Log.w(TAG, "Failed to start service. Falling back to legacy approach.", e);
|
||||
FcmFetchService.retrieveMessages(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public final class MiscellaneousValues extends SignalStoreValues {
|
|||
private static final String CENSORSHIP_SERVICE_REACHABLE = "misc.censorship.service_reachable";
|
||||
private static final String LAST_GV2_PROFILE_CHECK_TIME = "misc.last_gv2_profile_check_time";
|
||||
private static final String CDS_TOKEN = "misc.cds_token";
|
||||
private static final String LAST_FCM_FOREGROUND_TIME = "misc.last_fcm_foreground_time";
|
||||
|
||||
MiscellaneousValues(@NonNull KeyValueStore store) {
|
||||
super(store);
|
||||
|
@ -149,4 +150,12 @@ public final class MiscellaneousValues extends SignalStoreValues {
|
|||
.putBlob(CDS_TOKEN, token)
|
||||
.commit();
|
||||
}
|
||||
|
||||
public long getLastFcmForegroundServiceTime() {
|
||||
return getLong(LAST_FCM_FOREGROUND_TIME, 0);
|
||||
}
|
||||
|
||||
public void setLastFcmForegroundServiceTime(long time) {
|
||||
putLong(LAST_FCM_FOREGROUND_TIME, time);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public final class NotificationIds {
|
|||
public static final int USER_NOTIFICATION_MIGRATION = 525600;
|
||||
public static final int DEVICE_TRANSFER = 625420;
|
||||
public static final int DONOR_BADGE_FAILURE = 630001;
|
||||
public static final int FCM_FETCH = 630002;
|
||||
|
||||
private NotificationIds() { }
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue