In the part one of these series we have checked what PhoneGap mobile application framework is, downloaded its latest version and have created our initial first project for iOS smartphone platform. I have also outlined frame for example mobile app we are going to build and the set of web APIs that we will be using to make this example application somewhat useful for its users.

In this part of the tutorial we will take a closer look to PhoneGap framework structure, its main files and will write code to consume data from the web based APIs. Lets call it slightly advanced “Hello World” example which instead of printing just simple text will display 5 yummy receipts retrieved from external web service.
We will continue working on the code of the initial project created in the part one of this tutorial. You can follow the steps we took last time, they are quite simple.
As we have much more code in this part, the all source code for today’s finished tutorial is located at the bottom of the post. Feel free to download and use it for testing. Now, lets get started.

PhoneGap structure for iOS mobile project

Let’s take a look at the structure and contents of the project created by PhoneGap script. Open the project with XCode (key tool for developing iOS based mobile applications). The structure will look the same as I have pictured below, with the key files for iOS project as well as PhoneGap specific www directory and few configuration files.
For iOS apps main.m objective-c implementation file represents the main loop application is constantly running. From the contents of this file we see that AppDelegate is being referenced as a main controller. Quick view to AppDelegate.m implementation file shows us that it sets some configuration parameters for the mobile project. Cache size, window size, splash screen, default start page for view controller (project default is always index.html) and other properties. The main directory where all application files have to be placed is www and they will be served via special custom view (web view).

AppDelegate.m implementation file for newly created PhoneGap iOS project.

PhoneGap project files for iOS

At this time we don’t need to touch anything in the project setup, as we are quite happy with default settings and index.html being the start view for our mobile application. And in PhoneGap world its preferable to change settings via config.xml (it lists plugins and preferences for specific project) as opposed to tweaking objective-c implementation files.

Next we take a closer look at the source of main project file index.html as this is our start view. We see standard HTML5 markup code and the most interesting portion of the code where we are importing JavaScript files.

<script type="text/javascript" src="cordova-2.6.0.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
   app.initialize();
</script>

We need cordova version specific .js file as well as index.js. These 2 are providing all the functionality to the project. JavaScrip file with Cordova version in the name is warping up all PhoneGap framework code written in OS native language and enables JavaScript APIs for our use. index.js file is implementing these APIs. app.initialize(); for example is the call to function created in index.js:

 var app = {

    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },

    // Update DOM on a Received Event
    receivedEvent: function(id) {

        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    }
};

Above is the code from index.js and its quite self explanatory. During the initialize phase we have to bind to events and assign functions to be executed once these events fire. The full list of supported events can be found in PhoneGap documentation. At this time we only are interested in deviceready event and are going to come back to this part of code later to catch events once our mobile application will go to background state, will be retrieved from background state or will loose internet connection.

According to PhoneGap documentation deviceready event is fired once PhoneGap has fully loaded all required code, DOM and JavaScript. After this event we know that app PhoneGap JavaScript APIs are fully available to use.

Adding simple alert message

As a test lets add simple alert message to our iOS application which is displayed once application is started and PhoneGap JavaScript API are ready. For this we need to make sure that config.xml has Notification plugin enabled (by default it does) and add the following code to index.js to receivedEvent section after deviceready has fired.

// Callback function for dismissed alert
function alertDismissed() {
  // do something
}

navigator.notification.alert(
       'DOM and JavaScrip have loaded!!',  // message
       alertDismissed,                     // callback
       'YummyThings Hello World',          // title
       'I know'                            // buttonName
);

If you run your project now it will display alert once application is fully loaded and ready to function.
More about elements for notification.alert you can read in documentation section.

Webservices, Webservices

Now once we have some understanding about the key elements of PhoneGap based mobile application lets add functionality for consuming web API based data and for displaying received information.
Being able to communicate with web based servers and devices is now becoming the key requirement for any useful mobile application. In the part 1 of this tutorial we decided to use Yummly.com API’s for retrieving recipes based on the ingredients our mobile application users like.

Consuming data from 3rd party web services in most cases requires to obtain API credentials and authenticate your API calls by using them. Therefore its a common security practice for mobile app developers not to store such API credentials in the actual mobile application.

In our project we are going to do just that. In the simplified way for this tutorial (but before you go live with your project, make sure your server side code runs securely). I have created the following simple PHP script to represent your server side code.

<?php

// Get what's being sent to us

if ($_GET['q']) $question=$_GET['q'];
if ($_GET['requirePictures']) $rpictures=$_GET['requirePictures'];

////////////////////////////////
// API credentials /////////////

// TODO: please obtain API credentials form developer.yummly.com
$appid = "xxx";
$appkey = "xxx";

// Number of itens in response
$returnitems = 4; //will give us back 4+1=5 items

