Using PhoneGap 3.0 CLI on Mac OS X to Build iOS and Android Projects


At the time this was written PhoneGap Build does not support PG 3.0. These instructions assume Cordova PhoneGap is being used, not Build.

I highly recommend following the latest version of PhoneGap or Cordova. For instance, try these pages:

iOS: https://iphonedevlog.wordpress.com/2014/06/24/using-cordova-3-5-cli-on-mac-os-x-mavericks-to-build-ios-apps/

Android: https://iphonedevlog.wordpress.com/2014/06/20/using-cordova-3-5-cli-on-mac-os-x-mavericks-to-build-android-apps/

In this article, you will use CLI to build iOS and Android projects:

  • Install Cordova
  • Create a project with all necessary www folders and files
  • Add iOS and Android platform version folders and files
  • Build an Android debug apk for installation on a device for previewing
  • Build an Android project and view on a browser for previewing
  • Add the InAppBrowser and Splashscreen plugins
  • Update icons and splash screens for each platform
  • Update the config.xml, AndroidManifest.xml, and index.html files
  • Customize content for a particular platform
  • Finalize a product apk for Google Play upload, including keys and certificates

PhoneGap’s next releases will rely heavily on PhoneGap CLI (Command Line Interface), and to use it requires the installation of Node.js. Because Node.js will interface with the Eclipse (for Android) and Xcode (for Apple iOS) SDKs, the latest versions of those programs need to be installed as well. To read more about Node.js, one good read is the following (obviously for the technically minded among us): http://digitalfireflymarketing.com/what-nodejs-good

This article assumes you already have the latest version Xcode installed on your Mac. If not, download from here (I have articles on my site that give more directions).
Xcode: http://www.apple.com/osx/apps/app-store.html 
Android SDK + Eclipse + ADT plugin: http://developer.android.com/sdk/index.html

I am using part of Kerri Shott’s instructions for installing PhoneGap CLI, here:
http://photokandy.tumblr.com/post/46289610781/getting-started-with-cordova-cli
My article goes into more detail for the non-tech-savvy; hers assumes you already have some familiarity with using vi, among other things. I fill in the missing spaces in this article. Also, if you encounter something different from my experience, take a look at her article and see if it is addressed, or better yet, look at the PhoneGap resources following. My installation was not exactly the same.

Resources:
http://docs.phonegap.com/en/3.0.0/guide_platforms_index.md.html#Platform%20Guides
http://phonegap-tips.com/articles/the-nodejs-command-line-interface-for-phonegap.html

Install Node.js

1. I downloaded nodejs from http://nodejs.org/ It downloaded as node-v0.10.13.pkg in the Downloads folder. I double-clicked its icon to start the installation.

2. An installer appeared saying, “This package will install node and npm into /usr/local/bin.” I hit Continue and followed the prompts. The download came to 37.7MB of space. The final screen said,

Node was installed at 
/usr/local/bin/node
npm was installed at 
/usr/local/bin/npm

Make sure that /usr/local/bin is in your $PATH. To do so, type in the Terminal:

sudo pico /etc/paths

You’ll see a listing of paths. Add /usr/local/bin to the top and press enter if it isn’t. (It’s pretty standard and should be there already.)

/usr/local/bin

Node.js’s code in the Terminal references the $PATH, so let’s follow that instruction about the $PATH. (The $PATH is a listing of all directories where the system will look for commands. So if you type “ls” in the Terminal, it will look in those directories in order to find the file that executes the ls command.)

3. Open the Terminal and type the following to get to your root, then press Enter:

cd ~

4. Type the following to open the .profile hidden file, and then hit Enter (vi = visual editor):

vi .profile

I see on my screen:

".profile" [New File]

5. When I clicked to enter more text, I got white text on a red background saying,

E348: No string under cursor

