Wednesday 10 July 2013

Phone Gap Tutorial: A Cross-Platform Zombie App





Learn how to create a to-do app to survive the zombie apocalypse in this PhoneGap tutorial!
Learn how to create a to-do app to survive the zombie apocalypse in this PhoneGap tutorial!
PhoneGap is a mobile development framework that allows developers to build applications for a variety of mobile platforms, using familiar web technologies such as HTML, CSS, and JavaScript.
The concept is that you can develop one application using the PhoneGap architecture, and then deploy to multiple mobile platforms — without the need to re-write any code!
In this tutorial, you’ll learn the basics of using PhoneGap to make a simple to-do app, with a twist – it’s an app to help you survive the Zombie Apocalypse!
In the process, you’ll learn a ton about PhoneGap – such as installing PhoneGap, writing Javascript code, using local storage, and much more.
This tutorial assumes you have some basic familiarity with HTML, CSS, and Javascript. If you are new to these technologies you can still follow along with the tutorial, but you’ll be missing some background knowledge, so I recommend you read a book on those when you get a chance.
So if you think you have the brains, keep reading to get started – the zombies are waiting!

Getting Started

As with any new project, it’s always a good idea to plan ahead for what you’ll be building.
Here’s a sketch of what the app you’re developing will look like:
Basically this is an app to help you keep track of all the things you need to do in order to survive the Zombie Apocalypse.
The app’s logo sits at the top of the screen. Two buttons sit below the logo; one for adding a new task, and another for removing completed ones. When the user adds an item to their to-do list, a new table row will appear with four individual elements.
First, you have a checkbox which indicates a task’s status. Next is the content of the to-do item. Then, finally, there are two more buttons: one that will displays the text of the to-do item in a popup dialog, and another that will delete the to-do item.
The app will store the to-do list using the Local Storage API.
And, thanks to the graphic design talents of Vicki Wenderlich, this is how the final app will look:
Aww yeah. You’d never forget your zombie repellent spray if you had an app like that! :]
That’s it for the look and feel — time to take a look at how the app should behave.
  • Adding a task: When tapping the Add To-Do button, the user will be prompted to enter some text for their to-do list item.
  • Marking tasks as completed: The user will be able to mark tasks as completed by tapping the check box to the left of the task.
  • Removing completed tasks: Tapping the Remove Completed Tasks button will remove all completed tasks.
  • Viewing a task: When tapping the View button, the full text of the task will be displayed.
  • Deleting a task Tapping the Delete button will remove the corresponding task.
Altogether, it’s a relatively simple app. The purpose behind this PhoneGap tutorial is to demonstrate the development of a fully functional app without using any native code, and make it available on a variety of mobile platforms with nothing more than a single click!
Sound good? All right — time to get PhoneGap installed!

Installing PhoneGap

Note: If you already have PhoneGap and want to get started immediately, skip this section and download the starter project. If you choose to skip ahead, I encourage you to have a read through the official PhoneGap getting started guide and command line usage documentation, once you’ve completed the PhoneGap tutorial.
Head over to the PhoneGap website, and choose Download PhoneGap from the home page.
Click the big blue Download button on the next page to initiate the download, as shown in the screenshot below:
Unarchive the folder, and you might want to save it somewhere safe on your hard drive. And that’s all there is to installing PhoneGap!
It’s now time to create your project. Open up the Terminal app. It’s usually found in the Applications folder, within the Utilities folder. You’ll be presented with the Terminal interface, as below:
Type the following command in Terminal and hit enter (but replace the path with wherever your copy of PhoneGap is):
cd ~/Downloads/phoneGap-2.3.0/lib/ios/bin
Note: At the time of this writing, the most recent version of PhoneGap was 2.3.0. If the version you’ve downloaded is newer, then please replace the version number in the command above with the version you have.
To generate a new project, you need to use the command line script create, and pass in the project location, the bundle identifier and finally the project name as arguments to the call.
Type the following command into Terminal and hit Return to generate the project:
./create ~/Desktop/Zombie com.raywenderlich.zombie ZombieApocalypseToDoList
You’ll now find a Zombie folder on your desktop. Open it up, dive into the www folder and take a look at the files inside, as shown below:
The three key files and folders here are index.html, which is where you’ll be writing the app’s code;index.css, found in the css folder, which is used to style the look and feel of the app; and finally the imgfolder, which is where all the images for the app will be stored.
Go back to the top level folder and open up the ZombieApocalypseToDoList.xcodeproj file in Xcode.
In Xcode’s project navigator, open index.html. Then build and run your app. “Already?” you ask. Yes! Already! :]
You should see the following:
If your display matches the screenshot above, then everything is set up properly for your PhoneGap development environment.
Installation was a breeze – even the undead could have handled that one! :]
You’ll find that the coding of your PhoneGap app in the next section is almost as easy!

