Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Always fresh data in your mobile application

romemore
November 10, 2014

Always fresh data in your mobile application

romemore

November 10, 2014
Tweet

More Decks by romemore

Other Decks in Programming

Transcript

  1. It’s a synchronization problem ! kind of… mobile connection is

    not a network plug ! connection is not always available connection is shared : (very) variable bitrate
  2. PRO simple, well known model we ask for data only

    when we need it (application opened ?) CONS the data is not here when user want it what happens when no data or (worst) slow data when you open the app ? POLLING
  3. PRO push only when we have data data can be

    received in background by the app CONS server side filtering and triggering > server side dev we have to have a schema for datas to react on > update client AND server SERVER SIDE PUSH
  4. client and server are always connected (not really) mobile phone

    are sometimes often connected PERMANENT CONNECTION
  5. PRO bidirectional push instant data transfer large data allowed (files,

    …) CONS permanent connection to maintain server resources (sockets) PERMANENT CONNECTION
  6. NOT SERVER FRIENDLY work to allow many connection by server

    or cost to use a SAAS (Firebase, …) NOT MOBILE FRIENDLY you have to keep your app running to maintain the connection connection use a lot of battery PERMANENT CONNECTION
  7. An SDK based on Parse to get only the interesting

    data 'au fil de l'eau', as it has been saved on server ONE SOLUTION
  8. GOALS interesting data network friendly device friendly no server side

    development ! only data we care about freshest data topics we are interested in (filtered data)
  9. interesting data network friendly device friendly no server side development

    ! GOALS no request if no interesting data one request to get all the data data as small as possible (only newest data)
  10. interesting data network friendly device friendly no server side development

    ! GOALS only active when server have interesting data no permanent connection to server
  11. Polling, triggered by server side push, using the (already) available

    permanent connection. aka ’’triggered polling’’ ONE SOLUTION
  12. Mobile app subscribe to topic(s) On server side, when new

    data is saved or data modified, notify subscribed mobile apps Mobile apps receive the notification and download the new data Triggered polling ONE SOLUTION
  13. Google Play services maintain a permanent connection, that we can

    use to send push notification (GCM) on data changes. When the app receive this push notification, it can download the changes in background. Triggered polling ONE SOLUTION
  14. We can use a hook when we save data on

    Parse, and send pushes to mobiles who have subscribed to this data. Triggered polling ONE SOLUTION
  15. Command hook on « save » to trigger notification Query

    get data triggered by the notification CQRS ONE SOLUTION
  16. Delete is a flag on the object Can replay modifications

    on data since a time reference (last sync) Event sourcing ONE SOLUTION
  17. IMPLEMENTATION We use Parse to have : a central datastore

    hooks on data store ("AfterSave(object)") push notifications Server side
  18. Android because everything is easier on Android Parse SDK as

    we use Parse on server side (push + queries) GCM for push notifications Event bus because I just like it Client side IMPLEMENTATION
  19. /**
 * register to an object type
 * @param type


    */
 static public void register(String type) {
 ParseInstallation i = ParseInstallation.getCurrentInstallation();
 i.addUnique("sushi", type);
 i.saveInBackground();
 } // Dynamically register to class of data (can register many)
 Sushi.register("MyClassOfObject");
 CODE
  20. /**
 * Wrappers around Parse save methods
 */
 
 static

    public Task<Void> saveEventually(ParseObject obj) {
 Task<Void> result = obj.saveEventually();
 updateLastMod(obj.getClassName());
 return result;
 } /**
 * send the update trigger to the server
 * @param className the class of saved object
 */
 static private void updateLastMod(String className) {
 ParseObject ev = new ParseObject("SushiUpdates");
 ev.put("objectName", className);
 ev.saveEventually();
 } CODE
  21. Parse.Cloud.afterSave("SushiUpdates", function(request) {
 var objectName = ""+request.object.get("objectName");
 
 Parse.Cloud.useMasterKey();
 


    //send push to clients
 var pushQuery = new Parse.Query(Parse.Installation);
 pushQuery.equalTo("channels", "Sushi");
 pushQuery.equalTo("sushi", objectName);
 Parse.Push.send({
 where: pushQuery,
 data: {
 class: objectName
 }
 }, {
 success: function() {
 console.log("push sent for class " + objectName);
 },
 error: function(error) {
 console.error("push not sent : " + error.message);
 }
 });
 
 });
 CODE
  22. @Override
 protected void onPushReceive(Context context, Intent intent) {
 boolean isSushiEvent

    = false;
 if (intent != null) {
 String channel = intent.getExtras().getString("com.parse.Channel");
 if(channel != null && channel.equalsIgnoreCase("sushi")) {
 isSushiEvent = true;
 onSushiEvent( intent.getExtras().getString("com.parse.Data") );
 }
 }
 if(!isSushiEvent)
 super.onPushReceive(context, intent);
 }
 
 protected void onSushiEvent(String data) {
 try {
 JSONObject json = new JSONObject(data);
 String updatedObject = json.getString("class");
 Log.i(TAG, "updated " + updatedObject);
 EventBus.getDefault().post(new SushiUpdateEvent(updatedObject));
 } catch (JSONException e) {
 Log.d(TAG, "JSONException: " + e.getMessage());
 }
 } CODE
  23. IMPROVEMENTS //@todo Multiple push prevent multiple push to a same

    client for same class of data if he didn’t already query for the data Sync point the client must query new data since last sync Continuous query add parameters to subscription