Friday, January 31, 2014

iOS APNS & Android GCM Push with Apache Cordova (Phonegap)

Here are my instructions for Hello World, a tutorial with Aerogear's Unified Push Server that allows you to send iOS and Android push notifications to Apache Cordova/Phonegap/HTML5 client applications. If you need help, the best place to hang out is on irc.freenode.net #aerogear channel

The instructions can be found in the readme.txt file and the sample code, while not necessary to follow the tutorial is also available at github https://github.com/burrsutter/hellopush The primary difference between the instructions in the readme.txt and the provided solution is that I added logic to address the OS configuration. If you are an Eclipse user, JBoss is adding a plugin for Phonegap/Apache Cordova project creation - here is a video to see it in action: https://vimeo.com/82204444
https://vimeo.com/81565404

My Aerogear Unified Push Server instance is running at OpenShift - sign-up is free and it only takes a few clicks to select the Aerogear Push 0.X quickstart and you are up and running.

Aerogear Cordova Push Plugin (HelloWorld)

0. getting the Cordova command line tool installed for Mac
sudo npm install -g cordova
cordova -version
3.3.1-0.1.2
http://cordova.apache.org/blog/releases/2013/07/23/cordova-3.html

Cordova Command Line Guide
http://cordova.apache.org/docs/en/3.0.0/guide_cli_index.md.html

npm itself comes from Node.js http://nodejs.org/
npm -version
1.3.25
node --version
v0.10.25
You will also need the Android SDK installed for your OS and in your PATH - commands like "android" and "adb devices" should execute
You will also need "curl", if you type in "curl" and hit return
curl: try 'curl --help' or 'curl --manual' for more information

1. Cordova create has the following sequence: "cordova create folderName bundleID appName"

cordova create hellopush com.burrsutter.hellopush "Hello Push"

2. edit hellopush (bring up your editor) if you open config.xml, you should see <name>Hello Push</name> <widget id="com.burrsutter.hellopush" the widget id becomes the bundle identifier, it must unique identify your iOS app, globally when you setup your iOS provisioning profile, you will need this unique bundle ID

3. cd hellopush

4. cordova platform add android

5. cordova plugin search push

6. cordova plugin add org.jboss.aerogear.cordova.push

7. There is a console.log in the default project as well as in the suggested example code, so make sure to also add the console plugin

cordova plugin add org.apache.cordova.console

and to know the mobile OS install the device plugin

cordova plugin add org.apache.cordova.device

8. index.html - insert the following below <div id="deviceready"> but inside <div class="app"> <font size="6"> <div id="notify">notifications </div> <div id="debug">debug </div> </font>

9. index.js

   successHandler: function (message) {
            var debug = document.getElementById("debug");
            console.log(message);
            debug.innerHTML = "success: " + message;
   },
   errorHandler: function (message) {
            var debug = document.getElementById("debug");
            console.log(message);
            debug.innerHTML = "error: " + message;
   },  
   onNotification: function (e) {
            // alert(e.alert);
            var notify = document.getElementById("notify");
            notify.innerHTML = e.alert;
   },  

    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 
    // 'receivedEvent' function, we must explicity call 
    // 'app.receivedEvent(...);'
    onDeviceReady: function() {
        var config = {
                senderID: "492580885002",
                pushServerURL: "https://aerogear-html5.rhcloud.com",
                variantID: "b3852e72-92e1-4b05-a4bd-b549438d4943",
                variantSecret: "13c9daca-457e-4837-bc26-769ba572a940"
        };
        push.register(
            app.successHandler,
            app.errorHandler,
            {
            	"badge": "true",
                "sound": "true",
                "alert": "true",
                ecb: "app.onNotification",
                pushConfig: config
            });
            
        app.receivedEvent('deviceready');
   },
Note: senderID, variantID and variantSecret were all setup in the Push Console at pushServerURL

http://aerogear.org/docs/guides/aerogear-push-android/google-setup/

http://aerogear.org/docs/guides/AdminConsoleGuide/

