Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

Tuesday, October 27, 2015

PhoneGap-Plugin-Push Version 1.4.0 Has Been Released

The latest release of the PushPlugin is now available on npm. This release is the long awaited release that is fully tested with iOS9. I was able to test on an iPhone 6+ running iOS 8.4.1, iPod Touch running iOS 9.0.2 and an iPad Air 2 running iOS 9.1.0. Please let me know if you run into any problems with this release.

On Android the switch over to using Gradle is now complete. The deprecated gcm.jar has been removed from the plugin and replaced with the Google Play Services GCM framework. Even better news is that PhoneGap Build now supports Gradle builds.

The big feature that people have been clamoring for is background or silent notifications. It is now possible for your 'notification' event handler to run when you app is in the background on iOS and Android (support for Windows coming soon).

1.4.0 (2015-10-27)

Full Changelog
Implemented enhancements:
  • Use Google's InstanceID API #188
Closed issues:
  • How to handle a re-installed app? #203
  • interactive push notifications? #266
  • Empty registrationId Android #265
  • Run callback when clicking of notification body #261
  • Android BUILD FAILED #251
  • Re-register #250
  • how to work in background ? #249
  • installing plugin #244
  • No Sound and vibration #242
  • Unable to build apk #241
  • still having problems with build. #239
  • Registering on iOS 9 #238
  • Custom sound repeated multiple times on Android #237
  • Android: status bar notification is not shown #236
  • Multiple Push Notifications - phonegap build #234
  • error: cannot find symbol String token = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM); #231
  • Problem using "ledColor" and "VibrationPattern" #229
  • Notification event receive, but not notification showing on android #228
  • Events for registration not being fired #227
  • 'registration' event not firing on windows phone #224
  • Can i subscribe to a topic in using plugin? #219
  • GCMIntentService.java:472: error: cannot find symbol iconColor #217
  • Push Plugin registering on iOS 9 Devices but not showing Notification #216
  • Receiving a notification "outside app" while in it? #213
  • iOS push not working for device tokens when spaces removed #212
  • Error: Plugin PushPlugin failed to install. #210
  • Build error #205
  • Android push.on('registration', cb) fires correctly on device, but not in emulator. #204
  • 1.3.0 version not compatible with "crosswalk" by PGB #199
  • How to get data on didReceiveNotification Background Process #198
  • PushNotification is not defined in some devices #196
  • not getting notifications on the Android device #195
  • Installation Errors #186
  • IOS: on registration fired twice #185
  • Build failed with exit code 8 #184
  • iOS: Not able to schedule local notification after adding the plugin #183
  • How to show multiple notifications individually in android? #181
  • iOS init option type #180
  • Building for Android is a quest #179
  • How do i tell if the user open the app by tapping the notification? #176
  • IOS custom push sound when app is in background #175
  • Hi guys please post full working procedure, I'm not able to get registration id also. Please help #174
  • Has anyone tested this plugin on windows? #173

Tuesday, August 25, 2015

PhoneGap-Plugin-Push Version 1.2.0 Released!

The latest release of the PushPlugin is now available on npm. This release focuses on bringing a number of enhancements to Android notifications.

Fear not fans of other platforms as subsequent releases will have more features for your OS of choice. In fact release 1.3.0 will center around iOS9 support.

Picture Notifications

Embed a large picture in your notification. You let the plugin know you want to display a picture by setting the style of the push to picture and then giving it a picture property.

For example:
{
    title:"Big Picture", 
    message: "This is my big picture message", 
    style: "picture",
    picture: "http://36.media.tumblr.com/c066cc2238103856c9ac506faa6f3bc2/tumblr_nmstmqtuo81tssmyno1_1280.jpg",
    summaryText: "The internet is built on cat pictures"
}
Produces the cat picture on the right.

Inbox Notifications

Instead of stacking notifications in the tray you can now add multiple notifications to a single entry in the tray by setting the style to inbox. The first notification that arrives looks like normal but the subsequent ones will look like an inbox.

For example:
{
    title:"My Title", 
    message: "My first message", 
    style: "inbox",
    summaryText: "There are %n% notifications"
}
Followed by:
{
    title:"My Title", 
    message: "My second message", 
    style: "inbox",
    summaryText: "There are %n% notifications"
}
Produces the notification above.

Finally, my favourite new addition...

Action Buttons

