PhoneGap Sample - Diary (Database and Camera support)
Last week a reader wrote in with an interesting problem. They had a simple application that made use of PhoneGap's database support. They wanted to add camera support as well. Their idea was that a picture could be associated with their content. But then they ran into this issue:
iOS Quirks:
When destinationType.FILE_URI is used, photos are saved in the application's temporary directory. Developers may delete the contents of this directory using the navigator.fileMgr APIs if storage space is a concern.
So, right away, this brings up a useful reminder. Most things you do with PhoneGap will work cross platform, but it is crucial that you pay attention to the individual quirks for each platform. In this case, something that works fine in Android will cause problems in iOS. Even worse, because the images aren't removed immediately, you may think there isn't a problem at all. (As a side note, navigator.fileMgr is old code that has not been removed from the docs yet. I've filed a bug report to get this updated.)
I thought I'd help out the reader by building a simple application that made use of both technologies and then work out how I'd handle the iOS issue. I started off by building a simple Diary application. The Diary would allow you to write basic content entries, each with a title, body, and a creation date. I built a very simple "Single Page Architecture" framework to handle my application views and routing. I won't even call it a framework. Really it is just one simple JavaScript function that lets me load a page into the DOM.
Here's the home page - a simple list of entries with the ability to view an entry and add a new entry.

And the amazingly well-designed entry page:

Finally, the form to write entries:

I also built a wrapper for my Diary class that would abstract out the persistence for me. Here is that wrapper. Please don't laugh at my pitiful object-oriented-ish JavaScript code.
This wrapper class is used by index.js, which handles my views, adding and requesting data, etc. Basically, index.js acts like a controller in your typical MVC setup. I'm not going to share all of that file (to be clear, everything is shared via a Download link below), but here is an example.
So - nothing too terribly complex. I took this as a starting point (in the zip you can download, this may be found in www1) and then began to integrate camera functionality. I started by adding a new button to my entry field. This button, "Add Picture", would request the device camera and store the resulting image in a hidden form field. I began by using FILE_URIs even though I knew it would be an issue with iOS. In almost everything I do I start slowly, take baby steps, and try to build one thing at a time. So with that in mind, I went ahead and just built it in.
Here is that code:
Note that I've updated my form to include a preview and the entry detail view (not shown here) has been updated to display it.

Ok, so at this point, the core functionality is done. (You can find this version in the www2 folder.) I can add and view content (I didn't bother with edit/delete, but that would be trivial) and I can use the device camera to assign a picture to a diary entry. Now to look into the bug.
My initial thought was to make use of the File API to copy the image to a nice location. Even though Android didn't really need this feature, I thought I'd keep things simple and just use the same logic for all. (To be fair, when I say "all", I really was just testing Android and iOS.)
However, I ran into an interesting issue. When requesting the persistent file system, iOS gave me a directory that was customized for my application:
/var/mobile/Applications/362CC22A-BA60-4D81-876C-21072A06CE16/Documents
Unfortunately, the Android version of the exact same code returned a more generic folder. I could then make a folder for my Android app that was specific to the application itself, but that seemed to be a bit too much work. (Really, it wasn't, I was being lazy.)
I rang up Simon MacDonald, my goto guy for PhoneGap questions (or at least until I annoy him ;) and in discussions with him, I discovered that right now there isn't a simple way, cross platform, to ask the file system for "a safe application-specific place to store my crap." (My words, not his.)
I made a decision at this point. Even though it felt a bit wrong, I decided I'd write code just for iOS. I figured the 'forked' code would be pretty small and therefore it wouldn't "pollute" my code too much. This smells like one of those decisions I may regret later, but for now, it is what I'm going with.
I began by sniffing the device using PhoneGap's Device API.
Nothing too complex here. If I detect iOS, I request the persistent file system and remember the root directory it gives me.
Next - before I store the Diary entry, if I am on iOS, I simply copy the image over.
Overall, not as messy as I thought. You can find the complete source code attached below. Enjoy.

Thanks for sharing this!!
Uncaught Error: NOT_SUPPORTED_ERR: DOM Exception 9 at file:/
//android_asset/www/js/index.js:52
Any thoughts? Thanks in advance.
if(u.indexOf("?") >= 0) {
Is that what you see?
The line 52 to me is:
var evt = document.createEvent('CustomEvent');
inside:
$.get(u,function(res,code) {
mainView.html(res);
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent("pageload",true,true,data);
var page = $("div", mainView);
page[0].dispatchEvent(evt);
});
}
But overall this is one of my favorite phonegap tutorial that I have seen. Simple and yet practical.
@hellogap: You would use Ajax to speak to a server proxy for MySQL. Something like ColdFusion or PHP on the server could listen for, and respond, to your Ajax requests. I've done some examples of this here - just search my blog for phonegap.
- use command-line to create a new project using PG 2.5
- overwrite www folder with the one from the archive zip
- double-click on .xcodeproj and chose iPhone 6.1 simulator
I only got a pop-up with 'NetworkStatus125..."] and in xcode I notice a warning for "self.viewController.useSplashScreen = YES;" saying useSplashScreen is deprecated.
Can you pls let me know if that is the right way to build the app?
That being said, what you did was partially right. When you copy the files, be sure to then do a build (cordova build). That copies over the www files into the projects.
@buntu: It sounds like you may not know how PG works. I'd recommend the Getting Started guide: http://docs.phonegap.com/en/2.5.0/guide_getting-st...
is it possible to connect this phonegap app to parse.com, ?
Finally I found the reason why it didn't work. When using Eclipse, it doesn't work on Android 2.x version. I ran it on my galaxy tab with Android 4.0 something and it works beautifully. Not sure if this is true without Eclipse though. Is it?
I can't find a way to connect this phonegap app to parse.com, do you know how to upload an image with associated parse objects from a phonegap app ?
Best I can say it is on my list.
in android, this code work..????
--->>> entry.html?id="+id
cause in my app i use similar method, and error..
a network occured error..
*thanks Mr Camden.. i will try this.. :D
--->>> entry.html?id="+id
i think its different with my app.. :D
is this code for passing parameter in entry.html?id="+id ??
if(u.indexOf("?") >= 0) {
var qs = u.split("?")[1];
var parts = qs.split("&");
for(var i=0, len=parts.length; i<len; i++) {
var bits = parts[i].split("=");
data[bits[0]] = bits[1];
};
}
my problem same as http://community.phonegap.com/nitobi/topics/a_netw...
--> i try in 2.5.0 and its work..
--> thanks.. :D
but i found another error
--> the connection to the server was unsuccessful. (javascript: try{cordova.require(cordova/chanel).onDestroy.fire();}catch(e){console.log(exeption firing destroy event from native);};)
No worries about answering these if you're busy, I'm sure I'll struggle through figuring them out eventually... :)
Thanks again for this tutorial, saves me A LOT of time!
<input type="hidden" id="entryAudio">
<img id="imgPreview" class="audioPlay">
<button id="recordAudio">Record Audio</button>
it goes to the main.html I'm not sure what am missing anyone has an idea how to modify this to record, save and replay sound
@Hans: I'd have to see your code. To me, it sounds like you don't have a good handler for your recordAudio button. Make sure you preventDefault on the event object.
function onCaptureSuccess(audiofile) {
//var i, path, len;
//for (i = 0, len = audiofile.length; i < len; i += 1) {
//path = audiofile[i].fullPath;
// }
console.log(audiofile);
$("#entryAudio").val(audiofile);
console.log('set the file');
$('#audioPreview').attr("src", audiofile);
console.log('set the attr');
}
function onCaptureError(e) {
navigator.notification.alert(msg, null, 'Uh oh!');
}
$("#recordAudio").on("touchstart", function(e){
e.preventDefault();
e.stopPropagation();
navigator.device.capture.captureAudio(onCaptureSuccess, onCaptureError, options);
});
$("#addEntrySubmit").on("touchstart", function(e) {
e.preventDefault();
//grab the values
var title = $("#entryTitle").val();
var body = $("#entryBody").val();
var img = $("#entryPicture").val();
var sound = $("#entryAudio").val();
and the other thing is how do I show and replay this file the same way you show and display the image
am beginner for phone gap.am having doubt on
how to use sqlite in phone gap?
am having confusion ..pls help me
http://docs.phonegap.com/en/2.7.0/cordova_storage_...