In this series of blog entries we will describe the development of a mobile chat app using SAP NetWeaver Cloud as a backend. The last time we explained data storage on the mobile device and on NW Cloud. Now we want to explain how we enabled push notifications for our app.

 

Why we need Push Notifications

When a user sends a message the recipient needs to be informed about the new message. But of course the receiving user has not opened out Twaddle app the whole time. That’s the point push notifications come in: The device informs the recipient via a popup that a new message is available for him. The second reason why we need push notifications is that our app shouldn’t ask the server the whole time for new messages as this would mean a large waste of bandwidth and battery. So that’s why also when the Twaddle app is opened by the user it receives new messages via a push notification and doesn’t have to perform a GET-request against our web service.

 

The landscape behind push notifications

Push notifications are sent to the device via a server. This server is hosted by Apple and is called “Apple Push Notification Service” – APNS. So whenever you want to send a push notification to an apple device you have to connect to the APNS and ask it for sending a push notification to a certain device. Our system that connects to the APNS is NW Cloud. When a user sends a new message to our web service NW Cloud saves this message and sends a push notification to the recipient and therefore connects to the APNS. NW Cloud has to provide the APNS the device receiving the push notification. Therefore every device that uses our app is identified by a device token – iOS provides this information to our app. That’s why our task is that also NW Cloud knows this device token for every user. As a summary: When Alice sends a new message to Bob, NW Cloud checks the device token of Bob in its data base, connects to APNS and provides it the device token of Bob and the message content, and APNS delivers the push notification to Bob’s device.

 

Folie1.PNG

 

Apple Push Notification Certificates

There are several certificates needed to enable Push Notifications for your app, so we want to give a short overview of that.

 

  • First of all you have to create a Certificate Signing Request with the Keychain Access.
  • Next step: Creating an AppID and check the Enable for Apple Push Notification service box. After that, you have to configure the Push SSL Certificate – upload the Certificate Signing Request.
  • Now you can download and install your SSL Certificate.
  • Last step: After creating a Provisioning Profile for your App you can download it and add it to Xcode.

 

We found a really helpful step-by-step description, which could also be useful for you.

 

Our workaround for enabling NW Cloud to send push notifications

Unfortunately it’s not that simple. You have to establish a secure connection to the APNS via port 2195 – that’s the issue. Currently NW Cloud seems to be able to connect other servers only via port 80 and 443 for http(s)-traffic. How to solve this issue? Our idea was to use a proxy server: NW Cloud sends the push notification not directly to the APNS but to the proxy forwarding the notification. That’s why we created a simple PHP-Web service running on a colleague’s machine (Thank you John!) that connects to the APNS without difficulties. NW Cloud accesses this php script and passes device token and message to it. The php-script then connects to the APNS that delivers the message. Of course this solution makes the whole system more complex but we’re happy to see it working

 

Folie2.PNG

 

Some backend coding

For developing the php script connecting to the APNS we used this tutorial. We changed the script that it reads device token and payload from passed post-parameters. To access our proxy server running our php-script we use the following code:

 

// cut message if too long

if(text.length()>200)

       text = text.substring(0, 200);

// define php-script as proxy

URL url = new URL("http://XXXXXXXXXX/sendpush.php");

URLConnection connection = url.openConnection();    

 

// simple payload: The alert box contains the message, and the Twaddle app shows a

// bubble with a 1 in it to notifiy the user

String payload = "{\"aps\":{\"alert\":\""+ text + "\",\"badge\" : 1}}";

 

// convert payload and devicetoken to UTF8 for the php-script

String data = URLEncoder.encode("payload", "UTF-8") + "=" + URLEncoder.encode(payload, "UTF-8");

data += "&" + URLEncoder.encode("devicetoken", "UTF-8") + "=" + URLEncoder.encode(devicetoken, "UTF-8");

 

if(payload.length()>256)

    throw new TwaddleException("Push-Notification not sent because payload exceeds maximum size");

 

// send data to php-script

connection.setDoOutput(true);

OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream());

wr.write(data);

wr.flush();

 

// read response from php-script

BufferedReader in = new BufferedReader(

new InputStreamReader(connection.getInputStream()));

String line;

while ((line = in.readLine()) != null)

                 result += line;

 


Receiving Notifications on the Application

After creating all the certificates you have to make sure that your App is “listening” for notifications. This is really simple. You just have to insert the following lines to the didFinishLaunchingWithOptions in your AppDelegate:

 

