这是我的清单
<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>
当应用程序处于后台并且通知到达时,默认通知会出现,并且不会运行我的onMessageReceived
代码。
这是我的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]
答案 0 :(得分:556)
FCM(Firebase云消息传递)中有两种类型的消息:
onMessageReceived()
回调
onMessageReceived()
回调甚至 Firebase小组还没有开发用于向您的设备发送data-messages
的用户界面。
要实现此目的,您必须对以下网址执行POST
请求:
Content-Type
,价值 application/json
Authorization
,价值 key=<your-server-key>
{
"to": "/topics/my_topic",
"data": {
"my_custom_key": "my_custom_value",
"my_custom_key2": true
}
}
{
"data": {
"my_custom_key": "my_custom_value",
"my_custom_key2": true
},
"registration_ids": ["{device-token}","{device2-token}","{device3-token}"]
}
注意:请确保您未添加 JSON密钥
notification
注意:要获取服务器密钥,可以在firebase控制台中找到它:Your project -> settings -> Project settings -> Cloud messaging -> Server Key
这是您处理收到的消息的方式:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String myCustomKey = data.get("my_custom_key");
// Manage data
}
答案 1 :(得分:132)
要使firebase库在以下情况下调用 onMessageReceived()
你不能把JSON密钥和#39;通知&#39;在您对firebase API的请求中,而是使用&#39;数据&#39;,请参阅下文。
当您的应用在后台或被杀时,以下消息不会调用您的 onMessageReceived(),并且您无法自定义您的通知。
{
"to": "/topics/journal",
"notification": {
"title" : "title",
"text": "data!",
"icon": "ic_notification"
}
}
但是使用它会起作用
{
"to": "/topics/dev_journal",
"data": {
"text":"text",
"title":"",
"line1":"Journal",
"line2":"刊物"
}
}
基本上,消息在参数RemoteMessage中与您的数据对象一起作为Map发送,然后您可以在onMessageReceived中管理通知,如此处的代码段
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
//you can get your text message here.
String text= data.get("text");
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
// optional, this is to make beautiful icon
.setLargeIcon(BitmapFactory.decodeResource(
getResources(), R.mipmap.ic_launcher))
.setSmallIcon(smallIcon) //mandatory
.......
/*You can read more on notification here:
https://developer.android.com/training/notify-user/build-notification.html
https://www.youtube.com/watch?v=-iog_fmm6mE
*/
}
答案 2 :(得分:80)
我觉得所有的回复都不完整,但是当你的应用处于后台时,所有回复都需要处理包含数据的通知。
按照以下步骤操作,您就可以在应用处于后台时处理通知。
1.添加这样的intent-filter:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name=".MainActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
到您要处理通知数据的活动。
使用下一种格式发送通知:
{
"notification" : {
"click_action" : ".MainActivity",
"body" : "new Symulti update !",
"title" : "new Symulti update !",
"icon" : "ic_notif_symulti" },
"data": { ... },
"to" : "c9Vaa3ReGdk:APA91bH-AuXgg3lDN2WMcBrNhJZoFtYF9" }
这里的关键是添加
"click_action" : ".MainActivity"
其中.MainActivity是您在步骤1中添加的intent-filter的活动。
在“.MainActivity”的onCreate中获取通知中的“数据”信息:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get notification data info
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
//bundle must contain all info sent in "data" field of the notification
}
}
这应该就是你需要做的一切。我希望这有助于某人:)
答案 3 :(得分:31)
根据docs
处理背景应用中的消息
当您的应用在后台时,Android会指示通知 消息到系统托盘。用户点击通知即可打开 应用程序启动器默认情况下。
这包括同时包含通知和数据的邮件 有效载荷。在这些情况下,通知会传递给设备 系统托盘,数据有效负载是在附加的 你的发射器活动的意图。
如果要打开应用并执行特定操作,请进行设置 通知有效内容中的click_action并将其映射到intent 在要启动的活动中过滤。例如,设置 click_action到OPEN_ACTIVITY_1以触发类似的意图过滤器 以下内容:
<intent-filter> <action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
编辑:
基于此thread:
您无法使用Firebase控制台设置click_action有效内容。您可以尝试使用curl命令或自定义http服务器进行测试
curl --header "Authorization: key=<YOUR_KEY_GOES_HERE>"
--header Content-Type:"application/json" https://fcm.googleapis.com/fcm/send
-d "{\"to\":\"/topics/news\",\"notification\":
{\"title\": \"Click Action Message\",\"text\": \"Sample message\",
\"click_action\":\"OPEN_ACTIVITY_1\"}}"
答案 4 :(得分:29)
根据send downstream using firebase中的firebase文档,有两种类型的有效负载:
数据强>
此参数指定邮件有效内容的自定义键值对。 客户端应用程序负责处理数据消息。数据消息只有自定义键值对。
<强>通知强>
此参数指定通知有效内容的预定义的,用户可见的键值对。 FCM代表客户端应用自动向最终用户设备显示消息。通知消息具有一组预定义的用户可见键。
当您在前台时,您可以使用 onMessageReceived()在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,并将其映射到要启动的活动中的意图过滤器。例如,将click_action设置为OPEN_ACTIVITY_1以触发如下所示的意图过滤器:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
将该intent-filter放在您的一个活动代码中的清单上。当您单击通知时,它将打开应用程序并直接转到您在click_action中定义的活动,在本例中为&#34; OPEN_ACTIVTY_1&#34;。 在该活动中,您可以通过以下方式获取数据:
Bundle b = getIntent().getExtras();
String someData = b.getString("someData");
我在我的Android应用程序中使用FCM并使用两个有效负载。 以下是我使用的示例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"
}
}
答案 5 :(得分:20)
由于从Firebase Notification UI发送的display-messages
仅适用于您的应用位于前台的情况。对于data-messages
,需要对FCM
<强>步骤强>
添加以下标题
键:内容类型,值:application / json
添加正文
如果使用主题:
{
"to" : "/topics/topic_name",
"data": {
"key1" : "value1",
"key2" : "value2",
}
}
如果使用注册ID:
{
"registration_ids" : "[{"id"},{id1}]",
"data": {
"key1" : "value1",
"key2" : "value2",
}
}
多数民众赞成吧!现在像往常一样听onMessageReceived
回调。
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String value1 = data.get("key1");
String value2 = data.get("key2");
}
答案 6 :(得分:16)
要在后台捕获邮件,您需要使用BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.legacy.content.WakefulBroadcastReceiver
import com.google.firebase.messaging.RemoteMessage
class FirebaseBroadcastReceiver : WakefulBroadcastReceiver() {
val TAG: String = FirebaseBroadcastReceiver::class.java.simpleName
override fun onReceive(context: Context, intent: Intent) {
val dataBundle = intent.extras
if (dataBundle != null)
for (key in dataBundle.keySet()) {
Log.d(TAG, "dataBundle: " + key + " : " + dataBundle.get(key))
}
val remoteMessage = RemoteMessage(dataBundle)
}
}
并将其添加到您的清单中:
<receiver
android:name="MY_PACKAGE_NAME.FirebaseBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
答案 7 :(得分:16)
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
}
每次只有在app处于forground 时才调用
有一个覆盖方法每次调用此方法,无论前台或后台有什么应用程序或被杀死,但此方法适用于此firebase api版本
这是你必须从gradle导入的版本
compile 'com.google.firebase:firebase-messaging:10.2.1'
这是方法
@Override
public void handleIntent(Intent intent) {
super.handleIntent(intent);
// you can get ur data here
//intent.getExtras().get("your_data_key")
}
使用以前的firebase api这种方法不存在,所以在这种情况下 当应用程序处于后台时,防火基本处理....现在你有这个方法 你想做什么......你可以用这种方法做到这一点......
如果您使用的是先前版本,则会启动默认活动 在这种情况下,你可以获得相同的数据
if(getIntent().getExtras() != null && getIntent().getExtras().get("your_data_key") != null) {
String strNotificaiton = getIntent().getExtras().get("your_data_key").toString();
//做你想做的事.... }
通常这是我们收到通知中的服务器结构
{
"notification": {
"body": "Cool offers. Get them before expiring!",
"title": "Flat 80% discount",
"icon": "appicon",
"click_action": "activity name" //optional if required.....
},
"data": {
"product_id": 11,
"product_details": "details.....",
"other_info": "......."
}
}
它取决于你如何想要提供该数据密钥,或者你想要通知任何你可以给予的通知....... 你将用相同的密钥给你什么,你将获得该数据.........
如果你没有点击通知默认活动会打开,那么你很少发送点击动作的情况很少,但如果你想在应用程序处于后台时打开你的特定活动,你可以在handleIntent上调用你的活动方法,因为每次调用
答案 8 :(得分:13)
这里有关于firebase消息的更清晰的概念。我是从他们的支持团队那里找到的。
Firebase有三种消息类型:
通知消息:通知消息适用于后台或前台。当应用程序处于后台时,通知消息将传递到系统托盘。如果应用位于前台,则消息由onMessageReceived()
或didReceiveRemoteNotification
回调处理。这些基本上就是所谓的显示消息。
数据消息:在Android平台上,数据消息可以在后台和前台上运行。数据消息将由onMessageReceived()处理。这里的平台特定说明如下:在Android上,可以在用于启动活动的Intent中检索数据有效负载。要详细说明,如果您有"click_action":"launch_Activity_1"
,则只能通过getIntent()
从Activity_1
检索此意图。
包含通知和数据有效负载的邮件:在后台,应用会在通知托盘中收到通知有效内容,并仅在用户点击通知时处理数据有效内容。在前台时,您的应用会收到一个消息对象,其中包含两个可用的有效负载。其次,click_action
参数通常用于通知有效负载而不是数据有效负载。如果在数据有效内容中使用,则此参数将被视为自定义键值对,因此您需要实现自定义逻辑才能使其按预期工作。
另外,我建议您使用onMessageReceived
方法(请参阅数据消息)来提取数据包。根据您的逻辑,我检查了捆绑对象,但未找到预期的数据内容。以下是对可能提供更清晰的类似案例的引用。
有关详细信息,请访问我的this thread
答案 9 :(得分:10)
答案 10 :(得分:9)
根据文件:2017年5月17日
当您的应用处于后台时,Android 将通知消息定向到系统托盘。用户点击 通知默认情况下会打开应用启动器。
这包括同时包含通知和数据有效内容的邮件 (以及从Notifications控制台发送的所有消息)。在这些 例如,通知将传递到设备的系统托盘,并且 数据有效负载是在您的意图的附加内容中提供的 发射器活动。
因此,您应该同时使用有效负载通知+数据:
{
"to": "FCM registration ID",
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification"
},
"data": {
"someData" : "This is some data",
"someData2" : "etc"
}
}
没有必要使用click_action.You应该只关注 LAUNCHER活动的意图
<activity android:name=".MainActivity">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Java代码应该在MainActivity上的onCreate方法上:
Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
Bundle extras = intent.getExtras();
String someData= extras.getString("someData");
String someData2 = extras.getString("someData2");
}
您可以测试来自Firebase Notifications Console的两个有效负载通知+数据。不要忘记在高级选项部分
上填写自定义数据字段答案 11 :(得分:7)
像这样的简单摘要
如果您的应用正在运行;
onMessageReceived()
是触发器。
如果您的应用未运行(通过滑动杀死);
onMessageReceived()
不是由direclty触发和传递的。如果你有任何特定的键值对。他们不工作因为onMessageReceived()无效。
我发现了这种方式;
在你的启动器活动中,输入这个逻辑,
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());
使用这行代码,我关闭了我的应用程序并打开Google Play Market
快乐编码=)
答案 12 :(得分:6)
我想出了这些情景,
当应用位于前景时, 从 FirebaseService 调用 onMessageReceived()方法。因此,将调用服务类中定义的 pendingIntent 。
当应用程序位于后台时,会调用第一个活动。
现在,如果你使用启动活动,那么必须记住将调用 splashactivity ,否则如果没有splashActivity ,无论第一项活动是什么,都会被召唤。
然后你需要检查 firstActivity 的 getIntent(),看看它是否有捆绑。如果一切正常,你会看到bundle已填入值。如果从服务器发送的 data tag 中的值如下所示,
"data": {
"user_name": "arefin sajib",
"value": "user name notification"
}
然后在第一个活动中,你会看到, 有一个有效的意图( getIntent()不是空),有效的捆绑包和内部捆绑包,上面提到的整个JSON,数据为 键 强>
对于这种情况,提取值的代码将如下所示,
if(getIntent()!=null){
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
try {
JSONObject object = new JSONObject(bundle.getStringExtra("data"));
String user_name = object.optString("user_name");
} catch (JSONException e) {
e.printStackTrace();
}
}
}
答案 13 :(得分:3)
感谢大家的回答。但我通过发送数据消息而不是发送通知解决了这个问题。 服务器代码
<?php
$url = "https://fcm.googleapis.com/fcm/send";
$token = "C-l6T_a7HouUK****";
$serverKey = "AAAAaOcKS00:********";
define( 'API_ACCESS_KEY', $serverKey );
$registrationIds = array($token);
// prep the bundle
$msg = array
(
'message' => 'here is a message. message',
'title' => 'This is a title. title',
'subtitle' => 'This is a subtitle. subtitle',
'tickerText' => 'Ticker text here...Ticker text here...Ticker text
here',
'vibrate' => 1,
'sound' => 1,
'largeIcon' => 'large_icon',
'smallIcon' => 'small_icon'
);
$fields = array
(
'registration_ids' => $registrationIds,
'data' => $msg
);
$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 );
echo $result;
?>
并捕获了onMessageReceived中的数据
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
sendNotification(remoteMessage.getData().get("message"));
}
// Check if message contains a notification payload.
else if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, Notify.class).putExtra("msg",messageBody);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = "idddd";
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(MyFirebaseMessagingService.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
答案 14 :(得分:2)
即使应用程序处于后台和前台,发送消息的简便方法如下: - 要使用API发送消息,您可以使用名为AdvancedREST Client的工具,它的chrome扩展名,并使用以下参数发送消息。
Rest客户端工具链接:https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo
使用此网址: - https://fcm.googleapis.com/fcm/send 内容类型:应用程序/ JSON 授权:key =您的服务器密钥From或Authoization密钥(参见下面的参考资料)
{ "data": {
"image": "https://static.pexels.com/photos/4825/red-love-romantic-flowers.jpg",
"message": "Firebase Push Message Using API"
"AnotherActivity": "True"
},
"to" : "device id Or Device token"
}
可以通过访问Google开发人员控制台并单击项目左侧菜单上的“凭据”按钮来获取授权密钥。在列出的API密钥中,服务器密钥将是您的授权密钥。
你需要将接收者的tokenID放在使用API发送的POST请求的“to”部分。
答案 15 :(得分:2)
从服务器请求中完全删除通知有效内容。发送仅数据并在onMessageReceived()
处理,否则当应用处于后台或被杀时,您的onMessageReceived
将不会被触发。
以下是我从服务器发送的内容:
{
"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());
}
同样,您可以在onMessageReceived()
内获取从服务器发送的任何数据。
答案 16 :(得分:2)
我有同样的问题。经过一番挖掘后,为什么我的MainActivity是在没有数据的情况下被有意调用的,我意识到我的LAUNCHER活动(如清单中一样)是SplashActivity。在那里,我找到了消息数据,并将其转发给MainActivity。像sharm一样运作。我相信这可以帮助某人。
感谢所有其他答案。
答案 17 :(得分:1)
我在 firebase-messaging-sw.js
中添加了以下代码,
messaging.onBackgroundmessage((payload)=>{
console.log("background message detected!!");
console.log("message : ", payload);
})
每次在后台收到消息时都会触发。但是我无法在主线程中使用有效负载,因为 SW 不支持它。于是我查了很多资料,在一个安卓论坛上找到了解决办法。
所以解决方案是我们必须从请求负载中删除通知负载。
所以我改变了我的有效载荷
{
"notification": {
"title": "Hey there",
"body": "Subscribe to AMAL MOHAN N youtube channel"
},
"to": "your-browser-token",
"data": {
"value1": "text",
"value2": "",
"value3": "sample3",
"value4": "sample4"
}
}
到
{
"to": "your-browser-token",
"data": {
"value1": "text",
"value2": "",
"value3": "sample3",
"value4": "sample4"
}
}
负载的变化自动使 receiveMessage()
在前台消息和后台消息中触发。
我在一个 Android 论坛上找到了这个,这对我有用!如果这对您有用,请告诉我。
答案 18 :(得分:1)
根据OAUTH 2.0:
在这种情况下,由于现在使用OAUTH 2的FCM会出现Auth问题
所以我阅读了Firebase文档,根据文档,发布数据消息的新方法是;
POST: https://fcm.googleapis.com/v1/projects/YOUR_FIREBASEDB_ID/messages:send
标题
Key: Content-Type, Value: application/json
验证
Bearer YOUR_TOKEN
示例正文
{
"message":{
"topic" : "xxx",
"data" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message"
}
}
}
URL中有数据库ID,您可以在Firebase控制台上找到它。 (进行项目设置)
现在让我们获取令牌(仅1小时有效):
首先在Firebase控制台中,打开设置>服务帐户。点击生成新私钥,安全地存储包含密钥的JSON文件。我需要此JSON文件来手动授权服务器请求。我下载了。
然后我创建一个node.js项目,并使用此函数获取令牌;
var PROJECT_ID = 'YOUR_PROJECT_ID';
var HOST = 'fcm.googleapis.com';
var PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
var SCOPES = [MESSAGING_SCOPE];
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
getAccessToken().then(function(accessToken) {
console.log("TOKEN: "+accessToken)
})
});
function getAccessToken() {
return new Promise(function(resolve, reject) {
var key = require('./YOUR_DOWNLOADED_JSON_FILE.json');
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(function(err, tokens) {
if (err) {
reject(err);
return;
}
resolve(tokens.access_token);
});
});
}
现在,我可以在发布请求中使用此令牌。然后,我发布数据消息,该消息现在由我的应用程序onMessageReceived函数处理。
答案 19 :(得分:1)
您要在后台处理onMessageReceived(RemoteMessage remoteMessage),仅发送数据部分通知部分:
"data": "image": "", "message": "Firebase Push Message Using API",
“ AnotherActivity”:“ True”,“ to”:“设备ID或设备令牌”
通过此onMessageRecivied调用后台和前台,无需在启动器活动上使用通知托盘处理通知。
使用以下方法处理数据有效负载:
公共无效onMessageReceived(RemoteMessage remoteMessage)
如果(remoteMessage.getData()。size()> 0)
Log.d(TAG,“消息数据有效载荷:” + remoteMessage.getData());
答案 20 :(得分:1)
2018年6月答案-
您必须确保消息中的任何地方都没有“ notification”关键字。仅包含“数据”,该应用程序将能够在onMessageReceived中处理消息,即使在后台或已终止。
使用云功能:
const message = {
token: token_id, // obtain device token id by querying data in firebase
data: {
title: "my_custom_title",
body: "my_custom_body_message"
}
}
return admin.messaging().send(message).then(response => {
// handle response
});
然后在您的onMessageReceived()中,在您的类中扩展com.google.firebase.messaging.FirebaseMessagingService:
if (data != null) {
Log.d(TAG, "data title is: " + data.get("title");
Log.d(TAG, "data body is: " + data.get("body");
}
// build notification using the body, title, and whatever else you want.
答案 21 :(得分:0)
使用此代码,您可以在后台/前台获取通知,并执行操作:
//Data should come in this format from the notification
{
"to": "/xyz/Notifications",
"data": {
"key1": "title notification",
"key2": "description notification"
}
}
应用内使用此代码:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String key1Data = remoteMessage.getData().get("key1");
// use key1Data to according to your need
}
答案 22 :(得分:0)
除了以上答案外, 如果您正在使用 FCM控制台测试推送通知,则键和对象不会添加到“推送通知”捆绑包中。因此,当应用程序处于后台或被终止运行时,您将不会收到详细的推送通知。
在这种情况下,您必须选择后端管理控制台来测试App后台情况。
在这里,您将在推包中添加“数据”键。因此,详细的推送将按预期显示。 希望对您有所帮助。
答案 23 :(得分:0)
自2019年以来,Google 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是SplashScreen,也应在其中定义一个Intent。当您的应用程序在后台运行时,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");
答案 24 :(得分:0)
// Place this code on your MainActivity,then you will get your payload
// Handle possible data accompanying notification message.
// [START handle_data_extras]
if (getIntent().getExtras() != null) {
for (String key : getIntent().getExtras().keySet()) {
Object value = getIntent().getExtras().get(key);
Log.d(TAG, "Key: " + key + " Value: " + value);
}
}
答案 25 :(得分:0)
从2019年7月开始工作
Android compileSdkVersion 28,buildToolsVersion 28.0.3和firebase-messaging:19.0.1
经过许多小时的研究,研究了其他所有StackOverflow问题和答案,并尝试了无数过时的解决方案,该解决方案设法在以下三种情况下显示通知:
-应用程序处于前台:
该通知是通过MyFirebaseMessagingService类的onMessageReceived方法接收的
-应用已被杀死(它没有在后台运行): 通知将由FCM自动发送到通知托盘。当用户触摸通知时,将通过调用清单中具有android.intent.category.LAUNCHER的活动来启动应用。您可以通过onCreate()方法上的getIntent()。getExtras()获取通知的数据部分。
-应用程序处于后台: 通知将由FCM自动发送到通知托盘。当用户触摸通知时,通过启动清单中包含android.intent.category.LAUNCHER的活动,使应用程序进入前台。由于我的应用程序在该活动中具有launchMode =“ singleTop”,因此不会调用onCreate()方法,因为已经创建了同一类的一个活动,而是调用了该类的onNewIntent()方法,并且您获得了数据的一部分通过使用intent.getExtras()进行通知。
步骤: 1-如果您这样定义应用程序的主要活动:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:largeHeap="true"
android:screenOrientation="portrait"
android:launchMode="singleTop">
<intent-filter>
<action android:name=".MainActivity" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
2-在MainActivity.class的onCreate()方法上添加这些行
Intent i = getIntent();
Bundle extras = i.getExtras();
if (extras != null) {
for (String key : extras.keySet()) {
Object value = extras.get(key);
Log.d(Application.APPTAG, "Extras received at onCreate: Key: " + key + " Value: " + value);
}
String title = extras.getString("title");
String message = extras.getString("body");
if (message!=null && message.length()>0) {
getIntent().removeExtra("body");
showNotificationInADialog(title, message);
}
}
和这些方法复制到相同的MainActivity.class:
@Override
public void onNewIntent(Intent intent){
//called when a new intent for this class is created.
// The main case is when the app was in background, a notification arrives to the tray, and the user touches the notification
super.onNewIntent(intent);
Log.d(Application.APPTAG, "onNewIntent - starting");
Bundle extras = intent.getExtras();
if (extras != null) {
for (String key : extras.keySet()) {
Object value = extras.get(key);
Log.d(Application.APPTAG, "Extras received at onNewIntent: Key: " + key + " Value: " + value);
}
String title = extras.getString("title");
String message = extras.getString("body");
if (message!=null && message.length()>0) {
getIntent().removeExtra("body");
showNotificationInADialog(title, message);
}
}
}
private void showNotificationInADialog(String title, String message) {
// show a dialog with the provided title and message
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(title);
builder.setMessage(message);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
3-这样创建类MyFirebase:
package com.yourcompany.app;
import android.content.Intent;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public MyFirebaseMessagingService() {
super();
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(Application.APPTAG, "myFirebaseMessagingService - onMessageReceived - message: " + remoteMessage);
Intent dialogIntent = new Intent(this, NotificationActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.putExtra("msg", remoteMessage);
startActivity(dialogIntent);
}
}
4-像这样创建新的类NotificationActivity.class:
package com.yourcompany.app;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ContextThemeWrapper;
import com.google.firebase.messaging.RemoteMessage;
public class NotificationActivity extends AppCompatActivity {
private Activity context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
Bundle extras = getIntent().getExtras();
Log.d(Application.APPTAG, "NotificationActivity - onCreate - extras: " + extras);
if (extras == null) {
context.finish();
return;
}
RemoteMessage msg = (RemoteMessage) extras.get("msg");
if (msg == null) {
context.finish();
return;
}
RemoteMessage.Notification notification = msg.getNotification();
if (notification == null) {
context.finish();
return;
}
String dialogMessage;
try {
dialogMessage = notification.getBody();
} catch (Exception e){
context.finish();
return;
}
String dialogTitle = notification.getTitle();
if (dialogTitle == null || dialogTitle.length() == 0) {
dialogTitle = "";
}
AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(context, R.style.myDialog));
builder.setTitle(dialogTitle);
builder.setMessage(dialogMessage);
builder.setPositiveButton(getResources().getString(R.string.accept), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
5-将这些行添加到标签中的应用清单中
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id"/>
<activity android:name=".NotificationActivity"
android:theme="@style/myDialog"> </activity>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/notification_icon"/>
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/color_accent" />
6-在Application.java onCreate()方法或MainActivity.class onCreate()方法中添加以下行:
// notifications channel creation
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create channel to show notifications.
String channelId = getResources().getString("default_channel_id");
String channelName = getResources().getString("General announcements");
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(new NotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_LOW));
}
完成。
现在要使其在上述3种情况下都能正常运行,您必须通过以下方式从Firebase Web控制台发送通知:
在“通知”部分中:
通知标题=要在通知对话框中显示的标题(可选)
通知文本=向用户显示的消息(必填)
然后在“目标”部分中:
应用=您的Android应用
并在“其他选项”部分中:
Android通知频道= default_channel_id
自订资料
键:标题值:(此处与“通知”部分的“标题”字段中的文本相同)
键:正文值:(此处与“通知”部分的“消息”字段中的文本相同)
key:click_action值:.MainActivity
声音=已禁用
过期= 4周
您可以使用带有Google Play的API 28在仿真器中对其进行调试。
编码愉快!
答案 26 :(得分:0)
会有两种类型的通知
当应用程序在后台运行时,您必须使用数据通知来处理通知。
答案 27 :(得分:0)
FCM(Firebase云消息传递)中有两种消息类型:
显示消息:仅当您的应用位于前景
中时,这些消息才会触发onMessageReceived()回调。数据消息:即使您的应用程序处于前景/背景/已杀死
中,这些消息也会触发onMessageReceived()回调数据消息示例:
{
"to": "/path",
"data":
{
"my_custom_key": "my_custom_value",
"my_custom_key2": true
}
}
显示消息示例:
{
"notification": {
"title" : "title",
"body" : "body text",
"icon" : "ic_notification",
"click_action" : "OPEN_ACTIVITY_1"
}
}
Android端可以处理如下通知:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
…
@Override public void onMessageReceived(RemoteMessage remoteMessage){
Map<String, String> data = remoteMessage.getData();
String myCustomKey = data.get("my_custom_key");
}
…
}
有关FCM的更多详细信息,您可以在这里找到:Set up a Firebase Cloud Messaging client app on Android
答案 28 :(得分:0)
提供的解决方案在我的情况下不起作用。
归根结底,我发现某些电池优化应用可以让用户控制允许或阻止应用发送通知。就我而言,三星的智能管理器会在我的应用程序从最近列表中被杀死/清除后自动阻止它。
为我的应用关闭该功能是我能找到的唯一解决方案。
答案 29 :(得分:-4)
我遇到了同样的问题并重新编译了firebase库,并阻止它在应用程序在后台时发送通知
*库 https://github.com/erdalceylan/com-google-firebase-messaging
dependencies {
compile 'com.google.firebase:firebase-core:11.2.0'
compile 'com.github.erdalceylan:com-google-firebase-messaging:v1-11.2.0'
}
*
@WorkerThread
public void onMessageReceived(RemoteMessage var1) {
//your app is in background or foreground all time calling
}
希望有所帮助。祝你好运