Android未收到Firebase推送通知 - MismatchSenderId [英] Android not receiving Firebase Push Notification - MismatchSenderId
问题描述
我试图在Messenger应用程序上工作,但是这里有两个实体( 2个应用程序A和B )。
现在我正在尝试使用Firebase在两者之间传递消息逻辑。 Firebase不支持通过相同的 项目网址 在两个不同的应用程序( A& B )之间进行通信。为了克服这个限制,我也为应用程序B使用了与应用程序A相同的 google-service.json
。
对于应用程序B,我刚更改了项目 id
和 auth key
。这似乎按照我的意图工作。我已经测试了推送通知以及使用Firebase控制台,它似乎已经工作。
然后我试图实现服务器逻辑。制作一对一通知。
CASE 1
但是问题出现在这里,如果我发送一个通知请求,我会得到一个 MismatchSenderId
错误,其中的项目ID没有被调和过。
{ multicast_id:[删除], 成功:0, 失败:1, canonical_ids:0 结果:[{ 错误: MismatchSenderId} ]}
CASE 2
和应用程序A,这是我得到以下响应:
pre $ {code $ {multicast_id:[removed] ,success:1,failure:0,canonical_ids:0,results:[{message_id:0:1473661851590851%0e4bcac9f9fd7ecd}]}
为此,成功值是 1
因此,通知应该被发送,但不是发送当我从设备发出请求时。但是,当我使用Postman或任何其他客户端执行相同的服务器调用时,它是完美的。
以下是我的代码 MyFirebaseInstanceIDService.java
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG =MyFirebaseIIDService;
private static final String FRIENDLY_ENGAGE_TOPIC =friendly_engage;
@Override
public void onCreate(){
String savedToken = Utility.getFirebaseInstanceId(getApplicationContext());
String defaultToken = getApplication()。getString(R.string.pref_firebase_instance_id_default_key);
Log.d(GCM,savedToken);
if(savedToken.equalsIgnoreCase(defaultToken))
// currentToken当应用程序第一次安装且令牌不可用时为空
//如果令牌已经保存在首选项中,也会跳过...
{
String CurrentToken = FirebaseInstanceId.getInstance()。getToken();
if(CurrentToken!= null)
Utility.setFirebaseInstanceId(getApplicationContext(),CurrentToken);
Log.d(Value not set,CurrentToken);
updateFCMTokenId(CurrentToken);
}
super.onCreate();
}
/ **
*应用程序的当前实例ID令牌不再有效
*,因此必须要求新的实例ID令牌。
* /
@Override
public void onTokenRefresh(){
//如果需要处理代码的生成,最初或
//刷新后这是你应该这样做的地方。
String token = FirebaseInstanceId.getInstance()。getToken();
Log.d(TAG,FCM令牌:+令牌);
Utility.setFirebaseInstanceId(getApplicationContext(),token);
updateFCMTokenId(token);
private void updateFCMTokenId(final String token){
SQLiteHandler db = new SQLiteHandler(getBaseContext());
final HashMap< String,String> map = db.getUserDetails();
//更新推送通知的fcm标记
StringRequest str = new StringRequest(Request.Method.POST,AppConfig.UPDATE_GCM_ID,new Response.Listener< String>(){
@Override
public void onResponse(String response){
Log.d(GCM RESPONSE,response);
}
},new Response.ErrorListener ){
@Override
public void onErrorResponse(VolleyError error){
$ b}
}){
@Override
protected Map< String ,String> getParams()抛出AuthFailureError {
HashMap< String,String> param = new HashMap<>();
param.put(user_id,map.get(uid));
param.put(gcm_registration_id,token);
返回参数;
}
};
str.setShouldCache(false);
str.setRetryPolicy(new DefaultRetryPolicy(AppConfig.DEFAULT_RETRY_TIME,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
AppController.getInstance()。addToRequestQueue(str);
code
$ b $ p
$ b FirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
$ b $ private static final String TAG =MyFirebaseMsgService;
$ b $ @覆盖
public void onMessageReceived(RemoteMessage remoteMessage){
//显示日志
中的数据//可选
try {
Log.d(TAG,From:+ remoteMessage.getFrom());
$ b $ Log.d(TAG,Notification Message Body:+ remoteMessage.getData()。get(message));
} catch(Exception e){
e.printStackTrace();
//调用方法来生成通知
sendNotification(remoteMessage.getData()。get(message));
}
//这个方法只产生推送通知
//和前面的帖子一样
private void sendNotification(String messageBody){
Intent intent = new Intent(this,ChatRoomActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
android.support.v4.app.NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(NAME)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0,notificationBuilder.build());
这里是 Manifest 应用程序
标记
< service
android:name =。MyFirebaseMessagingService
android:exported =false>
< intent-filter>
< action android:name =com.google.firebase.MESSAGING_EVENT/>
< / intent-filter>
< / service>
< service
android:name =。MyFirebaseInstanceIDService
android:exported =false>
< intent-filter>
< action android:name =com.google.firebase.INSTANCE_ID_EVENT/>
< / intent-filter>
< / service>
TIA
<我已经设法解决了CASE 1,其中BI必须使用B的服务器api键,类似地A
编辑2
新增服务器端代码
public function sendNotification($ message,$ gcm_id,$ user_level)
{
if($ user_level ==level) {
$ server_key =xys;
} else $ server_key =ABC;
$ msg = array
(
'message'=> $ message,
'title'=>'Title',
'vibrate'=> 1,
'sound'=> 1,
'largeIcon'=>'large_icon',
'smallIcon'=>'small_icon'
);
$ fields = array
(
'to'=> $ gcm_id,
'data'=> $ msg
);
$ b $ headers $ array
(
'Authorization:key ='。$ server_key,
'Content-Type:application / json'
);
$ ch = curl_init();
curl_setopt($ ch,CURLOPT_URL,'https://fcm.googleapis.com/fcm/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;
解决方案
h3>
1)确保你发送一个有效的json到fcm。
2)确保您发送的是正确的令牌。
有关如何发送通知的其他信息:
向特定设备发送消息要将消息发送到特定设备,请将该消息设置为特定应用程序实例的注册标记 / p>
curl -HContent-type:application / json-HAuthorization:key =< Your Api key> -X POST -d{data:{score:5x1,time:15:10},to:< registration token>}'https:// fcm。 googleapis.com/fcm/send
发送消息至主题
这里的主题是:/ topics / foo-bar
curl -H Content-type:application / json-HAuthorization:key =< Your Api key> -X POST -d{to:/ topics / foo-bar,data:{message:这是Firebase云消息传递主题消息!}} https://fcm.googleapis .com / fcm / send
向设备组发送消息
>
发送消息到设备组非常类似于将消息发送到单个设备。设置参数为设备组的唯一通知键
curl -HContent-type:application / json - H授权:密钥=<您的API密钥> -X POST -d{to:< aUniqueKey>,data:{hello:这是Firebase云消息传递设备组消息!}} https://fcm.googleapis。 com / fcm / send
原始:
问题是你的服务器配置。如果您想要在单个服务器上管理两个Firebase应用,则必须使用位于以下位置的Firebase APK_KEY配置两个Firebase应用:
转到Firebase控制台中的应用 - >点击右上角的三个点 - >管理 - >云消息 - >(服务器密钥)
在获得两个应用程序的服务器密钥后,你必须像这样配置它:
var firebaseLib = require(firebase);
$ b var app1Config = {
apiKey:< PROJECT_1_API_KEY>,
authDomain:< PROJECT_1_ID> .firebaseapp.com,
databaseURL:https ://< PROJECT_1_DATABASE_NAME> .firebaseio.com,
storageBucket:< PROJECT_1_BUCKET> .appspot.com,
}
var app2Config = {
apiKey: < PROJECT_2_API_KEY>,
authDomain:< PROJECT_2_ID> .firebaseapp.com,
databaseURL:https://< PROJECT_2_DATABASE_NAME> .firebaseio.com,
storageBucket: < PROJECT_2_BUCKET> .appspot.com,
}
var firebaseApp1 = firebaseLib.initaize(app1Config); // Primary
var firebaseApp2 = firebaseLib.initaize(app2Config,Secondary); // Secondary
I'm trying to work on a messenger app, but the twist here is I have 2 Entities (i.e. 2 apps A & B) here.
Now I'm trying to put messaging logic between the two using Firebase. Firebase doesn't support communication between two different applications (A & B) over the same project url. In order to overcome that restriction, I have used the same google-service.json
of app A for app B as well.
For app B, I have just changed the project id
and auth key
. That seems to have worked as I intended. I have tested the push notification as well using the Firebase Console and it seemed to have been working.
Then I have tried to implement the server logic. To make one-on-one notification.
CASE 1
But the problem arises here is that from app B, if I send a notification request, I get a MismatchSenderId
error where the project id has not been tempered with.
{"multicast_id":[removed],"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"MismatchSenderId"}]}
CASE 2
and for app A, here is the following response I get:
{"multicast_id":[removed],"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1473661851590851%0e4bcac9f9fd7ecd"}]}
For this, the success value is 1
hence, the notification should be sent but it's not sending when I'm making the request from the device. But it works flawlessly when I perform the same server call using Postman or any other client.
Here are my codes MyFirebaseInstanceIDService.java
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";
private static final String FRIENDLY_ENGAGE_TOPIC = "friendly_engage";
@Override
public void onCreate() {
String savedToken = Utility.getFirebaseInstanceId(getApplicationContext());
String defaultToken = getApplication().getString(R.string.pref_firebase_instance_id_default_key);
Log.d("GCM", savedToken);
if (savedToken.equalsIgnoreCase(defaultToken))
//currentToken is null when app is first installed and token is not available
//also skip if token is already saved in preferences...
{
String CurrentToken = FirebaseInstanceId.getInstance().getToken();
if (CurrentToken != null)
Utility.setFirebaseInstanceId(getApplicationContext(), CurrentToken);
Log.d("Value not set", CurrentToken);
updateFCMTokenId(CurrentToken);
}
super.onCreate();
}
/**
* The Application's current Instance ID token is no longer valid
* and thus a new one must be requested.
*/
@Override
public void onTokenRefresh() {
// If you need to handle the generation of a token, initially or
// after a refresh this is where you should do that.
String token = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "FCM Token: " + token);
Utility.setFirebaseInstanceId(getApplicationContext(), token);
updateFCMTokenId(token);
}
private void updateFCMTokenId(final String token) {
SQLiteHandler db = new SQLiteHandler(getBaseContext());
final HashMap<String, String> map = db.getUserDetails();
//update fcm token for push notifications
StringRequest str = new StringRequest(Request.Method.POST, AppConfig.UPDATE_GCM_ID, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("GCM RESPONSE", response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> param = new HashMap<>();
param.put("user_id", map.get("uid"));
param.put("gcm_registration_id", token);
return param;
}
};
str.setShouldCache(false);
str.setRetryPolicy(new DefaultRetryPolicy(AppConfig.DEFAULT_RETRY_TIME, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
AppController.getInstance().addToRequestQueue(str);
}
}
FirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//Displaying data in log
//It is optional
try {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getData().get("message"));
} catch (Exception e) {
e.printStackTrace();
}
//Calling method to generate notification
sendNotification(remoteMessage.getData().get("message"));
}
//This method is only generating push notification
//It is same as we did in earlier posts
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, ChatRoomActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
android.support.v4.app.NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("NAME")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
And here is the declaration in the Manifest.xml within Application
tag
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name=".MyFirebaseInstanceIDService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
TIA
CASE 1 Solved
I have managed to solve CASE 1 where for B I had to use the server api key of B , similarly for A
EDIT 2
Added Server side code
public function sendNotification($message, $gcm_id, $user_level)
{
if ($user_level == "level") {
$server_key = "xys";
} else $server_key = "ABC";
$msg = array
(
'message' => $message,
'title' => 'Title',
'vibrate' => 1,
'sound' => 1,
'largeIcon' => 'large_icon',
'smallIcon' => 'small_icon'
);
$fields = array
(
'to' => $gcm_id,
'data' => $msg
);
$headers = array
(
'Authorization: key=' . $server_key,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/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;
}
解决方案 Edit #1:
1) Make sure you are sending a valid json to the fcm.
2) Make sure you are sending to the right token.
Other informations on how to send notifications:
Send messages to specific devices
To send messages to specific devices, set the to the registration token for the specific app instance
curl -H "Content-type: application/json" -H "Authorization:key=<Your Api key>" -X POST -d '{ "data": { "score": "5x1","time": "15:10"},"to" : "<registration token>"}' https://fcm.googleapis.com/fcm/send
Send messages to topics
here the topic is : /topics/foo-bar
curl -H "Content-type: application/json" -H "Authorisation:key=<Your Api key>" -X POST -d '{ "to": "/topics/foo-bar","data": { "message": "This is a Firebase Cloud Messaging Topic Message!"}}' https://fcm.googleapis.com/fcm/send
Send messages to device groups
Sending messages to a device group is very similar to sending messages to an individual device. Set the to parameter to the unique notification key for the device group
curl -H "Content-type: application/json" -H "Authorisation:key=<Your Api key>" -X POST -d '{"to": "<aUniqueKey>","data": {"hello": "This is a Firebase Cloud Messaging Device Group Message!"}}' https://fcm.googleapis.com/fcm/send
Original:
The problem is you server configuration. If you want to manage two firebase apps in single server you have you have to config two firebase apps with your Firebase APK_KEY that located at:
Go to your applications in Firebase console -> Click on three dots at the top right -> Manage -> CLOUD MESSAGES -> (Server key)
After you get your both server keys for your two apps, you have to configure it like this:
var firebaseLib = require("firebase");
var app1Config = {
apiKey: "<PROJECT_1_API_KEY>",
authDomain: "<PROJECT_1_ID>.firebaseapp.com",
databaseURL: "https://<PROJECT_1_DATABASE_NAME>.firebaseio.com",
storageBucket: "<PROJECT_1_BUCKET>.appspot.com",
}
var app2Config = {
apiKey: "<PROJECT_2_API_KEY>",
authDomain: "<PROJECT_2_ID>.firebaseapp.com",
databaseURL: "https://<PROJECT_2_DATABASE_NAME>.firebaseio.com",
storageBucket: "<PROJECT_2_BUCKET>.appspot.com",
}
var firebaseApp1 = firebaseLib.initailize(app1Config); // Primary
var firebaseApp2 = firebaseLib.initailize(app2Config, "Secondary"); // Secondary
这篇关于Android未收到Firebase推送通知 - MismatchSenderId的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!