Using Cordova CLI on Mac OS X to build Android apps

This article gets you up to speed on how to integrate your HTML/CSS/JS app with Apache Cordova into an Android app using a Mac and prepare it for App Store submission. This article assumes you’ve already followed the steps here to set up your environment:

I am referencing “cordova” in the command-line interface, not “phonegap.” This project will not use the PhoneGap Build service.

If you are making an app larger than 100MB for Google Play, you’ll need to make an expansion file. This 2014 article tells how to make one, though I don’t know if it works today. Back in 2014, the Amazon App Store allows apps up to 150MB before needing an expansion file.

Cordova uses the command-line interface (CLI) to generate the files needed to start the project. This article covers the creation of an app from CLI creation to upload a final apk to Google Play.

Create Cordova Project Files with CLI

1. Open a Finder window and select the folder you want to create your project’s folder inside of, such as /Apps
2. Open the Terminal app (click on its icon in the dock below, or click on the magnifying glass at top right and type in “terminal”), type cd and a space (for “change directory”), drag the selected folder to the Terminal screen, let go, click on the Terminal to select it, then hit Return. This will orient all commands to that folder.

For this project, all of your commands will always begin with “cordova.” Some online tutorials and PhoneGap documentation will tell you to use “phonegap;” in that case, change it to “cordova” and it should work fine.

3. Type the following in the terminal:

cordova create myApp

Basic files are generated in the /myApp folder.

4. Enter the new folder you created in Terminal with the cd (change directory) command:

cd myApp

5. CLI only downloaded the skeleton files needed for all platforms. Now you need to download the specific files for Android:

cordova platform add android

Open the myApp/platforms folder to see a new folder, /android.

Cordova included several files for a default one-screen app, complete with splashscreen and icon. To create a test apk file of the default Cordova app, type:

cordova build android

The apk file was built and saved as: myApp/platforms/android/app/build/outputs/apk/debug/app-debug.apk

To run the apk on your device, you’ll need to go into your device’s Settings and enable for debugging. I have Google Drive installed on my Android device and computer. It’s a simple matter to copy the file to Google Drive on the computer, turn on my device, open Google Drive there, and select the apk file to download, install and run it. You’ll know it’s running correctly when you see “APACHE CORDOVA DEVICE IS READY” on the screen. You can also email it to yourself and open it in your smartphone’s email client. Tapping on the file should download and install it.

If the smartphone won’t install it, you may have to set it up to accept files outside of Google Play. To do this, we’re told to enable Developer Options in Settings. Steps:

Open the Settings app.
(Only on Android 8.0 or higher) Select System.
Scroll to the bottom and select About phone.
Scroll to the bottom and tap Build number 7 times. (May have to select another step, like Software Information on my Galaxy 8.)
Return to the Settings screen to find Developer options near the bottom.

However, on my Samsung Galaxy 8, I found “Install unknown apps” under Biometrics and security.

For subsequent versions of the app (whenever you make changes to it), I always run the Refresh command in Google Drive to make sure I’m referencing the latest version of the app.

If you only have one platform installed, you can shorten the command above to “cordova build” and “cordova emulate.” If you have more than one platform installed, “cordova build” will build each platform.

If you have an early cordova version installed (check with “cordova -v”), you can update to the latest version with:

npm update -g cordova

I once received the message after inputting the above:

npm ERR! Error: EACCES: permission denied

You need to reclaim ownership of the .npm directory by typing this in the console, where xxx is the name at Macintosh HD/Users/xxx/ (where “xxx” is your folder’s name):

sudo chown -R xxx ~/.npm

… and need the write permission in node_modules directory by typing this in the console (where “xxx” is your folder’s name):

sudo chown -R xxx /usr/local/lib/node_modules

About Cordova Serve

We can also view the app in the browser with:

cordova serve android

I get this returned in the Terminal:

