Статьи

PhoneGap, Parse.com и Push-уведомления

Поскольку я работал над примером приложения, использующего Parse.com и PhoneGap , я хотел посмотреть, как Parse обрабатывает Push-уведомления. Я предполагал, что это будет легко, и я просто включил бы это в свою серию, но это оказалось более сложным, чем я ожидал. Поэтому я решил написать об этом в одиночку, чтобы все было как можно проще и понятнее. В конце концов, процесс получения уведомлений, работающих с PhoneGap и Parse, не был ужасно сложным, но есть несколько вещей, которые вы должны правильно организовать, чтобы получить желаемые результаты.

Во-первых, я должен предупредить вас о том, что уведомления будут немного отличаться в зависимости от каждой платформы. В общем, вы можете делать много разных вещей между Android и iOS, но есть несколько отличий. Вы можете взглянуть на документы для Android и iOS, а также посмотреть видео, созданное командой Parse для iOS. Вы можете заметить, что JavaScript API также имеет раздел Push-уведомлений, но он поддерживает только создание новых уведомлений. Это немного смутило меня, пока я не вспомнил, что за пределами нативных приложений для JavaScript не имеет смысла обрабатывать получение уведомлений. Поэтому вы должны использовать нативное решение. К счастью, PhoneGap позволяет нам сделать это и использовать JavaScript API, а также.

В этом посте я буду использовать Android. Только начальные аспекты настройки будут специфичны для Android. Код PhoneGap, который мы будем использовать позже, должен работать и в iOS.

Обратите внимание, что вам нужно немного испачкать руки и работать с Java. На самом деле вам не нужно писать какую-либо Java, но это означает, что PhoneGap Build не будет вариантом для приложений, использующих уведомления. Я использовал Eclipse для своего приложения, но вы, вероятно, можете обойтись без использования инструментов командной строки с PhoneGap.

Часть первая — Eclipse / Java Setup

Итак, начнем. Первый — создать проект Android PhoneGap. Я использовал плагин AppLaud, чтобы сделать его очень простым. Я склонен беспокоиться о таких вещах, поэтому, прежде чем что-то делать, я подтвердил, что он работает на моем мобильном устройстве. Кроме того, я предполагаю, что у вас уже есть приложение Parse.com. Я не говорю о мобильном приложении, я имею в виду приложение, определенное на веб-сайте Parse. Я использовал свое приложение CowTipLine.

Перейдите к загрузкам Parse и получите Android SDK. Обратите внимание, что этот SDK является просто файлом jar (Parse-1.1.6.jar). Скопируйте этот jar-файл в папку libs вашего проекта PhoneGap:

В этот момент вы, вероятно, захотите обновить представление в Eclipse, чтобы оно распознало новый файл. Как мы все знаем, Eclipse будет издеваться, если вы решитесь использовать свою файловую систему.

Теперь, следуя документам об уведомлениях Android , вас попросят изменить файл AndroidManifest.xml, добавив следующие строки:

<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
   <intent-filter>
      <action android:name="android.intent.action.BOOT_COMPLETED" />
      <action android:name="android.intent.action.USER_PRESENT" />
   </intent-filter>
</receiver>

Эти строки в основном действуют в качестве прослушивателя push-уведомлений Parse.com. Они позволят вашему приложению распознавать и отвечать на уведомления, отправленные сервером.

The Parse docs then tell you to add three sets of permissions, but by default PhoneGap already has two of them set. You should only need to add the RECEIVE_BOOT_COMPLETED permission from the set below:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />

Ok, now you need to get into the Java a bit. When you created your application, you had to give it a package name. I called mine org.camden.test1. I ended up with a Java file called MyPhoneGapActivity.java. You can find this under the src folder.

Do not worry about the com.borismus.webintent folder. You will not have it yet and we’ll come to that later.

You don’t normally need to edit this file if you use the AppLaud plugin. If you built the project by hand following the PhoneGap Android guide then you have already worked with this file a bit.

Get this file open, and do the following:

  • Add an import com.parse.*; below your other imports.
  • Add a Parse.initailize(this, a, b) line in your onCreate method. «a» is your application key and «b» is your client key.
  • Finally, add PushService.subscribe(this, «», MyPhoneGapActivity.class). Your «So and So.class» will differ depending on the name of your file. This line handles telling the application to listen in for messages from Parse. Parse supports multiple channels for filtered notifications, but the empty string represents the «broadcast» channel.

Here is my entire Java file.

