Hacer que GCM funcione para dispositivos iOS en segundo plano

Estoy tratando de usar GCM para clientes IOS y Android. Parece que funciona bien con IOS cuando la aplicación está en primer plano, sin embargo, cuando la aplicación está en segundo plano, el centro de notificaciones no recibe el mensaje y didReceiveRemoteNotification with completionHandler no recibe una llamada.

Identifiqué un problema como un mensaje con formato incorrecto de GCM a APNS. A saber, así es como se ve:

 [mensaje: Nuevo mensaje, colapso_clave: do_not_collapse, de: **************] 

Si bien, las notificaciones push de IOS deben tener una clave aps en la notificación, ¿estoy en lo cierto? Además de contenido disponible, establezca en 1. Por ejemplo:

{“aps”: {“contenido disponible”: 1}, “data-id”: 345}

Por cierto, en la aplicación de primer plano recibe el mensaje de todos modos, el problema es solo con el fondo. ¿Algún consejo sobre cómo abordar un problema para que GCM funcione tanto para iOS como para Android?

ACTUALIZACIÓN : Eso es lo que encontré en la red:

Con respecto a la comunicación real, siempre que la aplicación esté en segundo plano en un dispositivo con iOS, GCM usa APNS para enviar mensajes, y la aplicación se comporta de manera similar al sistema de notificación de Apple. Pero cuando la aplicación está activa, GCM se comunica directamente con la aplicación

Entonces el mensaje que recibí en el modo de primer plano:

[mensaje: Nuevo mensaje, colapso_clave: do_not_collapse, de: **************]

Fue el mensaje directo de GCM (APNS no participó en este asunto en absoluto). Entonces la pregunta es: ¿APNS reformatea lo que GCM le envía para cumplir con el formato de notificaciones ios? Si es así, ¿cómo sé que APNS realmente hace algo y si me envía una notificación en un formato diferente? ¿Hay alguna manera de ver los registros de los datos entrantes de APNS?

ACTUALIZACIÓN: Bien, logré cambiar la estructura del mensaje y ahora en el modo de primer plano recibo el siguiente mensaje:

Notificación recibida: [“aps”: {“alert”: “Simple message”, “content-available”: 1}, collapse_key: do_not_collapse, from: **************]

Ahora parece estar bien formateado, pero todavía no hay reacción cuando la aplicación está en segundo plano. didReceiveRemoteNotifification completionHandler no se llama! ¿Qué debería buscar y dónde puede haber un problema? ¿Puede el corchete ser un problema para la notificación push? Para ser aún más preciso, ios no publica ninguna alerta / insignia / pancarta de esa notificación entrante.

Por cada pobre alma que se pregunta en busca de una respuesta al misterio de fondo de GCM. Lo resolví y el problema estaba en el formato. Estoy publicando el formato correcto y el código Java necesarios para enviar una solicitud Http a GCM con algún mensaje. Entonces, la solicitud Http debe tener dos campos en el encabezado, a saber:

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

entonces el cuerpo del mensaje debe ser un diccionario json con las claves “a” y “notificación”. Por ejemplo:

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

Aquí está el progtwig java simple (usando solo bibliotecas Java) que envía push a un dispositivo específico, usando 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(); } } } 

Es importante tener en cuenta que en los dispositivos iOS, si su aplicación que usa GCM ha sido eliminada (deslizada en el selector de aplicaciones), su dispositivo solo se activará al recibir un mensaje si envía una notificación con la “notificación”, “content_available” y “prioridad” (establecido en “alto”). Si tiene uno u otro, puede funcionar cuando la aplicación ha sido asesinada. Pero una vez que la aplicación ha sido eliminada, DEBE tener todas las 3 de estas claves en su carga de notificación.

Algo como esto:

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

Intente configurar la clave de prioridad en Su carga de acuerdo con los documentos aquí: https://developers.google.com/cloud-messaging/concept-options#setting-the-priority-of-a-message

  • la prioridad normal es igual a 5 en la terminología APN
  • alta prioridad es igual a 10 en la terminología APN

Aquí tiene más información sobre las prioridades de Apple APN y su comportamiento aquí: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html

Ejemplo de carga útil:

 { "to": "gcm_device_token", "priority": "high", "content_available": false, "notification": { "sound": "default", "badge": "1", "title": "Push Title", "body": "Push Body" } } 
  1. Hice esto para C #, creo que esto podría ser de ayuda. También tuve este problema después de agregar content_available a true, funcionó. De acuerdo con la documentación de Apple, esa es la forma en que OS entiende que hay una notificación cuando la aplicación está en segundo plano.

      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") )) ); 

Utilizando nodeJS y la biblioteca node-gcm npm encontré que la siguiente carga útil funciona para iOS, para Android estoy enviando una carga útil ligeramente diferente porque quiero interceptar todas las notificaciones push antes de mostrarlas en la bandeja del sistema:

 { 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' } } 

Por supuesto, deberá asegurarse de que su aplicación iOS pueda gestionar la notificación entrante, pero esto debería realizarse cuando su aplicación esté en segundo plano.