Static file server running on port 8000 (i.e. http://localhost:8000)
CTRL + C to shut down

I opened a browser and copied/pasted the above URL in and saw a screen of text. Android was underlined, so I clicked on that and the app startup screen appeared. I clicked on OK to get rid of the message info box (which pops up when the default screen is not showing in a mobile device). The message displayed was, “APACHE CORDOVA Connecting to Device.” That is correct behavior for the default Cordova app — the message won’t update because the desktop monitor is not a “device” to connect to.

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.

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

Update config.xml


You’ll notice that the apk name was not “myApp,” the name of our app To rectify that, open the myApp/config.xml page in a text editor. Change the <widget id= line to your reverse domain name or bundle identifier (Apple’s term), such as com.developerName.myApp. On the same line, put the correct version number, from 0.0.1 to 1.0.0, for instance.

Change <name>HelloCordova</name> to your app’s name: <name>myApp</name>.

Update the <description> and <author> information with your own.

Go ahead and replace the default Cordova resource files with your own. In other words, you can safely delete the /www/css, www/img, and /www/js folders. Replace the entire /www/ contents with your own HTML/CSS/JavaScript files and all other content files, like images and videos. (For this blog’s sake, I’m keeping the Cordova default app contents.)

In the <widget tag, add:




… with a space before and after the lines above.

Learn more about versioning at

The top of my config.xml page begins like:

<?xml version='1.0' encoding='utf-8'?>
<widget android-versioncode="1" id="com.[companyname].[appname]" version="1.0.0" versionName="1.0.0" xmlns="" xmlns:cdv="">

Replace [companyname] and [appname] with your own information.


<allow-intent href="http://*/*" launch-external="yes" />
<allow-intent href="https://*/*" launch-external="yes" />

If you are using telephone, external URL links, and other link formats, then you’ll want to add the following to make sure they work.

<access origin="tel:*" launch-external="yes"/>
<access origin="geo:*" launch-external="yes"/>
<access origin="mailto:*" launch-external="yes"/>
<access origin="sms:*" launch-external="yes"/>
<access origin="market:*" launch-external="yes"/>

Set the proper minimum and maximum API levels for your app:

These lines go above the </widget> line and between any existing <platform-name=”android”>…</platform> section:

<platform name="android">
<preference name="android-minSdkVersion" value="22" />
<preference name="android-targetSdkVersion" value="28" />

Resources for permissions:

Android permissions until recently have been handled at install-time instead of runtime. These permissions are required to be declared on an application that uses the permissions, and these permissions need to be added to the Android Manifest. This can be accomplished by using the config.xml to inject these permissions in the AndroidManifest.xml file. The example below uses the Contacts and Camera permissions, and the lines can be placed right after the <platform-name=”android”>…</platform> section:

<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.CAMERA" />

To learn how else you can modify this file, please read

When I did a cordova build android, the old name was still there. So I removed the android platform with the following code (WARNING: the entire /platforms/android folder and all its contents will be removed with this command, so if you have added any content like splashscreen images, you’ll want to copy them to another folder first, then do the following commands):

cordova platform rm android

… then added it again with:

cordova platform add android

… and the new name appeared when I did a cordova build android.

Add a Cordova API plugin

To implement Cordova features into your app, you’ll need to add the following to the head of the index.html page, as well as any page that uses Cordova APIs (application programming interface) such as InAppBrowser or SplashScreen:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: 'unsafe-eval'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src *">
< script type="text/javascript" src="cordova.js"></script>
< script>
// Wait for device API libraries to load 
document.addEventListener("deviceready", onDeviceReady, false); 
// device APIs are available 
function onDeviceReady() { }

(WordPress isn’t retaining my formatted script tags when it contains opening and closing angle brackets, but I was able to include them above by inserting a space after an opening bracket like this: < script. If you copy/paste the above, make sure you remove that space from two locations. Also make sure your double-quotes are not curly. If they are, highlight them and tap your quotes key for each.)

The cordova.js file will be added for you at build time; no need to add it manually.

If you have questions about the <meta http-equiv=”Content-Security-Policy” lines, please read these pages:

Note the reference to cordova.js. This line must point to the www/ folder. If the page is in www/chapters/here.html, then you would add ../ for each folder away from www/; so in this case the line would read:


Add the InAppBrowser Plugin


Cordova adds extra functionality via plugins. Each plugin has its own code and must be downloaded separately. As an example of this process, we’ll load the InAppBrowser (IAB) plugin to the app. InAppBrowser enables external links in our app to remain in the app, otherwise an external link will take the user out of the app and open a browser. Then the user would need to exit the browser and reopen the app. The IAB will instead open a webView window to display the page, and a Done button (in iOS at bottom left) or an X (in Android at upper right) will close the window and return one to the app. The core Cordova plugins are here:

1. To install the IAB, make sure the Terminal shows the starting point as myApp, then type:

cordova plugin add cordova-plugin-inappbrowser

You’ll see it installed in /myApp/plugins

To see all available installed plugins, type:

cordova plugin list

2. [Step dropped for Cordova CLI 5.0+.]

3. Now we follow the instructions to style our links so they open in the IAB. For instance:

<a href="#" ontouchend="'','_blank');"> IAB with location bar (showing URL)</a>

For email, do the normal:

<a href="">Email:</a>

4.  Open PhoneGap’s /myApp/www/index.html page and replace portions with the following lines in these inAppBrowser instructions:

I edited the default Cordova project’s index.html page with the above page, typed cordova build android to build the apk, moved myApp-debug.apk to Google Drive, and opened it in my device. The screen shows several buttons, each one showing a different way to implement IAB, and what happens if you don’t use it. IAB works. Mission accomplished. Now you need to add the deviceready code to the top of all pages where you have external links, and make sure the links conform to the IAB link format.

5. Once I got the debug app loaded on my device for testing, I tapped on a link and got the dreaded error popup: “Your app has stopped working.” The rest of the app worked and the external link did not. So I updated the InAppBrowser plugin, tested again, and it worked.

Add Your Icons


This free service works fine for generating all your icons from a single artwork: You simply drag a 512×512 png icon to the screen and it immediately makes icons. Then click on the Android button to see the icons grouped individually for each platform. Just right-click each icon and save to its proper place as icon.png (in Android, to the myApp/res/drawable folders). You might want to create a 36×36 icon for the ldpi folder, although Google does not seem to require it.

You may have noticed that the Cordova icon appears on your home screen on your test device. Let’s replace it with your own. First make your 512×512 icon design, then use the service above (or not) to make the multiple size versions.

[1. Open /platforms/android and copy the /res folder to your root folder, making /myApp/res.] Skip this step — this is no longer there. 

2. In config.xml just above the </widget> line, put:

<platform name="android"> 
 <icon src="res/drawable-ldpi/icon.png" density="ldpi" />
<icon src="res/drawable-mdpi/icon.png" density="mdpi" />
<icon src="res/drawable-hdpi/icon.png" density="hdpi" />
 <icon src="res/drawable-xhdpi/icon.png" density="xhdpi" />
 <icon src="res/drawable-xxhdpi/icon.png" density="xxhdpi" />
 <icon src="res/drawable-xxxhdpi/icon.png" density="xxxhdpi" />

Note that Cordova does not provide all the folders that Android requests. So create the /xxxhdpi folder as shown and fill them with the following sizes of icons.


/drawable-xxxdpi = icon.png, 192 x 192px (4x mdpi). No splash.

3. Replace all the above stock Cordova icons in /myApp/res/drawables with your own. (This page gives all the icon sizes:

4. In addition, delete all the folders in both /res locations that don’t apply to your app — that you aren’t providing icons for. I’m talking about the “land” and “port” folders. Leave the ic_action*.png images in the /platform/android/res/drawable* folders — they are for the InAppBrowser plugin icons.

The above config.xml icon.png entries is using only four folders. If you are going to use more than four folders, then they should be listed in the config.xml file in the same format.

[The reason I copy the /res folder to the root /myApp folder is to preserve the icons in case I need to remove the android platform and add it again. Removing the android platform (the cordova rm android command) means that the entire /platforms/android folder will be deleted, and all those icons and screens will be lost.] This is no longer necessary, since I don’t see any android/res folder.

6. Go ahead and test in your device with cordova build android. After you exit the app, look for the app icon among the others and make sure the correct icon is showing. If a Cordova brand icon is shown, then delete all the icon.png files in the /myApp/platforms/android/res/drawable folders and test again. If it still doesn’t work, then just copy the /drawable folders over to the /platforms/android/res folder.

Tip From time to time I get error messages in the console (don’t we all?). What I do is post the error information from the console into a dedicated text file along with my attempts that failed and the solution. I copy/paste the line into Google and search, then click through to see what solutions work for me. The file is saved to the desktop where it is always at hand, and in Google drive where I can access it among my other computers. When I come upon an error, I can do a search for the error in that file to see if I’ve had the problem (and solution!) before.

Recently, after doing cordova build android while following the steps on this page, I had the console error:

Error: ENOENT: no such file or directory, scandir '/Users/.../platforms/android/src/com/...'

Based on my online web searches, these approaches did not work:
.  npm cache clean
.  cordova prepare android
.  Created subfolders: /src/com/… [“Error: No Java files found which extend CordovaActivity.”]

These steps worked:

cordova platform rm android
cordova platform add android
cordova build android

Add Your Splash Screen

We add splashscreen functionality with a plugin. In Terminal, making sure it starts within your myApp folder, add the plugin with:

cordova plugin add cordova-plugin-splashscreen

(To remove a plugin in the future, type cordova plugin list and view the list of available plugins, then type cordova plugin rm and copy/paste the plugin line, like cordova plugin rm cordova-plugin-splashscreen then hit Enter.) You’ll find a list of plugins already installed in /myApp/plugins.

You can create the same size splash screens as the default Cordova screens and replace them, or make them as 9-patch images. Both ways are covered below.

I. Replace Cordova images

[Copy the /platforms/android/res/drawable* folders into your /myApp/res folder. Delete the /values and /xml folders from myApp/res only.] This is no longer necessary, since I don’t see any android/res folder.

Default Cordova Android splash screen sizes:
land-hdpi: 800×480
land-ldpi: 320×200
land-mdpi: 480×320
land-xdpi: 1280×720
port-hdpi: 480×800
port-ldpi: 200×320
port-mdpi: 320×480
port-xdpi: 720×1280

Here’s how I quickly made the above sizes to replace them. Make a 700x700px icon in Photoshop (can make vector artwork first, then paste it into Photoshop at 700x700px). Easily make the sizes with these steps, saving each as screen.png in their respective folders in /myApp/res:
1. Use Image > Canvas Size to enlarge to the 720×1280 and 1280×720 sizes, landscape and portrait.
2. Use Image > Canvas Size to bring back to 700x700px.
3. Image > Image Size to reduce to 300px.
4. Image > Canvas Size to create the next four sizes, 800×480, 480×800, 480×320, 320×480.
5. Image > Image Size to bring to 200x200px.
6. Image > Canvas Size to make the final sizes, 320×200, 200×320.

Copy the folders from /myApp/res to /platforms/android/res/. This replaces the default Cordova screens. Since you are copying these directly into /platforms/android/res/, you don’t need to update the config.xml file.

Continue with “Final Steps” below.

II. Make 9-patch Images

Create your splash screens as 9-patch png images. For instructions on how to do this, see my article here:

The size for each should be:
xxlarge (xxhdpi): 1152 x 1536px.
xlarge (xhdpi): at least 720 x 960 (Cordova used 720 x 1280)
large (hdpi): at least 480 x 640 (Cordova used 480 x 800)
medium (mdpi): at least 320 x 470 (Cordova used 320 x 480)
small (ldpi): at least 200 x 320 (Cordova used 200 x 320)

There is no splash screen for the xxxhdpi folder.

In the Icons section above, I had you copy/paste the /platforms/android/res folder to the root /myApp folder, which created a /myApp/res folder. Add all your splash images to the /myApp/res/drawables folders. Delete their splash images and add your own and name each one as splash.9.png.

Final Steps

[If you remove and add the Android platform (with cordova platform rm android and cordova platform add android), you can simply copy the folders within /myApp/res and paste them into the other /res folder, overwriting the same-named /drawable* folders while preserving the non-drawable folders that are needed (/values and /xml). Icon files are copied over automatically at build time; splash screen images are not! So you’ll need to copy the /drawable* folders over any time you change your splash images or remove and add the android platform.] Skip this step.

In /www/config.xml, include above the </widget> line put the following. This assumes you made your splash screens of the filename “splash.png.” if you made it “screen.png” then update the “splash” to “screen:”

<preference name="SplashScreen" value="splash" /><!-- prefix of splashscreen's splash.png name -->
<preference name="SplashScreenDelay" value="2000" /><!-- view for 2 seconds-->

(Note that with “org.apache.cordova.SplashScreen,” you should pay attention to case — it’s not all lowercase.)

Highlight and copy your myApp/res/drawable folders and paste them into /myApp/platforms/android/res/. You should check that you are replacing them when the alert pops up asking if you want to replace.

Go ahead and test in your device with cordova build android. Make sure the splash screen shows before your app does. Make sure your icons are correct.

What if you need to use different versions of pages for different platforms?

a) I needed the home page of my app to be different on Android and iOS. That’s what the myApp/merges folder is for. The myApp/merges/android folder is the same as your myApp/www folder, so I moved the index.html file to the merges/android folder. When I did a cordova platform add ios, it created a merges/ios folder. I copied the index.html file there and made the changes for the iOS version. So when I do a cordova build ios or android it will use the correct file for each build.

b) When styling links for YouTube in the InAppBrowser, onclick=”” works in iOS to open a YouTube link in IAB but not in Android (it didn’t work in my Nexus 7). So I put differnt versions of those pages in /merges/android and /merges/ios, each page with its own link style:


