This research log looks into the push notification capabilities of parse.com. It also gives out a few code samples to test various scenarios. I will have a formal article soon here based on this information here.

quick start guide for push

Setting up your app for starting development with push


Register the parse push broadcast receiver
Register the parse push service
Set push related permissions
Tell parse the app is ready for push

Channels are just topic names. Clients can subscribe to them. Each channel may have a separate activity associated with them.

Can I get all the available channels for an App in parse?

Search for: Can I get all the available channels for an App in parse?

Here is a quick discussion

Can push channels be created using the parse dashboard?

Search for: Can push channels be created using the parse dashboard?

Parse error: This object has an outstanding network connection. wait

Search for: Parse error: This object has an outstanding network connection. wait

Here is some explanation from Parse for this behavior


public void onCreate() {
      super.onCreate();

      Log.d(tag,"initializing with keys");
      // Add your initialization code here
      Parse.initialize(this, PARSE_APPLICATION_ID, PARSE_CLIENT_KEY);

      //This will automatically create an annonymous user
      //The data associated to this user is abandoned when it is 
      //logged out.
      //ParseUser.enableAutomaticUser();
      ParseACL defaultACL = new ParseACL();
       
      // If you would like all objects to be private by default, remove this line.
      defaultACL.setPublicReadAccess(true);
      ParseACL.setDefaultACL(defaultACL, true);
      
      //Enable to receive push
      PushService.setDefaultPushCallback(this, RespondToPushActivity.class);
      ParseInstallation pi = ParseInstallation.getCurrentInstallation();
 
      //Subscribe to a channel
      Context ctx = this.getApplicationContext();
      PushService.subscribe(ctx, "ch1", RespondToPushActivity.class);
      
      pi.saveEventually();
      Log.d(tag,"initializing app complete");
   }

for instance the parseinstallation.saveinbackground() might work with this new sdk. I havent' tried. It is always dicey when you talk to a server and Android doesn't have a natural wait so all apis are best when they are asynchronous!

So for now i will rather use saveeventually() unless i need an immediate save.

Ofcourse saveinbackground is preferred when it works with a callback.


PushService.subscribe
PushService.unsubscribe
PushService.getSubscriptions

//First enable it on the dashboard...then

ParsePush push = new ParsePush();
push.setChannel("Giants");
push.setMessage("The Giants just scored! It's now 2-2 against the Mets.");
push.sendInBackground();

LinkedList<String> channels = new LinkedList<String>();
channels.add("Giants");
channels.add("Mets");
 
ParsePush push = new ParsePush();
push.setChannels(channels); // Notice we use setChannels not setChannel
push.setMessage("The Giants won against the Mets 2-3.");
push.sendInBackground();

// Saving the device's owner
ParseInstallation installation = ParseInstallation.getCurrentInstallation();
installation.put("owner",ParseUser.getCurrentUser());
installation.saveInBackground();

// Create our Installation query
ParseQuery pushQuery = ParseInstallation.getQuery();
pushQuery.whereEqualTo("owner", "satya");
 
// Send push notification to query
ParsePush push = new ParsePush();
push.setQuery(pushQuery); // Set our Installation query
push.setMessage("Hello this is just for you!");
push.sendInBackground();

is there a limit to the length of a parse Push message?

Search for: is there a limit to the length of a parse Push message?

Can I send a bit longer JSON data and a message through Parse Push Dashboard?

Search for: Can I send a bit longer JSON data and a message through Parse Push Dashboard?

A push can either have channels or a query. Setting this will unset the query.


public void sendMessage(View v)
   {
      ParsePush push = new ParsePush();
      String message = "Client message" + Integer.toString(i++);
      push.setMessage(message);
      push.sendInBackground();
   }

It is targeting no channels. So no clients seem match this criteria.

wonder what happens if I subscribe to a channel which is an empty string!

I will try this with a query to see if that can query all users!


Targeting : channels includes "ch1"
deviceType is "android"
Sending date : May 1st, 2013 at 3:13 PM
Expiration : None
Full target : { "channels": { "$in": [ "ch1" ] }, "deviceType": "android" }
Full data : {"alert"=>"Client message0"}

