这是我的舱单:
<service android:name=".fcm.PshycoFirebaseMessagingServices">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".fcm.PshycoFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
当应用程序在后台和通知到达,然后默认通知来,不运行我的onmessagerreceived代码。
这是我的onMessageReceived代码。如果我的应用程序在前台运行,而不是在后台运行,就会调用这个函数。我怎么能运行这段代码时,应用程序是在后台太?
// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
data = remoteMessage.getData();
String title = remoteMessage.getNotification().getTitle();
String message = remoteMessage.getNotification().getBody();
String imageUrl = (String) data.get("image");
String action = (String) data.get("action");
Log.i(TAG, "onMessageReceived: title : "+title);
Log.i(TAG, "onMessageReceived: message : "+message);
Log.i(TAG, "onMessageReceived: imageUrl : "+imageUrl);
Log.i(TAG, "onMessageReceived: action : "+action);
if (imageUrl == null) {
sendNotification(title,message,action);
} else {
new BigPictureNotification(this,title,message,imageUrl,action);
}
}
// [END receive_message]
像这样简单的总结
如果你的应用正在运行;
onMessageReceived ()
是触发器。
如果你的应用程序没有运行(通过滑动杀死);
onMessageReceived ()
不是直接触发和传递的。如果你有特殊的键值对。它们不工作,因为onmessagerecreceived()不工作。
我找到了这条路;
在你的启动器活动中,放入这样的逻辑,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.activity_splash);
if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("PACKAGE_NAME")) {
// do what you want
// and this for killing app if we dont want to start
android.os.Process.killProcess(android.os.Process.myPid());
} else {
//continue to app
}
}
在这个if块中,根据firebase UI搜索你的密钥。
在这个例子中,我的键和值就像上面那样;(对不起,语言=))
当我的代码工作时,我得到“com.rda.note”。
android.os.Process.killProcess(android.os.Process.myPid());
有了这行代码,我关闭了我的应用程序,打开谷歌播放市场
快乐编码=)
根据firebase文档在发送下游使用firebase,有两种类型的有效载荷:
数据
此参数指定消息有效负载的自定义键-值对。
客户端应用程序负责处理数据消息。数据消息只有自定义键值对。
通知
此参数指定通知有效负载的预定义的、用户可见的键-值对。FCM自动代表客户端应用程序将消息显示给最终用户设备。通知消息具有一组预定义的用户可见键。
当你在前台时,你可以使用onmessagerecreceived()在FCM内部获取数据,你可以从数据有效载荷中获取数据。
data = remoteMessage.getData();
String customData = (String) data.get("customData");
当您在后台时,FCM将根据通知有效载荷的信息在系统托盘中显示通知。系统托盘上用于通知的标题、消息和图标都来自通知有效负载。
{
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification",
"click_action" : "OPEN_ACTIVITY_1"
}
}
当你想在应用程序处于后台时自动在系统托盘上显示通知时,使用这个通知有效载荷。
当你的应用程序在后台运行时,为了获得通知数据,你应该在通知有效载荷中添加click_action。
如果你想打开你的应用并执行一个特定的动作(在后台),在通知有效载荷中设置click_action,并将其映射到你想要启动的Activity中的意图过滤器。例如,将click_action设置为OPEN_ACTIVITY_1来触发一个意图过滤器,如下所示:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
把intent-filter放在你的清单上,在你的一个activity标签里面。当你点击通知时,它将打开应用程序并直接进入你在click_action中定义的活动,在本例中为“OPEN_ACTIVTY_1”。
在这个活动中,你可以通过以下方式获取数据:
Bundle b = getIntent().getExtras();
String someData = b.getString("someData");
我使用FCM为我的android应用程序和使用两个有效载荷。
下面是我使用的JSON示例:
{
"to": "FCM registration ID",
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification",
"click_action" : "OPEN_ACTIVITY_1"
},
"data": {
"someData" : "This is some data",
"someData2" : "etc"
}
}
2023年1月
对于那些实现了最新的Firebase云消息(FCM)的应用程序,您可能不会被限制在后台或完全关闭的情况下分别为应用程序发送数据和通知以处理数据。正如这里的一些回答所解释的那样,简短的版本是:
在你的启动器活动上,监视启动时的额外内容;
测试您的FCM数据中的唯一键是否在列表中;
如果存在,获取必要的数据并调用您的活动来处理您想要做的处理。
//Firebase
// [START handle_data_extras]
if (getIntent().getExtras() != null) {
boolean fcmExtraFlag = false;
for (String key : getIntent().getExtras().keySet()) {
Object value = getIntent().getExtras().get(key);
Log.d(TAG, "Key: " + key + " Value: " + value);
if(key.equalsIgnoreCase("tracerId")){
//test your known key to be sure it is from fcm
//this must have come from notification (system) tray
//this will come whether the app was in the background or completely off
//generally, this could be in the main activity as it has the intent-filter already set
fcmExtraFlag = true;
}
}
//pick fcm values if present and notify and/or process accordingly
//you may add time-lookup to ignore delayed (time-passed) ones; and ignore
if(fcmExtraFlag){
String tracerId = (String) getIntent().getExtras().get("tracerId");
//prepare your data as needed
String tracerData = tracerId+">"+data-one+">"+data-two;
String msgBody = "This is a test notification; data received: "+tracerId;
String fcmMessage = msgBody;
//start your confirmation activity, directly or whichever way
SidUtils.firebaseStartConfirms(msgBody, tracerData, this);
}
}
// [END handle_data_extras]
如前所述,如果可能的话,这应该在你的主活动中,以处理你的应用程序实际上关闭的情况-而不仅仅是在后台。这些将通过点击系统托盘上的应用程序通知来触发。
自2019年以来,谷歌Firebase的api有了很大的变化
我的意思是:
“com.google.firebase: firebase-messaging: 18.0.0”
在18.0.0中,他们删除了MyFirebaseInstanceIDService,你需要在MyFirebaseMessagingService中获取令牌,所以你只需要写:
@Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
}
在你的AndroidManifest.xml中,你必须删除:
<service android:name=".service.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
此外,建议您设置默认值以自定义通知的外观。您可以指定自定义默认图标和自定义默认颜色,在通知有效负载中没有设置等效值时应用它们。
在应用程序标记中添加这些行来设置自定义默认图标和自定义颜色:
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_notification" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/push_channel" />
现在要在后台应用程序中处理通知消息,你应该在你的第一个Activity中定义一个Intent,即使它是SplashScreen。当你的应用程序在后台时,Android将通知消息定向到系统托盘。用户点击通知会默认打开应用启动器。
例如,如果你的Json是这样的:
"data": {
"message": "2",
"title": "1",
"pushType" : "banner",
"bannerLink": "http://www.google.com",
"image" : "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"}
你只需要写一个简单的意图来获取这些值:
Bundle extras = intent.getExtras();
String bannerLink = extras.getString("bannerLink");
...
String channelId = extras.getString("channelId");
此情况仅用于firebase管理通知
如果应用程序在后台,则不会触发FirebaseMessagingService
要处理这种情况,请转到launcher activity,检查附加的intent bundle,并使用以下代码打印出所有数据:
intent?.extras?.let {it->
for (key in bundle.keySet()) {
val value = bundle[key]
Log.d("NotificationData", String.format("%s %s (%s)", key, value.toString(), value!!.javaClass.name))
}
}
显示所有数据类型的签入日志;
例子:
我想从通知中获得周和标题将使用这段代码
intent?.extras?.let {it->
if (it.containsKey("week")){
}
if (it.containsKey("title")){
}
从服务器请求中完全删除通知有效负载。只发送数据并在onmessagerreceived()中处理它,否则当应用程序在后台或被杀死时,你的onmessagerreceived将不会被触发。
这是我从服务器发送的:
{
"data":{
"id": 1,
"missedRequests": 5
"addAnyDataHere": 123
},
"to": "fhiT7evmZk8:APA91bFJq7Tkly4BtLRXdYvqHno2vHCRkzpJT8QZy0TlIGs......"
}
你可以像这样在onMessageReceived(RemoteMessage message)中接收你的数据(假设我需要获取id)
Object obj = message.getData().get("id");
if (obj != null) {
int id = Integer.valueOf(obj.toString());
}
类似地,你可以在onmessagerecreceived()内从服务器获得任何数据。