That’s because I should have first typed i for the insert command. (To learn more about commands in this environment, see: http://www.cs.colostate.edu/helpdocs/vi.html ) While that text is still there go ahead and type i. — INSERT — should appear, telling you what mode you are in (you were in the command mode earlier). Type the following. When you start typing, your text will appear at the top of the Terminal window, not at the INSERT line. Type as shown on separate lines. Do NOT hit Enter when you are done:

# for NODE
PATH="${PATH}:/usr/local/bin"
export PATH
# for npm
PATH="${PATH}:/usr/local/bin/npm"
export PATH

6. Do not hit Enter just yet! Press the ESC key to enter command mode.

7. Type the following command to write the files and hit Enter:

:w

This should write the contents to file. At the bottom of my screen, it said,

".profile" [New] 3L, 54C written

Evidently, three lines of 54 characters were written. Quit the vi editor by typing:

:q

This will return you to Terminal’s bash screen. Go ahead and quit Terminal. If you wish, you can open the file again following steps 3-4 and see if the file retained the contents you typed in.

Xcode Command Line Tool

7. Open Xcode and select to start a new project. When I did that, a notice appeared that a Command Line Tools update was available. I installed at that point. If you have not installed the tools yet, follow these steps to do so.

8. In Xcode: Xcode > Preferences… > Downloads. Click on Install to install. This is a hefty 118MB, so it’ll take a while.

Add PATH Statements to .profile

9. We need to add Android Tools to the $PATH via the .profile file. First you need to find your path to it. Try “adt-bundle” or “android-sdk” in the Spotlight and see which one you get. Or try “tools.” When you click on a result, the Finder will open the folder.
10. Click on Go > Enclosing folder and Finder opens the enclosing folder. Make sure it’s the right tools folder; it should have an “android” command file in it.
11. Open up Terminal and drag the tools folder to it. Make a note of the folder path. Mine was:

/Users/Steve/Developer/adt-bundle-mac-x86/sdk/tools

We can safely shorten it to:

~/Developer/adt-bundle-mac-x86/sdk/tools

12. Follow steps 4-6 above, but use the arrow keys to get to the end of the previous entries, then starting on a new line with Enter, enter your PATH information like this (you can actually copy/paste in the information in the Terminal window from your own notes). You’ll need two entries, one to the tools folder and the other to the platform-tools folder:

# for android
PATH="${PATH}:~/Developer/adt-bundle-mac-x86/sdk/tools:~/Developer/adt-bundle-mac-x86/sdk/tools"
export PATH
# for adb
PATH="${PATH}:~/Developer/adt-bundle-mac-x86/sdk/platform-tools:~/Developer/adt-bundle-mac-x86/sdk/platform-tools"
export PATH

Add the above information on separate lines as shown. Remember, after adding the above lines, to hit ESC to go into command mode, then type :w to save the contents, then :q to quit vi. Quit Terminal.

Install Cordova CLI

13. Open Terminal and issue the following command:

sudo npm install -g cordova

Pay attention to the inconsistency in the PhoneGap documentation between the use of “phonegap” and “cordova” in the command line. For instance, the Command-line Interface online page uses “phonegap” while the InAppBrowser API online page uses “cordova.” They are not interchangeable when using CLI. As seen in the above command, we are asking to download “cordova.” So we would replace all instances of “phonegap” in the documentation with “cordova,” or the command will generate a “not found”-type error.

Use “phonegap” in place of “cordova” if you expect to use the PhoneGap Build service.

14. Give the root password and hit Enter. I got a series of ERR lines, ending with:

npm ERR! not ok code 0

I kept pasting the command and hitting Enter over and over until it completed (maybe three times). When successful, you should get a long list of lines beginning with “npm http,” then finally ending with a series of words containing the @ symbol and digit/dot pairings, terminating with your username at the end.

15. Quit Terminal.

Create a Test Project

16. Ready to give it a dry run? Open Terminal and type the following:

cordova create FolderName com.myproject MyProject

We are not done with the installation yet. If we want to use the iOS emulator, we’ll need to install a few more files.

Homebrew

Homebew installs packages to their own directory and then symnlinks their files into /usr/local. To learn more about Homebrew visit: http://mxcl.github.com/homebrew/. [link no longer exists.]

17. Homebrew directs us to paste the following into Terminal to install itself:

ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"

It will tell you what it is about to do; just press Enter to continue or any other key to stop the program. If you trust what it wants to do to your system, then press Enter, enter your root password, and wait a while. It ended with:

==> Installation successful!
You should run 'brew doctor' *before* you install anything.
Now type: brew help

18. We’ll follow the advice above to run “brew doctor.” Brew doctor seems to be a fix-it program to get Homebrew ready to use.

Type the following into the Terminal:

brew doctor

I waited until the command prompt was returned and got:

Your system is ready to brew.

19. Let’s use Homebrew to install the ios simulator. Type the following into the Terminal:

brew install ios-sim

I received the output (including a color icon of a mug of beer!):

==> Downloading https://github.com/phonegap/ios-sim/archive/1.7.tar.gz
######################################################################## 100.0%
==> /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/rake install pr
<color pic of beer>/usr/local/Cellar/ios-sim/1.7: 4 files, 100K, built in 25 seconds

Project Creation, PhoneGap CLI-style

20. I wanted to create an app called TestApp2 in the folder /Documents/AndroidApps/TestApp2. So I built up the command line like the following and hit Enter:

cordova create ./Documents/AndroidApps/TestApp2 com.stevehusting.TestApp2 TestApp2

It took several minutes to create on my Mac Mini.

21. After the above create command, indicate what platform you are building. Make sure the Terminal indicates that the current folder is the TestApp2 folder (if not, type cd in the Terminal, drag the TestApp2 folder to the Terminal, click on the Terminal to activate it, hit Enter), and type:

cordova platform add ios

*** ERROR ***

I received the error when I started the command from the TestApp2 folder:

[Error: An error occured during creation of ios sub-project. /bin/sh: /Users/Steve/.cordova/lib/ios/cordova/2.9.0/bin/create: No such file or directory]

error went away when I followed step 2 to enter the Node and npm lines in the $PATH

*****

I asked the program to list the platforms associated:

cordova platform list

Terminal showed:

[ 'ios' ]

22. Now let’s add the Android platform. Type:

cordova platform add android

I get the error message:

cordova platform add android
[Error: The command 'android' failed. Make sure you have the latest Android SDK installed, and the 'android' command (inside the tools/ folder) added to your path. Output: /bin/sh: android: command not found

a. After asking for help on the PhoneGap group, I was told to add the path to a .bash_profile hidden file. To do this, type the following and press Enter in Terminal. To get to the home directory:

cd ~/

b. Now type the following to create a .bash_profile in case there isn’t one already (don’t worry – it won’t overwrite an existing one):

touch .bash_profile

c. Then open the file with the following, and press Enter:

open -e .bash_profile

d. Enter the following into the new window that opens, and press Enter (remember to change the path, since yours is different from mine):

export PATH=~/Developer/adt-bundle-mac-x86/sdk/tools:~/Developer/adt-bundle-mac-x86/sdk/tools:$PATH

e. Save and exit that window. Now type the following in Terminal to activate the file and press Enter to switch to the new file:

. .bash_profile

24. Now let’s try again to add the Android platform from within the TestApp2 folder (type cd in the Terminal, drag the TestApp2 folder to the Terminal, click on the Terminal to activate it, hit Enter), and type:

cordova platform add android

25. The Terminal should return normally. Now test whether the platform has been added. Type the following and press Enter:

cordova platform list

The Terminal should return:

[ 'android', 'ios' ]

26. Now open your TestApp2 folder. Open the folder for “platforms” and see two folders, “android” and “ios.” If you look in there, you’ll see that PG has already created a skeleton site. Let’s run a CLI build command and see what happens.

Testing various CLI Commands

1. All the CLI commands will start with your project’s folder; in my case, TestApp2. From there, in Terminal:

phonegap emulate ios

Uh-oh, I got the result:

-bash: phonegap: command not found

I should have typed cordova, not phonegap. Some online instructions will say to use phonegap, some will say cordova. Which one to use? It depends on step 13 above, in which we typed “sudo npm install -g cordova.” In this case, it should be “cordova” in all commands in this installation. Now type:

cordova emulate ios

The title bar of Terminal will update with different messages, then the iOS Simulator should start, showing in a faux iPhone Retina/iOS 6.1 the home page with the Apache Cordova logo, name under it, and DEVICE IS READY below that.

When you typed this command, it built the app in your TestApp2/www folder, and overwrote some of the contents of the TestApp2/platforms/ios folder.

To return to the device’s home page and check out your device’s icon, go to Hardware > Home. I notice in the Simulator a new Debug menu and Window > Scale menu item. Try those out. The Scale 75% helped me to fit the simulator comfortably on my screen.

Click on the simulator to select it, then in the menu bar, turn it off with iOS Simulator > Quit iOS Simulator.

2. Now try:

cordova build ios

After the Terminal finishes, look in the project folder’s platforms > ios > build folder to view the .app file that was was created.

3.  Let’s try another command:

cordova build android

This resulted in:

BUILD FAILED
/Users/Steve/Developer/adt-bundle-mac-x86/sdk/tools/ant/build.xml:955: The following error occurred while executing this line:
/Users/Steve/Developer/adt-bundle-mac-x86/sdk/tools/ant/build.xml:966: The following error occurred while executing this line:
/Users/Steve/Developer/adt-bundle-mac-x86/sdk/tools/ant/build.xml:310: com.android.sdklib.build.ApkCreationException: Debug Certificate expired on 4/24/12 3:57 PM

It failed because of an expired certificate. I found the issue resolved here: http://stackoverflow.com/questions/2194808/debug-certificate-expired-error-in-eclipse-android-plugins

I deleted the certificate (a hidden file at ~/.android/debug.keystore) and ran the command again. This time it rebuild the certificate and I got no errors. Go to your TestApp2/platforms/android/bin folder to see the apk generated. Mine was called TestApp2-debug.apk

I dragged the file to my Dropbox folder, waited until the blue loading symbol turned into a checkmark, accessed it through my device’s Dropbox app, selected it, and installed the app. I notice it had “Full network access” permission and none else, which was fine. The app played back flawlessly, with “Device is Ready” pulsating and the page displaying the Cordova icon.

4. Plugins are not added automatically, according to the docs: “For the app to communicate closely with various device-level features, you need to add plugins that provide access to core PhoneGap APIs.” Each plugin is in its own repository and must be downloaded separated via CLI. When we look up the InAppBrowser page in the API Reference online for 3.0 (http://docs.phonegap.com/en/3.0.0/cordova_inappbrowser_inappbrowser.md.html#InAppBrowser), we find the URL. There, we also learn how to change the config.xml page differently for each platform.

Special note: you add the config.xml information for each platform to the SAME file; no multiple config.xml files needed.

To add the InAppBrowser using CLI, for example, start the command line from within your app’s folder and type:

cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-inappbrowser.git

Wait a while for the command line to update. When the command line returns, take a look in your TestApp2/platforms/ios/www/plugins folder to see the inappbrowser file. It should appear in the Android plugins folder as well.

Then we view the online API reference to find out how to modify the TestApp2/www/config.xml page with a text editor, in this case, for iOS, right above the </widget> line:

<feature name="InAppBrowser">
    <param name="ios-package" value="CDVInAppBrowser" />
</feature>

Save and close the document, then do a build for iOS:

cordova build ios

When the command line returns, take a look in your TestApp2/platforms/ios/www/config.xml to see the change we made.

Now we go back to the config.xml file opened previously and add:

<feature name="InAppBrowser">
    <param name="android-package" value="org.apache.cordova.InAppBrowser" />
</feature>

Save and close the document, then do a build for Android to test. At one point during testing in my device, I got the “[ERROR] Error initializing Cordova: Class not found” alert message. That’s because I was referring to cordova-2.9.0.js instead of cordova.js on that page. With the change corrected, the error was gone. Since this app was build on top of an earlier app, I did a search for that old js file for all pages.

5. View the app in the browser with:

cordova serve android

I get this returned in the Terminal:

Static file server running at:  => http://localhost:8000/
CTRL + C  to shutdown

I opened a browser and copied/pasted the above URL in and the app startup screen appeared. The message displayed was, “Connecting to Device.” I also received a popup with a text field containing text I wasn’t sure what to do with. Clicking on OK turned it off.

This is a “static” file, meaning if you opened the html page, made a change, and saved it, refreshing the browser will not show the changes. Not sure what the advantage is over opening the file by double-clicking it. However, Google Tools works both ways.

I clicked on the Terminal and then CTRL + C returned me to the prompt.

6. Don’t forget to read the help section:

cordova help

Updating Icons through CLI

How do we supply the icons for each platform? TestApp2/www/res has folders for icons and screens; within each of these folders are supported platform names, including android and ios. Those folders are NOT duplicated or copied into the platforms/ folders when you do a build. Don’t update those. I’m not sure of their purpose. They are probably used for PhoneGap Build, and if they are, you’ll want your files in those locations if you are using Build.

Replace the Android icons within TestApp2/platforms/android/res/drawable. Do a build for Android and test.

Part of the build result was:

clean:
 [delete] Deleting directory /Users/Steve/Documents/AndroidApps/TestApp2/platforms/android/bin
 [delete] Deleting directory /Users/Steve/Documents/AndroidApps/TestApp2/platforms/android/gen

This tells me that the /bin and /gen directories are overwritten at build time.

Update: for 3.4.0, the directories are different:platforms/android/ant-build and platforms/android/ant-gen. The apk file is found in platforms/android/ant-build.

WHOA! It just hit me – I just fully compiled an Android apk without ever using Eclipse!

Updating Android Splashscreens through CLI

1. Starting from within the app’s folder, type in Terminal this information, which we get from the Splashscreen API page on phonegap.com:

cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-splashscreen.git

2. Update for iOS in config.xml:

<feature name="SplashScreen">
    <param name="ios-package" value="CDVSplashScreen" />
</feature>

Update for Android in config.xml:

<feature name="SplashScreen">
    <param name="android-package" value="org.apache.cordova.SplashScreen" />
</feature>

3. The Splashscreen API doc says, “Copy the splash screen image into the Android project’s res/drawable directory.” This is not strictly true if you have multiple images. I copied/pasted each of the of the project’s screen folder portrait splash screen images into its appropriate platforms/android/res/drawable folder. Then I renamed each of the portrait versions as “splash.png.”

For iOS, the doc says, “Copy your splash screen images into the iOS project’s Resources/splash directory. Only add the images for the devices you want to support, such as iPad or iPhone.” I would drag the splash screens right into the Xcode program.

4. Go to platforms/android/src/com/name/TestApp2/TestApp2.java and open it in a text editor (I use TextWrangler). “In the onCreate method of the class that extends DroidGap, add the following two lines:”
super.setIntegerProperty(“splashscreen”, R.drawable.splash);
super.loadUrl(Config.getStartUrl(), 10000);

Change this:

super.onCreate(savedInstanceState);
 // Set by <content src="index.html" /> in config.xml
 super.loadUrl(Config.getStartUrl());
 //super.loadUrl("file:///android_asset/www/index.html")

to this:

super.onCreate(savedInstanceState);
super.setIntegerProperty("splashscreen", R.drawable.splash);
super.loadUrl(Config.getStartUrl(), 2000);
 // Set by <content src="index.html" /> in config.xml
 // super.loadUrl(Config.getStartUrl());
 // super.loadUrl("file:///android_asset/www/index.html")

The “2000” means show the splash screen for two seconds. The “R.drawable.splash” means it expects to find a file called “splash.png” in the drawable folders. We did that when we renamed all the splash screens in each drawable folder in step 2.

Highly recommended that you use a 9patch image for your splash screen. For full instructions on this, see:  https://iphonedevlog.wordpress.com/2013/07/02/creating-and-installing-a-splash-screen-for-android-using-eclipse-and-phonegap/

5. Open the project’s index.html and add the following right after the cordova.js line:

<script type="text/javascript" charset="utf-8">
// Wait for device API libraries to load
 //
 document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
 //
 function onDeviceReady() {
 navigator.splashscreen.show();
 }
</script>

A little more work needs to be done for the iOS splash screen. Modify the above code’s last lines so it looks like:

function onDeviceReady() {
 navigator.splashscreen.show();
 setTimeout;
 }

 setTimeout(function() {
 navigator.splashscreen.hide();
 }, 2000);
</script>

More About Icons and Splash Screens

When I built my Android app as is, the size of the default Cordova app was 8.6MB. Pretty heavy for displaying only one HTML page! It was loading all the icons and splash screens for all the platforms into the same app — after all, they are all in the TestApp2/www folder. When I removed all the TestApp2/www/res/icon/ and screen/ folders other than android/ and did a build, the app came to 2.9MB. That’s more like it.

Since I was building for more than one platform, I created two folders on my desktop, naming one “temp www icon folders” and the other “temp www screen folders” and dragged the bada, etc. folders unrelated to the platform I’m building at the time from the www directory to those temp folders. It’s a simple matter to drag them back when building for the other platforms.

It seems, though, that Cordova should be coded to recognize that with “cordova build ios” it should copy only ios folders. I hope this will be done with a later version.

Updating PhoneGap

First check what version you are running:

cordova -v

My output was:

3.0.6

Update to the latest version of via CLI like:

sudo npm update -g cordova

[or replace cordova with phonegap, whichever one you started out with]

I get this output:

npm http GET https://registry.npmjs.org/cordova
npm http 304 https://registry.npmjs.org/cordova

I still got the 3.0.6 returned, so there was no update available. A few days later, I used the above to updat to 3.0.7, but it was a build with problems that prevented any CLI commands from working. Is it possible to revert to an earlier version? Yes.

We can learn what versions we can update to (or revert to) with:

npm info cordova

I reverted to 3.0.6 with this command, and my commands started working again:

sudo npm install -g cordova@3.0.6

To upgrade from versions prior to 3.0, follow the Platform Guides: http://docs.phonegap.com/en/3.0.0/guide_platforms_index.md.html#Platform%20Guides

Updating config.xml

For Android: Make sure you open TestApp2/platforms/android/res/xml/config.xml to change the Android app version when updating the app. You’ll want to change the name, description, and author information there to match your app. Right now, for instance, it says:

<name>Hello Cordova</name>
<description>
 A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev@cordova.apache.org" href="http://cordova.io">
 Apache Cordova Team
</author>

The above <name></name> space is where you’ll put the text that goes under the launch icon on the device’s home screen.

This default entry permits full access to any URL (all URLs are “whitelisted”):

<access origin="*" />

For more about whitelisting, see http://docs.phonegap.com/en/edge/guide_whitelist_index.md.html#Domain%20Whitelist%20Guide

If you are using PhoneGap Build, you’ll need to customize this file more (when PG Build supports 3.0+).

Default preference name/values in Android config.xml are:

<preference name="useBrowserHistory" value="true" />
<preference name="exit-on-suspend" value="false" />
<preference name="fullscreen" value="true" />
<preference name="webviewbounce" value="true" />

Please read the following documents for further steps to customize for your platform:

iOS configuration: http://docs.phonegap.com/en/3.0.0/guide_platforms_ios_config.md.html#iOS%20Configuration

Android configuration: http://docs.phonegap.com/en/3.0.0/guide_platforms_android_config.md.html#Android%20Configuration

More suggested changes are noted here: http://docs.phonegap.com/en/edge/guide_project-settings_index.md.html#Project%20Settings

Updating AndroidManifest.xml

You’ll want to update TestApp2/platforms/android/AndroidManifest.xml with your permissions. Almost all of these are missing; enter what’s required for your app:

<uses-permission android:name="android.permission.CAMERA"/>
 <uses-permission android:name="android.permission.VIBRATE"/>
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
 <uses-permission 
 android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.RECEIVE_SMS"/>
 <uses-permission android:name="android.permission.RECORD_AUDIO"/>
 <uses-permission android:name="android.permission.RECORD_VIDEO"/>
 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
 <uses-permission android:name="android.permission.READ_CONTACTS"/>
 <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
 <uses-permission android:name="android.permission.BROADCAST_STICKY"/>

Update the version code as well if it’s more than version 1. VersionCode is what will display in the store; versionName is for your internal use and won’t be shown:

android:versionCode="1" android:versionName="1.0.0"

Customizing a Platform

What if I wanted a css file in Android, but not in iOS? Cordova provides a merges/ folder so we can customize our apps. The merges/ folder has folders for each platform. You’ll need to manually recreate the folder structure in those folders. Here is a sample:

1. Double-click on android/ to open it in its own window.

2. Click on the gear symbol in the window’s menu bar, then on New Folder.

3. Call the folder new-css/

5. Copy the TestApp2/www/css/index.css file into that folder.

6. Delete everything in the copied file so it contains only the following, and save.

/* Android */
.customized {
font-family:serif;
font-size:12px;
 padding: 10px; margin: 10px;
 color: green;
text-transform:none;
}

7. Copy/paste the merges/android/new-css/ folder to the merges/ios/ folder, open the index.css file, and modify it so it contains only:

/* iOS */
.customized {
font-family:serif;
font-size: 36px;
 padding: 10px; margin: 10px;
color: red;
text-transform:none;
}

8. Open index.html and add this line under the css/index.css line and save. It will  point to the new file you just made:

<link rel="stylesheet" type="text/css" href="new-css/index.css" />

9. In the same index.html file, modify the following lines  and save:

    <body onload="onLoad()">
            <p class="customized">Android: Small green text. iOS: Huge red text.</p>
        <div>
            <h1>Apache Cordova</h1>

10. In Terminal, starting from your TestApp2 folder, build the Android project (cordova build android), then view in browser (cordova serve android). The text will be smaller (12pt) than the APACHE CORDOVA line (24pt), and green.

11. Click in Terminal to select it and tap CTRL + C to shut down the server. Run cordova build ios. Now open platforms/ios/ and double-click on TestApp2.xcodeproj to open it in Xcode. Click on the round Run button in Xcode at upper left to view it in the Simulator. The text will be large and red. In Xcode, click on Stop to stop the Simulator. Click on the Simulator to select it, then click on iOS Simulator > Quit.

You’ve customized the text in two different platforms. This is a stilly example, though. I can think of using it in a page of links in which I’d want a button in the iOS version to link to the Apple App Store for my iOS apps, and in the Android platform a link to my Google Play store. Linking to a different js page in each folder (same file name, remember?) will do this nicely.

Think of it as an extra tool that Cordova has provided for us to make small tweaks to our apps for different platforms.

Prepare Promotional Artwork

You’ll want to include screen captures for upload to Google Play. Choose screens carefully to present your app in its best light. What if your device doesn’t do screen captures? My Google Nexus 7 did not have this native functionality, nor did I find apps that performed this function. All is not lost, though; here is what I did.

1. Just double-click the index.html file in the Finder (workspace folder) to open it in a the Google Chrome browser, then narrow the browser window (if you want a Portrait view) to approximate the device screen proportion.
2. Use your favorite screen grab utility to get the picture.
3. Use GIMP or other photo-retouching program to crop it appropriately.

Prepare Copy and Graphic Assets for App Store

You’ll need this information on hand when filling out the form for apk submission in Google Play. Follow this template:

https://iphonedevlog.wordpress.com/google-play-app-publishers-template-22013/

Build your App in Eclipse

You have two options to create your app in Eclipse: project from existing code or as a new project. The first way lets your AndroidManifest and config.sys files set up everything for you. The second way means entering a lot of the information into Eclipse that you’ve already entered in those two files. The first way is the short way; the second way is the long way. I will present both options to you. If you have problems with the first option, then in Eclipse, Refactor > Rename the project, and try the second option.

Option 1: From Existing Code

First check for updates to Eclipse and install: Help > Check for Updates.

1. File > New > Project…
2. Android > Android Project from Existing Code
3. Click on Browse and select the Root Directory of the project, AppProject. The Root Directory field should then be filled in, and Project to Import will show “platforms/android” selected. Now select Copy projects into workspace if you wish. Click Finish.

END OF OPTION 1. Continue to “Check Your Work.”

Option 2: As New Project

First check for updates to Eclipse and install: Help > Check for Updates.

1. Launch Android’s ADT + Eclipse and select menu item File > New > Project.
2. Under Wizards, select Android > Android Application Project, then Next.
3. In the New Android Application screen, fill out:
Application Name (as it will appear under the icon on the home screen).
Project Name (usually same as app name, but no spaces allowed).
Package Name (in this format: com.your_domain_name.app_name).
Minimum SDK (I put API 8)
Target SDK (put the highest number your test device will use)
Compile with (I put 18)
Theme: (none)
4. Check: Create custom launcher icon, Create Activity, Create project in workspace and indicate your workspace location. Next.
5. Configure Launch Icon. click on Browse and select your project’s drawable-xhdpi/ icon.png in platforms/android/bin/res. You should see the default icon updated with your own. Next.
6. Create Activity; leave defaults. Next.
7. Blank Activity; leave defaults. Finish.

Copy your PhoneGap files to Eclipse

1. Select your project’s www/ folder in the Finder window and copy.
2. In Eclipse, right-click on the assets/ folder and paste.
3. In Eclipse, open assets/www/ and delete the res/ folder.
4. In Eclipse, right-click on your project’s name and select New > Folder.
5. In the Folder window enter libs in the Folder name box, and click Finish (check to see if /libs is already present).
6. We need to copy over the Cordova jar (Java ARchive) file. In Eclipse, right-click on the /libs folder and go to Build Path > Configure Build Path. Then, click on the Libraries button or tab, click on Add External JARs, and navigate again to the cordova-3.0.0.jar file in TestApp2/platforms/android/libs to add it to the project. You should see it appear at the top of the list. Click OK to finish.
7. Now we need to copy over all the icon and splash screens. In Eclipse, delete all the /drawable folders (but NOT the /res folder) and replace them with the ones from TestApp2/platforms/android/res/ BUT retain the /drawable-xxhdpi folder. Copy the /drawable-xhdpi content into that folder.

Update AndroidManifest.xml

1. Our icons were named “icon.png” so we need to make sure Android recognizes them. In Eclipse, Right-click on AndroidManifest.xml choose Open with > Text editor, and change:

android:icon="@drawable/ic_launcher"

to:

android:icon="@drawable/icon"

2. Right above <application, put the following:

<supports-screens
 android:largeScreens="true"
 android:normalScreens="true"
 android:smallScreens="true"
 android:resizeable="true"
 android:anyDensity="true" />
 <uses-permission android:name="android.permission.VIBRATE" />
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.RECEIVE_SMS" />
 <uses-permission android:name="android.permission.RECORD_AUDIO" />
 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
 <uses-permission android:name="android.permission.READ_CONTACTS" />
 <uses-permission android:name="android.permission.WRITE_CONTACTS" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.GET_ACCOUNTS" />
 <uses-permission android:name="android.permission.BROADCAST_STICKY" />

3. Remove all the above permissions your app doesn’t need. Or comment them out NOW with /* at left and */ at right of each line. To learn more about permissions, see
http://developer.android.com/guide/topics/manifest/uses-feature-element.html
http://developer.android.com/guide/topics/manifest/uses-permission-element.html
http://developer.android.com/reference/android/Manifest.permission.html

4. Make sure the following two lines show the correct version numbers, the second being the actual version shown to users:

android:versionCode="1"
android:versionName="1.0" >

5. Support orientation changes by pasting the following right after the <intent-filter> line:

android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"

Update Activity.java

1. [Steps 1-2 may be optional; may be able to leave as is.] In Eclipse, open src/ and navigate to the projectnameActivity.java file (or MainActivity.java). Right-click, Open With > Text Editor. We need to add in the information we used to update the same file earlier, located at platforms/android/src/com/name/projectname/projectname.java. Right now this section in Eclipse reads:

@Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 }
}

I copied pasted from the earlier file to change it to:

@Override
 public void onCreate(Bundle savedInstanceState)
 {
super.onCreate(savedInstanceState);
// super.setIntegerProperty("splashscreen", R.drawable.splash);
super.loadUrl(Config.getStartUrl(), 2000);
 // Set by <content src="index.html" /> in config.xml
 // super.loadUrl(Config.getStartUrl());
 // super.loadUrl("file:///android_asset/www/index.html")
 }
}

