简体   繁体   中英

Call method in a running activity from a service

I am currently working on a Android project.

So far, I have implemented Firebase, in particular the FirebaseInstanceIdService and the FirebaseMessagingService:

public class FirebaseIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseIDService";

private Context context;

@Override
public void onTokenRefresh() {
    context = getApplicationContext();
    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    Log.e(TAG, "Refreshed token: " + refreshedToken);

    SharedPreferences sharedPreferences = context.getSharedPreferences("token", context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString("token", refreshedToken);
    editor.commit();

    sendRegistrationToServer(refreshedToken);
}

/**
 * Persist token to backend.
 * @param token The new token.
 */
private void sendRegistrationToServer(String token) {
    SendRegistrationKey task = new SendRegistrationKey(context);
    task.execute(token);
}

}

public class MessagingService extends FirebaseMessagingService {

private static final String TAG = "MsgService";

/**
 * Called when message is received.
 *
 * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
 */
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.e(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.e(TAG, "Message data payload: " + remoteMessage.getData());
    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.e(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());

        sendNotification(remoteMessage);
    }

    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
}
// [END receive_message]

private void sendNotification(RemoteMessage remoteMessage) {
    RemoteMessage.Notification notification = remoteMessage.getNotification();
    PushNotificationManager PNManager = PushNotificationManager.getInstance(getApplicationContext());
    PNManager.buildNotification(notification.getTitle(), notification.getBody());
}

What I want to achieve is the following:

When the App is in background, I just want to have a simple notification in the notification center. (This is already working)

BUT, when the app is in foreground and currently running, I want to have a different behaviour: I want to consume the push notification and show an alert instead.

But my question is: how can I interact with the running activity from the service or what is the correct way to achieve the intended behaviour? Ther must be a simple soultion, right?

Thanks in advance

write this code in application class

 public Context currentactvity = null;
public Context getCurrentactvity() {
    return currentactvity;
}

public void setCurrentactvity(Context currentactvity) {
    this.currentactvity = currentactvity;
}

write this code in each activity onresume method and in onpause method set null

 // in onresume
MyApplication.getInstance().setCurrentactvity(this);

// in onpause
MyApplication.getInstance().setCurrentactvity(null);

now you can call activity method from service class

  if (MyApplication.getInstance().getCurrentactvity() != null && MyApplication.getInstance().getCurrentactvity() instanceof youractivityname) {
            ((youractivityname) MyApplication.getInstance().getCurrentactvity()).youmethodname(parameter);

        }

how can I interact with the running activity from the service or what is the correct way to achieve the intended behaviour?

The best way would be simply to use Event Bus (ie GreenRobot's or local broadcast ). Your activity registers listener in onResume() (and deregisters in onPause() ) and your service simply broadcasts the message when times comes.

The main benefit is that you keep both elements (service and activity) completely separated. You also avoid worst possible solution - calling Activity's methods directly.

To find out when you are in background or not, it's best to utilis Application's GreenRobot's ActivityLifecycleCallbacks - there's no point of forcing activities to report that as there's completely no benefit from that.

try with this:

This method check for all running apps, and return true or false whether current app is in background state or in foreground state.

    public static boolean isAppIsInBackground(Context context) {
        boolean isInBackground = true;
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
            List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
                if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    for (String activeProcess : processInfo.pkgList) {
                        if (activeProcess.equals(context.getPackageName())) {
                            isInBackground = false;
                        }
                    }
                }
            }
        } else {
            List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
            ComponentName componentInfo = taskInfo.get(0).topActivity;
            if (componentInfo.getPackageName().equals(context.getPackageName())) {
                isInBackground = false;
            }
        }

        return isInBackground;
    }

Try

1. Register custom broadcast receiver in your activity

context.registerReceiver (myBroadcastReceiver, new IntentFilter ("CUSTOM_ACTION"));
private final BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver () {

    @Override
    public void onReceive (Context context, Intent intent) {

        //Do something
    }
};

2. Send broadcast from your service

Intent intent = new Intent ("CUSTOM_ACTION");
context.sendBroadcast (intent)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM