Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making GCM work for iOS device in the background

I'm trying to use GCM for IOS and Android clients. It seems to work fine with IOS when app is in the foreground, however, when the app is in the background, the notification center doesn't receive the message and didReceiveRemoteNotification with completionHandler doesn't get called.

I identified a problem as a wrongly formatted message from GCM to APNS. Namely, that's how it looks:

 [message: New message, collapse_key: do_not_collapse, from: **************]
While, the IOS push notifications should have aps key in the notification, am I right ? As well as content-available set to 1. For example:

{ "aps" : { "content-available" : 1 }, "data-id" : 345 }

By the way, in the foreground app receives the message anyway, the problem is only with the background. Any advice on how should I approach a problem, to make GCM work for both ios and android?

UPDATE: That is what I found on the net:

Regarding actual communication, as long as the application is in the background on an iOS device, GCM uses APNS to send messages, the application behaving similarly as using Apple’s notification system. But when the app is active, GCM communicates directly with the app

So the message I received in the foreground mode:

[message: New message, collapse_key: do_not_collapse, from: **************]

Was the direct message from GCM(APNS did not participate in this affair at all). So the question is: does APNS reformat what GCM sends to it to adhere to ios notifications format? If so how do I know that APNS actually does something and whether it sends me a notification in different format ? Is there any way to view logs of incoming data from APNS ?

UPDATE: Okay, I managed to change the structure of the message and now in the foreground mode I receive the following message:

Notification received: ["aps": {"alert":"Simple message","content-available":1}, collapse_key: do_not_collapse, from: **************]

Now it seems to be well formatted, but there is still no reaction when the app is in the background. didReceiveRemoteNotifification completionHandler doesn't get called! What should I look for and where can a problem be ? Can the square bracket be a problem for push notification ? To be even more precise, ios doesn't post any alerts/badges/banners from that incoming notification.

like image 220
Olexiy Burov Avatar asked Jun 29 '15 06:06

Olexiy Burov


People also ask

Can FCM send notification to iOS?

Once your client app is installed on a device, it can receive messages through the FCM APNs interface. You can immediately start sending notifications to user segments with the Notifications composer, or messages built on your application server.

What is GCM APN?

From this thread, GCM is a service that helps developers send data from servers to their Android applications on Android devices. Same with APN which is a service for app developers to propagate information to iOS (and, indirectly, watchOS), tvOS, and macOS devices.

Why do we need GCM?

Using GCM, your server can notify your app running on a particular device that there is new data available for it. Compared to polling, where your app must regularly ping the server to query for new data, this event-driven model allows your app to create a new connection only when it knows there is data to download.


Video Answer


1 Answers

For every poor soul wondering in quest for an answer to GCM background mystery. I solved it and the problem was in the format. I'm posting the right format as well as Java code needed to send Http request to GCM with some message. So the Http request should have two field in the header, namely:

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

then the message body should be a json dictionary with keys "to" and "notification". For example:

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

Here is the simple java program (using only java libraries) that sends push to a specified device, using 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();         }     } } 
like image 97
Olexiy Burov Avatar answered Oct 04 '22 09:10

Olexiy Burov