2. In the same file, change:

import android.app.Activity;
import android.os.Bundle;

to:

import android.app.Activity;
import android.os.Bundle;
import org.apache.cordova.*;

3. In the same file, change:

extends Activity {

to:

extends DroidGap {

4. Save the file.

END OF OPTION 2.

Check Your Work

1. Let Eclipse check your work for errors. First click on Project > Clean. The lower right of the window will show the progress. Use Project > Clean between each of the following steps.

2. Now right-click on your project name and select Validate. If it mentioned errors or warnings in a popup, then you can find those messages in Window > Show View > Problems. You can actually double-click on the lines and Eclipse will open to the page and line of the problem. Fix all those problems, Clean, and Validate again.

3. Right-click on your project name and select Android Tools > Run Lint and fix those errors. If you find errors under Eclipse’s Lint Warnings tab, use this article to help deal with some of them: https://iphonedevlog.wordpress.com/2013/06/26/fixing-android-lint-warnings-found-when-building-a-phonegap-project/

4. Right-click on your project name again, and select Run As > Android Application. If you have a working emulator installed, then it will launch and you’ll see the home screen. Slide the lock over and the app will launch, if all is well (or you’ll need to tap on the app icon to start it).

Also, you’ll see the LogCat and Error Log screens at the bottom of the Eclipse environment as it records what is happening in the emulator. If you don’t understand the errors, you can double-click on the line, copy, and paste it into Google for a search.

If you get this in the emulator before the app has even opened: “The application . . . has stopped unexpectedly. Please try again,” problems may exist in AndroidManifest.xml, because that has to be processed before the index.html file starts. One of the three parts of the “package=” line may be wrong. the name may have upper/lowercase inconsistencies. You may not have the right AVD.

If you get a “Failed to load properties file for android project” message in Eclipse when testing, right-click on the project name in Eclipse, select Android Tools > Fix project properties, do a Clean, and see if that helps.

If you get in the Console tab: “Could not find appName.apk!” then this may help: Right-click on the project name in Eclipse, then on Properties. Select the latest Project Build Target, then click on OK. Restart Eclipse.

If you get lost among the log messages and want to get back to the key windows, go to Window > Open Perspective > Java.

5. You can choose among Android devices to target for testing. In menu bar at top use Run > Debug Configurations > Target tab to choose which Android API to test in the emulator. Click on the AVD Name then Debug. Create new AVDs with Window > Android Virtual Device Manager. Resource: http://developer.android.com/tools/devices/managing-avds.html

Sign the App

Apps in the app store must be “signed” with keys. Here are the steps to accomplish this. These steps create the “apk” file that is uploaded to the app store for purchasers’ download.

1. Right-click on the project name in Eclipse, then click on Android Tools > Export Signed Application Package.
2. “Project Checks” dialog:
This screen will tell you if you have serious errors that need to be fixed before you can go further. If you have problems, copy the error into Google and search for resolutions if you are unfamiliar with these problems.
3. “Keystore selection” selection dialog:
Create the key using the app name, no spaces, ending in “.keystore”. WARNING: if this is an upgrade, use the same name as the earlier version! Browse to the location to save the keystore and in the same box give the name of the keystore. Back in the Keystore selection dialog, add the password twice and hit Next.
4. Key [“Private Key”] Creation dialog:
Alias: same as app_name, no spaces.
password of keystore.
validity: 50 [meaning, good for 50 years].
First and Last name:
Organizational unit: [division of company, or leave blank]
Organization: [use no punctuation – only letters and numbers, or you’ll get an “keytool error” notice later.]
City:
State: [2-letter abbr. is fine.]
Country: 01. [which is U.S.]
Destination APK file: This is the hard disk location where Eclipse will save the program’s .apk file that you will later upload to Google Play or other app store. Browse, then click Finish when done.

Write down the above Key Creation information, passwords, and APK destination and keep it safe for later retrieval and app updates. If it is lost, you can’t upgrade the app any further. To release the app after this file has been lost, you’ll have to create a whole new app and release it separately, making your customers ineligible for any updates.

Perhaps make a separate private key for each app, especially if you expect to sell the rights to an app to someone else. Save the keystore and apk files to a separate location for safety.

If you get: “keytool error: java.io.IOException: Incorrect AVA format,” then an invalid character was used in one of the previous screens. Solution: remove any punctuation so only letters, spaces, and numbers remain.

Test the apk File in Device

1. Check with your device as to how to install the apk file. In my defunct eLocity tablet, it was s a simple matter of copying the file to the SD card, navigating to it from Settings, and selecting and choosing to install it. My Google/Asus Nexus 7 does not include an SD card. So I downloaded DropBox.com software to the computer and the DropBox app to the Nexus. Once I signed up for a Dropbox account, I copied the apk file to the computer’s DropBox, then it was accessible on the Nexus. Then I tapped on the file and it asked if I wanted to install. Simple.
2. Once installed, you’d click on Open, and you should see it on the home screen. If not, tap the middle button at the bottom of the screen to see all the installed apps and look for your icon. Check your app title underneath to make sure it is not truncated.
3. Tap the icon and check out your work.
4. Make changes to the files as necessary and redo.

Ready For Public Release

Congratulations! You are now ready to show off your baby to the world!

To register as a Google Play developer and set up your publisher account, visit the Google Play publisher site: https://play.google.com/apps/publish/Home

My Helpful Links page gives a small listing of other sites where you can upload your apps. Visit https://iphonedevlog.wordpress.com/phonegapcordova-crib-sheet/ and look under “App Stores.”

26 thoughts on “Using PhoneGap 3.0 CLI on Mac OS X to Build iOS and Android Projects

  1. Wow. Thank you so much for writing all this. I am going to go back through and see if I can get Cordova to work. Phonegap works except plugins are kind of hit and miss. I’d like to get Cordova working too.

  2. I keep getting:

    [Error: downloaded www assets in /Users/SBCERA/.cordova/lib/www/cordova/3.0.0/www does not contain index.html, or www subdir with index.html]

  3. Steve – Thank you so much for writing this. I was having lots of problems getting Cordova set-up but this really saved me. Don’t know if the problem was bad documentation, a screwed up mac that needed cleaning, or user error, but I’m all set now because of this excellent article. Thanks.

  4. In order to run your app with the Android emulator, you need to:

    1- Open the ADT Bundle ( Eclipse )
    2- Go to Window -> Android Virtual Device manager
    3- Add a New Virtual Device.
    4- Select the Device and Click Start.

    Once the device is running, you can run the command:

    cordova emulate android

    And it will run the app in the emulator.

  5. Pingback: Using PhoneGap 3.3 CLI on Mac OS X Mavericks to Build iOS Projects | iPhone Dev Log

  6. Pingback: Adding Cordova APIs to Android via CLI: Accelerometer and Camera | iPhone Dev Log

  7. Pingback: Installing Chris Brody’s SQLite Database with Cordova CLI (Android) | iPhone Dev Log

  8. Pingback: Push! | Craig’s Blog

  9. Pingback: Using PhoneGap 3.0 CLI on Mac OS X to Build Android Projects | iPhone Dev Log - appgong

  10. Pingback: Installing a 9-Patch Splash Screen for Android (using Eclipse and PhoneGap) | iPhone Dev Log

  11. Pingback: Using Cordova 3.5 CLI on Mac OS X Mavericks to build iOS apps | iPhone Dev Log

  12. Pingback: Getting Cordova to work on MacOSX for Android | psybercity

  13. Your step by step tutorial saved me from a lot of effort, as it puts things in a nice and neat order. I made a blog post on my own site including solutions to some problems I came across while following your procedure. I provided links to this post and references to specific steps, and what I did instead, if an error occured. My post is here: http://psybercity.co.uk/2015/02/13/getting-cordova-to-work-on-macosx-for-android/
    The main step I focused on was on modifying the PATH and setting the environmental variables of JAVA_HOME, ANDROID_HOME and ANT_HOME on the .bash_profile file, in order for everything to work correctly.

    Thank you very much for this post, again.

  14. Dude you nailed it. You ve also saved my day as well as with so many others. Kind Regards hope you are good and blogging!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.