Create Your First Mobile App with PhoneGap Build – Connecting to an API

by Brian Rinaldi

This is part 3 in an ongoing series. You can find part 1 here and part 2 here. The sample files are available here.

At this point, we’ve simply taken some pre-existing code and uploaded it to PhoneGap Build to create various device-specific builds for us. The application, simply responds to PhoneGap’s onDeviceReady() event and changes the image. This isn’t terribly exciting.

In this step, we’ll start the process of building a real mobile application. This application will load data containing a list of open source JavaScript applications from the GitHub API. The sample code comes from my CORS tutorial that is available here.

Loading External API Data

I chose the GitHub API specifically for this example because it supports CORS, which stands for Cross-Origin Resource Sharing. As you can read in my prior blog post, CORS is a new standard that can overcome the cross-browser restrictions that you might encounter previously when loading external data via JSON, for instance. While that restriction doesn’t apply to installed mobile apps, I chose to use it to make it easier for those readers who do not have a device ready to test on, so that they can test in the browser.

It is important to note however, that due to to browser restrictions, you must run CORS calls inside a web server not using the file:/// protocol. OSX already comes with Apache pre-installed if you choose to use that for your web server. For Windows, you can use Mongoose to turn any folder into a web server. Alternatively, you can use Node-based applications like HTTPster or node-static to create local static web servers on the fly.

Building the App

We’ll start building our application using straight HTML/JS code without any frameworks. Later on we’ll add jQuery Mobile.

Assuming you are working from the sample starter application, we’ll need to clean up the HTML a bit in index.html. Truth be told, we won’t keep much of the pre-existing code in the long run but for now, we’ll just remove everything but the scripts from inside the <body> tags. In it’s place, we will just add a <div> with the id of allrepos.

<div id="allRepos"></div>

We should also replace the viewport meta tag so that the content doesn’t show up incredibly tiny.

<meta name="viewport" content="width=device-width, initial-scale=1">

Next we are going to add the XHR request for the GitHub to the deviceready method in js/index.js. This will request the data we need from the GitHub API and return the result in a JSON format.

About the deviceready Function

PhoneGap has a number of lifecycle events that fire during the course of your app running. These include events to notify you that certain hardware buttons have been clicked or your app has moved to the background. The deviceready event is one that nearly every PhoneGap application will use as it notifies your application that PhoneGap has fully loaded.

Adding any code that needs to run when your application starts within the deviceready function will prevent errors from trying to make PhoneGap API calls before PhoneGap is loaded. It is important to note, however, that the DOM may not have loaded when deviceready is called, meaning that attempts to access or modify elements within the HTML of your page may still fail.

For a full list of PhoneGap events, see the PhoneGap documentation.

First, be sure to clear out any existing JavaScript code within the deviceready method. Next, add the following code within the deviceready function. I’ll explain what the code is doing in a moment.

var xhr = new XMLHttpRequest();
 xhr.open('GET', 'https://api.github.com/legacy/repos/search/javascript', true);
  // Response handlers.
  xhr.onload = function () {
     var repos = JSON.parse(xhr.response), i, reposHTML = "";
     for (i = 0; i < repos.repositories.length; i++) {
       reposHTML += "<p><a href='https://github.com/" + repos.repositories[i].username + "/" + repos.repositories[i].name + "'>" + repos.repositories[i].name + "</a><br>" + repos.repositories[i].description + "</p>";
     }
     document.getElementById("allRepos").innerHTML = reposHTML;
  };

  xhr.onerror = function () {
     alert('error making the request.');
  };

xhr.send();

Let’s briefly walk through what this code is doing. Once the request is loaded, we are looping through all of the results contained in the JSON response. The JSON response contains a collection of JavaScript objects that include the details about the GitHub repositories returned by our search for repositories matching the search team “javascript.” During the loop, we are assembling a string containing HTML to display the results and, when the loop is complete, we inject this HTML into the <div> we created earlier using the innerHTML property.

Feel free to customize the output if you choose. To see the data being returned, you can go to  https://api.github.com/legacy/repos/search/javascript. You can also modify the search term in the GitHub API call if you like simply by changing the URL. For example, this URL searches CSS instead of JavaScript, https://api.github.com/legacy/repos/search/css.

To test the app before uploading it to PhoneGap Build, simply load it in your browser via your localhost (see the discussion earlier about setting up a local server). Since this is not running on a device, nothing will actually appear on the screen unless we manually trigger app.deviceready() method via Chrome Dev Tools (or the developer tools of whatever browser you are using). In Chrome, you’d go to Tools > Developer Tools and select the Console tab if it isn’t already selected. You may notice an error for a missing resource of phonegap.js. This is the file that allows you to access the PhoneGap API, however, for now, don’t worry about that as this gets added when the app is run on the device and we aren’t yet using the API. Now simply type app.deviceready() into the console and you should see a result similar to the screenshot below. Keep in mind it may take a few seconds for the data to load.

