it-swarm.com.ru

Заставить GCM работать на iOS-устройстве в фоновом режиме

Я пытаюсь использовать GCM для IOS и клиентов Android. Кажется, что он отлично работает с IOS, когда приложение находится на переднем плане, однако, когда приложение находится в фоновом режиме, центр уведомлений не получает сообщение и didReceiveRemoteNotification with completionHandler не вызывается.

Я идентифицировал проблему как неправильно отформатированное сообщение от GCM к APNS. А именно так это выглядит: 

 [сообщение: новое сообщение, collapse_key: do_not_collapse, от: **************]
В то время как push-уведомления IOS должны иметь в уведомлении ключ aps, я прав? А также для содержимого доступно установлено значение 1. Например:

{ "aps": { "контент-доступен": 1 }, "data-id": 345 }

Кстати, на переднем плане приложение все равно получает сообщение, проблема только с фоном. Любой совет, как я должен подходить к проблеме, чтобы заставить GCM работать как для IOS, так и для Android?

UPDATE: Вот что я нашел в сети:

Что касается фактической связи, пока приложение находится в фоновом режиме на устройстве iOS, GCM использует APNS для отправки сообщений, приложение работает так же, как и система уведомлений Apple. Но когда приложение активно, GCM напрямую связывается с приложением

Итак, сообщение, которое я получил в режиме переднего плана:

[сообщение: новое сообщение, collapse_key: do_not_collapse, от: **************]

Было прямое сообщение от GCM (APNS вообще не участвовала в этом деле). Таким образом, вопрос заключается в следующем: переформатирует ли APNS то, что отправляет ему GCM, чтобы придерживаться формата уведомлений ios? Если да, то как я узнаю, что APNS действительно что-то делает и отправляет ли мне уведомление в другом формате? Есть ли способ просмотреть логи входящих данных из APNS?

ОБНОВЛЕНИЕ: Хорошо, мне удалось изменить структуру сообщения, и теперь в режиме переднего плана я получаю следующее сообщение:

Получено уведомление: ["aps": {"alert": "Простое сообщение", "content-available": 1}, collapse_key: do_not_collapse, from: **************]

Теперь он выглядит хорошо отформатированным, но пока приложение не работает в фоновом режиме. завершение didReceiveRemoteNotifificationHandler не вызывается! Что я должен искать и где может быть проблема? Может ли квадратная скобка стать проблемой для push-уведомлений? Чтобы быть еще более точным, ios не публикует оповещения/значки/баннеры из этого входящего уведомления.

25
Olexiy Burov

Для каждой бедной души, интересующейся поиском ответа на фоновую загадку GCM. Я решил это, и проблема была в формате. Я публикую правильный формат, а также Java-код, необходимый для отправки запроса Http в GCM с некоторым сообщением . Поэтому в запросе Http должно быть два поля в заголовке, а именно:

Authorization:key="here goes your GCM api key"
Content-Type:application/json for JSON data type

тогда тело сообщения должно быть словарем json с ключами «to» и «уведомлением». Например:

{
  "to": "gcm_token_of_the_device",
  "notification": {
    "sound": "default",
    "badge": "2",
    "title": "default",
    "body": "Test Push!"
  }
}

Вот простая Java-программа (использующая только библиотеки Java), которая отправляет Push на указанное устройство, используя GCM:

public class SendMessage {

    //config
    static String apiKey = ""; // Put here your API key
    static String GCM_Token = ""; // put the GCM Token you want to send to here
    static String notification = "{\"sound\":\"default\",\"badge\":\"2\",\"title\":\"default\",\"body\":\"Test Push!\"}"; // put the message you want to send here
    static String messageToSend = "{\"to\":\"" + GCM_Token + "\",\"notification\":" + notification + "}"; // Construct the message.

    public static void main(String[] args) throws IOException {
        try {

            // URL
            URL url = new URL("https://Android.googleapis.com/gcm/send");

            System.out.println(messageToSend);
            // Open connection
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            // Specify POST method
            conn.setRequestMethod("POST");

            //Set the headers
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Authorization", "key=" + apiKey);
            conn.setDoOutput(true);

            //Get connection output stream
            DataOutputStream wr = new DataOutputStream(conn.getOutputStream());

            byte[] data = messageToSend.getBytes("UTF-8");
            wr.write(data);

            //Send the request and close
            wr.flush();
            wr.close();

            //Get the response
            int responseCode = conn.getResponseCode();
            System.out.println("\nSending 'POST' request to URL : " + url);
            System.out.println("Response Code : " + responseCode);

            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            //Print result
            System.out.println(response.toString()); //this is a good place to check for errors using the codes in http://androidcommunitydocs.com/reference/com/google/Android/gcm/server/Constants.html

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
26
Olexiy Burov

Важно отметить, что на устройствах iOS, если ваше приложение, использующее GCM, было уничтожено (проведено в переключателе приложений), ваше устройство будет активировано только после получения сообщения, если вы отправите уведомление с «уведомлением», «content_available» и «приоритет» (установлен на «высокий»). Если у вас есть один или другой, он может работать, когда приложение было убито. Но как только приложение будет убито, вы ДОЛЖНЫ иметь все 3 из этих ключей в своем уведомлении.

Что-то вроде этого:

{
    "to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification": {
        "title": "test",
        "body": "my message"
    },
    "priority": "high",
    "content_available": true
}
23
jwenz723

Попробуйте установить приоритетный ключ в своей полезной нагрузке в соответствии с документами здесь: https://developers.google.com/cloud-messaging/concept-options#setting-the-priority-of-a-message

  • нормальный приоритет равен 5 в терминологии APNs
  • высокий приоритет равен 10 в терминологии APNs

Здесь у вас есть больше информации о приоритетах Apple APN и их поведении здесь: https://developer.Apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html

Пример полезной нагрузки:

{
  "to": "gcm_device_token",
  "priority": "high",
  "content_available": false,
  "notification": {
    "sound": "default",
    "badge": "1",
    "title": "Push Title",
    "body": "Push Body"
  }
}
7
Marcin Kapusta

Используя nodeJS и библиотеку node-gcm npm, я обнаружил, что для меня работает следующая полезная нагрузка для iOS, для Android я отправляю немного другую полезную нагрузку, потому что хочу перехватить все Push-уведомления перед их отображением в системный трей:

{ dryRun: false,
  data: 
   { customKey1: 'CustomValue1',
     customKey2: 'CustomValue2',
     content_available: '1',
     priority: 'high' },
  notification: 
   { title: 'My Title',
     icon: 'ic_launcher',
     body: 'My Body',
     sound: 'default',
     badge: '2' } }

Конечно, вам нужно убедиться, что ваше приложение iOS может обрабатывать входящие уведомления, но это должно происходить, когда ваше приложение находится в фоновом режиме.

0
GreensterRox
  1. Сделал это для C #, думаю, это могло бы помочь. У меня также была эта проблема После добавления content_available к true, это работало. Согласно документации Apple, ОС понимает, что существует уведомление , Когда приложение находится в фоновом режиме.

        JObject notification =new Object(
        new JProperty("to","put token which you get from running client application "),   
        new JProperty("content_available",true),
        new JProperty("priority","high"),
        new JProperty("notification",new JObject(
        new JProperty("title","message"),
        new JProperty("body","test message")
         ))
        );
    
0
ireshika piyumalie