[[UIApplication sharedApplication] registerForRemoteNotificationTypes:

(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

 

To send Notifications to a special device, you have to know the device token. You can easily get this with the help of the method didRegisterForRemoteNotificationsWithDeviceToken.

 

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken

{

    NSString* newToken = [deviceToken description];

}

 

Handle received Notifications

When your device receives a notification and the app is in the foreground at the moment, the method didReceiveRemoteNotification is called. So that’s the place where we handle those notifications. After receiving a notification, we post our own notification in the NSNotificationCenter and named it “pushReceived”.

 

- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary *)userInfo{

    application.applicationIconBadgeNumber = 0;

    NSLog(@"Received notification: %@", userInfo);

 

    // Post a notification

    [[NSNotificationCenter defaultCenter] postNotificationName:@"pushReceived" object:nil];

}

 

Every ViewController, which should react after receiving a notification, has an observer. So when the notification “pushReceived” is sent to the NSNotificationCenter the observer calls the declared method. In this code example the data will be refreshed. 

 

// Observer that will respond to pushReceived

[[NSNotificationCenter defaultCenter] addObserver:self

   selector:@selector(refreshData:)

   name:@"pushReceived" object:nil];

 

In our use case there is nothing special to do when the device receives a notification and the app is in the background. When you launch the app, all the data will be refreshed either the device received a notification before or not.

 

We hope our explanation about APNS on NW Cloud was useful for you. In the next blog post we will describe how the authentication for our app works . We always appreciate your feedback so please feel free to suggest any ideas of improvement.

In this series of blog entries we will describe the development of a mobile chat app using SAP NetWeaver Cloud as a backend. The last time we explained the functionality and the architecture of our app. Now we want to tell you more about our web service: how it works and how we consume it via the app.

 

How our Twaddle web service works

 

As mentioned in our second blog post the mobile app connects to a servlet hosted by NW Cloud. This servlet acts like a web service: the app can ask for or send data and gets a response. To exchange the data between app and servlet we decided to use JSON. The great advantage of JSON is that its overload is very low (especially compared to XML) which is important in our mobile use case where we have to pay attention to exchange a small amount of data. The request-JSON is transported to the servlet via an HTTP-POST. The response-JSON is then returned to the app via the HTTP-response.

 

25-06-2012 15-46-49.jpg

 

Let’s take a deeper look in the syntax of our request- and response-JSON. Every request-JSON has to include a string parameter called function. In this parameter you specify the task of the web service: e.g. return all users or return messages for a given chat room. It’s also possible to use a function that creates resources, e.g. post a message or create a chat room. Depending on the function there have to be other parameters in the request-JSON. Nearly every function has to know for which user this function is called. By now the current user is a part of the request-JSON. That might be changed in the future when we got the authentication feature running. The response-JSON always includes the whole request-JSON. We enabled this functionality for debugging reasons; actually the app currently doesn’t need this parameter. Depending on the requested function the other parameters of the response-JSON can include e.g. a list of users or messages in a chat room.

 

How iOS talks to NW Cloud

For the communication between our iOS App and NW Cloud we are using post requests of the HTTP protocol. First of all we create a JSON with all the information the web service needs to give us the requested data back. There are a lot of free JSON classes you can use to create a JSON in Objective-C but we’re fine with those Apple provides. It’s basically the NSJSONSerialization Class.

 

We’ve created an NSDictionary object with all the information for the web service. The next step was to create a NSData Object with the help of NSJSONSerialization and the NSDictionary. As a last step we converted the NSData object into a NSString, which we need later for the HTTP post request.

 

// Creating JSON for HTTP post request

NSDictionary *dictJSONRequest = [NSDictionary dictionaryWithObjectsAndKeys:

                       @"getusers", @"function",

                       myuser, @"user", nil];

 

NSError *error;

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictJsonRequest

                           options:NSJSONWritingPrettyPrinted error:&error];

NSString *resultAsString = [[NSString alloc] initWithData:jsonData

encoding:NSUTF8StringEncoding];

 

After that we created a NSMutableURLRequest with the URL of our servlet. We set the parameters for the post request and included the string of our JSON data.

 

// Creating URL of own servlet

NSURL *url = [[NSURL alloc] initWithString:@"https://twaddlep142549XXXXtrial.nwtrial.ondemand.com/Twaddle/"];

 