Your notification can include action buttons. If you wish to include an icon along with the button name they must be placed in the res/drawable directory of your Android project. Then you can send the following JSON from GCM:
{
    title:"AUX Scrum", 
    message: "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.", 
    actions: [
        { icon: "emailGuests", title: "EMAIL GUESTS", callback: "app.emailGuests"},
        { icon: "snooze", title: "SNOOZE", callback: "app.snooze"},
    ]
}
This will produce the following notification in your tray:


When the user clicks on one of the buttons it will execute the JavaScript code you specified as a callback for that button.

Check out the plugin's README for more details.

Full Change Log
1.2.0 (2015-08-25)

Implemented enhancements:
  • Implement Big Picture Style for Android #75
  • Implement Inbox style for Android #74
  • on("registration" is not getting called... #66
  • multi-line text support #63
  • Add image property to iOS and Android #39
  • Programmatically register #31
Fixed bugs:
  • Pushes being deleted from notification bar when cold start #67
  • No default sound in Android #53
  • Multiple push notification problem #48
Closed issues:
  • oficial push plugin and windows and wp8 compatibility #71
  • On Android, GCMIntentService.onError() doesn't get passed to the JavaScript "error" event #65
  • Android: add property to vibrate phone on received notification #61
  • push.on => "registration" will trigger twice times that only in iOS #57
  • Publish plugin to PhoneGap Build #22
Merged pull requests:

Monday, April 7, 2014

Comic Covers Now Supports DC Comics

My extension to Muzei called Comic Cover now supports DC covers. You can now select Marvel, DC or all under the customization section.




Let me know what comic company I should target next in the comics.

Tuesday, February 25, 2014

Introducing Comic Cover Muzei

If you own an Android phone you should know about the wonderful new live wallpaper app, Muzei coded by Roman Nurik. I was hooked on it from day one. You see Muzei automatically downloads and sets a new wallpaper image for you every day. By default the app will download art curated by Roman's fiancée. The first image it showed was van Gogh "The Starry Night" which is one of my favourite paintings and I'm getting a chance to see it at MOMA this summer but I digress.

After I downloaded the app I was reminded of a blog post by my buddy Raymond Camden. In the post on the Marvel Comic's API, Ray shows how to query the Marvel database and display covers. So I decided to combine chocolate and peanut butter into one awesome combination.

The Muzei app provides a way to write an extension to provide a new data source. So what I've done is to create an extension that randomly picks a Marvel Comic book cover and sets it as your wallpaper. It's called Comic Cover Muzei.


Select the data source


Set your options


Enjoy your art

Right now you can set an option to only download the images over wifi if you are worried about bandwidth usage and you can set the refresh interval from 3 to 24 hours. I've got plans to add more options to allow you to pick the character or series to pull the images from. 

Also, right now the app only uses Marvel Comic covers but I'd love to add other companies like DC, Image, etc.



Sunday, November 24, 2013

Three Things That Tripped Me Up This Week

I've had a pretty productive week at work but here are three things that tripped me up this week. I'm putting them down in blog post format so that I'll remember them and maybe they'll help you as well.

1) Concurrent Modification Exception

So I was working on some code where I needed to loop through a collection of users and remove one when it meets a certain criteria. Which I coded up as:

        List users = um.getUsers();
        
        for (User user : users) {
            if (user.isAnAss()) {
                users.remove(user);
            }            
        }

Do you see the problem? No, neither did I as I wasn't thinking and luckily enough for most of my test runs the user who isAnAss was at the end of the List so the exception wasn't throw. When the isAnAss user was in the middle of the list BOOM! ConcurrentModificationException.

To get around this problem I ended up doing an old school iteration through the list.

        List users = um.getUsers();
        
        User user = null;
        for (int i = 0; i < users.size(); i++) {
            user = users.get(i);
            if (user.isAnAss()) {
                users.remove(user);
            }            
        }

2) Relative Layouts in Android are Slow for Complex Layout

I've been working on a lot of complex layouts for an Android app I'm working on and I was using the RelativeLayout judiciously. One of my dialogs was taking quite awhile to load and doing some profiling I determined it to be the measure method for the RelativeLayout was being called many, many times. Switching to a LinearLayout helped reduce these calls.

Romain Guy recently posted a slide deck on how RelativeLayout's are getting better in Android 4.4 and here is a video or Romain and Adam Powell talking about writing custom Android views.