step1

You may notice that in the screenshot above our console is giving us an error noting that the included script, phonegap.js, was not found. You can ignore this error for now. The phonegap.js file is automatically injected by PhoneGap Build at build time, so while testing in the browser, we can expect this error. The phonegap.js file is necessary for accessing the PhoneGap API, which we aren’t actually using just yet (but we will).

Now, before we upload this application to PhoneGap Build, let’s also modify the config.xml to have our correct information. Feel free to change the app name, author details and description as you see fit. The config.xml file allows you to specify things like your applications title, the icons that it will use on various platforms, the splash screen that will show while it is loading and many other important properties. It is also where you assign your applications unique app id and manage version numbers. In addition, you can specify a number of platform-specific options and specify which features (ex. camera, geolocation, contacts) that are required by your application.

As our sample application is purposefully simple, we won’t need to specify any platform-specific properties or enable any features, but as you build more complex applications you’ll need to understand how config.xml works. For a full reference on the config.xml go to https://build.phonegap.com/docs/config-xml. There are also tools, like Chris Griffith’s ConfiGAP, that can assist you in building your config.xml file. As noted before, with PhoneGap Build, you are not required to use config.xml but if you do certain app settings cannot be modified via the web site.

Once you are done, you can simply zip up the results and upload it to your PhoneGap Build project. Since we enabled Hydration earlier, we should be notified that a new build is available when we reopen the app on our device (note: sometimes it may be necessary to force stop the app before reopening it in order to see the update screen). Install the update and you should see the app running on your device (again, it may take a moment for the data to load, especially if it is over your mobile network).

Unfortunately, our app looks and behaves like a web page and not an app. This is an important thing to consider. Not only will your users be confused and disappointed if they download an app that doesn’t look and feel like a native app, but you’ll likely never get this accepted into the iOS App Store. In the next steps, we’ll start to make this app look like a real mobile app using jQuery Mobile and then start to add functionality to make it behave more like a native app.

However, let me just note here that it is important to consider why you are creating an app versus a web page. If you are simply packaging the functionality of your web page into an app, your customers won’t be pleased. However, if you intend to take advantage of device features that aren’t available consistently in the browser, then it may be worth building an app.

Debugging

Since PhoneGap apps are built with web technologies, much of your initial debugging can occur in the browser. Of course, you will need to test on devices and it might initially seem that debugging the app on your devices might be a complex. Thankfully, PhoneGap has an invaluable solution to that problem with its online device debugging features built with weinre. Let’s take a quick look at how it works.

As you may recall, earlier when we created our project on PhoneGap Build, we checked the “enable debugging” option. Since we have enabled debugging, you will see the debug button when viewing the project details on PhoneGap Build as in the screenshot below.

debug-button

First, open the application on your device and then click the button, which will open up debug.phonegap.com in a new tab. You should now see something similar to below, where it displays an active device connection to the app running on your test device.

debug-connection

If you’ve used some of the browser debugging tools such as Chrome Dev Tools, this interface should feel familiar. You can inspect and even modify the HTML and CSS styles as seen in the screenshot below, and as you choose selections in the HTML, you will even see those highlighted in the app running on your device.

debug-elements

You can also see anything logged to the console or use the console to enter statements and test scripts as you would in the browser console. For example, in the screenshot below I have selected the main div in our simple sample application via the console. I should note that responses can take a few seconds to return, especially when you are returning a large amount of data, so be patient.

debug-console

 

Next Step

In the next step, we’ll make our PhoneGap app look and feel more like a real mobile app using jQuery Mobile. Go to step 4.