10. Run "adb devices" to see if an android device is plugged in correctly then cordova run android

this will install and launch the app on your plugged in, developer-ready Android phone/tablet

11. then send a message

curl -3 -u \
"f07c43a6-bb0a-4bb7-a1eb-a368db272212:e2cf19c3-6636-4712-bbe8-26b7c1ac9c09" \
   -v -H "Accept: application/json" -H "Content-type: application/json" \
   -X POST -d '{"message": {"alert":"Hello AeroGear", "badge":1}}' \
   https://aerogear-html5.rhcloud.com/rest/sender
NOTE: this is not wrapping correctly here in Blogger, here is the gist and I included a send.sh to make sending in numerous messages a little easier. Usage: ./send.sh "My Message" 3

where f07c43a6-bb0a-4bb7-a1eb-a368db272212
is your Application ID from the web console
where e2cf19c3-6636-4712-bbe8-26b7c1ac9c09
is the Master Secret also from the web console

Success, send a few more messages, changing the "Hello AeroGear Unified Push!"

Note: If you wish to deploy the app to another Android device, unplug the current one and plug in the new one - use "cordova run android" again and it will deploy to the new device - the app will still function and receive push notifications without being plugged in on USB.

12. Add iOS, if on Mac OS X, with XCode installed (via Mac AppStore is easiest) and you have previously paid your $99 and know how to get around at http://developer.apple.com

cordova platform add ios
13. Setup your provisioning profile:

http://aerogear.org/docs/guides/aerogear-push-ios/app-id-ssl-certificate-apns/ and

http://aerogear.org/docs/guides/aerogear-push-ios/provisioning-profiles/ and

http://aerogear.org/docs/guides/AdminConsoleGuide/

14. Add the variant for iOS via the Unified Push Server web console - uploading the .p12 file and its associated passphrase

15. look under platforms\ios and you should see a Hello Push.xcodeproj - double click on the .xcodeproj

If you see the General tab, double check the bundle identifier of com.burrsutter.hellopush or whatever you made yours

Modify the index.js (in XCode) for the proper variantID and variantSecret from the Unified Push Server console

16. Assuming you have previously registered your plugged in iOS device with the developer.apple.com portal, you can now hit the big arrow and target your device.

When the app installs it should prompt you to accept push notifications.

17. Look for a new installation/device token under your newly added iOS variant in the UPS web console. If you see no instance/device token then something failed.

18. Finally, send a message, it should hit all the android & iOS devices that you have deployed the app to.

Wednesday, December 18, 2013

Eclipse does not contain the JNI_CreateJavaVM - Mac OS X (10.9) Mavericks

Based on a recent experience, I thought it would be useful to post this blog for others who might also be struggling with this particular error message. After the Mac OS X Mavericks (10.9) upgrade, I hit the following error message from Eclipse Kepler (4.3.1) 32-bit
The JVM shared library "/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/../jre/lib/server/libjvm.dylib" does not contain the JNI_CreateJavaVM symbol.
Also, there is another error message you might receive from Eclipse:
To open “Eclipse.app” you need a Java SE 6 runtime. Would you like to install one now?
I read through this bug report at eclipse.org - https://bugs.eclipse.org/bugs/show_bug.cgi?id=411361 and that gave me some ideas as to how to workaround my Eclipse on Mavericks issues. Easy solution, download & install the Oracle JDK 7 and make sure to use the 64-bit version of Kepler. I have had Java 7 on the machine for a while and Java 8. I have historically used the 32-bit version of Eclipse which worked great with Java 6 which was the default from the Mac OS X perspective. Here is what I think happened, Mac OS X Lion (10.7) included Apple's Java 6 JRE, with Mac OS X Mavericks (10.9) it is no longer included. The Apple Java 6 supported 32-bit & 64-bit with a command line switch, Eclipse Juno & Kepler were seemingly able to handle that scenario. Now, Java 7 comes directly from Oracle and is installed separately on my box. In order to address the "you need a Java SE 6 runtime" specifically, I also needed to update your Info.plist in the JDK7 at /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Info.plist with the following in the JVMCapabilities section:
                JVMCapabilities
                
                        CommandLine
                        JNI
                        BundledApp
                        WebStart
                        Applets
                
