Parse.com android 的后台未显示推送通知
Parse.com push notifications not shown in background on android
我将 Parse.com 与 Ionic 应用程序和 PushPlugin 一起使用,并尝试使用自定义发件人 ID 通过 GCM 实施 Parse 的推送通知。
当我向所有设备发送消息时,或将 REST API 与 cURL 一起使用时,
iOS 当应用程序在后台时通知会正常触发,但 android 通知不会。
这是我对其余部分 API 的尝试,首先是 iOS,效果很好:
curl -X POST \
-H "X-Parse-Application-Id: APP-ID" \
-H "X-Parse-REST-API-Key: API-KEY" \
-H "Content-Type: application/json" \
-d '{
"where": {
"deviceType": "ios"
},
"data": {
"alert": "Hello World!"
}
}' \
https://api.parse.com/1/push
即使应用程序在后台关闭或打开,也会收到并显示 iOS 通知。
现在,当我为 android 台设备尝试相同的定位时:
curl -X POST \
-H "X-Parse-Application-Id: APP-ID" \
-H "X-Parse-REST-API-Key: API-KEY" \
-H "Content-Type: application/json" \
-d '{
"where": {
"deviceType": "android"
},
"data": {
"alert": "Hello World!"
}
}' \
https://api.parse.com/1/push
通知已被设备接收并部分登录adb logcat
,但未显示在通知栏中或以其他方式确认。我尝试将 'alert'
更改为 'message'
但没有效果。
但是,如果我尝试将 GCM HTTP API 与 Postman 或 cURL 一起使用,一切正常:
curl 'https://android.googleapis.com/gcm/send' \
-H 'authorization: key=API-KEY' \
-H 'content-type: application/json' \
-d '{
"registration_ids" : [
"DEVICE-REGISTRATION-ID"
],
"data" : {
"message": "You Go I Go, Buddy!"
}
}'
当记录 adb logcat
时,使用 GCM API 和 Parse 的推送通知 API 时的日志不同:
使用解析:
I/GCM (10319): GCM message co.yougoigo.mobile 0:1423318254669687%bd9ff524f9fd7ecd
V/GCMBroadcastReceiver(11506): onReceive: com.google.android.c2dm.intent.RECEIVE
V/GCMBroadcastReceiver(11506): GCM IntentService class: com.plugin.gcm.GCMIntentService
V/GCMBaseIntentService(11506): Acquiring wakelock
V/GCMBaseIntentService(11506): Intent service name: GCMIntentService-GCMIntentService-3
D/GCMIntentService(11506): onMessage - context: android.app.Application@251ee33b
并使用 GCM cURL 调用:
I/GCM (10319): GCM message co.yougoigo.mobile 0:1423318321652064%bd9ff524f9fd7ecd
I/ActivityManager( 745): Start proc co.yougoigo.mobile for broadcast co.yougoigo.mobile/com.plugin.gcm.CordovaGCMBroadcastReceiver: pid=11788 uid=10187 gids={50187, 9997, 3003} abi=armeabi-v7a
V/GCMBroadcastReceiver(11788): onReceive: com.google.android.c2dm.intent.RECEIVE
V/GCMRegistrar(11788): Setting the name of retry receiver class to com.plugin.gcm.CordovaGCMBroadcastReceiver
V/GCMBroadcastReceiver(11788): GCM IntentService class: com.plugin.gcm.GCMIntentService
V/GCMBaseIntentService(11788): Acquiring wakelock
V/GCMBaseIntentService(11788): Intent service name: GCMIntentService-GCMIntentService-1
D/GCMIntentService(11788): onMessage - context: android.app.Application@251ee33b
E/GCMIntentService(11788): Number format exception - Error parsing Notification ID: Invalid int: "null"
V/GCMBaseIntentService(11788): Releasing wakelock
当前清单如下:
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="4" android:versionName="0.0.4" package="co.yougoigo.mobile" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="CordovaApp" android:theme="@android:style/Theme.Black.NoTitleBar" android:windowSoftInputMode="adjustResize">
<intent-filter android:label="@string/launcher_name">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:exported="true" android:name="com.plugin.gcm.PushHandlerActivity" />
<receiver android:name="com.plugin.gcm.CordovaGCMBroadcastReceiver" 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="co.yougoigo.mobile" />
</intent-filter>
</receiver>
<service android:name="com.plugin.gcm.GCMIntentService" />
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/fb_app_id" />
<activity android:label="@string/fb_app_name" android:name="com.facebook.LoginActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" />
</application>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="co.yougoigo.mobile.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="co.yougoigo.mobile.permission.C2D_MESSAGE" />
</manifest>
有没有人有让 GCM 通知在 phonegap 应用程序上工作的经验?
为了将 phonegap/cordova PushPlugin 与 Parse Push 一起使用,您必须意识到 Parse 实际上以非标准方式包装其内容。这会导致 PushPlugin 在应用程序处于前台时收到推送通知,但在后台时则不会。
来自 GCMIntentService.java
的源代码片段
@Override
protected void onMessage(Context context, Intent intent) {
Log.d(TAG, "onMessage - context: " + context);
// Extract the payload from the message
Bundle extras = intent.getExtras();
if (extras != null)
{
// if we are in the foreground, just surface the payload, else post it to the statusbar
if (PushPlugin.isInForeground()) {
extras.putBoolean("foreground", true);
PushPlugin.sendExtras(extras);
}
else {
extras.putBoolean("foreground", false);
// Send a notification if there is a message
if (extras.getString("message") != null && extras.getString("message").length() != 0) {
createNotification(context, extras);
}
}
}
}
如您所见,当 PushPlugin.isInForeground()
检查失败时,它会检查附加包上的 'message' 属性。
2 个观察:
- Parse 不在通知中包含 'message',因此 PushPlugin 不会调用
createNotification(content, extras)
- 如果您查看捆绑包的 'payload' 属性,它还通过将通知放在 object 中,将其包裹得比 "traditional" GCM 通知深一层键 'data'.
JSON
中的捆绑包如下所示
{ ...
"payload" : {
"data" : {
"message" : "your message here",
"title": "your title here",
...,
"customData": { ... }
}
}
因此,您必须执行一些自定义逻辑以从包 extras.getString("payload")
中提取有效负载,然后创建一个新的 JSONObject(此处的文档:http://developer.android.com/reference/org/json/JSONObject.html).
您需要检查 payload.data 是否存在,而不是检查 bundle.getString("message")
,然后解析消息和标题,并确保它们位于正确的位置,以便 createNotification 函数正常工作通过重新打包捆绑包(或创建您自己的捆绑包)。
我的建议是保留现有代码,但单独检查解析格式的通知并调用自定义 createNotification 函数。
如:
if (PushPlugin.isInForeground()) {
extras.putBoolean("foreground", true);
PushPlugin.sendExtras(extras);
} else if (extras.getString("message") && extras.getString("message").length() != 0) {
extras.putBoolean("foreground", false);
createNotification(context, extras);
} else {
JSONObject payload = extras.getString("payload");
JSONObject data = payload.getJSONObject("data");
String message = data.getString("alert") //parse puts the message as an alert if you don't use custom json payload
extras.putString("message", alert)
createNotification(context, extras)
}
希望这对您有所帮助。老实说,我希望 parse 像其他人一样发送数据,以便它与开箱即用的 PushPlugin 兼容。
在此处找到 PushPlugin GCMIntentService.java 的源代码(官方 github 回购):https://github.com/phonegap-build/PushPlugin/blob/master/src/android/com/plugin/gcm/GCMIntentService.java
我将 Parse.com 与 Ionic 应用程序和 PushPlugin 一起使用,并尝试使用自定义发件人 ID 通过 GCM 实施 Parse 的推送通知。
当我向所有设备发送消息时,或将 REST API 与 cURL 一起使用时, iOS 当应用程序在后台时通知会正常触发,但 android 通知不会。
这是我对其余部分 API 的尝试,首先是 iOS,效果很好:
curl -X POST \
-H "X-Parse-Application-Id: APP-ID" \
-H "X-Parse-REST-API-Key: API-KEY" \
-H "Content-Type: application/json" \
-d '{
"where": {
"deviceType": "ios"
},
"data": {
"alert": "Hello World!"
}
}' \
https://api.parse.com/1/push
即使应用程序在后台关闭或打开,也会收到并显示 iOS 通知。
现在,当我为 android 台设备尝试相同的定位时:
curl -X POST \
-H "X-Parse-Application-Id: APP-ID" \
-H "X-Parse-REST-API-Key: API-KEY" \
-H "Content-Type: application/json" \
-d '{
"where": {
"deviceType": "android"
},
"data": {
"alert": "Hello World!"
}
}' \
https://api.parse.com/1/push
通知已被设备接收并部分登录adb logcat
,但未显示在通知栏中或以其他方式确认。我尝试将 'alert'
更改为 'message'
但没有效果。
但是,如果我尝试将 GCM HTTP API 与 Postman 或 cURL 一起使用,一切正常:
curl 'https://android.googleapis.com/gcm/send' \
-H 'authorization: key=API-KEY' \
-H 'content-type: application/json' \
-d '{
"registration_ids" : [
"DEVICE-REGISTRATION-ID"
],
"data" : {
"message": "You Go I Go, Buddy!"
}
}'
当记录 adb logcat
时,使用 GCM API 和 Parse 的推送通知 API 时的日志不同:
使用解析:
I/GCM (10319): GCM message co.yougoigo.mobile 0:1423318254669687%bd9ff524f9fd7ecd
V/GCMBroadcastReceiver(11506): onReceive: com.google.android.c2dm.intent.RECEIVE
V/GCMBroadcastReceiver(11506): GCM IntentService class: com.plugin.gcm.GCMIntentService
V/GCMBaseIntentService(11506): Acquiring wakelock
V/GCMBaseIntentService(11506): Intent service name: GCMIntentService-GCMIntentService-3
D/GCMIntentService(11506): onMessage - context: android.app.Application@251ee33b
并使用 GCM cURL 调用:
I/GCM (10319): GCM message co.yougoigo.mobile 0:1423318321652064%bd9ff524f9fd7ecd
I/ActivityManager( 745): Start proc co.yougoigo.mobile for broadcast co.yougoigo.mobile/com.plugin.gcm.CordovaGCMBroadcastReceiver: pid=11788 uid=10187 gids={50187, 9997, 3003} abi=armeabi-v7a
V/GCMBroadcastReceiver(11788): onReceive: com.google.android.c2dm.intent.RECEIVE
V/GCMRegistrar(11788): Setting the name of retry receiver class to com.plugin.gcm.CordovaGCMBroadcastReceiver
V/GCMBroadcastReceiver(11788): GCM IntentService class: com.plugin.gcm.GCMIntentService
V/GCMBaseIntentService(11788): Acquiring wakelock
V/GCMBaseIntentService(11788): Intent service name: GCMIntentService-GCMIntentService-1
D/GCMIntentService(11788): onMessage - context: android.app.Application@251ee33b
E/GCMIntentService(11788): Number format exception - Error parsing Notification ID: Invalid int: "null"
V/GCMBaseIntentService(11788): Releasing wakelock
当前清单如下:
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="4" android:versionName="0.0.4" package="co.yougoigo.mobile" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="CordovaApp" android:theme="@android:style/Theme.Black.NoTitleBar" android:windowSoftInputMode="adjustResize">
<intent-filter android:label="@string/launcher_name">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:exported="true" android:name="com.plugin.gcm.PushHandlerActivity" />
<receiver android:name="com.plugin.gcm.CordovaGCMBroadcastReceiver" 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="co.yougoigo.mobile" />
</intent-filter>
</receiver>
<service android:name="com.plugin.gcm.GCMIntentService" />
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/fb_app_id" />
<activity android:label="@string/fb_app_name" android:name="com.facebook.LoginActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" />
</application>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="co.yougoigo.mobile.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="co.yougoigo.mobile.permission.C2D_MESSAGE" />
</manifest>
有没有人有让 GCM 通知在 phonegap 应用程序上工作的经验?
为了将 phonegap/cordova PushPlugin 与 Parse Push 一起使用,您必须意识到 Parse 实际上以非标准方式包装其内容。这会导致 PushPlugin 在应用程序处于前台时收到推送通知,但在后台时则不会。
来自 GCMIntentService.java
的源代码片段@Override
protected void onMessage(Context context, Intent intent) {
Log.d(TAG, "onMessage - context: " + context);
// Extract the payload from the message
Bundle extras = intent.getExtras();
if (extras != null)
{
// if we are in the foreground, just surface the payload, else post it to the statusbar
if (PushPlugin.isInForeground()) {
extras.putBoolean("foreground", true);
PushPlugin.sendExtras(extras);
}
else {
extras.putBoolean("foreground", false);
// Send a notification if there is a message
if (extras.getString("message") != null && extras.getString("message").length() != 0) {
createNotification(context, extras);
}
}
}
}
如您所见,当 PushPlugin.isInForeground()
检查失败时,它会检查附加包上的 'message' 属性。
2 个观察:
- Parse 不在通知中包含 'message',因此 PushPlugin 不会调用
createNotification(content, extras)
- 如果您查看捆绑包的 'payload' 属性,它还通过将通知放在 object 中,将其包裹得比 "traditional" GCM 通知深一层键 'data'.
JSON
中的捆绑包如下所示{ ...
"payload" : {
"data" : {
"message" : "your message here",
"title": "your title here",
...,
"customData": { ... }
}
}
因此,您必须执行一些自定义逻辑以从包 extras.getString("payload")
中提取有效负载,然后创建一个新的 JSONObject(此处的文档:http://developer.android.com/reference/org/json/JSONObject.html).
您需要检查 payload.data 是否存在,而不是检查 bundle.getString("message")
,然后解析消息和标题,并确保它们位于正确的位置,以便 createNotification 函数正常工作通过重新打包捆绑包(或创建您自己的捆绑包)。
我的建议是保留现有代码,但单独检查解析格式的通知并调用自定义 createNotification 函数。
如:
if (PushPlugin.isInForeground()) {
extras.putBoolean("foreground", true);
PushPlugin.sendExtras(extras);
} else if (extras.getString("message") && extras.getString("message").length() != 0) {
extras.putBoolean("foreground", false);
createNotification(context, extras);
} else {
JSONObject payload = extras.getString("payload");
JSONObject data = payload.getJSONObject("data");
String message = data.getString("alert") //parse puts the message as an alert if you don't use custom json payload
extras.putString("message", alert)
createNotification(context, extras)
}
希望这对您有所帮助。老实说,我希望 parse 像其他人一样发送数据,以便它与开箱即用的 PushPlugin 兼容。
在此处找到 PushPlugin GCMIntentService.java 的源代码(官方 github 回购):https://github.com/phonegap-build/PushPlugin/blob/master/src/android/com/plugin/gcm/GCMIntentService.java