33 Comments

  1. Anderson said:

    Hey guy very nice article! I helped me a lot! thanks
    But I have a question: When I come to this section 3, the code runs perfectly in the browser… but I have tested in 3 android devices (2.2, 2.3 4.0) and it still doesnt works. Do you know what is happening?

    • Williams Araújo said:

      Hi Anderson,

      I had the same problem, I solved setting network permissions in config.xml. After you do this, you have to reinstall application because the Hydration doesn’t make the update to the config.xml file.

      • Marco said:

        Hi Williams,
        I have the same problem, could you tell me exactly what did you change in the config.xml file?

        Thanks

  2. remotesynth said:

    Anderson, what happens? Does the app load but not the GitHub API data?

    • Anderson said:

      Yes.. on the browser it fully loads also emulating with ripple, but not on these phones I spoke. thanks!

      • remotesynth said:

        Hard to know exactly what is going on in this case. I would try the debugging built into PhoneGap Build to see if it logs any sort of errors in the console when the app is running. Let me know if that brings up anything that would add insight.

        • Anderson said:

          Thanks! Whatever… I am gratefull for you tutorial, cause I started to see ponegap with other eyes! Thank you!

        • jorge said:

          I have the same issue, in browser runs perfect but in 3 diferent devices…doesn’t work.

  3. Pallab Banerjee said:

    I am getting an application error saying :

    The connection to the server was unsuccessful. (file://data/data/com.phonegap.hello_world/hydra_app/index.html).

    I have changed few basic info in config.xml, like name description and author.

    • remotesynth said:

      Is it a consistent error? I can’t tell based on the error if that is a problem with the Hydration loading or with the app loading jQuery Mobile via the CDN. A quick Google search indicated that that can be an issue, particularly on Androind, especially if the data connection is inconsistent. Perhaps try turning Hydration off and then uninstalling/reinstalling the app? Let me know what you find out.

      • Pallab Banerjee said:

        The application error problem got solved by reverting the changes in config.xml. But at this stage, I do not see the list for the JavaScript project. The response always returns with undefined. Though this works perfectly in the browser.

        • Pallab Banerjee said:

          The issue was with the ‘response’ attribute of the XMLHttpRequest object. I could not found this attribute when I log the XMLHttpObject. But I had the response in responseText. So just used that instead.

          var responseStr = xhr.respose || xhr.responseText,
          repos = JSON.parse(responseStr),

          Remote debugging came into the rescue.

          • Jeremy Taylor said:

            I had the same issue as Pallab. Modifying the code to use xhr.responseText instead of xhr.response solved the problem.

  4. Pari said:

    Hi Ian trying to make a phonegap app , I have used the phonegap api , I am building it in eclipse, it works fine in the android virtual device , and also on the device when I connect nit to the computer via USB and deploy..but when I download the app from the phonegap build the jquery mobile is working fine but thh storage api doesn’t, work at all please help

    • remotesynth said:

      @pari – if you check the comments above, it looks like the source needs to be changed. I will hopefully be updating the project soon.

  5. Kristof VdA said:

    I’m having the same problem. With the files from step2 , everything works fine in browser & ripple emulator. But when installing on phone , only the title shows up , no actual data. Any idea how this comes / how I can debug further. Thx for fine tutorial btw.

    • remotesynth said:

      I need to update the samples. However, I think the commenter above isolated the issue which is with the xhr.response which should be changed to xhr.responseText. Let me know if this works or you are encountering a separate issue.

  6. Kristof VdA said:

    This is a separate issue. In the example “step2″ you are already using the jquery syntax within the ‘loadRepos’ function.
    ( so nothing to do with xhr.response ). And because on browser & ripple emu all works fine I’m a bit blocked on how to debug further. thx for the answer.

  7. Kristof VdA said:

    Seems it was an issue with the config.xml file. Nowadays you have to grant acces to retreive external links. ( such as the jquery framework. ) So adding the line : in the config.xml file did the trick. Maybe this could be usefull for others having the same problem. But again , thx for this fine tutorial , keep up the good work !

    • Tim said:

      I had to change my in the config.xml file stated in the build.phonegap.com/docs/config-xml docs.
      Access Element then it finally worked for me.

      ” : the access element provides your app with access to resources on other domains – in particular, it allows your app to load pages from external domains that can take over your entire webview.
      A blank access tag – – denies access to any external resources. A wildcard – – allows access to any external resource. Otherwise, you can specify allowed domains individually: “

  8. Phill [Code Clinic] said:

    Hi,
    Great tutorial and example code. I just thought it worth mentioning that to get the list of links
    you need to type the following into the Chrome Console:

    app.onDeviceReady()

    rather than:

    app.deviceready()

  9. Patrick said:

    Just to add to this, I discovered that on the iPhone the change to the “access” element in config.xml doesn’t take effect when you update the app through hydration (hydration doesn’t update the config.xml file), you have to uninstall and reinstall the app for this change to take effect and to get the tutorial working.

  10. Jose Torres said:

    Hello,
    In my case app is calling to initialize it also calls to bindEvents but never calls to onDeviceReady when I just open the index.html using Chrome. Any idea?

    • remotesynth said:

      If you are opening this within Chrome, you may have to go into the developer console and type app.deviceready() as shown in the screenshot within the article. DeviceReady is a PhoneGap event and when not running on a device, it will not occur by default.

  11. Adrian said:

    First, thanks for the tutorial =)

    I have the same problem like other people.

    When I start the application, it displays the alert message: error making the request.

    I’ve done two changes:
    1º. var responseStr = xhr.responseText;
    var repos = JSON.parse(responseStr), i, reposHTML = “”;

    2º. I add the next permissions:
    AndroidManifest.xml:

    assests/www/config.xml:

    res/xml/config.xml

    And the problem continues.

    We will solve it. Thanks.

  12. nikhil said:

    hi, thanks for this tutorial.. I am able to run it on FF and Crome but on Ripple it is not showing any result on deviceready event.
    I am not downloaded any sdk and other stuff. I am using eclipse, tomcat only.

    • nikhil said:

      Hi, it is working now after adding cordova.js.
      thanks

*

*

Top