Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use dataSync service on receiving FCM notifications #3312

Merged
merged 9 commits into from
Sep 23, 2024
6 changes: 6 additions & 0 deletions jni/dc_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@ JNIEXPORT void Java_com_b44t_messenger_DcAccounts_setPushDeviceToken(JNIEnv *env
}


JNIEXPORT jboolean Java_com_b44t_messenger_DcAccounts_backgroundFetch(JNIEnv *env, jobject obj, jint timeout_seconds)
{
return dc_accounts_background_fetch(get_dc_accounts(env, obj), timeout_seconds) != 0;
}


JNIEXPORT jint Java_com_b44t_messenger_DcAccounts_addAccount(JNIEnv *env, jobject obj)
{
return dc_accounts_add_account(get_dc_accounts(env, obj));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.service.FetchForegroundService;
import org.thoughtcrime.securesms.util.Util;

public class FcmReceiveService extends FirebaseMessagingService {
Expand Down Expand Up @@ -92,12 +92,15 @@ public static String getToken() {
return prefixedToken;
}

@WorkerThread
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
Log.i(TAG, "FCM push notification received");
// the app is running (again) now and fetching and notifications should be processed as usual.
// to support accounts that do not send PUSH notifications and for simplicity,
// we just let the app run as long as possible.
FetchForegroundService.start(this);
if (!ApplicationContext.dcAccounts.backgroundFetch(19)) { // we should complete within 20 seconds
r10s marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this call be moved inside the FetchForegroundService?

Otherwise it seems we create a FetchForegroundService that does nothing except showing a notification, but then immediately start fetching messages.

If starting FetchForegroundService takes some time or somehow fails then we fetch the messages without the service actually starting and may not have network access yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i abandoned the idea initially, as it requires an additional worker thread in FetchForegroundService.onCreate() - whereas FcmReceiveService.onMessageReceived() already arrives from a worker thread. and for "just running" code, that seems fine.

If starting FetchForegroundService takes some time or somehow fails then we fetch the messages without the service actually starting and may not have network access yet.

not having internet or being killed too soon indeed is a strong argument, so thanks for the pointer, i added a commit.

it is indeed cleaner and more logical that way - and also when it comes to other push handlers, it is good to have things more concentrated in once class

FetchForegroundService.stop(this);
}
Log.i(TAG, "background fetch done");
}

@Override
Expand Down
4 changes: 4 additions & 0 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@
android:name=".service.GenericForegroundService"
android:foregroundServiceType="dataSync" />

<service
android:name=".service.FetchForegroundService"
android:foregroundServiceType="dataSync" />

<service
android:name=".service.IPCAddAccountsService"
android:foregroundServiceType="dataSync"
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/b44t/messenger/DcAccounts.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public void unref() {
public native void stopIo ();
public native void maybeNetwork ();
public native void setPushDeviceToken (String token);
public native boolean backgroundFetch (int timeoutSeconds);

public native int addAccount ();
public native int migrateAccount (String dbfile);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/b44t/messenger/DcContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class DcContext {
public final static int DC_EVENT_WEBXDC_STATUS_UPDATE = 2120;
public final static int DC_EVENT_WEBXDC_INSTANCE_DELETED = 2121;
public final static int DC_EVENT_WEBXDC_REALTIME_DATA = 2150;
public final static int DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE = 2200;

public final static int DC_IMEX_EXPORT_SELF_KEYS = 1;
public final static int DC_IMEX_IMPORT_SELF_KEYS = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.service.FetchForegroundService;
import org.thoughtcrime.securesms.util.Util;

import java.util.ArrayList;
Expand Down Expand Up @@ -177,6 +178,10 @@ public long handleEvent(@NonNull DcEvent event) {
DcHelper.getNotificationCenter(context).removeNotifications(accountId, event.getData1Int());
break;

case DcContext.DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE:
FetchForegroundService.stop(context);
r10s marked this conversation as resolved.
Show resolved Hide resolved
break;

case DcContext.DC_EVENT_IMEX_PROGRESS:
sendToCurrentAccountObservers(event);
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ private PendingIntent getMarkAsReadIntent(ChatData chatData, int msgId, boolean
public static final int ID_PERMANENT = 1;
public static final int ID_MSG_SUMMARY = 2;
public static final int ID_GENERIC = 3;
public static final int ID_FETCH = 4;
public static final int ID_MSG_OFFSET = 0; // msgId is added - as msgId start at 10, there are no conflicts with lower numbers


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.thoughtcrime.securesms.service;

import android.app.Notification;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;

import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.notifications.NotificationCenter;

public final class FetchForegroundService extends Service {
private static final Object SERVICE_LOCK = new Object();
private static Intent service;

public static void start(Context context) {
GenericForegroundService.createFgNotificationChannel(context);
synchronized (SERVICE_LOCK) {
if (service == null) {
service = new Intent(context, FetchForegroundService.class);
ContextCompat.startForegroundService(context, service);
}
}
}

public static void stop(Context context) {
synchronized (SERVICE_LOCK) {
if (service != null) {
context.stopService(service);
service = null;
}
}
}

@Override
public void onCreate() {
super.onCreate();

Notification notification = new NotificationCompat.Builder(this, NotificationCenter.CH_GENERIC)
.setContentTitle(getString(R.string.connectivity_updating))
.setSmallIcon(R.drawable.notification_permanent)
.build();

startForeground(NotificationCenter.ID_FETCH, notification);
}

@Override
public void onDestroy() {
stopForeground(true);
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ synchronized void replaceProgress(int id, int progressMax, int progress, boolean
}

@TargetApi(Build.VERSION_CODES.O)
static private void createFgNotificationChannel(Context context) {
static public void createFgNotificationChannel(Context context) {
if(!CHANNEL_CREATED.get() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CHANNEL_CREATED.set(true);
NotificationChannel channel = new NotificationChannel(NotificationCenter.CH_GENERIC,
Expand Down
Loading