3) Android's Handling of Images Sucks

It just sucks so hard. I was doing some performance tuning of one of our dialogs and found that about 90% of the time it was taking before being show was loading the three images it was using. Cache those images folks, doesn't matter how small they are.

Monday, October 7, 2013

My PhoneGap Day US Talk on Speech Recognition

Back in July I went out to Portland to talk at PhoneGap Day US. The video has just become available so I figured I would post it up here. The talk I did at PhoneGap Day EU is very similar to this one with a bit of updated information and mostly new jokes.


Thursday, June 13, 2013

My PhoneGap Presentation to Ottawa JS

So on Wednesday night I did my Introduction to PhoneGap/Apache Cordova (GitHub repo) presentation for Ottawa JS at the beautiful Shopify lounge. I've given this presentation a ton of times so I decided to give it a twist this time around.

The first thing I did was convert my old slide deck into a reveal.js presentation. Then I popped all the assets into a PhoneGap iPad project to see how it looked. Well, reveal.js looks and works great on an iPad.

At this point I started to get fancy. When I got to the part of the presentation where I would usually switch from the presentation software to Eclipse/Xcode to show the code and emulator I decided to call out to PhoneGap to take a picture instead. All I needed to do was include cordova.js in the app and make a call to Camera.getPicture and the results were:


this is my view from the stage


the view from the audience

And Darren took a picture of me taking the picture, while the picture I was taking was being put up on the big screen which is also in this picture. So I was able to do a presentation on PhoneGap in a PhoneGap app calling the PhoneGap API. It got meta pretty damn quick!





Sunday, June 2, 2013

Why Don't My Plugins Work in PhoneGap Android 2.7?

Well it's pretty simple, the Plugin class which has been deprecated for awhile has been removed from the package and should be replaced with CordovaPlugin.

I'm going to go through the steps needed to upgrade your old style plugins to the new style. For this example I'm going to use the Google Analytics plugin.

The first thing you will notice in 2.7.0+ is that the GoogleAnalyticsTracker class now has 4 errors in Eclipse. To get rid of them you would change:


import org.apache.cordova.api.Plugin;

into:

import org.apache.cordova.api.CordovaPlugin;

and:

