Firebase (FCM):打开活动并在通知点击时传递数据。安卓

新手上路,请多包涵

应该清楚地实现如何使用 Firebase 通知和数据。我阅读了很多答案,但似乎无法使其发挥作用。这是我的步骤:

1.) 我在 PHP 中将通知和数据传递给 android,这似乎很好:

 $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 返回 null。

 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();
    }
}}

如果有人可以指导或建议我如何在任一场景(前台或后台)中从 Firebase 检索 MainActivity.java 中的数据,那将是非常棒的。

原文由 Vaidas 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

在尝试了所有答案后,博客提出了解决方案。如果有人需要,请使用此视频作为参考

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());
}}

并在 onCreate 或 onResume 的新 NotificationReceive 活动中添加此

    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);

原文由 Vaidas 发布,翻译遵循 CC BY-SA 3.0 许可协议

因此,首先,我将介绍 处理消息文档 中提到的细节。

Both 行下的摘要中,它显示当应用程序处于 前台 时,有效负载将在您的 onMessageReceived() 中处理。

为了从 onMessageReceived() 打开活动,您应该检查您需要的数据是否在有效负载中,如果是,请调用您的特定活动,然后通过意图传递您需要的所有其他详细信息。

现在,如果应用程序在 后台,文档中提到通知由 Android 系统托盘接收,并且可以从 Intent 的附加内容中检索 data 有效负载

只需在我的答案中添加详细信息, 几乎只是给出了文档声明和示例链接:

在后台应用程序中处理通知消息

当您的应用程序处于后台时,Android 会将通知消息定向到系统托盘。默认情况下,用户点击通知会打开应用启动器。

这包括同时包含 通知和数据负载 的消息(以及从通知控制台发送的所有消息)。在这些情况下,通知会被传递到设备的系统托盘,而 数据负载会在启动器 Activity 的意图的附加部分中传递。

我认为@ArthurThompson 的 回答 很好地解释了这一点:

当您发送带有数据负载(通知和数据)的通知消息并且应用程序在后台时,您可以从由于用户点击通知而启动的意图的附加内容中检索数据。

在点击通知时启动 MainActivity 的 FCM 示例

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

原文由 AL. 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题