package org.camden.test1;

import org.apache.cordova.DroidGap;
import android.os.Bundle;
import com.parse.*;

public class MyPhoneGapActivity extends DroidGap {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		super.loadUrl("file:///android_asset/www/index.html");
		
		Parse.initialize(this, "oe3dboiG0RzJNULxKvdHYGWEb3Cq7mzHRC3Dwh6E", "HhVc3o0xptixz1Lv7ICnckICFPRpLaJNtdk3CEjK"); 
		PushService.subscribe(this, "", MyPhoneGapActivity.class);
	}
}

Ok, at this point you want to ensure the application still compiles. Hit the nice little green arrow Eclipse button to rerun the application. In theory, you will see nothing different, but you want to ensure it at least runs ok on your device. Also, by running the application once, your application «subscribes» to push notifications from your application on Parse. That will be crucial for the next step.

Testing Notifications at Parse

I know I sound like a Parse fanboy (even though they don’t seem to want to ever tweet about my blog posts ? but I cannot stress how nice the developer tools are at Parse. Creating messages can be done with Android, iOS, REST, and the JavaScript API. But they went ahead and built in a push notifications panel on their application dashboard:

I recognize that screen shot has a lot of information on it, so let me quickly review it. You can see a list of all previously sent messages on top. Beneath it is a form to let you send messages. I mentioned above that applications can choose to subscribe to a particular channel. What channels you use are entirely dependent on your application. For now you will just ignore this and use the default Broadcast channel. In the Push Data box, keep the radio button at the default (Message) and enter something wise.

Hit the Send button and you should see — pretty darn immediately — the alert arrive on your device:

You can even close the application. If you send a new notification and select it in your Android… err…. whatever they call it (notification tray?) your application should open up.

Congratulations. You can now send notifications to your device.

Responding Intelligently to Notifications

So all of the above took me less than an hour. It was pretty cut and dry. But then I hit a pretty big roadblock. How could I make my application recognize when it was loaded via a notification and actually tell me what the notification was?

From what I read in the Android docs, it seemed to imply that you had to write a custom Java class. I wasn’t opposed to this, but I really wanted a solution that would let me use JavaScript to respond to the notification.

I went back to the article I wrote back in May about Intents and PhoneGap. In that article I discussed how the WebIntents PhoneGap plugin would give us access to both creating and responding to intents with JavaScript.

I won’t repeat the instructions from that article, but the basics are — you copy the jar from that plugin (remember in that first screen shot when I said you wouldn’t have that particular folder?) as well as the JavaScript file and then add a script tag reference in your index.html to load it.

The WebIntents plugin has a few APIs, but the ones we care about are hasExtra and getExtra. hasExtra is used to see if extra «stuff» was passed in from the intent that loaded us and getExtra is what actually gets the data. This is where I got stuck though. The WebIntents docs show using a few constants (EXTRA_TEXT, EXTRA_SUBJECT, EXTRA_STREAM, and EXTRA_EMAIL) and I assumed I had to use one of those four. I built quick blocks of code to check for all four, updated my application on the device, sent a message, clicked on the notification, and waited to see which JavaScript block would pass the getExtra test. Unfortunately none of them did.

At this point I figured I was pretty much toast. I Googled a bit. Scratched my head. Pouted a bit too. Finally, I tried something new. In my getExtra call, I tried using what I had seen as a class related to Push Notifications:

window.plugins.webintent.hasExtra(«com.parse.Data»

To my surprise, this worked! So it turns out the WebIntent plugin’s JavaScript API can work with any form of intent data as long as you know the proper identifier. I quickly whipped up the following:

window.plugins.webintent.hasExtra("com.parse.Data", 
   function(has) {
      if(has) {
         window.plugins.webintent.getExtra("com.parse.Data", 
            function(d) {
               console.log(JSON.stringify(d))
            }, function() {
               // There was no extra supplied.
            }
         );
   }, function() {
      alert('fail');
   }
);

All I do is run the has test followed by a get call. I take the data, JSON stringify it, and log it to my console.

And that’s it. Obviously real code would parse this data and do, well, whatever you want with it. As should be clear from the Parse.com form, you can send more than simple messages. Complex structures of data can be sent to your listening devices. Again, the whole Push Notification feature as a whole is very powerful. I definitely encourage you to look at it yourself, and knowing that you can use it within PhoneGap as well just makes it even better.

If you have any questions, or suggestions for improvement, just leave a comment below.