public class GoogleAnalyticsTracker extends Plugin {

to:

public class GoogleAnalyticsTracker extends CordovaPlugin {

and now you'll notice you only have one error left in the file and that has to do with the execute method. You'll need to change the method signature from:

public PluginResult execute(String action, JSONArray data, String callbackId) {

to:

public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {

then you need to add a new import line at the top of the Java file:


import org.apache.cordova.api.CallbackContext;

and we still have one error which is now the line in which we are returning the PluginResult. That's because the method now expect a boolean to be the return value. To fix this issue you would replace:

return result;

with:

callbackContext.sendPluginResult(result);
return true;

Finally our Java code is free of error messages. Whew, were done but what's with the change to the execute method? Well let's just say there have been improvements in the way the Plugins are handled internally. What you need to know is that when you want to send a result back to the JavaScript side you now have a choice of three methods:

1) callbackContext.sendPluginResult(...)

Use this if you have constructed your own PluginResult and you want to send it to the JavaScript side.

2) callbackContext.error(int | String | JSONObject) 

Skip creating a PluginResult and just invoke the error callback on the JavaScript side sending back an int, a String or a JSONObject as the method payload.

3) callbackContext.success(empty | int | String | JSONObject | JSONArray)

Again, just skip creating the PluginResult and invoke the success callback on the JavaScript side sending back an int, a String, JSONObject or JSONArray as the method payload. If you don't provide any payload the method on the JS side will be executed with no payload.

So that should get you unstuck if you have a Plugin that no longer works for you as of PhoneGap 2.7.0. You should also check out my posts on the GalleryPlugin as shows how to write a Plugin using the new API for JS and Java.

IMPORTANT UPDATE!!!

We've heard your screams of pain and we are putting the Plugin class back for PhoneGap 2.8.1. Go read Joe Bowser's post. The class is back in 2.8.1 and will be in 2.9.0 then gone for good in the 3.0.0 stream!





Monday, May 13, 2013

The Ottawa City Councillor PhoneGap app

So a couple of friends of mine wanted to learn more about programming mobile applications so we decided to get together and create an application for the Apps4Ottawa competition.

We settled on creating an application that would enable folks from Ottawa to learn more about and connect with their city councillors. Sadly, I didn't even know who my city councillor was until I started working on this app.

It uses the open data Ottawa to get the city councillor information and it the Open North API to do reverse geocoding to turn your GPS co-ordinates into the correct ward.

Currently the app is available on the Google Play store and we are going through the process of getting approval for the app on the Apple store.

PhoneGap was definitely the way to go with this project. We developed pretty much in Android then when we were ready to release a version of the app we just compiled it in Xcode and it just worked. The only thing we changed were the break points for the CSS media queries to deal with the different iPhone screen sizes. Support for Windows 8 and BlackBerry 10 are also coming as we have time.

I'm going to write up a post later in the week to talk about some of the micro libraries we used in order to accelerate development.

Please give the app a try and let me know what you think of it and what can be done better. If you are so inclined we wouldn't mind a vote or two in the app in the Apps4Ottawa competition.

Wednesday, April 3, 2013

My Home Screen

Kind of a departure from my regular posts but here is what my is currently on the home screen of my Nexus 4. Look it over and share with me what apps must be on your home screen.

Twitter - pretty obvious what this is used for. Today, hockey trade updates. Great new holo themed update released.

CIBC - my bank

theScore - out of all the mobile apps for quickly checking hockey scores (anyone see a pattern?) this one is my favourite. Apps like TSN and NHL GameCenter take too much time to load.

Untappd - one of my favourite apps built on top of the PhoneGap framework. It is a social beer check in app. Great to see what your friends are drinking and helps find new beers.

Gmail - All. The. Emails.

feedly - with the upcoming demise of Google Reader I've completely switched over to feedly for my RSS reading. It's a great app that syncs with Google Reader and has a great UI experience.

Google+ - I'm not completely sold on this app yet. I know Google wants it to be a Twitter/Facebook killer but until more of my friends start using it and the network effect takes over it won't be used as much as they'd hope.

Pocket Casts - after trying out a bunch of different podcast listening apps I've settled on Pocket Casts. It has a great UI and most importantly has variable rate playback which is a must for me. If I can't listen to podcasts at 2.0x speed I go crazy listening to the um's and ah's.

IMDB - I don't even think I can watch TV or Movies without this app. I'm constantly using it to look up what other shows/movies that actor was in.

TWN - The Weather Network, pretty useful app but it may be supplanted by the weather card in Google Now.

Starbucks - I'm a coffee addict. I use the Starbucks app to pay for my coffee fix whenever I can. Plus, it's one less card I have to carry around in my Costanza sized wallet.

OPL - Ottawa Public Library, I'm an avid reader who is constantly churning through books. Luckily Ottawa has a great public library system that feeds my addiction. Again, one less card is needed in my wallet.

Google Folder - this is my shortcut to all the other Google apps I use frequently but not enough to make the home screen like Play Music, YouTube, Calendar and People.

Instagram - currently testing out this photo service to see if it is a suitable replacement for the stock camera.

Instapaper - absolutely fantastic app for saving articles and reading them later, even when you are off line.

Play Store - with the new phone I find myself constantly installing new apps so the store has made it's way to the home screen.

So that's it. What are some of your favourite apps that I'm missing?

Monday, February 18, 2013

PhoneGap Android XhrFileReader

The FileReader API works great as long as the file you want to read is on the device's file system. However if you want to read a file you've packed in the Android assets folder you would need to use XHR to read the file. I'm providing an interface that follows the same API as the regular FileReader. Of course the XhrFileReader is not limited to only reading files from the assets folder, it can also read files from the file system and over HTTP.

Adding the plugin to your project 

To install the plugin, move XhrFileReader.js to your project's www folder and include a reference to it in your html files.

Using the plugin 

To instantiate a new reader use the folling code:
var reader = cordova.require("cordova/plugin/xhrfilereader"); 
Setup your event handlers:
// called once the reader begins
reader.onloadstart = function() {
    console.log("load start");
};
// called when the file has been completely read
reader.onloadend = function(evt) {
    console.log("File read");
    console.log(evt.target.result);
}; 
Unfortunately, you will only get an error on files read over HTTP. When you specify a file:// path the request status is always 0. There is no way to tell between a successful read or an error. So if you specify a file that does not exist like "file:///does.not.exist.txt" you will get an empty evt.target.result in your onloadend handler.
// called if the reader encounters an error
reader.onerror = function(error) {
    console.log("Error: " + error.code);
}; 
Progress events are fired but are not very useful as they don't contain partial results.
// called while the file is being read
reader.onprogress = function(evt) {
    console.log("progress");
}; 
Finally call your read method, for instance:
reader.readAsText("http://www.google.com"); reader.readAsText("file:///android_asset/www/config.json"); reader.readAsText("file:///sdcard/error.log");
and that's about it. Obviously, this plugin is most useful when you need to read a text file from the assets folder.

Thursday, February 14, 2013

What's New in PhoneGap Android 2.4.0

Well PhoneGap 2.4.0 has been released. So here are couple of the new things you can look forward to:

1. Support Reading Slices of Text Files.

The File object now has a slice method. Suppose the file we're reading contains the text:

"All that is gold does not glitter, not all those who wander are lost." 

Then...