< a href="#" onclick="'', '_blank');">


< a href="">

The Android link did not appear in IAB, but that was fine – the user simply used the Back button to return to the app.

c) If you have a /www/css folder and want different style sheets for each app, just create a /css folder inside each merges platform folder (like myApp/merges/android/css/style.css) and put the css there instead of in the /myApp/www/css folder. That will style each platform differently according to your CSS files.

To quickly test this, create a /merges/android folder if you don’t have one and simply move the /www/index.html file there. Open the index.html file and add the following right after the button code we added earlier:

This index.html page is in the /platforms/merges folder.

Go ahead and test in your device with cordova build android. The above text should appear at the bottom of the screen.

About the myApp/Hooks Folder

If you open myApp/hooks, you’ll see a readme text file there. That folder is for adding scripts that will execute as part of your CLI operation. For instance, you can add a before_build script which will automatically add all your plugins before the actual build commences. So each time you create a new app, you’ll copy/paste that file into the new app’s /hooks/before_build folder. I’m not familiar enough with this process to explain it here, but if you already know node.js scripting, you might look into it. For instance, this page gives the hooks steps for automatically creating app icons (requires installation of Homebrew and ImageMagick):

Update Cordova

1. If you encounter issues with an individual plugin, by all means let your debugging include removing the plugin and adding it again. To do that, follow these steps:

a. In terminal: cordova plugin ls to see the plugins installed. Highlight the plugin you want to remove, and copy it.

b. In terminal: cordova plugin rm and paste in the copied plugin (like this: cordova plugin rm cordova-plugin-inappbrowser). Hit Enter.

c. To install again, in terminal: cordova plugin add and paste in the copied plugin (like this: cordova plugin add cordova-plugin-inappbrowser –save). Hit Enter.

Note that Cordova does not have a way to update plugins. If you know of an updated plugin, then you simply following the a, b, c steps above to install the new plugin version.

2. If you need to update Cordova, then do this way:

npm update -g cordova

3. To update a particular platform (perform this command one at a time for each platform):

cordova platform update android

More updating and reverting steps are here if you need them:

Delete DS_Store files

You won’t want to clutter your app with .DS_Store files. Open Terminal, start it at your app’s root folder, then type and run:

rm -f .DS_Store

Build your apk file for upload to an app store

For 2019: Google Play is pushing developers to create aab files. Read more about that here:

Prepare Copy and Other Graphic Assets for App Store

You’ll need this information on hand when filling out the form for apk submission within Google Play. Fulfill these steps (which will be easier to understand once you sign up as a developer, below, and can see the steps yourself):

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: 

My Steps to Update an App in the Google App Dashboard