Structuring Your App

When your app first launches it displays index.html, so in this section you’ll edit that to give your app some bones to build upon.
Replace all of the existing template code in index.html with the following:
<!DOCTYPE html>
<html>
    <head>
        <title>Zombie Apocalypse To-Do List</title>
        <link rel="stylesheet" type="text/css" href="css/index.css"/>
        <script type="text/javascript" language="JavaScript">
 
        </script>
    </head>
    <body>
 
    </body>
</html>
What you see above is the main structure of any HTML code that leverages JavaScript; it contains html,headbody, and script tags. On a standard web page, JavaScript is usually found between the head tags, while the HTML lives between the body tags.
Now you’ll need to structure the app as designed in the mockup above. Recall that there were two main buttons at the top, followed by a table.
Add the following code to index.html between the body tags:
<input type="button" value="Add To-Do"/>
<input type="button" value="Remove Completed Tasks"/>
<br/><br/>
<table id="dataTable" width="100%" border="1">
 
</table>
Build and run your app! If all goes according to plan, it should look like this:
With a few simple lines of code, you now have some functional buttons displaying on the screen.
Now you need to add some logic behind the buttons to really bring your app to life!

Bring on the Javscript: An Overview

In order to support your app’s functionality, you’ll need to implement a number of JavaScript functions.
Before you start implementing them, let’s start with an overview of the functions you’ll need to create for this app.
createNewToDo()
Prompts the user to enter a new to-do item. Once the user presses the OK button on the resulting dialog, a new row is added to the table.
addTableRow(todoDictionary, appIsLoading)
Adds a row to the to-do list table. It accepts several arguments: a dictionary containing both the text of the to-do along with the checkbox state, as well as with a boolean value which indicates if the app is loading or not. This will be explained a little later.
checkBoxClicked()
Called whenever the state of a checkbox is changed. It loops through all checkboxes and either applies or removes a strike-through style to the text of the corresponding to-do.
viewSelectedRow(todoTextField)
Displays the value of the passed-in text field in a popup dialog.
deleteSelectedRow(deleteButton)
Deletes the row that corresponds to the row of the button that was passed into the function.
removeCompletedTasks()
Loops through all the table rows and removes the rows where the to-do item is marked as complete.
saveToDoList()
Saves the to-do list using the Local Storage API.
loadToDoList()
Loads the to-do list when the app is first launched using the Local Storage API.
deleteAllRows()
Removes all rows from the table.
And that’s it. You can refer back to this section if you have any questions about how each part fits in as you continue working through this PhoneGap tutorial.

Bring on the Javascript: Implementation