// Building string for GET request
$requeststr = "http://api.yummly.com/v1/api/recipes?";

$requeststr=$requeststr."_app_id=".$appid;
$requeststr=$requeststr."&_app_key=".$appkey;

$requeststr=$requeststr."&q=".$question;
if ($rpictures) $requeststr=$requeststr."&requirePictures=".$rpictures;

// Debug
//echo $requeststr

// CURL for communicating with web service

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$requeststr);
curl_setopt($ch, CURLOPT_VERBOSE, 1);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

$response = curl_exec($ch);

// We can do some heavy lifting on the server side
// and send back already prepared html from only the elements
// we need.
$response_decoded = json_decode($response, true);

$returnstring = "";

for ($i=0; $i<=$returnitems; $i++) {

  $returnstring = $returnstring."<p><img src='".
  $response_decoded['matches'][$i]['smallImageUrls']['0']."' />Recipe Name: ".
  $response_decoded['matches'][$i]['recipeName'].", it has ".count($response_decoded['matches'][$i]['ingredients'])." ingridients.</p>";
}

echo $returnstring;

?>

If you are not a PHP guru, what this code does – it accepts incoming request from mobile client (with the list of ingredients – no sensitive data being sent over the network), uses received data to make a API call to 3rd party web service, parses received JSON response and returns 5 results wrapped into HTML markup code (not bad for PHP 60 liner, huh?). Feel free to copy this code to your server, or write similar functionality in the programming language you know best. The beauty of web services is that functionality is not dependent on programming language being used.

Making HTTP call from PhoneGap application

Next is our PhoneGap mobile application code. We have to make a HTTP call to our back end server, pass the values of ingredients selected by app user and receive prepared markup with number of responses. We are going to employ one of the most popular JavaScript libraries to do this work for us. I’m talking about jQuery library which is much loved by many web developers and makes great fit for hybrid mobile applications. Download the library and add it to your project by importing in index.html

<script type="text/javascript" src="js/jquery.js"></script>

The following code is added to main index.html file

<script type="text/javascript">
  app.initialize();
</script>

<script type="text/javascript">
$( document ).ready(function() {
  $(".share").click(function (e) {
    $('.content').toggleClass('show');
    e.preventDefault();
  });
});
</script>

<script type="text/javascript" charset="utf-8">

function callWebService(){

  // We don't want API call to be made and data refreshed
  if ($('#yummy').is(':empty')){

    // Adding spinner image until we will get response
    $("#yummy").append("<img class='spinner' src='img/loadinfo.net.gif' />");

    var question = $("#question").val();

    // Log
    console.log("Questions value: " + question);

    //create request url
    var url = "http://your.test.server.url/?q=" + question + "&requirePictures=true";

    // Log
    console.log("Request string: " + url);

    // Call to web server
    $.get(url, function(data) {

    // Clear spinner
    $("#yummy").empty();

    // Add results to HTML
    $("#yummy").html(data);

    // Log received content
    console.log("Received string: " + data);

  }
 );

} // end if

}//end of method

</script>

<div id="menu">
<input id="question" type="text"></input>
<div type="button" onclick="callWebService()" id="webservice_call">Find recipes</div>
<div id="yummy"></div>
</div>

Lets split above code into parts. First I’m using app.initialize() PhoneGap function to initialize all framework JavaScript API’s (even if in this tutorial part we are not really using them). Next I have code which displays drop down menu on the click of the button with id="webservice_call" on the click. This element will not only extend drop down menu, but once clicked will execute another function callWebService(). In it I’m preparing request string to be send to our back end server (by taking input value of text element with id="question"), displaying spinning image until we receive results for our API call and populating drop down list with received values once we get them. I’m using console.log() function in many places to print variable values to the console simply for debugging purposes.

To make our test project UI look beautiful I have reused some of the styles and markup from previous tutorials here on htmlcenter. Once compiled and run this is how our PhoneGap mobile project looks now.

The resulting print screens of loading results and finished recipe list

PhoneGap loading web service data

PhoneGap finished loading web services data

We did a lot of work in this tutorial (well done! for reaching this far) and now have created PhoneGap based mobile application which can consume content from external web servers and display results within iOS view. Similar technique can be used to dynamically change larger portions of mobile application content or styles (load them remotely from your back end if there were any changes made).

Whats next

This is the end of tutorial part 2. In the next part of this tutorial we are adding even more functionality: Local storage and Native Controls. I’m looking forward for any questions, comments and feedback, you can leave them in the comments area under the post or reach out to me on Twitter.

Full source code for what we have done so far can be found and downloaded here. Have fun!

Related posts:

  1. Developing PhoneGap mobile project. Part 3
  2. Developing PhoneGap mobile project. From start to finish
  3. Developing PhoneGap mobile project. Final part