First let me say I love what PhoneGap offers; easy to get an app up and running on multiple devices in a relative short timeframe. Having said that, what is lacking is a better understanding of using Plugins or in the case of WebOS in using node.js services. What I found out was if you are a noob with a particular OS and trying to learn what was needed to do a certain function it was either assumed that is was so simple and so no samples or it was so complex there were not any samples. This was the case with me and WebOS, I needed to do a simple little file IO from a PhoneGap app, my app needed to save the canvas data to a local directory. Sounds very simple, but for someone who is learning the front end (Javascript, Css, and Html) it turned into a very real frustrating experience. My app which was original written for iOS ported over to WebOS with 1 line change, other than a plugin that I used to save the image/canvas data to the PhotoRoll it went very smoothly. Don’t get me wrong, I had a similar experience with iOS and will blog about it soon. I know that what I will write here is probable not the best way to do it, but it worked, I am always looking to learn so if you know how to do something better, please comment. I put this out here to help me as much as everyone else that is trying to figure how speak to WebOS services from a PhoneGap app that was not written in enyo.
So first I will assume that you have followed the directions from PhoneGap on how to get started with WebOS. I followed the steps and was able to get the sample app to work both in the emulator and on my touchpad (yes I scored one of the fire sale ones). From there I modified the existing sample app and this is what I will go over.
First, you will need to create a couple of directories, WebOS requires a total of 3 main folders. I kept the “framework” folder, this one holds all of the application code (www) that came with the sample, I then created a “service” folder this will hold all of the code needed for the backend or home for the node.js services and finally one called “pack”(will explain lower why I called it pack and not package) for package information that holds the information that ties the services and application code together.
In the framework folder there should be a file called appinfo.json, it is basically the configuration file for the app, not really any changes here and you can find examples all over the place . This is a sample of mine.
{
“id”: “com.phonegap.webossvctst”,
“version”: “1.0.0″,
“vendor”: “Palm”,
“type”: “web”,
“main”: “index.html”,
“title”: “PhoneGap WebOS PG test”,
“uiRevision”: 2
}
In the “index.html” file, since I knew that it worked, I commented out everything that I knew I did not need in the body, here is a copy of mine.
<html lang=”en”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>
<title>PhoneGap WebOS</title>
<script type=”text/javascript” src=”phonegap-1.0.0.js”></script>
<script type=”text/javascript”>
// create global var for sqlite database instance
// var db;
</script>
<link rel=”stylesheet” type=”text/css” href=”menu.css”>
</head>
<body>
<button onclick=”testtest();”>test just service</button>
<script>
document.addEventListener(‘deviceready’, function () {
// PhoneGap is ready, do all your stuf here
}, false);
function testtest()
{
console.log(“############ ready to to the write service”);
this.service = navigator.service.Request(‘palm://com.phonegap.webossvctst.service’,
{
method: ‘hello’, parameters: {“name”: “World” },
onSuccess: this.mySuccess.bind(this),
onFailure: this.myFailure.bind(this)
});
}
function mySuccess(thereturn)
{
console.log(“write success”);
navigator.notification.alert(‘sucess webos call=’ + thereturn.reply);
}
function myFailure(thereturn)
{
console.log(“write failure”);
navigator.notification.alert(‘fail webos call=’ + thereturn.reply);
}
</script>
</body>
</html>
The key part is in the testtest() function. You will need to use the navigator.service.Request that PhoneGap offers. you will also need to put your service id in along with the method calls and parameters that are needed. In my case you see the method called “hello” being called it has one parameter called “name” and the value I am passing is “World”. Yes I have basically incorporated the “Hello World” services example from the developer’s site that is located here into my phonegap example. It has two return callbacks one for success and one for failure.
In the Service folder there are 3 files one “sources.json” that stores all of the file configuration data for the services. One “service.json” that define all of the method calls and parameters for your service and finally in my case “HelloCommandAssistant.js” that stores all of the actual code of the service.
In the services.json file I have included the following.
{
“id”: “com.phonegap.webossvctst.service”,
“description”: “Hello World Demo Service”,
“activityTimeout” : 30,
“services”: [{
"name": "com.phonegap.webossvctst.service",
"description": "helloworld example",
"commands": [{
"name" : "hello",
"assistant" : "HelloCommandAssistant",
"public" : true
}]
}]
}
There are other post on the site that break down what every thing is, but a few notes the id needs to be unique and MUST be under the app’s domain, so if you take the app id from the appinfo.json file and add “.service” to it you are done. No in case you are wondering can I have a generic service that any other apps I might write can all use the same one, from all I found you can not.
My “sources.json” has the following lines included:
[{
"library": {
"name": "foundations",
"version" : "1.0"
}
},
{
"source": "HelloCommandAssistant.js"
}]
As you can see it identifies that my source code for the service is located in “HelloCommandAssistant.js” file, it also show that we will be using the “foundations” library that is part of the OS.
In the “HelloCommandAssistant.js” file the following lines have been included.
var HelloCommandAssistant = function() {}
HelloCommandAssistant.prototype.run = function(future) {
console.log(“***************Hello “+ this.controller.args.name);
future.result = {reply: “Hello ” + this.controller.args.name + “!”};
}
Key things to note here. You can see the “this.controller.args.name” is the parameter that was pasted in from the “testtest()” function. and that the “future.result” is the return callbacks that were defined in the services.json file and index.html file.
So at this time you have created the folder structure that is needed, you have created each of the files needed and now it is time to compile and test…
Now we need to edit the “Makefile” in the root folder of your project. Now if you want you can call each of the commands in order, me I preferred to use the makefile. My change was at the “Package:” label. I changed it to this:
package:
palm-package framework/www/ service pack
What you will notice is that I have the folder name to the “Application”, the folder name to the “service” and the folder name to the “pack” (package). Here is also the reason that I named the folder “pack” and not package. I kept getting an error “Package is up to date”, the second I renamed the folder to “pack” everything compiled and deployed with out any problems.
And that was it. when you ran the app and pushed the button it slide the notification out across the top with the message “Hello World”. It took me about an hour to make my actual service that I needed for my app. I have also included a zipped up file of the project that I talk about here.
A few notes… looking back on the whole experience, this is pretty simple, the biggest problem was me not knowing a few things, I did ask for some help on Stack Overflow and the Nitobi support site as well as the palm developer site. I did get some help, but it was still a frustrated struggle mainly due to the fact most of the answers were cryptic or too short, they did give me more paths to follow to find the answer, but if only one of them took the time to post something like above and included a example set of files the amount of hours of trial and error would have been about a quarter of what I had to spend. This frustration has been felt by others as I also saw and have to agree with their comments. I also understand if you are given everything there is nothing to learn, but that is why we have “Hello World” examples all over the place. So this is exactly why I have made this post. I am sure it can be improved on, as I learn a little bit more, I will try and keep it updated.
my next post will be on testing your app from the console, another thing that took me a little while to find from many different sources. I think these type of problems will exist more and more as we move into cross device programming…
Anyway I still love PhoneGap and recommend it all of the time. I suggest you follow a bunch of the Nitobi folks on twitter as there is a great deal of good information being past around. And if you would like to see my app, currently it is in submission to BlackBerry, WebOS and iOS, I am currently working on the Android version. It is called “iCanColor” it is written in PhoneGap, and Jquery Mobile and allows you to use your finger to paint coloring book pages as you move it, do word searches, find your way through the mazes, connect the dots, and play games like hangman and Tic-Tac-Toe.
The support page is here. Happy PhoneGapping…