Now that the basic structure of the functions has been covered, it’s time to implement them in your app.
Note: Each code block that you encounter below, unless indicated, should be placed between thescript tags in index.html.
Add the code below:
// create a new to-do
function createNewToDo()
{
    var todoDictionary = {};
 
    // prompt the user to enter to-do
    var todo = prompt("To-Do","");
    if (todo != null)
    {
        if (todo == "")
        {
            alert("To-Do can't be empty!");
        }
        else
        {
            // append the new to-do with the table
            todoDictionary = { check : 0 , text : todo};
            addTableRow(todoDictionary, false);
        }
    }
 
}
createNewToDo() is relatively straightforward; it simply prompts the user to enter a new to-do item.
If the text of the to-do is empty, this function alerts the user, otherwise it calls addTableRow(), passing a dictionary containing the text of the to-do along with the initial checkbox state. In the case of a new to-do item, the checkbox state will be set as false.
Add the following code:
// add a row to the table
var rowID = 0;
function addTableRow(todoDictionary, appIsLoading)
{
    rowID +=1;
    var table = document.getElementById("dataTable");
    var rowCount = table.rows.length;
    var row = table.insertRow(rowCount);
 
    // create the checkbox
    var cell1 = row.insertCell(0);
    var element1 = document.createElement("input");
    element1.type = "checkbox";
    element1.name = "chkbox[]";
    element1.checked = todoDictionary["check"];
    element1.setAttribute("onclick", "checkboxClicked()");
    cell1.appendChild(element1);
 
    // create the textbox
    var cell2 = row.insertCell(1);
    var element2 = document.createElement("input");
    element2.type = "text";
    element2.name = "txtbox[]";
    element2.size = 16;
    element2.id = "text" + rowID;
    element2.value = todoDictionary["text"];
    element2.setAttribute("onchange", "saveToDoList()");
    cell2.appendChild(element2);
 
    // create the view button
    var cell3 = row.insertCell(2);
    var element3 = document.createElement("input");
    element3.type = "button";
    element3.id = rowID;
    element3.value = "View";
    element3.setAttribute("onclick", "viewSelectedRow(document.getElementById('text' + this.id))");
    cell3.appendChild(element3);
 
    // create the delete button
    var cell4 = row.insertCell(3);
    var element4 = document.createElement("input");
    element4.type = "button";
    element4.value = "Delete";
    element4.setAttribute("onclick", "deleteSelectedRow(this)");
    cell4.appendChild(element4);
 
    // update the UI and save the to-do list
    checkboxClicked();
    saveToDoList();
 
    if (!appIsLoading) alert("Task Added Successfully.");
}
When addTableRow() is called it adds a new row to the table with four separate cells. Then it adds an HTML element to each cell, namely a checkbox, a text box, a View button, and a Delete button. This also sets the necessary attributes on these four elements.
Finally, it calls checkboxClicked() and saveToDoList(), which update the UI and save the to-do list respectively.
addTableRow() is called not only when the user adds a new to-do item, but it’s also called when the app is first launched and the to-do list is being loaded. Hence, that’s why you pass the appIsLoading boolean value to this function.
If you didn’t check this condition, then the user would be alerted for every to-do that’s loaded on startup — which would get annoying REALLY fast! :]
Add the following code:
// add the strike-through styling to completed tasks
function checkboxClicked()
{
    var table = document.getElementById("dataTable");
    var rowCount = table.rows.length;
 
    // loop through all rows of the table
    for(var i = 0; i < rowCount; i++)
    {
        var row = table.rows[i];
        var chkbox = row.cells[0].childNodes[0];
        var textbox = row.cells[1].childNodes[0];
 
        // if the checkbox is checked, add the strike-through styling
        if(null != chkbox && true == chkbox.checked)
        {
            if(null != textbox)
            {  
                textbox.style.setProperty("text-decoration", "line-through");
            }
        }
 
        // if the checkbox isn't checked, remove the strike-through styling
        else
        {
            textbox.style.setProperty("text-decoration", "none");
        }
 
    }
 
    // save the to-do list
    saveToDoList();
}
checkboxClicked() performs only a single task. It loops through the all the rows of the table, determines the state of each checkbox, and applies the strike-through styling to the to-do text if the checkbox is set. Once complete, checkboxClicked() then calls saveToDoList().
Add the following code:
// view the content of the selected row
function viewSelectedRow(todoTextField)
{
    alert(todoTextField.value);
}
There’s not much to viewSelectedRow(); it’s just a simple function that displays an alert containing the full text of the to-do item.
Add the following code:
// delete the selected row
function deleteSelectedRow(deleteButton)
{
    var p = deleteButton.parentNode.parentNode;
    p.parentNode.removeChild(p);
    saveToDoList();
}
deleteSelectedRow() is another relatively simple function. It takes the button reference that was passed in and deletes the corresponding to-do item from the list.
Add the following code:
// remove completed tasks
function removeCompletedTasks()
{
    var table = document.getElementById("dataTable");
    var rowCount = table.rows.length;
 
    // loop through all rows of the table
    for(var i = 0; i < rowCount; i++)
    {
        // if the checkbox is checked, delete the row
        var row = table.rows[i];
        var chkbox = row.cells[0].childNodes[0];
        if(null != chkbox && true == chkbox.checked)
        {
            table.deleteRow(i);
            rowCount--;
            i--;
        }
    }
 
    // save the to-do list
    saveToDoList();
 
    alert("Completed Tasks Were Removed Successfully.");
}
removeCompletedTasks() loops through all table rows and determines the state of each row’s checkbox. If the checkbox is checked, then the table row is removed. Then the updated to-do list is saved and the user is alerted that the action is complete.
Add the following code:
// save the to-do list
function saveToDoList()
{
    var todoArray = {};
    var checkBoxState = 0;
    var textValue = "";
 
    var table = document.getElementById("dataTable");
    var rowCount = table.rows.length;
 
    if (rowCount != 0)
    {
        // loop through all rows of the table
        for(var i=0; i<rowCount; i++)
        {
            var row = table.rows[i];
 
            // determine the state of the checkbox
            var chkbox = row.cells[0].childNodes[0];
            if(null != chkbox && true == chkbox.checked)
            {
                checkBoxState = 1;
            }
            else
            {
                checkBoxState= 0;
            }
 
            // retrieve the content of the to-do
            var textbox = row.cells[1].childNodes[0];
            textValue = textbox.value;
 
            // populate the array
            todoArray["row" + i] =
            {
                check : checkBoxState,
                text : textValue
            };
        }
    }
    else
    {
        todoArray = null;
    }
 
    // use the local storage API to persist the data as JSON
    window.localStorage.setItem("todoList", JSON.stringify(todoArray));
}
saveToDoList() does what it says on the tin. It loops through all table rows and populates a dictionary for each row with the checkbox state and to-do text. This collection of dictionaries are then added to an array, which is then saved using the local storage API.
Now that you have your to-do list saved, you’ll need a way to load it back up, won’t you?
Add the following code:
// load the to-do list
function loadToDoList()
{
    // use the local storage API load the JSON formatted to-do list, and decode it
    var theList = JSON.parse(window.localStorage.getItem("todoList"));
 
    if (null == theList || theList == "null")
    {
        deleteAllRows();
    }
    else
    {
        var count = 0;
        for (var obj in theList)
        {
            count++;
        }
 
        // remove any existing rows from the table
        deleteAllRows();
 
        // loop through the to-dos
        for(var i = 0; i < count; i++)
        {
            // adding a row to the table for each one
            addTableRow(theList["row" + i], true);
        }
    }
}
loadToDoList() provides a mechanism to load up the to-do list that you’ve persisted with saveToDoList().
The Local Storage API is leveraged to the load the JSON formatted to-do list and then decode it. Any existing rows are removed from the current table, then a new row is added for each to-do item. As before, you pass true to addTableRow() to prevent the user from being alerted as each row is loaded at startup.
Add the following code:
// delete all the rows
function deleteAllRows()
{
    var table = document.getElementById("dataTable");
    var rowCount = table.rows.length;
 
    // loop through all rows of the table
    for(var i = 0; i < rowCount; i++)
    {
        // delete the row
        table.deleteRow(i);
        rowCount--;
        i--;
    }
 
    // save the to-do list
    saveToDoList();
}
deleteAllRows() simply removes all rows from the table; it’s used to clean up the UI in an efficent fashion.
Okay, that’s it for the JavaScript functions! Now you need to update the HTML in your app to make use of these functions.