NSMutableURLRequest *request = [NSMutableURLRequest

                                  requestWithURL:tmpURL];

 

// Setting parameters for post request

NSString *params = [[NSString alloc] initWithFormat:@"post=%@", resultAsString];

[request setHTTPMethod:@"POST"];

[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];

 

 

   

 

So all the preparatory work is almost done. After creating three more objects to manage the post request we sent a synchronous request with the help of NSURLConnection to our servlet. The response data is stored in a NSData object which can be converted into a NSString and later in a NSDictionary object so we can access to each keyword in the JSON response and work with the data.  With the help of the method “valueForKey” we can create a NSMutableArray with all the objects belonging to the keyword “users”.

 

NSData *data = nil;

NSError *error2 = nil;

NSHTTPURLResponse *response = NULL;

 

data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error2];

 

// do something with the data

NSLog(@"Succeeded! Received %d bytes of data",[data length]);

 

// Converting NSData Object into NSString

NSString *plainString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

 

NSError *e = nil;

 

// Creating NSDictionary object out of NSString - so you can access to each keyword in the JSON Response

NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&e];

 

NSMutableArray *allUsers = [jsonResponse valueForKey:@"users"];

 

 

 

Note: It’s also possible to send an asynchronous request to the servlet with the help of NSURLConnection. There is a Programming Guide from Apple regarding to this topic.

 

Servlet programming

The servlet has to parse the Post-Parameter as a JSON. To convert the JSON string into a Java object we use the library given on json.org because its license is unrestrictive.  When the parsing was successful the servlet checks the function-string to determine which procedure to start. All the data of the request-JSON is added to the response-JSON for debugging reasons.

 

// try to parse Post-parameter as JSON

try    {

       requestjson = new JSONObject(request.getParameter("post"));

}

catch(Exception e){

       throw new TwaddleException("Problems parsing request-string as JSON");

       }

 

// get function from request json

String function = requestjson.getString("function");

 

// add request-json to response-json for debugging reasons

responsejson.put("request",requestjson);

 

// depending on the function call special procedure

 

 

Here we will give you the example of our procedure for fetching all the users:

 

try    {

       EntityManager em = MainService.emf.createEntityManager();

       List<User> resultList = em.createQuery(

             "SELECT u FROM User u WHERE u.id <>'" +

             requestjson.getString("user").toUpperCase() + "'",

             User.class).getResultList();

            responsejson.put("success",true);

       HashMap<Object, Object> user;

// append all users to reponse-json

            for (User result : resultList)

             {

             user = new HashMap<Object, Object>();

             user.put("id", result.getId());

             user.put("name", result.getName());

                       responsejson.append("users",user);

             }

       }

catch (JSONException e) {

// Error-Handling

       }

// servlet returns the resonse-json

response.getWriter().write(responsejson.toString());

 

 

 

So these are basically the technics for our Twaddle web service. In our next blog post we want to focus on how we store the data on NW Cloud via JPA and also on the device via the CoreData framework to offer the user an offline view of our application. We always appreciate your feedback so please feel free to suggest any ideas of improvement.

Hi there,

 

and welcome to our blog. Here we will share the experiences we gain during the development of a mobile app that uses SAP NetWeaver Cloud as the back-end.

 

Why did we create this blog?

SAP NetWeaver Cloud is a very new product of SAP that offers a Java Platform which you can use to develop applications "on the cloud". Many people will test this new product on their own. On this blog we will share our first steps and idaeas about developing a mobile application on NW Cloud. Maybe you can avoid some of the mistakes we made when you get started with NW Cloud by reading our posts.

 

What's Twaddle about?

Twaddle is the name for the mobile app we are going to create. This mobile app will be a chatapp that can be used to send short messages between two or more users via their mobile devices. NW Cloud will be used as the back-end: It stores and provides all the messages, users and chatrooms. For the front-end we currently focus on iOS-devices, so the app will be available for iPhones and iPads.

 

Who writes this blog?

We are two students employed by SAP and are currently working in Global IT. It is our task to develop a mobile app that connects to NW Cloud. Julia Lakatos concentrates on the front-end-programming on the mobile device, while I  focus on the back-end-programming with NW Cloud.

 

In our second blog post we will demonstrate the architecture we use for Twaddle and show how we got started with NW Cloud. We always appreciate your feedback so please feel free to suggest any ideas of improvement.

Filter Blog

By author:
By date: By tag: