![]() |
Friday, September 30, 2011
Books I've Read This Week
Thursday, September 29, 2011
Final New DCU Guest Post on The Signal Watch
Ryan is still not fed up with me so I've sounded off once more on this weeks DC new releases on his blog, The Signal Watch. My favourite book of the week was easily All Star Western which seems to be a mash up of Spagetti Westerns, Sherlock Holmes type mysteries and Hitchcockian horror!
Monday, September 26, 2011
Upcoming PhoneGap Speaking Engagements
Just some updates on some places I'm going to be this year talking about PhoneGap:
- Ottawa Android Droidhack October 8th - we are going to be spending the day hacking some PhoneGap Plugins for Android.
- InterLab, US Dept. Of Energy October 31st - Workshop on Building Cross Platform Mobile Apps with PhoneGap
- Boulder Digital Arts November 1st - Open Source Mobile Development with PhoneGap
- AnDevCon II November 9th - Extending Your PhoneGap Application with Plug-ins
Friday, September 23, 2011
Books I've Read This Week
As a child of the 80's the references in this book really resonated with me. Besides that it is an excellently written sci-fi novel that I can't recommend highly enough. |
See you next Friday.
Tuesday, September 20, 2011
Saving Contacts with PhoneGap Android
Frequently on the Phonegap Google Group I'm responding to users who have problems saving contacts on Android using PhoneGap. There are a number of steps that you need to follow in order to be able to save a contact on your device/emulator and I thought I'd go over them here so that others can benefit.
First off is the choice of API you use when creating your emulator. Most people will use the "Android" version of the API level they want to target. Amazingly enough this is a bad choice. Say you wanted to target API level 10 you shouldn't select "Android 2.3.3 - API Level 10" instead you should select "Google APIs (Google Inc.) - API Level 10".
Update 2012/02/29: I've fixed an issue in PhoneGap 1.4.1 and you should now be able to save contacts to the local database and not require a Google account anymore.
So let's get started by creating a new AVD:
Once you've got the code in place run the application in the AVD created earlier. You should see the following:
At this point you are probably thinking "well that's not good". Well no it isn't but at least there is a good reason for it. Your AVD has no account so let's go create one. You have to go to Applications -> Settings
Accounts & Sync
I recommend using the Google account option as it is the easiest to setup and it's far more likely you have access to a Google account for testing rather than an MS Exchange account.
Select Next
Select Create if you don't have a Google account or Sign In if you already do.
Provide your user id and password, then click Sign In.
You should see the following success screen.
Now click Finish Setup and re-run your application and you should see this screen:
Alright, we did it. Let's head into the Contacts application to make sure that the contact has saved successfully. To which we are greeted with this screen:
Now at this point I've probably lost all credibility with you but wait don't click off the post just yet as this is completely normal. Click the Menu button and select Display Options
Then you'll need to select the new account that you added and click the checkbox to show All Contacts.
Then once you click the Done button you'll be taken back to the Contacts application and you will finally get to see the contact you saved.
That is a bit of a pain to setup but once it is done you won't need to ever do it again as long as you keep your AVD around.
However, there are two other things that trip up people when they are trying to save on contact from a PhoneGap application. The first is that people forget to put the WRITE_CONTACTS permission in their manifest file. You should have this line in your AndroidManifest.xml file:
The second gotcha is that the developer never actually calls the save() method. You see the code:
First off is the choice of API you use when creating your emulator. Most people will use the "Android" version of the API level they want to target. Amazingly enough this is a bad choice. Say you wanted to target API level 10 you shouldn't select "Android 2.3.3 - API Level 10" instead you should select "Google APIs (Google Inc.) - API Level 10".
Update 2012/02/29: I've fixed an issue in PhoneGap 1.4.1 and you should now be able to save contacts to the local database and not require a Google account anymore.
So let's get started by creating a new AVD:
Once you have a your new Google API AVD setup you'll want to create you PhoneGap application and use the following HTML as your main page:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Contact Example</title> | |
<script type="text/javascript" charset="utf-8" src="phonegap-1.0.0.js"></script> | |
<script type="text/javascript" charset="utf-8"> | |
// Wait for PhoneGap to load | |
// | |
document.addEventListener("deviceready", onDeviceReady, false); | |
// PhoneGap is ready | |
// | |
function onDeviceReady() { | |
// create | |
var contact = navigator.contacts.create(); | |
contact.displayName = "Plumber"; | |
contact.nickname = "Plumber"; //specify both to support all devices | |
var name = new ContactName(); | |
name.givenName = "Jane"; | |
name.familyName = "Doe"; | |
contact.name = name; | |
// save | |
contact.save(onSaveSuccess,onSaveError); | |
} | |
// onSaveSuccess: Get a snapshot of the current contacts | |
// | |
function onSaveSuccess(contact) { | |
alert("Save Success"); | |
} | |
// onSaveError: Failed to get the contacts | |
// | |
function onSaveError(contactError) { | |
alert("Error = " + contactError.code); | |
} | |
</script> | |
</head> | |
<body> | |
<h1>Example</h1> | |
<p>Find Contacts</p> | |
</body> | |
</html> |
Once you've got the code in place run the application in the AVD created earlier. You should see the following:
At this point you are probably thinking "well that's not good". Well no it isn't but at least there is a good reason for it. Your AVD has no account so let's go create one. You have to go to Applications -> Settings
Accounts & Sync
Click Add an Account
I recommend using the Google account option as it is the easiest to setup and it's far more likely you have access to a Google account for testing rather than an MS Exchange account.
Select Next
Select Create if you don't have a Google account or Sign In if you already do.
Provide your user id and password, then click Sign In.
You should see the following success screen.
Now click Finish Setup and re-run your application and you should see this screen:
Alright, we did it. Let's head into the Contacts application to make sure that the contact has saved successfully. To which we are greeted with this screen:
Now at this point I've probably lost all credibility with you but wait don't click off the post just yet as this is completely normal. Click the Menu button and select Display Options
Then you'll need to select the new account that you added and click the checkbox to show All Contacts.
Then once you click the Done button you'll be taken back to the Contacts application and you will finally get to see the contact you saved.
That is a bit of a pain to setup but once it is done you won't need to ever do it again as long as you keep your AVD around.
However, there are two other things that trip up people when they are trying to save on contact from a PhoneGap application. The first is that people forget to put the WRITE_CONTACTS permission in their manifest file. You should have this line in your AndroidManifest.xml file:
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>
The second gotcha is that the developer never actually calls the save() method. You see the code:
var contact = navigator.contacts.create();Does not persist the contact to the internal database. Rather it creates an object contact that is an instance of a Contact. If you want to save your contact to the database you need to call contact.save():
contact.save(successCB, errorCB);So if you've followed all of these instructions and you still can't seem to get the contact to save come on over to the PhoneGap Google Groups and ask for some help. You might just have found a bug. Please mention details of what the problem is. A bug report called "Contacts are broke" doesn't give anyone enough information to help you.
Friday, September 16, 2011
Books I've Read This Week
See you next Friday.
Wednesday, September 14, 2011
Another Guest Post on The Signal Watch
Again my buddy Ryan let's me sound off on this weeks DC new releases on his blog, The Signal Watch!
Tuesday, September 13, 2011
Droidhack with Imerj's Smartpad
On Saturday September 10th we had our latest Ottawa Android Droidhack event with participation from Imerj. They had a number of their new Smartpad devices on hand for everyone to play with and they were providing folks with their SDK.
The Imerj Smartpad is a dual screen Android device not unlike the Kyocera Echo but unlike the Echo the Smartpad does not have a flimsy hinge. The Smartpad opens like a book and doesn't require any flipping, pushing or clicking.
Although the Smartpad does not run stock Android and you will need to get the SDK from Imerj in order to take advantage of the dual screen phone. In the time I had to play with the phone I was able to get a PhoneGap application running on the device without any changes to the application or PhoneGap code.
The next Droidhack will be held on October 8th and the focus of the day will be creating PhoneGap-Android plugins. So if you've ever wanted to learn more about PhoneGap and you'll be in the Ottawa area you should stop on by.
The Imerj Smartpad is a dual screen Android device not unlike the Kyocera Echo but unlike the Echo the Smartpad does not have a flimsy hinge. The Smartpad opens like a book and doesn't require any flipping, pushing or clicking.
Although the Smartpad does not run stock Android and you will need to get the SDK from Imerj in order to take advantage of the dual screen phone. In the time I had to play with the phone I was able to get a PhoneGap application running on the device without any changes to the application or PhoneGap code.
The next Droidhack will be held on October 8th and the focus of the day will be creating PhoneGap-Android plugins. So if you've ever wanted to learn more about PhoneGap and you'll be in the Ottawa area you should stop on by.
Saturday, September 10, 2011
My Guest Post on the Signal Watch
If you care to ready my thoughts on this weeks new releases from DC you can over at my buddy Ryan's blog, The Signal Watch!
Friday, September 9, 2011
PhoneGap Android ChildBrowser Revamp
Recently I've been spending quite a bit of time revamping the Android ChildBrowser so that it is more in line with the ChildBrowser available for iOS. The big problem was that on Android we started a new Intent to view the web page and there was no way to communicate back to the original application. This new approach uses a dialog with an embedded web view to show the new web page but don't worry you can still use the old way if you really want.
Installation of the new plugin is much the same as it was previously.
1. To install the plugin, move www/childbrowser.js to your project's www folder and include a reference to it in your html file after phonegap.{ver}.js.
<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>
<script type="text/javascript" charset="utf-8" src="childbrowser.js"></script>
2. Copy the image files folder www/childbrowser to your project'w www folder. Note you need the entire folder not just the images. Feel free to provide your own images, these are only some default place holders we are providing.
3. Create a directory within your project called "src/com/phonegap/plugins/childBrowser" and copy "src/com/phonegap/plugins/childBrowser/ChildBrowser.java" into it.
4. Add the following activity to your AndroidManifest.xml file. It should be added inside the <application> tag.
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name">
<intent-filter>
</intent-filter>
</activity>
5. In your res/xml/plugins.xml file add the following line:
<plugin name="ChildBrowser" value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
Once installed properly, you should be able to browse external sites. I've provided the full listing of my test html at the end of this post but for now here's a screen shot of what the app would look like:
As you can see there are three buttons. The first "Show Page" is going to give you a dialog that looks like this:
This is accomplished by calling the following JavaScript:
Which is accomplished by calling the following JavaScript:
Finally if you push the last button "Old ChildBrowser" you would have a new Intent being launched to handle the page view:
Now the syntax for getting the old ChildBrowser behaviour has changed a bit. It is now:
Installation of the new plugin is much the same as it was previously.
1. To install the plugin, move www/childbrowser.js to your project's www folder and include a reference to it in your html file after phonegap.{ver}.js.
<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>
<script type="text/javascript" charset="utf-8" src="childbrowser.js"></script>
2. Copy the image files folder www/childbrowser to your project'w www folder. Note you need the entire folder not just the images. Feel free to provide your own images, these are only some default place holders we are providing.
3. Create a directory within your project called "src/com/phonegap/plugins/childBrowser" and copy "src/com/phonegap/plugins/childBrowser/ChildBrowser.java" into it.
4. Add the following activity to your AndroidManifest.xml file. It should be added inside the <application> tag.
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name">
<intent-filter>
</intent-filter>
</activity>
5. In your res/xml/plugins.xml file add the following line:
<plugin name="ChildBrowser" value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
Once installed properly, you should be able to browse external sites. I've provided the full listing of my test html at the end of this post but for now here's a screen shot of what the app would look like:
As you can see there are three buttons. The first "Show Page" is going to give you a dialog that looks like this:
This is accomplished by calling the following JavaScript:
window.plugins.childBrowser.showWebPage( "http://www.phonegap.com", { showLocationBar: true });The second button "Show Page No Toolbar" once pressed gives you a dialog that looks like this:
Which is accomplished by calling the following JavaScript:
window.plugins.childBrowser.showWebPage( "http://www.phonegap.com", { showLocationBar: false });As you can see the only difference between it and the first example is that the showLocationBar parameter has been set to false. Currently this is the only optional parameter we support right now but more can be added easily if required.
Finally if you push the last button "Old ChildBrowser" you would have a new Intent being launched to handle the page view:
Now the syntax for getting the old ChildBrowser behaviour has changed a bit. It is now:
window.plugins.childBrowser.openExternal("http://www.phonegap.com");Now this is all well and good but how does it help us communicate between the application and the child browser. To do this we provide a couple of event handler on the ChildBrowser for onClose and onLocationChanged. You provide your own functions which are called when the ChildBrowser gets a close event or a locationChanged event. For instance:
function showPage(locbar) { window.plugins.childBrowser.onLocationChange = locationChanged; window.plugins.childBrowser.onClose = closed; window.plugins.childBrowser.showWebPage( "http://www.phonegap.com", { showLocationBar: locbar }); } function locationChanged(newurl) { console.log("The JS got this url = " + newurl); } function closed() { console.log("The JS got a close event"); }Well I hope people find the changes useful. It should make doing oauth a lot easier. No, I don't have an example for that yet.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="viewport" content="width=320; user-scalable=no" /> | |
<meta http-equiv="Content-type" content="text/html; charset=utf-8"> | |
<title>Child Browser Example</title> | |
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8"> | |
<script type="text/javascript" charset="utf-8" src="phonegap-1.0.0.js"></script> | |
<script type="text/javascript" charset="utf-8" src="childbrowser.js"></script> | |
<script type="text/javascript" charset="utf-8"> | |
// Wait for PhoneGap to load | |
// | |
function init(){ | |
document.addEventListener("deviceready", onDeviceReady, false); | |
} | |
// PhoneGap is ready | |
// | |
function onDeviceReady() { | |
console.log("PhoneGap is ready"); | |
} | |
function locationChanged(newurl) { | |
console.log("The JS got this url = " + newurl); | |
} | |
function closed() { | |
console.log("The JS got a close event"); | |
} | |
function showPage(locbar) { | |
window.plugins.childBrowser.onLocationChange = locationChanged; | |
window.plugins.childBrowser.onClose = closed; | |
window.plugins.childBrowser.showWebPage("http://www.phonegap.com", { | |
showLocationBar: locbar | |
}); | |
} | |
function openExternal() { | |
window.plugins.childBrowser.openExternal("http://www.phonegap.com"); | |
} | |
</script> | |
</head> | |
<body onload="init()" id="stage" class="theme"> | |
<a href="#" class="btn large" onclick="showPage(true); return false;">Show Page</a></p> | |
<a href="#" class="btn large" onclick="showPage(false); return false;">Show Page No Toolbar</a></p> | |
<a href="#" class="btn large" onclick="openExternal(); return false;">Old ChildBrowser</a></p> | |
</body> | |
</html> |
Books I've Read This Week
I was on vacation and travelling for most of the week. Surprisingly I didn't get a chance to read as many books as I would have liked.
See you next Friday.
The main character, John Taylor, is searching for the origins of the Nightside and clues to his mother's identity. We are treated to lots and lots of exposition as John uncovers the answers he seeks. Basically this book didn't have a lot of conflict in it but rather seemed to be setting up the next novels and fleshing out the world of the Nightside. |
See you next Friday.
Thursday, September 8, 2011
There Goes a Day!
In my continuing saga to use Android only for a month straight I decided to upgrade my Samsung Galaxy S from Android 2.1 to 2.3 as the update is now available. As I mentioned in my last post Samsung Kies, the software used to upgrade your firmware, is not supported on my Mac. The solution of course was to dust off my old T61p ThinkPad and load up the Kies software on it.
At least that was fairly straight forward although nothing after that was. I plugged in my phone after installing Kies and the software could not determine my phones current firmware level. After a reboot of my phone and PC it finally identified I was running Android 2.1.
Going to the update firmware section Kies informed me I would upgrade in two steps, 2.1 -> 2.2 and 2.2 -> 2.3. Fair enough, I thought. So everything was going along swimmingly until a dialog box popped up telling me the upgrade failed and I should unplug my phone reboot and try again. Everything in my nature told me this was the wrong thing to do but I went along with it any way.
Big mistake, my phone was now bricked. I was treated with this image on my phone:
Reading up on this I was able to find out the magic three key combination of volume down, home and power that would put the phone back in download mode. Even after that no amount of prompting would get the phone to reconnect with Kies.
ARG!!!
I don't know why I bothered to try and do it the "right way". Instead I ended up following this instructions which actually worked! Basically it uses Odin to flash the firmware on my phone. After a few minutes of flashing by Odin, and a factory reset, my phone was back to working properly. Because I did a factory reset I needed to re-install all my apps but who cares the phone works again.
My first impression of Android 2.3.3 is that it fixes the issue with the GPS on my phone. I can actually get a location now!
At least that was fairly straight forward although nothing after that was. I plugged in my phone after installing Kies and the software could not determine my phones current firmware level. After a reboot of my phone and PC it finally identified I was running Android 2.1.
Going to the update firmware section Kies informed me I would upgrade in two steps, 2.1 -> 2.2 and 2.2 -> 2.3. Fair enough, I thought. So everything was going along swimmingly until a dialog box popped up telling me the upgrade failed and I should unplug my phone reboot and try again. Everything in my nature told me this was the wrong thing to do but I went along with it any way.
Big mistake, my phone was now bricked. I was treated with this image on my phone:
Reading up on this I was able to find out the magic three key combination of volume down, home and power that would put the phone back in download mode. Even after that no amount of prompting would get the phone to reconnect with Kies.
ARG!!!
I don't know why I bothered to try and do it the "right way". Instead I ended up following this instructions which actually worked! Basically it uses Odin to flash the firmware on my phone. After a few minutes of flashing by Odin, and a factory reset, my phone was back to working properly. Because I did a factory reset I needed to re-install all my apps but who cares the phone works again.
My first impression of Android 2.3.3 is that it fixes the issue with the GPS on my phone. I can actually get a location now!
Tuesday, September 6, 2011
Android Has a Month to Woo Me
Well my 3 year contract with Rogers came due on September 4th. I decided to have them park my number for a month while I put my iPhone away and decided to use my Android phone full time. Basically, Android has a month to woo me before I make a decision to get a fancy new Android phone or an iPhone 5.
Right now I'm using a Samsung Galaxy S running Android 2.1 and I totally threw it into the deep end right off the bat. My first day using the phone full time was on our trip from Sydney, NS back home to Ottawa, ON. The phone got used a lot to play games and look up info while we were waiting in lines and flying in planes. Sadly, on the drive home from the airport to the house the phone ran out of battery. This is a strike against the phone as this level of usage doesn't typically drain my iPhone battery down to zero.
Day two was a much more reasonable day of kicking around Ottawa but still by the end of the day the phone battery was drained. A few of my most frequently used applications on the iPhone are Twitter and Foursquare. On my Android phone Twitter crashes frequently so I switched to TweetDeck and Foursquare can never get a GPS location. So far things are not going as smoothly as I'd have like.
I'll continue to use the Android phone and see what I can do to improve it's performance and battery life. First up I'll see if I can get it upgraded to 2.3 but the Samsung software for this does not run on my Mac.
Right now I'm using a Samsung Galaxy S running Android 2.1 and I totally threw it into the deep end right off the bat. My first day using the phone full time was on our trip from Sydney, NS back home to Ottawa, ON. The phone got used a lot to play games and look up info while we were waiting in lines and flying in planes. Sadly, on the drive home from the airport to the house the phone ran out of battery. This is a strike against the phone as this level of usage doesn't typically drain my iPhone battery down to zero.
Day two was a much more reasonable day of kicking around Ottawa but still by the end of the day the phone battery was drained. A few of my most frequently used applications on the iPhone are Twitter and Foursquare. On my Android phone Twitter crashes frequently so I switched to TweetDeck and Foursquare can never get a GPS location. So far things are not going as smoothly as I'd have like.
I'll continue to use the Android phone and see what I can do to improve it's performance and battery life. First up I'll see if I can get it upgraded to 2.3 but the Samsung software for this does not run on my Mac.
Friday, September 2, 2011
Books I've Read This Week
See you next Friday.
Subscribe to:
Posts (Atom)