Насочените известия на Parse.com не се показват на заден план на android

Използвам Parse.com с приложение Ionic и PushPlugin и се опитвам да внедря Push Notifications на Parse чрез GCM с персонализиран ID на изпращача.

Когато изпращам съобщение до всички устройства или използвам REST API с cURL, известията за iOS се задействат добре, когато приложението е на заден план, но известията за android не са.

Ето какво опитах с останалия API First за 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 регистрационните файлове са различни при използване на API на GCM и API на Push Notifications на Parse:

С анализ:

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, за да работят с приложения за разрез на телефона?


person BarakChamo    schedule 07.02.2015    source източник
comment
Имам точно същия опит. Има ли късмет с това? Как настроихте инсталацията си в анализ?   -  person James Gilchrist    schedule 18.02.2015
comment
Причината, поради която известията не се показват, е, че Parse изпраща android известия до различен, персонализиран приемник. Трябва да включите Parse SDK, като използвате нещо като github.com/avivais/phonegap-parse-plugin но при мен плъгинът се поврежда. Това, което в крайна сметка направих, е да изпращам насочени известия за Android директно през GCM, а не чрез Parse Push.   -  person BarakChamo    schedule 18.02.2015
comment
Това беше моето подозрение. Също така се опитвах да използвам същата приставка за разбор, но тя се срива всеки път, когато се отвори. Предполагам, че това означава, че тогава не разработвате за iOS. Търся добро хибридно решение.   -  person James Gilchrist    schedule 18.02.2015
comment
Отворих проблем в репото за разбор на приставката, но досега не е помръднало. Всъщност разработвам за iOS и моето ужасно решение е да използвам помощник на Cloud Code, който сортира инсталациите по тип устройство и използва само Parse Push за iOS, останалите отиват в GCM с REST заявка. Честно казано, обмислям просто да внедря собствен сървър за насочване на Heroku с node-apns и да използвам изцяло персонализирано решение.   -  person BarakChamo    schedule 19.02.2015
comment
Почти съм сигурен, че имам решение... Ще актуализирам, когато проверя. Определено не е проблем с плъгин за натискане. Това е начинът, по който parse обгръща данните им и се анализира в GCMIntentService.java по същество анализира обгръща данните им с един слой по-дълбоко, отколкото очаква плъгинът за насочване.   -  person James Gilchrist    schedule 20.02.2015
comment
Бих се радвал да знам дали успявате, моля, актуализирайте :)   -  person BarakChamo    schedule 24.02.2015


Отговори (1)


За да използвате 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 Наблюдения:

  1. Анализът не включва „съобщение“ в известието, така че 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).

Вместо проверка bundle.getString("message") трябва да проверите за проверка за съществуването на payload.data и след това да анализирате съобщението и заглавието и да се уверите, че са на правилните места, за да работи функцията createNotification, като преопаковате пакета (или създадете свой собствен).

Моята препоръка е да оставите съществуващия код такъв, какъвто е, но да направите отделна проверка за форматирано известие за анализ и да извикате персонализирана функция createNotification.

As in:

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

person James Gilchrist    schedule 27.02.2015
comment
Това е фантастично @james-gilchrist! Наистина имам много малък опит в разработването на Android и не знаех откъде да започна с този проблем. - person BarakChamo; 28.02.2015