  • f.slice(4, 8) would result in "that" 
  • f.slice(9) would be "is gold does not glitter, not all those who wander are lost." 
  • f.slice(-5, -1) would be "lost"


2. Added input type=file support

Now if you specify an input field of type file you will get a "Choose File" button:


Then when you click the button you will launch an intent that can handle file picking:


Now the value of your input tag will be the file you selected.

3. Additional preferences in config.xml

I completely missed this one so Joe Bowser wrote it up.

Saturday, February 9, 2013

PhoneGap Plugin Updates to TelephoneNumber, IMEI and TTS

I've updated the TelephoneNumber, IMEI and TTS plugins to use the Apache Cordova 2.2.0 API's. That means no more deprecation notices in the Java code and the JavaScript code uses the cordova.require method. However, I'm still slapping the objects into window.plugins so you shouldn't need to change any of your JavaScript code after upgrading.

This completes the upgrade of my plugins that everyone voted on. Next up will be some new work and hopefully I'll be able to get to that WebSpeech shim I've been threatening to do.

Thursday, January 31, 2013

GalleryPlugin

I've updated the GalleryPlugin to the Cordova 2.2.0 API but I've realized that I've never really talked about it. The GalleryPlugin is used when you need to add or remove a file from the Gallery or Music apps. Typical use cases include downloading an image from the internet and wanting it to show up in the Android Gallery app or conversely you delete a file and you don't want the dreaded black rectangle to be left in the Gallery app.


First lets take a look at what the gallery.js file. It's written using the cordova.define template but it still adds itself into window.plugins for those of you using the old style plugins:

Then will move on to the Java code. I've trimmed down code only to show the execute method for brevity.

In order to use this plugin you'll need to include the gallery.js in your HTML as a script tag:

and add a line to res/xml/config.xml to tell the JavaScript side where to find your Java class:

Now you should be able to add and remove images from the gallery. Here is some sample code to get you going:

Sunday, January 27, 2013

PhoneGap Plugin Updates to BarcodeScanner and AppPreferences

I've updated the BarcodeScanner and AppPreferences to use the Apache Cordova 2.2.0 API's. That means no more deprecation notices in the Java code and the JavaScript code uses the cordova.require method. However, I'm still slapping the objects into window.plugins so you shouldn't need to change any of your JavaScript code after upgrading.

The BarcodeScanner code has also been updated to use the ZXing 2.1 library. If all goes well there I will contact Ryan over at PhoneGap Build to pick up my changes.

Next up will be the GalleryPlugin. The only thing holding it up is that I want to add a remove method to go along with the add.

Monday, January 21, 2013

PhoneGap Plugin Updates

In the past few days I've spent some time upgrading my plugins so they work in PhoneGap/Cordova 2.2.0 or greater without requiring the users to make any changes. I've done the FtpClient and VideoPlayer. Basically I'm removing any deprecation warnings by moving from the org.apache.cordova.api.Plugin class to the org.apache.cordova.api.CordovaPlugin class. Also, I've been moving to the cordova.require way of defining a plugin on the JavaScript side while retaining the old window.plugins object for people who've written their code to use this object.

I'm currently running a poll to see which of my plugins should get upgraded next so go please vote for your favourite:


I'll start picking them off as I have time this week.

Tuesday, December 18, 2012

What's New in PhoneGap Android 2.3.0

Well we've tagged Apache Cordova 2.3.0 release candidate 2 which means that Cordova 2.3.0 will be out soon in source release form which will be followed quickly by the binary PhoneGap 2.3.0 release. Shaz wrote up a post on what's new in iOS so I followed suit to do this one for Android. So without further ado here's what you should expect on Android:

1. InAppBrowser – includes events

More details here. In a nutshell, this has the same functionality as the ChildBrowser, and has events support as well. It supports this simplified spec. Also, the InAppBrowser does not use the app whitelist. Example usage:
2. Device API changes

Minor changes as specified here. For Android, device.name is now deprecated for all platforms. For all platforms, there is a new property called device.model which returns what device.name used to return.

3. Various Bug Fixes
  • Searching for emails in Contacts throws an exception always errors out
  • Create script improvement: Display usage and exit when no arguments given
  • Fixed adding a Photo from a HTTPS address to Contact
  • Fixed NPE in onReceivedError with non local errorUrl
  • Camera.getPicture gives error when get a picture from photo library with spaces in its name on Android is now fixed
  • Online/Offline events now fire on subsequent pages of an app
  • fixing cordova commands for paths with spaces in them
  • FileEntry.moveTo across file systems incorrectly calls the success callback

Thursday, December 6, 2012

How to Get the Device's Phone Number Using PhoneGap Android

I was a bit surprised when three people asked me how to do this in one day. I figured if there was enough interest in it then maybe it deserved a post of it's own. Basically you want to know the primary phone number of the device your app is running on. In order to do that in PhoneGap you will need to write a plugin to access the TelephonyManager service on Android.

As always the code for this plugin is is GitHub at my TelephoneNumberPlugin repo. If you'd rather have a more detailed walk through please read on.
First up let's code our JavaScript interface which we will use to get the telephone number. We'll setup a new interface at "cordova/plugin/telephonenumber" to avoid name collisions. Then the rest is fairly boiler plate code where we declare and error object that we won't even use and finally provide a get method. When you call the get method you should provide a success callback. The success callback will be invoked with a string that will contain the devices phone number. If something goes wrong the failure callback will be invoked.

I've extracted the execute method from TelephoneNumber.java which extends from the new CordovaPlugin interface. The method is fairly self explanatory. If the device has a phone number it will be returned. If not the error call back is invoked with the NO_TELEPHONE_NUMBER error code. If you try to call anything other than "get" on this class you'll get a INVALID_ACTION error.

In order to use this plugin you'll need to include the telephonenumber.js in your HTML as a script tag:

and add a line to res/xml/config.xml to tell the JavaScript side where to find your Java class:

and if you don't already have READ_PHONE_STATE as a permission in your AndroidManifest.xml you will need to add it as well.

Now you should be able to get your devices phone number. Here is some sample code that writes the phone number out to the console:

Friday, November 16, 2012

Getting the create Command to Work on PhoneGap 2.2.0 Android

Okay as of PhoneGap 2.2.0 the Getting Started guide has been "simplified" to make creating your first Phonegap Android project easier. Boy, that's not the  impression I get after helping people on the PhoneGap Google Group for the past week and a half.

From what I understand most of us Cordova core developers use a Mac as our main machine. Now I don't want to and won't start an OS holy war since there is a very good reason why we do that, you can't do iOS without a Mac and the tools for Android and BlackBerry development will run on a Mac so it makes sense for those of us who have to jump back and forth to be using a Mac. However, we've really dropped the ball in explaining what the proper setup needs to be when you are on a PC. So that's why I'm writing this blog post from my old Windows laptop that I dusted off so I can feel your pain.

Required Software
  1. Java Development Kit
  2. Apache Ant
  3. Android Development Kit
Go ahead and download and install those packages if you haven't already. I'll wait. I'm not up to anything else right now. But please pay attention to where you install these packages as you'll need those paths later.

Oh good, you're back.

First problem

Once you navigate to the phongeap\lib\android\bin directory the getting started guide tells you to run the following command:
./create <project_folder_path> <package_name> <project_name>
but that is not accurate on a Windows system as it won't be able to find the create command. The line should be:
create <project_folder_path> <package_name> <project_name>
Second problem

Once you do that you probably will see this error:


So basically and unhelpful error telling you that you are missing a package. We'll need to make sure the following commands can be run from the command prompt. Let's start by testing if the command line can find java.exe first. So type:
java
into the command line. If you see something like this:


then you will need to modify your PATH environment variable so that the script can find Java. First you'll need to discover where your JDK is installed. I can't tell you where that is so I hope you took my advice and noted where the installer placed those files. Armed with the path to your Java Development Kit do the following:

