我曾经尝试使用GCM,但是我无法使用Parse Server。所以我采用了stackoverflow用户的建议并尝试使用FCM。
我的设备从FCM获取注册ID,如下所示:
04-15 17:01:29.773 I/parse.GcmRegistrar(30144): GCM registration successful. Registration Id: APA91bFoNUPYdsjN6O_CkPje-O0hXjNz9kvURZMex72xClyBr_5o6D0vYtI-F0iyAGgSYjpIEaJt2QQ2CXk2qpI11gPFUSUdzH-NxQRXSK3hPkuaiC_lciVV3E0fp6A_VZUoYJ8VxOIh
我尝试从firebase控制台发送一个带有此ID的通知,并且它的工作我的事件被触发了,一切都很好。
当我想使用ParseCloud函数向我的用户发送通知时,问题就出现了。当我在设备输出日志中搜索错误时,我找到了这个:
04-15 17:01:25.490 E/parse.GcmRegistrar(30144): Found com.parse.push.gcm_sender_id <meta-data> element with value "id:767075137222", but the value is missing the expected "id:" prefix
这个是奇怪的,因为我的清单包含gcm_sender_id加上它包含前缀id:这是我的清单
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.companyname.appname.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.companyname.appname.permission.C2D_MESSAGE" />
<application android:label="Fuse.Android" android:icon="@mipmap/ic_launcher">
<service android:name="parse.ParsePushService" />
<receiver android:name="parse.ParsePushBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.companyname.appname" />
</intent-filter>
</receiver>
<meta-data android:name="com.parse.push.gcm_sender_id"
android:value="id:767075137222"/>
</application>
我在网上搜索,人们说当你没有使用正确的API KEY&amp;发件人ID ..我正在使用这些:
接下来,我的Parse Server索引如下所示:
// Example express application adding the parse-server module to expose Parse
// compatible API routes.
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
var databaseUri = process.env.DATABASE_URI || process.env.MONGODB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var pushConfig = {};
if (process.env.GCM_SENDER_ID && process.env.GCM_API_KEY) {
pushConfig['android'] = {
senderId: process.env.GCM_SENDER_ID || '',
apiKey: process.env.GCM_API_KEY || ''};
}
var api = new ParseServer({
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'myAppId',
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret!
serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse', // Don't forget to change to https if needed
push: pushConfig,
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query subscriptions
}
});
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
// If you wish you require them, you can set them as options in the initialization above:
// javascriptKey, restAPIKey, dotNetKey, clientKey
var app = express();
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('I dream of being a website. Please star the parse-server repo on GitHub!');
});
// There will be a test page available on the /test path of your server url
// Remove this before launching your app
app.get('/test', function(req, res) {
res.sendFile(path.join(__dirname, '/public/test.html'));
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
我已将GCM_SENDER_ID和GCM_API_KEY定义为Heroku主机Parse的配置变量。
在我从客户端应用程序调用ParseCloud函数后,我在heroku日志中得到了这个:
Apr 15 08:03:02 fuseparse app/web.1: } method=POST, url=/parse/push, host=fuseparse.herokuapp.com, connection=close, user-agent=node-XMLHttpRequest, Parse/js1.11.1 (NodeJS 9.11.1), accept=*/*, content-type=text/plain, x-request-id=ea046fd0-5fb7-46b7-9ceb-e6a0fd2ebad1, x-forwarded-for=54.81.77.161, x-forwarded-proto=https, x-forwarded-port=443, via=1.1 vegur, connect-time=0, x-request-start=1523804582292, total-route-time=0, content-length=270, installationId=e2dc9f85-3c2f-464e-beca-c8b9d2cba528, alert=The Giants scored!
Apr 15 08:03:02 fuseparse app/web.1: verbose: RESPONSE from [POST] /parse/push: {
Apr 15 08:03:02 fuseparse app/web.1: "headers": {
Apr 15 08:03:02 fuseparse app/web.1: "X-Parse-Push-Status-Id": "upnMh1652U"
Apr 15 08:03:02 fuseparse app/web.1: },
Apr 15 08:03:02 fuseparse app/web.1: "response": {
Apr 15 08:03:02 fuseparse app/web.1: "result": true
Apr 15 08:03:02 fuseparse app/web.1: }
Apr 15 08:03:02 fuseparse app/web.1: } X-Parse-Push-Status-Id=upnMh1652U, result=true
Apr 15 08:03:02 fuseparse app/web.1: #### PUSH OK
Apr 15 08:03:02 fuseparse app/web.1: verbose: _PushStatus upnMh1652U: sending push to installations with 1 batches
Apr 15 08:03:02 fuseparse app/web.1: verbose: Sending push to 1
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM sending to 1 device
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM GCM Response: {
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM "multicast_id": 5516369214301735000,
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM "success": 0,
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM "failure": 1,
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM "canonical_ids": 0,
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM "results": [
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM {
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM "error": "MismatchSenderId"
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM }
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM ]
Apr 15 08:03:02 fuseparse app/web.1: node-pre-gyp verb parse-server-push-adapter GCM }
Apr 15 08:03:02 fuseparse app/web.1: verbose: _PushStatus upnMh1652U: sent push! 0 success, 1 failures
Apr 15 08:03:02 fuseparse app/web.1: verbose: _PushStatus upnMh1652U: needs cleanup devicesToRemove=[]
我已经好几天了。有人可以告诉我,我试图做什么是可能的,如果有可能我可能做错了什么?
答案 0 :(得分:0)
如果您使用的是fcm通知,则需要在清单中添加此内容!
<!-- Firebase Notifications -->
<service android:name=".HERE_YOUR_CLASS_WHICH_EXTENDS_FirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".HERE_YOUR_CLASS_WHICH_EXTENDS_FirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<!-- ./Firebase Notifications -->
答案 1 :(得分:0)
遇到此错误的任何人:
04-15 17:01:25.490 E/parse.GcmRegistrar(30144): Found com.parse.push.gcm_sender_id <meta-data> element with value "id:767075137222", but the value is missing the expected "id:" prefix
但是已经定义了androidmanifest中的gcm_sender_id,很可能是安装了错误的sdk或parse.dll。我做的是我下载了parseplatform github中提供的开源SDK,并修改了GcmRegistrar.cs类,不为sender_id返回null:
这花了我很长时间,但对于遇到同样问题的人请下载最新的.dll,或者如果问题仍然存在,则意味着dll没有更新,你必须手动执行此操作。在我的情况下,我使用.NET Sdk并且它没有更新。
下载开源sdk并用此替换Internal / Push / GcmRegistrar.cs
using System;
using Android.App;
using Android.Content;
using Android.OS;
using System.Threading.Tasks;
namespace Parse {
internal class GcmRegistrar {
private const string LogTag = "parse.GcmRegistrar";
private const string ExtraRegistrationId = "registration_id";
private const string ExtraSenderId = "com.parse.push.gcm_sender_id";
private const string ParseGcmSenderId = "1076345567071";
public const string IntentRegisterAction = "com.google.android.c2dm.intent.REGISTER";
private readonly Object mutex = new Object();
private Request request;
private Context context;
public static GcmRegistrar GetInstance() {
return Singleton.Instance;
}
private static class Singleton {
public static readonly GcmRegistrar Instance = new GcmRegistrar(Application.Context);
}
private GcmRegistrar(Context context) {
this.context = context;
}
private string getActualSenderIdFromExtra(Object senderIdExtra) {
if (senderIdExtra == null ) {
return null;
}
string senderId = senderIdExtra.ToString();
if (!senderId.StartsWith("id:")) {
return null;
}
return senderId.Substring(3);
}
public void Register() {
ParseInstallation installation = ParseInstallation.CurrentInstallation;
lock (mutex) {
if (installation.DeviceToken == null && request == null) {
var metadata = ManifestInfo.GetApplicationMetaData();
object senderIdExtra = null;
if (metadata != null) {
senderIdExtra = metadata.Get(ExtraSenderId);
}
string senderIds = ParseGcmSenderId;
if (senderIdExtra != null) {
string senderId = getActualSenderIdFromExtra(senderIdExtra);
if (senderId != null) {
senderIds += "," + senderId;
} else {
Android.Util.Log.Error("parse.GcmRegistrar", "Found " + ExtraSenderId + " <meta-data> element with value \""
+ senderIdExtra.ToString() + "\", but the value is missing the expected \"id:\" prefix");
}
}
request = Request.CreateAndSend(this.context, senderIds);
}
}
}
/// <summary>
/// Handles GCM registration intent from <see cref="ParsePushBroadcastReceiver"/> and saves the GCM registration
/// id as <see cref="ParseInstallation.CurrentInstallation"/> device token.
/// </summary>
/// <remarks>
/// Should be called by a broadcast receiver or service to handle GCM registration response
/// intent (com.google.android.c2dm.intent.REGISTRATION).
/// </remarks>
/// <param name="intent"></param>
public Task HandleRegistrationIntentAsync(Intent intent) {
if (intent.Action == ParsePushBroadcastReceiver.ActionGcmRegisterResponse) {
string registrationId = intent.GetStringExtra(ExtraRegistrationId);
if (registrationId != null && registrationId.Length > 0) {
Android.Util.Log.Info(LogTag, "GCM registration successful. Registration Id: " + registrationId);
ParseInstallation installation = ParseInstallation.CurrentInstallation;
// Set `pushType` via internal `Set` method since we want to skip mutability check.
installation.Set("pushType", "gcm");
installation.DeviceToken = registrationId;
return installation.SaveAsync();
}
}
return Task.FromResult(0);
}
/// <summary>
/// Encapsulates the GCM registration request-response, potentially using <c>AlarmManager</c> to
/// schedule retries if the GCM service is not available.
/// </summary>
private class Request {
private Context context;
private string senderId;
private PendingIntent appIntent;
public static Request CreateAndSend(Context context, string senderId) {
Request request = new Request(context, senderId);
request.Send();
return request;
}
private Request(Context context, string senderId) {
this.context = context;
this.senderId = senderId;
appIntent = PendingIntent.GetBroadcast(context, 0, new Intent(), 0);
}
private void Send() {
Intent intent = new Intent(IntentRegisterAction);
intent.SetPackage("com.google.android.gsf");
intent.PutExtra("sender", senderId);
intent.PutExtra("app", appIntent);
ComponentName name = null;
try {
name = context.StartService(intent);
} catch (Exception) {
// Do nothing.
}
}
}
}
}