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.
satya - 4/29/2013 4:32:48 PM
Setting up your app for starting development with push
satya - 4/29/2013 4:34:12 PM
At a high level
Register the parse push broadcast receiver
Register the parse push service
Set push related permissions
Tell parse the app is ready for push
satya - 4/29/2013 4:45:43 PM
You can setup channels to target messages
Channels are just topic names. Clients can subscribe to them. Each channel may have a separate activity associated with them.
satya - 4/29/2013 4:55:16 PM
Can I get all the available channels for an App in parse?
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?
satya - 4/29/2013 4:58:01 PM
Can push channels be created using the parse dashboard?
Can push channels be created using the parse dashboard?
Search for: Can push channels be created using the parse dashboard?
satya - 4/30/2013 9:49:54 AM
Parse error: This object has an outstanding network connection. wait
Parse error: This object has an outstanding network connection. wait
Search for: Parse error: This object has an outstanding network connection. wait
satya - 4/30/2013 9:52:39 AM
Here is some explanation from Parse for this behavior
satya - 4/30/2013 10:59:49 AM
This seem to work
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");
   }
satya - 5/1/2013 11:26:40 AM
Apparently the parse sdk v1.2.3 might fix some of these threading issues
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.
satya - 5/1/2013 11:27:15 AM
Ofcourse saveinbackground is preferred when it works with a callback.
Ofcourse saveinbackground is preferred when it works with a callback.
satya - 5/1/2013 11:36:47 AM
There are three apis to control channels
PushService.subscribe
PushService.unsubscribe
PushService.getSubscriptions
satya - 5/1/2013 11:37:20 AM
Sending client side pushes
//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();
satya - 5/1/2013 11:37:51 AM
Or this
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();
satya - 5/1/2013 11:43:26 AM
You can do this also
// Saving the device's owner
ParseInstallation installation = ParseInstallation.getCurrentInstallation();
installation.put("owner",ParseUser.getCurrentUser());
installation.saveInBackground();
satya - 5/1/2013 11:45:34 AM
Now that allows
// 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();
satya - 5/1/2013 1:56:21 PM
is there a limit to the length of a parse Push message?
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?
satya - 5/1/2013 1:57:02 PM
Can I send a bit longer JSON data and a message through Parse Push Dashboard?
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?
satya - 5/1/2013 3:08:04 PM
Nature of parsepush
A push can either have channels or a query. Setting this will unset the query.
satya - 5/1/2013 3:09:51 PM
This doesn't seem to work
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!
satya - 5/1/2013 3:10:13 PM
I will try this with a query to see if that can query all users!
I will try this with a query to see if that can query all users!
satya - 5/1/2013 3:15:26 PM
Here is what a serverside push structure looks like
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"}
satya - 5/1/2013 3:20:00 PM
You have to enable client side push to see the channel subscriptions to work!
You have to enable client side push to see the channel subscriptions to work!
satya - 5/1/2013 3:30:29 PM
What is the limit (180) to the amount data that can be sent on a push message in Parse?
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?
satya - 5/1/2013 3:45:19 PM
Looks like you can do this
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);
      }
   }
satya - 5/2/2013 12:21:48 PM
Read up on sending notifications in Android
satya - 5/2/2013 1:54:19 PM
Here is how you send data using an intent
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!
satya - 5/2/2013 1:55:09 PM
Here is the TestBroadcastReceiver
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
satya - 5/2/2013 2:02:15 PM
There is a bug above
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!