Bringing it All Together

Phew – finally done – just one final bit left to see this working!
Calling the functions you created above is quite simple. You’re just adding the relevant function call to theonClick property of the UI controls.
Add the following code between the body tags of index.html:
<body onload="loadToDoList()">
    <input type="button" value="Add To-Do" onclick="createNewToDo()"/>
    <input type="button" value="Remove Completed Tasks()" onclick="removeCompletedTasks()"/>
    <br/><br/>
    <table id="dataTable" width="100%" border="1">
 
    </table>
</body>
In the code above, loadToDoList() is called when the page is first loaded. As well, createNewToDo() andremoveCompletedTasks() are called when their respective buttons are tapped.
Build and run your app! It should look similar to the screenshot below:
One of the disadvantages of JavaScript is that it’s an interpreted language. Unlike a compiled language such as Objective-C, JavaScript will execute the code line by line until an error occurs. If an error does occur and it’s not handled properly, the app will likely crash.
Feel free to play around with the app; add some tasks and then delete them.
Well, the app seems to work okay – but it’s pretty bland! You can’t save the world with a corporate-looking app like that!
Don’t worry — the next part of this PhoneGap tutorial will walk you through polishing the app to a standard that any zombie warrior would be proud of! :]

Oppa Zombie Style – Reworking Your App’s Graphics