  • From the Desktop, right-click My Computer and click Properties. 
  • Click Advanced System Settings link in the left column. 
  • In the System Properties window click the Environment Variables button. 
  • Select the PATH variable from the System variables section. 
  • Select the Edit button.
which means you should have a dialog something like this:


This is where you will add the JDK\bin directory to your PATH. Notice you need to point to the bin directory where commands line java and javac are kept. For example "c:\jdk\bin". Also make sure to separate different path entries using a ";". Now you need to click OK then OK once more. After that close your command prompt and start a new one so the updated PATH variable will be used. In the new command prompt run:
java
once again and you should see something like this:


Now the create script will be able to find java. Unfortunately you'll need to repeat the process for the following commands:
  • javac
  • ant
  • adb
  • android
If you get the "blah" is not a recognized internal or external command error message for any of the above you'll need to add it to the PATH.

Third problem

The environment variable JAVA_HOME may be set incorrectly. Make sure that this variable is set and it refers to the root directory of your JDK and not JRE. The create.js script looks for %JAVA_HOME%\bin\javac.exe and if it can't find it there will be an error.

Fourth problem

Don't use '-' in your package name. The '-' is not a valid character in a Java package name.

Bad:    ./create ./name com.my-company.name name
Good:  ./create ./name com.mycompany.name name

Okay, I hope that helps everyone. I'm going to make the error messages more descriptive while I'm on my PC for the upcoming 2.3.0 release.


Monday, November 12, 2012

Building a Native Context Menu for PhoneGap Android

So I know I promised that I'd write about a HTML only menu but I thought folks might be interested in native context menus as well. It's not much different than my last blog post on menu's so it should be easy to follow.

So when I talk about a native context menu I mean the menu that clicks when you do a long press on an Android device. Again this is well covered on the Android Developer page. Here is an example of an context menu from the Contacts app:


The first step in creating the menu is to define it in XML. My recommendation is to create a menu folder under the res folder in your Android Eclipse project. Then you create a new File with an XML extension. For this post I'll call mine example.xml. When you're done your res folder should look something like this:


Don't worry about the red X's as we haven't edited the XML file yet so it is going to complain about a premature end of file. For a real good description of what goes into a menu XML file read this. For our purposes I'm just going to give you the XML to paste into the file:

But when you view the file in Eclipse you'll still see errors:


and that is to be expected as we haven't added the two images to the drawables folder nor have we added our two new strings to strings.xml. To fix these issues first download these two images:


and copy them to your projects res/drawable-hdpi folder. When you want to put out a professional application you'll need to provide icons of various sizes but the above is enough for our needs.

To fix the rest of the red X's you'll need to open the res/values/strings.xml and add two new Strings. The first should have the name "settings" and a value of "Settings. The second should have the name"help" and, predictably, the value of "Help". At this point all the red X's from example.xml and from the res folder hierarchy should have disappeared. 


If they haven't, well then you've done something wrong and should probably go back over all the steps to make sure you haven't missed anything.

Okay, so now we've got all the resources in place. Let's go write some actual Java code. Don't worry much of it will be cut and paste. In Eclipse open up your main Java class, you know the one that extends DroidGap.

First you'll need to register the context menu in the onCreate method. Basically, you'll need to add the call to registerForContextMenu to your onCreate method:


Secondly we'll need to tell your application what to do when it detects a long press. You'll need to paste the following code into you main Java class:

You shouldn't need to change anything unless you've called your menu XML file something different than example.xml. If you have you'll need to change R.menu.example into R.menu. where you replace with the name of your file minus the .xml extension.

The last bit of code you need to add is a method that will tell your application what to do when the individual menu items are clicked. Here's some example code:


When you click on the Setting button we'll use an Android intent to load the devices Settings panel. If you click on the Help button then we'll execute some JavaScript code. That's it! You don't need to add anything to your HTML/JS code to get a native Android context menu working with your PhoneGap application. Here is what it would look like:



Please note, I'm just providing a quick example and you are not limited to how you handle the menu button clicks in the least. You may want to handle it in Java and do something that you can't do in JavaScript or you may want to call a JavaScript function on your page to have your UI react in some interesting way.

So, there you go. The process is nearly identical to creating an options menu that I described in my previous post. I promise that in my next post I'll show you how to handle everything in HTML and JavaScript!