Q: Remote Message Notification for Delphi iOS apps (without Kinvey/Parse)

1

Now Parse has decided to stop their remote push notification service, I'm looking for an alternative.

Of course I can move to Kinvey, which has a similar service, but you never know how long Kinvey will last (as a free service).

So, I was looking to implement my own independent and free solution for my app (both android and ios).

 

For android it seems pretty easy. I've just set up gcm for my project at https://developers.google.com/cloud-messaging/, and I received my GCM Sender Id and API key.

 

In my android app I can now easily register my android device for a device token with:

 

  {$IFDEF ANDROID}

  PushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM); // Google Cloud Messaging

  PushService.AppProps[TPushService.TAppPropNames.GCMAppID] := <>;

  {$ENDIF}

  {$IFDEF IOS}

  PushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.APS); // Apple Push Service

  {$ENDIF}

  PushServiceConnection := TPushServiceConnection.Create(PushService);

  PushServiceConnection.Active := True;

  DeviceToken = PushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken];



 

And from my php server I can now send a downstream message with:

 

  $Request = curl_init();

  try

  {

    curl_setopt($Request, CURLOPT_URL, 'https://gcm-http.googleapis.com/gcm/send');

    curl_setopt($Request, CURLOPT_POST, 1);

    curl_setopt($Request, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization:key=' . <>));

    curl_setopt($Request, CURLOPT_POSTFIELDS, {"registration_ids" : ["' . <> . '"],"data":{"message":"My message","title":"My title"}});

    curl_setopt($Request, CURLOPT_SSL_VERIFYPEER, false);

    curl_setopt($Request, CURLOPT_RETURNTRANSFER, true);

    $Response = curl_exec($Request);

  }

  finally

  {

    curl_close($Request);

  }



It all works (i.e. for Android)! The message is received in the PushServiceConnection.OnReceiveNotification event if the app is active or in the android's notification center if the app is inactive.

 

But howabout iOS? With the Delphi code above I actually get an APN device token, but how do I "translate" this to a GCM device token? Or what php code do I need to send a downstream message to APN?

 

Google gives some information at https://developers.google.com/cloud-messaging/ios/client, but this explanation is based on XCode and C++ and not Delphi. Has someone a Delphi explanation?

 

Note. I've already created a APN developer and production certificate.

 

Responses (3)
  • Accepted Answer

    Monday, January 30 2017, 04:03 AM - #Permalink
    0

    Hello, I did the above mentioned procedures, when sending the POST to FCM, I receive success however I am not receiving the notification in IOS.

     

    Are there any download examples?

    The reply is currently minimized Show
  • Accepted Answer

    Monday, December 12 2016, 05:06 AM - #Permalink
    0

    Wonderful, It works! Using your REST examples, I was able to convert my APS device token to a GCM/FCM token, and I was able to send a notification to it.

     

    But still, I have some concerns regarding retrieving the device token in my Delphi App, see code below (using Berlin 10.1 update 2).

     

    (1) First, I still need REST.Backend.ParsePushDevice unit in my uses clause. It will build without it, but than I get a crash on run-time. Apparently TPushServiceConnection is using some global vars defined in REST.Backend.ParsePushDevice.

    So I wonder what will happen in February 2017 when Parse has stopped.

     

    (2) On iOS, the first time i call function below, I get a empty string. If I wait a second and try again, I get the right device token. So apparently, on iOS, activating PushServiceConnection (for the first time) will start a background process that takes some time before it results in a device token. This is a little bit mystic.

     

     

    uses
    
      System.PushNotification, System.Notification, REST.Backend.ParsePushDevice;
    
     
    
    function GetDeviceToken: string;
    
    var
    
      PushService: TPushService;
    
      PushServiceConnection: TPushServiceConnection;
    
    begin
    
      Result := '';
    
     
    
      {$IFDEF ANDROID}
    
      PushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM); // Google Cloud Messaging (Firebase)
    
      PushService.AppProps[TPushService.TAppPropNames.GCMAppID] := '<>';
    
      {$ENDIF}
    
      {$IFDEF IOS}
    
      PushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.APS); // Apple Push Service
    
      {$ENDIF}
    
     
    
      PushServiceConnection := TPushServiceConnection.Create(PushService);
    
      try
    
        PushServiceConnection.Active := True;
    
        Result := PushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken];
    
      finally
    
        PushServiceConnection.Free;
    
      end;
    
    end;
    
     



    The reply is currently minimized Show
  • Accepted Answer

    Saturday, September 24 2016, 09:57 AM - #Permalink
    1

    I don't know if you already find out, how to do it, but I stumbled across this post everytime I googled a solution to this.

    I finally found a way how to make it work for iOS.

    Google has changed the service name from GCM to FCM (Firebase). But, the old API requests still work for Android devices.

    1. I migrated my project to Firebase.

    2. Create an "app" in your Firebase project for iOS.

    3. Add the APNS certificates (the same that you had to add in Parse).

    4. With your code you already will receive the APN device token on iOS. This token has to be registered with google. I found an API call on google pages that is primarily designed to batch import existing APNs and get the registration ids as a response:

    curl -X POST --header "Authorization: key=APIKEY" --header "Content-Type: application/json" https://iid.googleapis.com/iid/v1:batchImport -d "{\"application\":\"APPLICATIONNAME\",\"sandbox\":false,\"apns_tokens\":[\"APNTOKEN\"]}"



    You can make this request with NetHTTPClient on the ios device prior to sending your PHP script or server a token.

    5. The response will look like this:

    {"results":[{"registration_token":"REGTOKEN","apns_token":"APNTOKEN","status":"OK"}]}



    6. Now, you can use REGTOKEN the same way like an Android/GCM device token to push notifications.

    One thing worth to mention: I find out, that you should set the priority to "high" when pushing notifications to iOS. Otherwise, they will not go through when the app is not running or phone is in standby.

    And Android and iOS is handling the messages different. Here is something that works for me:

    curl -X POST --header "Authorization: key=APIKEY" --header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d "{\"to\":\"FCMTOKEN\",\"priority\":\"high\",\"notification\":{\"body\":\"This msg will show on iOS\",\"sound\":\"default\"},\"data\":{\"message\":\"This msg will show on Android\"}}"



    Don't know if this is the only way how to make it work, but it works! Now, finally I got rid of Parse. They can shut down their service already. ;)

    The reply is currently minimized Show
Your Reply

Please login to post a reply