it-swarm.com.ru

Firebase (FCM): открыть действие и передать данные по щелчку уведомления. андроид

Должна быть четкая реализация того, как работать с уведомлениями и данными Firebase. Я прочитал много ответов, но не могу заставить его работать. вот мои шаги:

1.) Я передаю уведомление и данные на Android в PHP, и, похоже, все в порядке:

$msg = array
    (
         "body" => $body,
         "title" => $title,
         "sound" => "mySound"
    );

    $data = array
    (

         "user_id" => $res_id,
         "date" => $date,
         "hal_id" => $hal_id,
         "M_view" => $M_view
    );

    $fields = array
    (
        'registration_ids' => $registrationIds,
        'notification' => $msg,
        'data' => $data
    );



    $headers = array
    (
        'Authorization: key='.API_ACCESS_KEY,
        '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 );
    curl_close( $ch );

2.) когда уведомление и данные получены в Android, это показывает уведомление. Когда я нажимаю на это уведомление, открывается приложение. Но я не могу понять, как обрабатывать данные, когда приложение открыто. Есть пара различий, когда приложение находится на переднем и заднем плане. Код, который у меня есть сейчас, следующий: 

public class MyFirebaseMessagingService extends FirebaseMessagingService {

private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    String user_id = "0";
    String date = "0";
    String cal_id = "0";
    String M_view = "0";

    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        user_id = remoteMessage.getData().get("user_id");
        date = remoteMessage.getData().get("date");
        hal_id = remoteMessage.getData().get("hal_id");
        M_view = remoteMessage.getData().get("M_view");
    }

    //Calling method to generate notification
    sendNotification(remoteMessage.getNotification().getBody(), user_id, date, hal_id, M_view);
}

private void sendNotification(String messageBody, String user_id, String date, String hal_id, String M_view) {
    Intent intent = new Intent(this, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

    intent.putExtra("fcm_notification", "Y");
    intent.putExtra("user_id", user_id);
    intent.putExtra("date", date);
    intent.putExtra("hal_id", hal_id);
    intent.putExtra("M_view", M_view);
    int uniqueInt = (int) (System.currentTimeMillis() & 0xff);
    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

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

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notificationBuilder.build());
}}

3.) Когда я использую код выше и когда я нажимаю на уведомление все, что он делает, он открывает приложение, если в фоновом режиме. Если приложение на переднем плане, то при нажатии на уведомление оно просто отклоняет уведомление. Тем не менее, я хочу получать данные и открывать конкретные действия в обоих сценариях (фон и передний план). У меня в MainActivity следующий код, но я не могу получить данные. fcm_notification, date, hal_id возвращает ноль.

public class MainActivity extends Activity {
 UserFunctions userFunctions;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
    Intent intent_o = getIntent();
}

@Override
protected void onResume() {
    super.onResume();
    userFunctions = new UserFunctions();
    if(userFunctions.isUserLoggedIn(getApplicationContext())){
        Intent intent_o = getIntent();
        String fcm_notification = intent_o.getStringExtra("fcm_notification") ;
        String user_id = intent_o.getStringExtra("user_id");
        String date = intent_o.getStringExtra("date");
        String hal_id = intent_o.getStringExtra("hal_id");
        String M_view = intent_o.getStringExtra("M_view");
        Intent intent = new Intent(this, JobList.class);

        // THIS RETURNS NULL, user_id = null
        System.out.print("FCM" + user_id);
        startActivity(intent);
        finish();
    }else{
        // user is not logged in show login screen
        Intent login = new Intent(this, LoginActivity.class);
        startActivity(login);
        // Closing dashboard screen
        finish();
    }
}}

ЕСЛИ кто-то может направить или посоветовать, как я могу получить данные в MainActivity.Java из Firebase в любом сценарии (на переднем или на заднем плане), это было бы фантастически. 

33
Vaidas

Перепробовав все ответы и блоги, пришли к решению. если кому-то нужно, пожалуйста, используйте это видео в качестве ссылки

https://www.youtube.com/watch?v=hi8IPLNq59o

В дополнение к видео добавить намерения сделать в MyFirebaseMessagingService:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    String user_id = "0";
    String date = "0";
    String hal_id = "0";
    String M_view = "0";

    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        user_id = remoteMessage.getData().get("user_id");
        date = remoteMessage.getData().get("date");
        cal_id = remoteMessage.getData().get("hal_id");
        M_view = remoteMessage.getData().get("M_view");
    }

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

    //Calling method to generate notification
    sendNotification(remoteMessage.getNotification().getBody(), remoteMessage.getNotification().getTitle(), user_id, date, hal_id, M_view, click_action);
}

private void sendNotification(String messageBody, String messageTitle, String user_id, String date, String hal_id, String M_view, String click_action) {
    Intent intent = new Intent(click_action);
    intent.putExtra("user_id", user_id);
    intent.putExtra("date", date);
    intent.putExtra("hal_id", hal_id);
    intent.putExtra("M_view", M_view);

    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent,
            PendingIntent.FLAG_ONE_SHOT);

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

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notificationBuilder.build());
}}

и в новой активности NotificationReceive в onCreate или onResume добавьте это

    notification_Y_N = (TextView) findViewById(R.id.notification_Y_N);
    user_id_text = (TextView) findViewById(R.id.user_id_text);

    Intent intent_o = getIntent();
    String user_id = intent_o.getStringExtra("user_id");
    String date = intent_o.getStringExtra("date");
    String hal_id = intent_o.getStringExtra("hal_id");
    String M_view = intent_o.getStringExtra("M_view");

    notification_Y_N.setText(date);
    user_id_text.setText(hal_id);
20
Vaidas

Итак, во-первых, я добавлю детали, упомянутые в Обработка сообщений .

В сводке под строкой Both показано, что когда приложение находится в foreground, полезная нагрузка будет обрабатываться в вашей функции onMessageReceived().

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

Теперь, если приложение находится в background, в документах упоминается, что уведомление получено в системном трее Android, и что полезную нагрузку data можно получить из дополнения к намерению.

Просто добавив подробности из моего ответа здесь , который в значительной степени просто дает утверждение документа и ссылку на образец:

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

Когда ваше приложение находится в фоновом режиме, 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);
    }
}
31
AL.

Для вызова метода onMessageReceived() вам потребуется использовать другой метод для отправки уведомлений (например, создание веб-API для отправки уведомлений). Затем, используя его, 

удалите полезную нагрузку уведомлений из ваших сообщений FCM, чтобы доставить полезную нагрузку данных методу onMessageReceived().

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

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

Для получения дополнительной информации, пожалуйста, обратитесь к следующим ссылкам:

1
Ashu

Вам не нужно реализовывать sendNotification и onMessageReceived самостоятельно.

При отправке:

$data = array
(
    "user_id" => $res_id
    //whatever fields you want to include
);

$msg = array
(
     "body" => $body,
     "title" => $title,
     "data" => $data
     // more fields
);

Сторона Android (на вашей MainACtivity:

private void handleIntent(Intent intent) {
    String user_id= intent.getStringExtra("user_id");
    if(user_id!= null)
        Log.d(TAG, user_id);
}

и конечно:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    handleIntent(intent);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    handleIntent(getIntent());
}

все поля, которые вы вводите в data, будут отправлены вашему намерению extra.

0
Ohad Cohen