我正在开发一款使用推送通知功能的Android应用。我需要从服务器推送。我使用Firebase。坦率地说,这是我第一次使用Firebase。我是Firebase的新手。但是当我使用PHP和CURL从服务器推送时,它给了我无效的注册错误。
我在Android中获得了Firebase令牌
String token = FirebaseInstanceId.getInstance().getToken();
然后我将该令牌保存到服务器并保存在数据库中。
在服务器上,我正在这样推动
class Pusher extends REST_Controller {
function __construct()
{
parent::__construct();
}
public function notification_get()
{
$rows = $this->db->get('device_registration')->result();
$tokens= array();
if(count($rows)>0)
{
foreach($rows as $row)
{
$tokens[] = $row->token;
}
}
$message = array("message"=>"FCM PUSH NOTIFICATION TESTING");
if(count($tokens)>0)
{
$result = $this->send_notification($tokens,$message);
if(!$result)
{
die("Unable to send");
}
else{
$this->response($result, REST_Controller::HTTP_OK);
}
}
}
function send_notification($tokens,$message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids'=>$tokens,
'data'=>$message
);
$headers = array(
'Authorization:key = AIzaSyApyfgXsNQ3dFTGWR6ns_9pttr694VDe5M',//Server key from firebase
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if($result==FALSE)
{
return FALSE;
}
curl_close($ch);
return $result;
}
}
我正在使用CodeIgniter 3框架来构建Rest API。当我从浏览器推送访问URL时,它会返回带有错误的JSON数据,如下面的屏幕截图所示。
正如您所看到的,它提供了InvalidRegistration错误,并且未将消息推送到设备。我的代码出了什么问题?
这是我的FirebaseMessagingService类,它在android
中显示通知public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
showNotification(remoteMessage.getData().get("message"));
}
private void showNotification(String message)
{
Intent i = new Intent(this,MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setAutoCancel(true)
.setContentTitle("FCM Test")
.setContentText(message)
.setSmallIcon(R.drawable.info)
.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
manager.notify(0,builder.build());
}
}
答案 0 :(得分:3)
对于 Android 中的 Java 不要使用 FirebaseInstallation 生成令牌我不知道为什么,但它没有返回有效的令牌。每次尝试通过 FCM REST API POST 时收到“InvalidRegistration”。
{
"multicast_id": 8303815118005358735,
"success": 0,
"failure": 1,
"canonical_ids": 0,
"results": [
{
"error": "InvalidRegistration"
}
]
}
改为使用这个:
if (firebaseUser != null) {
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
Log.d(TAG, "getInstanceId failed", task.getException());
return;
}
if (task.getResult() != null) updateToken(task.getResult().getToken());
});
}
private void updateToken(String refreshToken) {
DocumentReference documentReference;
Token token1 = new Token(refreshToken);//just a class with str field
Map<String, Object> tokenMAp = new HashMap<>();
tokenMAp.put("tokenKey", token1.getToken());
Log.d(TAG, "updateToken: " + token1.getToken());
String id = firebaseUser.getUid();
baseref=sp.getString(BASE_REF,DEFAULT);
documentReference= FirebaseFirestore.getInstance().document(baseref);
updateDocWithToken(documentReference,tokenMAp);
}
private void updateDocWithToken(DocumentReference documentReference, Map<String, Object> tokenMAp) {
documentReference.set(tokenMAp, SetOptions.merge());
}
答案 1 :(得分:2)
无效的注册ID检查注册ID的格式 你传递给服务器。确保它与注册ID匹配 手机会在com.google.firebase.INSTANCE_ID_EVENT中收到 意图,并且您不会截断它或添加额外的 字符。错误代码为InvalidRegistration时发生。
请与应用方和您方共同确认,移动设备上的应用程序在onTokenRefresh
方法中将相同的注册ID存储在服务器中。您应该已经收到与FirebaseInstanceId.getInstance().getToken()
当我收到您的评论并且您已经更新了代码时,您的代码中的一些更改是来自Google doc自己...
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
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());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// 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.
}
Firebase有三种消息类型:
通知消息:通知消息适用于后台或 前景。当应用程序在后台时,通知消息是 送到系统托盘。如果应用程序在前台, 消息由onMessageReceived()或。处理 didReceiveRemoteNotification回调。这些本质上是什么 称为显示消息。
数据消息:在Android平台上,可以使用数据消息 背景和前景。数据消息将由。处理 onMessageReceived()。这里的平台特定说明将是:开 Android,可以在Intent中检索数据有效负载 发起你的活动。
包含通知和数据有效负载的消息:当在。时 后台,应用程序在通知中接收通知有效负载 托盘,仅在用户点击时处理数据有效负载 通知。在前台时,您的应用会收到一条消息 两个有效负载都可用的对象。其次,click_action 参数通常用于通知有效负载而不是数据 有效载荷。如果在数据有效负载内使用,则将处理此参数 作为自定义键值对,因此您需要实现 自定义逻辑,使其按预期工作。
答案 2 :(得分:1)
虽然我没有使用codeigniter,并且在发送到InvalidRegistration
设备时遇到iOS
错误,但我想我会分享我是如何解决这种情况的。
在向{em>单设备令牌发送Notification message
时,我必须在PHP中将 registration_ids 更改为到,并确保到的值是一个字符串,而不是一个数组。
改变这个:
'registration_ids'=>$tokens,
对此:
'to'=>$tokens[0],