Firebase (FCM):打开活动并在通知点击时传递数据。安卓
Posted
技术标签:
【中文标题】Firebase (FCM):打开活动并在通知点击时传递数据。安卓【英文标题】:Firebase (FCM): open activity and pass data on notification click. android 【发布时间】:2017-03-04 01:27:23 【问题描述】:应该明确实现如何使用 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 中的数据,那就太棒了。
【问题讨论】:
【参考方案1】:所以首先,我将在Handling Messages docs中提到的细节。
在Both行下的摘要中,显示当应用在前台时,payload会在你的@ 987654325@.
为了从onMessageReceived()
打开活动,您应该检查您需要的数据是否在有效负载中,如果是,请调用您的特定活动,然后通过意图传递您需要的所有其他详细信息。
现在如果应用在background中,文档中提到通知由Android系统托盘接收,并且data
有效载荷可以从extras中检索的意图。
只需添加我的答案here 中的详细信息,这几乎只是提供了文档声明和示例链接:
在后台应用中处理通知消息
当您的应用处于后台时,Android 会将通知消息定向到系统托盘。默认情况下,用户点击通知会打开应用启动器。
这包括包含通知和数据负载的消息(以及从通知控制台发送的所有消息)。在这些情况下,通知会发送到设备的系统托盘,数据负载会在启动器 Activity 的 Intent 的附加部分中发送。
我认为@ArthurThompson 的answer 解释得很好:
当您发送带有数据负载(通知和数据)的通知消息并且应用程序在后台时,您可以从由于用户点击通知而启动的额外意图中检索数据。
来自FCM sample,它在点击通知时启动 MainActivity:
if (getIntent().getExtras() != null)
for (String key : getIntent().getExtras().keySet())
String value = getIntent().getExtras().getString(key);
Log.d(TAG, "Key: " + key + " Value: " + value);
【讨论】:
我只是在我的附加组件中获得有效负载。知道当应用甚至不在后台时如何在启动活动中获取通知文本和标题? @SyedaZunaira 一种选择是将title
和body
作为data
属性发送,这样您就可以将它们作为附加信息阅读。
非常感谢!这是我的工作!这非常有帮助!
非常感谢您的澄清【参考方案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);
【讨论】:
我没有注意到您已经在答案中添加了。迟到 8 分钟。哈哈 感谢您回答 AL。做了更多的研究,终于想出了解决方案。 不客气。请接受您的正确答案,以便正确标记您的帖子。干杯! 不确定。您应该与视频制作者联系,因为我只是将此链接用作 YouTube 视频的示例.. 嗨!您的代码在前台工作,但是当应用程序在后台时如何直接指定活动?【参考方案3】:要调用onMessageReceived()
方法,您需要使用另一种方法来发送通知(例如创建一个Web API 来发送通知)。然后使用它,
从您的 FCM 消息中删除通知负载,以便将数据负载传送到
onMessageReceived()
方法。
当您的应用在后台时,只有在没有通知负载的情况下,才会将数据负载传递给onMessageReceived
方法。
如果两个有效载荷都存在,则系统会自动处理 通知部分(系统托盘)和您的应用程序获取数据有效负载 启动器活动意图的额外内容(用户点击后 通知)。
更多信息请参考以下链接:
Why is this happening? How to? How to handle push notifications? Original answer by kws. Give him an upvote.【讨论】:
【参考方案4】:您不需要自己实现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
。
【讨论】:
你能解释一下 onCreate 中的 handleIntent 是什么时候调用的吗?当用户点击 fcm 消息时? @famfamfam 查看最后一个代码块,onCreate
如果应用程序关闭并且用户单击消息,则调用,onNewIntent
如果应用程序打开并且用户单击消息,则调用消息 - 所以只需实现两者并从他们那里调用handleIntent
。【参考方案5】:
首先,如果您有响应的数据对象和通知对象。然后要求后端开发人员删除通知对象。 我希望我自己的班级有所帮助。
public class MyFirebaseService extends FirebaseMessagingService
private static final String TAG = "MyFirebaseService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage)
super.onMessageReceived(remoteMessage);
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0)
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
Log.d(TAG, "Message data payload:id " + remoteMessage.getData().get("mode_id"));
sendNotification(remoteMessage.getData().get("body"),
remoteMessage.getData().get("mode_id"), remoteMessage.getData().get("click_action"));
private void sendNotification(String messageBody, String id, String clickAction)
Intent intent = new Intent(clickAction);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(intent);
intent.putExtra("id", id);
intent.putExtra("body", messageBody);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "111")
.setSmallIcon(R.drawable.venus_logo)
.setContentText(messageBody)
.setAutoCancel(true)
.setVibrate(new long[]1000, 1000, 1000, 1000, 1000)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(pendingIntent)
.setLights(Color.GREEN, 3000, 3000);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel("111", "NOTIFICATION_CHANNEL_NAME", importance);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setShowBadge(false);
notificationChannel.setVibrationPattern(new long[]100, 200, 300, 400, 500, 400, 300, 200, 400);
assert notificationManager != null;
notificationBuilder.setChannelId("111");
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(0, notificationBuilder.build());
else
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, notificationBuilder.build());
然后将其添加到您的清单文件中。
<service
android:name=".data.services.MyFirebaseService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<activity
android:name=".ui.notifications.NotificationsDetailsActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:parentActivityName=".ui.home.HomeActivity"
android:taskAffinity="">
<intent-filter>
<action android:name="co.example.yourApp.ui.notifications_TARGET_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
【讨论】:
以上是关于Firebase (FCM):打开活动并在通知点击时传递数据。安卓的主要内容,如果未能解决你的问题,请参考以下文章
Firebase FCM通知click_action有效内容
如何通过单击 firebase 通知打开新活动并在 textview 上打印通知消息
推送通知 - Firebase 控制消息 (FCM) - 无法运行应用程序(未找到默认活动)