【问题标题】:Parse.com push notifications not shown in background on androidParse.com 推送通知未在 android 的后台显示
【发布时间】:2015-02-07 14:29:45
【问题描述】:

我将 Parse.com 与 Ionic 应用程序和 PushPlugin 一起使用,并尝试通过 GCM 使用自定义发件人 ID 实现 Parse 的推送通知。

当我向所有设备发送消息,或使用带有 cURL 的 REST API 时, 当应用在后台时,iOS 通知可以正常触发,而 android 通知则不是。

这是我尝试使用 iOS 的其余 API First 的方法,效果很好:

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 应用上工作方面有任何经验?

【问题讨论】:

  • 我也有同样的经历。这有什么好运气吗?您是如何在 parse 中设置安装的?
  • 通知未显示的原因是 Parse 将 android 通知发送到不同的自定义接收器。您必须使用 github.com/avivais/phonegap-parse-plugin 之类的东西包含 Parse SDK,但对我来说插件会中断。我最终做的是直接通过 GCM 而不是 Parse Push 发送 android 推送通知。
  • 这是我的怀疑。我也尝试使用相同的解析插件,但每次打开它都会崩溃。我猜这意味着你那时不是为 iOS 开发的。我正在寻找一个好的混合解决方案。
  • 我在 parse-plugin repo 上打开了一个问题,但到目前为止它还没有移动。实际上,我正在为 iOS 开发,我糟糕的解决方法是使用 Cloud Code 助手,它按设备类型对安装进行排序,并且只使用 Parse Push for iOS,其余的通过 REST 请求转到 GCM。老实说,我正在考虑使用 node-apns 在 Heroku 上实现我自己的推送服务器,并完全使用自定义解决方案。
  • 我很确定我有一个解决方案...我会在验证时更新。这绝对不是推送插件问题。它如何 parse 包装他们的数据,它在 GCMIntentService.java 中被解析基本上 parse 将他们的数据包装得比推送插件预期的更深一层。

标签: cordova parse-platform google-cloud-messaging ionic-framework phonegap-pushplugin


【解决方案1】:

为了将 phonegap/cordova PushPlugin 与 Parse Push 一起使用,您必须意识到 Parse 实际上以非标准方式包装其内容。这会导致 PushPlugin 在应用程序处于前台时收到推送通知,但在后台时则不会。

来自 GCMIntentService.java 的源代码 sn-p

@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() 失败时,它会检查附加包上的“消息”属性。

2 观察:

  1. Parse 在通知中不包含“消息”,因此 PushPlugin 不会调用 createNotification(content, extras)
  2. 如果您查看捆绑包的“有效负载”属性,它还通过将通知放置在具有键“数据”的对象中,将其包装比“传统”GCM 通知更深一层。

这是捆绑包在 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 函数。

如:

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

【讨论】:

  • 太棒了@james-gilchrist!我在 Android 开发方面的经验真的很少,不知道从哪里开始。
猜你喜欢
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多