I’m really starting to enjoy the most recent JQuery Mobile release paired with PhoneGap. It really allows a developer to build a hybrid mobile application relatively quickly. I recently started a project to develop a mobile app that takes pictures and uploads them to a web server (LAMP stack).

Here is a short explanation how to get a quick app rolling.

  • Download PhoneGap (if you haven’t already)
  • Download JQuery Mobile (the ZIP file – scroll down the download page a bit)
  • Download JQuery framework
  • Download James Padolsey’s Cross Domain Ajax Plugin - jquery.xdomainajax.js
  • Unzip both files and create a new folder for your project. (mine is called “myCameraApp”)

Step 2:
  • The PhoneGap zip file contains a folder called “iOS”.
  • Open that folder and install the DMG file (PhoneGap-1.3.0.dmg)
  • After installing PhoneGap open up XCode – (Note if you don’t have a MAC you can still follow these instructions using a good text editor like Notepad++ and compile your app using PhoneGap Build.)
Follow the steps from PhoneGaps Documentation: http://phonegap.com/start#ios-x4

  • Choose a directory to store your app
  • You should see your project in Xcode 4 now.
  • Now it’s time to run your application. Click the run icon in top left corner.

  • The first time you run your application you will get an error. Don’t fret this is normal and its required to go through this stage.

  • To fix this, we need to copy the www directory into the project. Right click on the project in the left navigation window and click show in finder.

  • Finder will open to the project folder. You should see a “www” folder along with your project files.

  • Drag the “www” folder into your Xcode project and drop it on top of the “myCameraApp” heading.

  • After you do the drag operation a new dialog will appear.
  • Make sure to select “Create folder references for any added folders” and the top checkbox to copy the files into the destination group.

  • You can now expand the “www” folder in Xcode. We are ready to start putting JQuery Mobile code in.

  • Go back to the JQuery Mobile Zip file you extracted and copy the following files into your “www” folder.

  • Note: I forgot to include the JQuery Framework. You will also need to download it and copy it to the www folder.
  • Note: I also forgot to include James Padolsey’s cross-domain-ajax script. Download jquery.xdomainajax.js from his Github and copy it to your “www” folder.
  • So these are the files you should have in your “www” folder:

  • Open up Xcode and replace everything in the “index.html” with the code below.




        myCameraApp



<script charset="utf-8" type="text/javascript" src="phonegap-1.2.0.js"></script><script type="text/javascript" src="jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="jquery.mobile-1.0.min.js"></script><script type="text/javascript" src="jquery.xdomainajax.js"></script>

<script type="text/javascript">// <![CDATA[

                    $(function() {

                      $.ajaxSetup ({
                                   cache: false
                                   });

                      $.support.cors = true;

                      });

                    $(document).bind('mobileinit', function() {

                                     $.mobile.allowCrossDomainPages = true;

                                     });

                    $('#main').live('pageinit', function(event) {

                                    $('#browse_photo').click(function() {

                                                             navigator.camera.getPicture(uploadPhoto, function(message) {
                                                                                         alert('get picture failed');
                                                                                         },{ quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY });

                                                             });

                                    $('#take_photo').click(function() {

                                                           navigator.device.capture.captureImage(captureSuccess, captureError, {limit: 1});

                                                           });

                                    });

                    $('#view').live('pageinit', function(event) {

                                    $.get('http://www.domain.com/view.php', function (data) {

                                          $('#photos').html(data.responseText);

                                          });

                                    });

                    function captureError(error) {

                        $('#loading').hide();

                        var msg = 'An error occurred during capture: ' + error.code;
                        navigator.notification.alert(msg, null, 'Uh oh!');
                    }

                    function captureSuccess(mediaFiles) {

                        var i, len;
                        for (i = 0, len = mediaFiles.length; i < len; i += 1) {
                            uploadFile(mediaFiles[i]);
                        }

                        $('#loading').show();

                    }

                    function uploadFile(mediaFile) {
                        var ft = new FileTransfer(),
                        path = mediaFile.fullPath,
                        name = mediaFile.name;

                        ft.upload(path, "http://www.domain.com/upload.php", function(result) {

                                  //var msg = result.bytesSent + ' bytes sent';
                                  //navigator.notification.alert(msg, null, 'Upload success');

                                  sessionStorage.setItem('filename', result.response);
                                  findLocation();

                                  $('#loading').hide();

                                  }, function(error) {

                                  $('#loading').hide();

                                  var msg = 'Error uploading file ' + path + ': ' + error.code;
                                  navigator.notification.alert(msg, null, 'Error');

                                  },{ fileName: name, fileKey: 'file' });   
                    }

                    function uploadPhoto(imageURI) {

                        $('#loading').show();

                        var options = new FileUploadOptions();
                        options.fileKey="file";
                        options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
                        options.mimeType="image/jpeg";

                        var params = new Object();
                        params.value1 = "test";
                        params.value2 = "param";

                        options.params = params;

                        var ft = new FileTransfer();
                        ft.upload(imageURI, "http://www.domain.com/upload.php", win, fail, options);

                    }

                    function win(result) {

                        $('#loading').hide();

                        //var msg = result.bytesSent + ' bytes sent';
                        //navigator.notification.alert(msg, null, 'Upload success');

                        sessionStorage.setItem('filename', result.response);

                        findLocation();

                    }

                    function fail(error) {

                        $('#loading').hide();

                        var msg = 'An error has occurred: Code = ' + error.code;
                        navigator.notification.alert(msg, null, 'Error');

                    }

// ]]></script>

</pre>
<div id="main" data-role="page">
<div data-role="content">
Choose an option below</div>
<div data-role="footer" data-position="fixed" data-theme="e">
<div data-role="navbar" data-iconpos="bottom">
<ul>
	<li><a id="take_photo" href="#" data-icon="grid">Take Photo</a></li>
	<li><a id="browse_photo" href="#" data-icon="star">Browse Photo</a></li>
	<li><a href="view.html" data-icon="gear">View</a></li>
</ul>
</div>
</div>
</div>
<pre>


  • Now run your app in the simulator.

  • Now you app really doesn’t do anything yet because we haven’t created the PHP script necessary to upload the files.
  • Here is the “upload.php” file.

<?php	
if (isset($_FILES['file'])) {

	$filename = md5(date('Y-m-d H:i:s:u')) . $_FILES["file"]["name"];
	move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/" . $filename);
	echo $filename;

}
?>
  • Upload the the PHP file to your web server and create a “uploads” directory. Make sure to CHMOD it 777 or 755.

  • You can run your application now. You will not be able to access the camera from the iPhone simulator. You will need to have a provision profile installed on your iPhone. If you don’t already have an Apple developer account fork over the $100 bucks and grab one.
  • Bonus: If you want to allow people to view photos from your app, create a view.php file and read the contents of a directory.

This is a very primitive example. Using the knowledge I’ve gained from working with PhoneGap and JQuery Mobile I was able to build a full featured, database driven, camera/video/audio recording mobile app that tags media using geolocation features and organizes the media into content groups. Each content group has an owner. When new content is submitted to that group the owner receives an email notification. Make sure to check out the PhoneGap documentation.

  • renato0408

    Nice post. But i cant reproduce it. Where is the #loading div and #photos div?