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!