Как получить данные, отправленные с сервера с помощью fcm, если приложение находится в фоновом режиме?

Я отправляю fcm-уведомления в свое приложение с сервера.

Я отправляю данные с сервера, который содержит user_id. Я получаю этот userId в классе FirebaseMessageService, если приложение находится на переднем плане. Но не получать его, когда приложение находится в фоновом режиме. Поскольку класс FirebaseMessagingService запускается только тогда, когда приложение находится на переднем плане.

Итак, как я могу получить этот идентификатор, когда приложение находится в фоновом режиме?

    public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMsgService";
    private String mUserId;
    private Boolean mUpdateNotification;

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        //Displaying data in log
        //It is optional
        Log.d(TAG, "From: " + remoteMessage.getFrom());
        Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());

        String clickAction = remoteMessage.getNotification().getClickAction();

        mUserId = remoteMessage.getData().get("user_id");

        String title = remoteMessage.getNotification().getTitle();

        //Calling method to generate notification
        sendNotification(remoteMessage.getNotification().getBody(),clickAction,title);
    }

    //This method is only generating push notification
    //It is same as we did in earlier posts
    private void sendNotification(String messageBody,String clickAction,String title) {

        mUpdateNotification = true;

        Intent intent = new Intent(clickAction);

        intent.putExtra("userId",mUserId);
        intent.putExtra("updateNotification",mUpdateNotification);

        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle(title)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0, notificationBuilder.build());
    }
}

EDIT:

Я использую полезную нагрузку данных еще наMessageReceived доза не вызывается, когда приложение находится в фоновом режиме.

 public function sendPush($text, $tokens, $apiKey,$user_id)
{

    $notification = array(
        "title" => "User updated profile.",
        "text" => $text,
        'vibrate' => 3,
        "click_action" => "OPEN_ACTIVITY_2",
        'sound' => "default",
        'user_id' => $user_id
    );

    $data = array("user_id" => $user_id);

    $msg = array
    (
        'message' => $text,
        'title' => 'User updated profile.',
        'tickerText' => 'New Message',
    );
    $fields = array
    (
        'to' => $tokens,
        'data' => $data,
        'notification' => $notification
    );

    $headers = array
    (
        'Authorization: key=' . $apiKey,
        'Content-Type: application/json'
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));

    $result = curl_exec($ch);
    //  echo($result);
    //    return $result;
    curl_close($ch);
}

Может ли кто-нибудь помочь с этим, пожалуйста? Спасибо..

Ответ 1

Я вижу. В вашей полезной нагрузке вы используете как полезную нагрузку notification, так и data, которая изменяется там, где вы должны получать данные, когда приложение находится в фоновом режиме. В doc, о котором я упоминал в комментариях, вы можете увидеть в сводке, если оба включены в полезную нагрузку:

Данные: в дополнение к намерению.

Более конкретно:

Отправлять уведомления в фоновом приложении

Когда ваше приложение находится в фоновом режиме, Android направляет уведомления на системный трей. Пользователь по нажатию на уведомление открывает панель запуска приложения по умолчанию.

Это включает сообщения, содержащие как полезную нагрузку уведомлений и данных (и все сообщения, отправленные с консоли уведомлений). В этих случаях уведомление доставляется на системный лоток устройства, а полезная нагрузка данных доставляется в дополнение к цели вашей активности запуска.

Я думаю, что этот ответ от @ArthurThompson очень хорошо объясняет:

Когда вы отправляете сообщение уведомления с полезной нагрузкой (уведомлением и данными), а приложение находится в фоновом режиме, вы можете получить данные из дополнительных функций намерения, которые запускаются в результате нажатия пользователем уведомления.

Из образец FCM, который запускает MainActivity при прослушивании уведомления:

if (getIntent().getExtras() != null) {
    for (String key : getIntent().getExtras().keySet()) {
        String value = getIntent().getExtras().getString(key);
        Log.d(TAG, "Key: " + key + " Value: " + value);
    }
}

Ответ 2

Зарегистрируйте свою службу в манифесте

    <service android:name=".MyFirebaseMessagingService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    <service android:name=".MyFirebaseInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service> 

вы можете проверить, что приложение находится в Foreground или нет

    public static boolean CheckAppIsRunningForground(Context mcontext) {

    ActivityManager am = (ActivityManager) mcontext
            .getSystemService(mcontext.ACTIVITY_SERVICE);

    // get the info from the currently running task
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);

    ComponentName componentInfo = taskInfo.get(0).topActivity;
    if (componentInfo.getPackageName().equalsIgnoreCase(<YOUR PACKAGE>)) {
        return true;
    } else {
        return false;
    }

}

и добавьте этот код внутри onMessageReceived

    Boolean IsForground = CheckAppIsRunningForground(AgentService.this);
    if (IsForground) {

                  //App is FourGround

                } else {
                     sendNotification(remoteMessage.getNotification().getBody(),clickAction,title);
                }