Now that the app fully functional, it’s time to make it look great.
Download the necessary images here, and copy them to the img folder of the project.
Blood? Boards? Nails? Yup, sounds like an awesome header image for your app! :]
Add the following line to index.html, just below the opening body tag:
<img src="img/header.png" width="100%" />
This inserts the header image into your app via the HTML img tag.
Since you’re using web technologies at the heart of your application, you’ll be using CSS to influence how the rest of your app looks. Buttons, backgrounds, and other elements in your app can all be controlled by the definitions in your CSS files.
Each UI element that you want to style requires a class element — this indicates which style(s) in your CSS should apply to the element in question.
You’ll begin your foray into CSS by styling the buttons in your app.
Update the existing button related code in index.html as in the code block below:
<button type="button" class="addToDo" onclick="createNewToDo()"><img src="img/button_addtodo.png" /></button>
<button type="button" class="removeTasks" onclick="removeCompletedTasks()"><img src="img/button_removetasks.png" /></button>
Notice that you added a class attribute to each button; this will allow you add a CSS style to it later. As well, each button now contains a reference to an image file that will be displayed, instead of the default buttons of the host UI.
You now need to add class attributes to the checkboxes, the textboxes, as well as the other buttons in your app so that they can also be styled using CSS.
Update the JavaScript section of index.html, adding the lines below:
...
element1.setAttribute("onclick","checkboxClicked()");
element1.className = "checkbox"; // ADD ME - Add the class name 'checkbox' to element1
cell1.appendChild(element1);
...
element2.setAttribute("onchange", "saveToDoList()");
element2.className = "textbox"; // ADD ME - Add the class name 'textbox' to element2
cell2.appendChild(element2);
...
element3.setAttribute("onclick", "viewSelectedRow(document.getElementById('text' + this.id))");
element3.className = "viewButton"; // ADD ME - Add the class name 'viewButton' to element3
cell3.appendChild(element3);
...
element4.setAttribute("onclick", "deleteSelectedRow(this)");
element4.className = "deleteButton"; // ADD ME - Add the class name 'deleteButton' to element4
cell4.appendChild(element4);
...
Now it’s time to define all of the styles you’ve been referencing in your HTML above.
Open index.css (found in the css folder of your project), and find the following lines at the top:
background-color:#E4E4E4;
background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
background-image:-webkit-gradient(
    linear,
    left top,
    left bottom,
    color-stop(0, #A7A7A7),
    color-stop(0.51, #E4E4E4)
);
background-attachment:fixed;
Those lines were providing the background gradient effect, which you won’t need in your app. You’ll be replacing it with something more fitting to your post-apocalyptic masterpiece!
Replace all of those lines with the following one line of code:
background-image: url('../img/bg_pattern.png');
That indicates that the background of the app is now just represented by a single image resource.
Scroll to the very end of index.css and add the following code:
.addToDo {
background-color: Transparent;
border-color: Transparent;
float: left;
margin-left: 0;
position: absolute;
left: 0px
}
 
.removeTasks {
background-color: Transparent;
border-color: Transparent;
float: right;
margin-right: 0;
position: absolute;
right: 0px;
}
 
.checkbox {
background-color: Transparent;
background-image: url('../img/check_box.png');
width: 34px;
height: 32px;
}
 
.textbox {
background-color: grey;
}
 
.viewButton { 
background-color: Transparent;
background-image: url('../img/button_view.png');
width: 64px;
height: 32px;
}
 
.deleteButton { 
background-color: Transparent;
background-image: url('../img/button_delete.png');
width: 64px;
height: 32px;
}
Each style class above — .deleteButton.viewButton, and so on — defines the appearance of each UI element by way of setting such properties as width, height, background color, and positioning, among other things.
For example, every checkbox in your app does not need to be individually styled when it’s defined; it just needs to reference the .checkbox class and it will take on the characteristics defined in the CSS.
Ready to see how it all works together?
Build and run your app! It should look like the image below:
Wow! Quite a difference, isn’t it?
The changes that you can effect with simple CSS are quite stunning. Just by adjusting the dimensions of the buttons and adding some graphical elements to your app, you’ve really made your app “pop”.
Okay, so your app is complete! But you need to get it out to all the other zombie hunters in the world – and you can bet that they own a mix of mobile devices. What to do?
One of PhoneGap’s great features is that you can publish your application to various platforms without changing a bit of code. There’s a few steps that you need to follow in order to get your app published — but it sure beats rewriting code! :]

Putting the “Gory” in App Store Category – Publishing Your App

First of all, you need to compress your project prior uploading it to Adobe Build.
Head to your desktop, right click on your Zombie folder and choose Compress “Zombie”.
Launch the browser of your choice and head on over to http://build.phonegap.com to get started. Just click the big blue Get started! button to initiate the publishing process, as such:
You can investigate the paid plan when you have a need for more private apps, but for the purposes of this PhoneGap tutorial, choose the free package, as below:
If you have an existing Adobe ID (or wish to create a new Adobe ID), you can use that option to login. If you don’t have or want an Adobe ID, you can also use your GitHub account to log in, as seen below:
If you choose the GitHub option, you’ll need to authorize the login attempt.
Once you’ve authorized your GitHub account login, or chosen to use an Adobe ID, simply choose your country, agree to the Terms of Use and click Complete my registration.
Now you’re ready to upload the compressed archive you created earlier.
Click Upload a .zip file and choose the Zombie.zip archive located on your desktop. Once the archive has finished uploading, click the Ready to build button, like so:
Once the build is done, you’ll see a screen showing the compile state of the multiple mobile OS that PhoneGap supports. Notice that both the iOS and Blackberry indicators are red, while the others are blue, as shown in the screenshot below:
This indicates that there were issues when building the application for that particular platform.
In order to build your app for iOS, there are a few more things that you need to take care of.
Click the iOS button. You’ll end up at the screen below:
Aha! It turns out you need to provide two more pieces of information to compile your app under iOS: your developer certificate and a provisioning profile.
If you’ve been doing iOS development in the past, you already have a certificate, so let’s export it. If you don’t already have a certificate, check out Apple’s App Store Submission Tutorial.
Using Spotlight, search for KeyChain Access. If you previously installed your developer certificate issued by Apple via the provisioning portal, this is where you’ll find it.
You now need to export the certificate.
Choose the My Certificates category, right-click the iPhone Distribution… certificate and choose Export “iPhone Distribution…” from the popup menu, like so:
Save the exported certificate to your desktop, making sure it’s in the Personal Information Export (.p12)format. Choose a password for this certificate and enter it. You’ll need this password along with your certificate later, so choose something that’s easy for you to remember (but hard for the zombies to guess!).
Finally, click OK, and your desktop will now contain your exported certificate.
Now that you have your certificate, you need to generate a provisioning profile. To do this, head todeveloper.apple.com and sign in with your iOS developer account.
To get started with your provisioning profile, you’ll first need to create an App ID for your Zombie Apocalypse app.
Choose App IDs from the options on the left. On the next page, click New App ID. Complete the form as necessary, making sure to enter com.raywenderlich.zombie for the Bundle Identifier, since that’s what you used earlier when first generating the initial project using PhoneGap.
Your form should look similar to the screenshot below:
Finally, click Submit.
Now that you’ve created an App ID for your new app, choose Provisioning from the options on the left. On the next page, select the Distribution tab and click New Profile. Fill out the form as necessary, selecting the App ID you just created, and select the devices on which you plan to install the app.
Finally, click Submit. The page will now generate your provisioning profile.
Once the portal has finished generating the profile, download it to your desktop. You may need to refresh the page a couple of times to see when it’s complete.
Now that you have both your certificate and provisioning profile, head back over to the Adobe Build site, enter a name for your app, and upload your certificate and your profile as shown below:
Click on the yellow lock icon and enter the certificate’s password that you created previously, as such:
Finally, Click Submit key. After a short wait, you will be presented with a button on the top of the screen to download the .ipa file as shown here:
Download the .ipa file, and install it to your iOS device by simply dragging the file into iTunes and then syncing your device.
w00t – you are now prepared for the worst – fill in your to-do list and get your shotgun ready!
As you’ve seen, iOS requires a few additional steps in order to build the app using Adobe Build. However, it is very much a one-click process for other platforms such as Android, where you can directly download your builds without any extra steps required!

Where to Go Next?

You can download the completed project here.
You’ve only seen a small portion of the features that PhoneGap has to offer for your cross-platform development needs. I recommend you take a quick look at the the PhoneGap API reference to find out about the huge list of APIs you can leverage in your apps.
I should mention that although PhoneGap makes it nice and easy to create cross-platform apps, if you’re looking for a nice and polished experience, nothing matches what you can do with native APIs. Some people even say that you can create a native iOS app and native Android app in less time than making a polished cross-platform app with something like PhoneGap.
On the other hand, there’s a ton of apps that have been successfully made with PhoneGap already –check out the full list to see for yourself. It kinda depends on what you’re going for.
Either way, I hope this tutorial showed you a little bit about PhoneGap and how it works, so you can make the decision that is best for your app. If you have any questions or comments, please join the forum discussion below!

No comments:

Post a Comment