You have to enable client side push to see the channel subscriptions to work!

What is the limit (180) to the amount data that can be sent on a push message in Parse?

Search for: What is the limit (180) to the amount data that can be sent on a push message in Parse?


public void sendMessageAsData(View v)
   {
      JSONObject data = getJSONDataMessage();
      ParsePush push = new ParsePush();
      push.setChannel("ch1");
      push.setData(data);
      push.sendInBackground();
   }
   
   private JSONObject getJSONDataMessage()
   {
      try
      {
         JSONObject data = new JSONObject();
         data.put("alert", "Main Message");
         data.put("customdata", "custom data value");
         return data;
      }
      catch(JSONException x)
      {
         throw new RuntimeException("Something wrong with JSON", x);
      }
   }

Read up on sending notifications in Android


private JSONObject getJSONDataMessageForIntent()
   {
      try
      {
         JSONObject data = new JSONObject();
         //Notice alert is not required
         //data.put("alert", "Message from Intent");
         //instead action is used
         data.put("action", TestBroadcastReceiver.ACTION);
         data.put("customdata", "custom data value");
         return data;
      }
      catch(JSONException x)
      {
         throw new RuntimeException("Something wrong with JSON", x);
      }
   }
   public void sendMessageAsIntent(View v)
   {
      JSONObject data = getJSONDataMessageForIntent();
      ParsePush push = new ParsePush();
      push.setChannel("ch1");
      push.setData(data);
      push.sendInBackground();
      reportTransient("Sent as data");
   }

notice how "action" is used instead of "alert". If you use both you will get both behaviors: your broadcast receiver will be invoked. You also get the alert as a notification.

Instead if you just use the action, the broadcast receive can then notify if needed or be silent if appropriate!


public class TestBroadcastReceiver 
extends BroadcastReceiver 
{
   public static final String ACTION="com.androidbook.parse.TestPushAction";
   public static final String PARSE_EXTRA_DATA_KEY="com.parse.Data";
   public static final String PARSE_JSON_ALERT_KEY="alert";
   public static final String PARSE_JSON_CHANNELS_KEY="com.parse.Channel";
      
   private static final String TAG = "TestBroadcastReceiver";
    
   @Override
   public void onReceive(Context context, Intent intent) 
   {
      try 
      {
         String action = intent.getAction();
         
         //"com.parse.Channel"
         String channel = 
            intent.getExtras()
               .getString(PARSE_JSON_CHANNELS_KEY);
         
         JSONObject json = 
            new JSONObject(
                  intent.getExtras()
                     .getString(PARSE_EXTRA_DATA_KEY));
    
         Log.d(TAG, "got action " + action + " on channel " + channel + " with:");
         Iterator itr = json.keys();
         while (itr.hasNext()) 
         {
            String key = (String) itr.next();
            Log.d(TAG, "..." + key + " => " + json.getString(key));
         }
         notify(context,intent,json);
      } 
      catch (JSONException e) 
      {
         Log.d(TAG, "JSONException: " + e.getMessage());
       }
   }
   private void notify(Context ctx, Intent i, JSONObject dataObject)
   throws JSONException
   {
         NotificationManager nm = (NotificationManager)        
            ctx.getSystemService(Context.NOTIFICATION_SERVICE);
         
         int icon = R.drawable.robot;
         String tickerText = 
            dataObject.getString("alert");
         long when = System.currentTimeMillis();         
         Notification n = new Notification(icon, tickerText, when);
         
         //Let the intent invoke the respond activity
         Intent intent = new Intent(ctx, RespondToPushActivity.class);
         //Load it with parse data
         intent.putExtra("com.parse.Data", 
               i.getExtras().getString("com.parse.Data"));
         
         PendingIntent pi = PendingIntent.getActivity(ctx, 0, intent, 0);

         n.setLatestEventInfo(ctx, "Parse Alert", tickerText, pi);
            
         nm.notify(1, n);         
   }
}//eof-class

getting an alert string from the json object will throw an exception if the incoming message doesn't have it. So put enough checks for robust behavior!