Sign in to your site and click on app name in the app listing.

Release management > App releases
Production track: MANAGE link.
Click CREATE RELEASE button.
Drag aab file to BROWSE FILES box.
Fill out: What’s new in this release?

Store presence > Store listing
Update text for Full description.
Add new 512×512 High-res icon.
Add new screenshots.
Add your 1024×500 feature graphic.
If including a link to a YouTube video, add a Promo graphic, 120×80.
Add the URL to the YT video.
Fill in any other relevant fields that need to be updated.
Click SUBMIT UPDATE button.

Further Recommended Steps

If you are going to be involved with Apache Cordova regularly, keep up to date with the release announcements of upcoming versions, updated plugins, and other news.

Helpful links:

Official site:

Cordova news:

Online support:

9 thoughts on “Using Cordova CLI on Mac OS X to build Android apps

  1. Pingback: Using Android Studio Beta with Cordova PhoneGap | iPhone Dev Log

  2. Pingback: Using PhoneGap 3.0 CLI on Mac OS X to Build iOS and Android Projects | iPhone Dev Log

  3. Pingback: Submitting an Android App to Amazon | iPhone Dev Log

  4. I used this procedure with my own Android Cordova app. I followed the example using my own source. Everything went perfectly except my mp3 files would not play and no error was displayed, code was clean. The same program using the iOS instruction ran perfectly. Would you know why audio can be an issue. I am using HTML5 (audio tag), jQuery mobile and CSS.


  5. Pingback: How to use Grunt to automate repetitive tasks | iPhone Dev Log

  6. Pingback: Using Android Studio with Cordova projects | iPhone Dev Log

  7. Pingback: Come creare applicazioni per cellulare con PhoneGap

  8. Pingback: Workflow | iPhone Dev Log

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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