Firebase(FCM):在通知点击时打开活动并传递数据。安卓
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"); } //调用生成通知的方法 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.) 当我使用上述代码,并且当我点击通知时,它只是在后台打开应用程序。如果应用程序在前台,则在通知点击时它只是取消通知。然而,我希望在两种情况下(前台和后台)都能接收数据并打开特定的Activity。我在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中检索数据(无论是在前台还是后台),那将是太棒了。
问题原因:在使用Firebase Cloud Messaging (FCM)发送通知时,如果通知载荷(notification payload)存在,那么数据载荷(data payload)将不会传递给onMessageReceived()
方法。
解决方法:移除FCM消息的通知载荷,以便将数据载荷传递给onMessageReceived()
方法。当应用程序处于后台时,只有在没有通知载荷的情况下,数据载荷才会传递给onMessageReceived()
方法。如果两个载荷都存在,则系统会自动处理通知部分(系统托盘),而您的应用程序会在启动器活动的意图的额外信息中获取数据载荷。
原始答案和更多信息请参考以下链接:
- [为什么会出现这种情况?如何处理推送通知?](https://stackoverflow.com/a/37845174/4836759)
- [kws的原始答案,请给他点赞。](https://stackoverflow.com/a/40311918/4836759)
问题的出现原因:通过查看视频以及参考其他答案和博客后,找到了解决方法。
解决方法:在MyFirebaseMessagingService类中的onMessageReceived方法中添加意图,然后在sendNotification方法中创建PendingIntent,并将意图作为参数传递。在NotificationReceive活动的onCreate或onResume方法中获取意图中的额外数据,并进行相应的操作。
解决方法中的代码如下:
public class MyFirebaseMessagingService extends FirebaseMessagingService { private static final String TAG = "MyFirebaseMsgService"; 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"); hal_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活动中的代码 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);
需要注意的是,在Android Oreo中,NotificationCompat.Builder(this)已被弃用,请参考文档并使用Notification Channel实现。
对于在后台时指定活动的问题,请在发送通知时使用数据类型而不是通知类型,在服务器端发送通知时进行相应的设置。
以上是解决Firebase (FCM): open activity and pass data on notification click. android问题的原因和解决方法。
问题的出现原因:当应用程序位于前台时,可以在onMessageReceived()方法中处理推送的数据。但是当应用程序位于后台时,通知会被发送到Android系统托盘,并且可以从启动Activity的意图的附加信息中检索到数据负载。
解决方法:在启动的Activity中,通过检查意图的附加信息来获取通知的文本和标题,以及其他需要的数据。
以下是一个示例代码,可以在接收到通知后在启动Activity中获取通知的文本和标题:
if (getIntent().getExtras() != null) { for (String key : getIntent().getExtras().keySet()) { String value = getIntent().getExtras().getString(key); Log.d(TAG, "Key: " + key + " Value: " + value); } }
另外,还可以将标题和正文作为数据属性发送,以便在启动Activity时作为附加信息读取它们。