Once the changes to Info.plist have been made you will need to reboot for it to take effect. Some other settings that might be important: JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home And I do not recall making any changes to Eclipse.ini that mattered, what follows is what I have right now on my machine, provided in case there is something tweaked in your installation. EDIT: It turns out that I did need to update my eclipse.ini, eclipse was picking up a Java 8 installation that I had and I needed to force it back to Java 7 as it was causing some other problems. Eclipse.ini for the 64-bit installation of Eclipse (underneath Eclipse.app-Contents-MacOS)
-startup
../../../plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar
--launcher.library
../../../plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.200.v20130807-1835
-product
org.eclipse.epp.package.standard.product
--launcher.defaultAction
openFile
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vm
/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.6
-XstartOnFirstThread
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XX:MaxPermSize=256m
-Xms40m
-Xmx512m
-Xdock:icon=../Resources/Eclipse.icns
-XstartOnFirstThread
-Dorg.eclipse.swt.internal.carbon.smallFonts
Also, I did make the change recommended at Eclipse.org/downloads. It should be noted that you won't actually see something named "gatekeeper" in the UI.
Hopefully that helps, I spent plenty of time using Google looking at Bugzilla and StackOverflow entries but could not find something like this blog post that helped me address both issues (64-bit required, missing Java SE 6 runtime).

Tuesday, November 26, 2013

Personal Technology Radar: How to keep up?

I gave a short presentation/demonstration to NCSU Computer Science students last night, it was full of various buzzwords, thoughts, random associations, high speed talking, etc. :-)

I focused on things like Aerogear (SDKs for mobile app dev, Push Notifications, storage), Vert.x (polyglot async services for the JVM) and showed off JBoss Tools for mobile app dev (https://vimeo.com/67480300).

One fellow posed a very interesting question to me, "how do you keep up?" and what follows was my off-the-cuff response.

Personally,

  • I am no longer able to follow news sites such as HackerNews
  • I am no longer to follow RSS feeds
  • I am no longer to keep up with the blogs (via RSS) that show up in my Flipboard account and
  • I am unable to read even 10% of the messages that follow through Google+ or Twitter, which is where I follow key colleagues and industry experts.
Basically, I am unable to consume the "push" news, I am only able to consume the topics I seek out.

So, how does a topic show up on my personal technology radar, I follow conference agendas. If you simply look at key conference agendas and then drill-down on those topics yourself it is pretty easy to keep your finger on the pulse of things. Conferences that I have participated in and always enjoy attending when I can are:

and we, Red Hat folks, are working on a really cool developer conference ourselves - watch the twitter stream for that announcement. Plus, I am also very interested in UberConf and The Rich Web Experience - anything that Jay Zimmerman is putting on.

There is one slight disadvantage of using this particular filtering mechanism, your feeling for how important a topic is can be slanted based on the abilities of the associated speakers. For instance, someone like James Ward, who is one of the best developer advocates in our industry is not only a great public speaker but he is also fairly high volume - therefore you may be more inclined to delve deeper into one of his topics. The same could be said for many of the excellent presenters that show up for these conferences.

There is another more significant disadvantage, if a particular innovation/tool/technique has no evangelist, nobody to talk about it, is so "unpopular" that it does not show up at a conference...well then it tends to miss my radar. So I do have a personal bias towards "popular" topics, ones with buzz, ones with somebody willing to talk about it in public. I allow for this bias because, at the end-of-the-day, I have found that "popular" topics are more likely to have staying power over the course of several years.

You would rather not invest dozens if not hundreds of hours in learning a new thing to only have that item fade into history with nobody left using it. Granted, learning for learning sake is still a very good thing. :-)

Burr