Adding Cordova APIs to Android via CLI: Accelerometer and Camera


In this beginner’s article, we’ll see what’s involved in adding the Cordova APIs to an PhoneGap Android project. It was written to help get your feet wet in case you’ve never tried it. An API (application programming interface) will allow us to use the features of the smartphone, such as accelerometer, camera, com
pass, and other features. In the case of Cordova’s PhoneGap, this APIs come in the form of plugins. They need to be added to the project on an as-needed basis.

If you’ve never built a PhoneGap project before, it’s better to follow the steps in https://iphonedevlog.wordpress.com/2013/08/16/using-phonegap-3-0-cli-on-mac-osx-10-to-build-ios-and-android-projects/ first so you’ll already have all program files need to create any Android project.

The Cordova APIs are found at phonegap.com under Developer > Docs. Scroll down to the API Reference section for the clickable list. We will open those links and copy/paste the code into our document. As usual, I’ll note every click needed to make the project.

Set Up the Android Project

1. Click on the Terminal icon in the dock to get it running.
2. Type “cd” without the quotes, a space, then drag your containing folder (into which we’ll put a new project folder) from the Finder window to the Terminal screen, and hit Enter. This orients the Terminal to your new folder.
3. In Terminal, type the following command to get the basic Cordova/PhoneGap files set up. I am going to think outside the box and cleverly call the project CordovaAPI:

cordova create CordovaAPI com.stevehusting.CordovaAPI CordovaAPI

(Notice that I am starting my commands with cordova and not phonegap. You may have installed phonegap instead, and if so, you should start all your commands with phonegap. This project will not be used for PhoneGap Build, so I use cordova in my commands.)

5. Type the following to see what Cordova version you have. Mine said 3.3.0-0.1.1:

cordova -v

6. We need to change directories to the project’s folder in Terminal so follow instructions in step 3 but drag the TestApp folder over. If you don’t do this, you’ll get the message: “Error: Current working directory is not a Cordova-based project” when trying to do a cordova command.

7. Create the platform files for the project, in our case, Android:

cordova platform add android

I received an error: “Error: An error occured during creation of android sub-project.
Error: ERROR : executing command ‘ant’, make sure you have ant installed and added to your path.” I resolved this error. Scroll down to note in the comments for this step.

8. Verify the platform was installed:

cordova platform list

9. Open /TestApp/www/index.html in a text editor (I use TextWrangler). You might want to save a copy of it an put it somewhere.
10. Copy and paste the below content in place of the current contents:

<!-- ********************* HMTL5 Skeleton begin *********************** --> 
<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8" /> 
<meta name="format-detection" content="telephone=no" /> 
<!-- WARNING from Cordova: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 --> 
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" /> 
<title>Cordova APIs</title>

<style type="text/css">
.buttonClass {
border-radius:8px; background-color:#fff;
border:#878787 solid 1px; padding:0 1em;margin:.5em;
height: 3em; width: 46%;
font-family: "Helvetica"; color: #000; font-size:1em; text-align:center;
-webkit-appearance:none;
}
.segment {
display:block; border-radius:8px; background-color:#eee;
border:#878787 solid 1px; padding:1em; margin:.5em;
font-family: "Helvetica"; color: #000; font-size:1.3em; text-align:left;
-webkit-appearance:none;
}
@media screen and (max-width:700px) {
.buttonClass { width: 100%;}
}
</style>
 <script type="text/javascript" src="cordova.js"></script> 
</head> 
<body>
</body> 
</html> 
<!-- ********************* HMTL5 Skeleton end *********************** -->

Now we’re starting from the same code.

Accelerometer

The accelerometer captures the motion along the x, y, and z axis. We’ll follow this page from the docs to set it up: http://docs.phonegap.com/en/3.3.0/cordova_accelerometer_accelerometer.md.html#Accelerometer
Please review the page to gain an understanding of the steps we’ll be following.

1. Download the plugin in terminal:

cordova plugin add org.apache.cordova.device-motion

2. Make sure it’s downloaded:

cordova plugin ls

3. Open CordovaAPI/platforms/android/res/xml/config.xml in a text file and add the following to just above </widget> and save:

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

4. In index.html, remove everything between the <body></body> tags and replace with the following. We will be updating the x, y, and z coordinates every 3 seconds:

<!-- ********************* Accelerometer begin *********************** -->
<div class="segment"><h2>Accelerometer</h2>
<p id="accelerometer">Waiting for accelerometer...</p>
<input type="button" class="buttonClass" onclick="stopWatch();" value="Stop Watching">
<input type="button" class="buttonClass" onclick='window.location="https://iphonedevlog.wordpress.com/2014/01/31/adding-cordova-apis-to-android-via-cli-accelerometer-and-camera/"' value="View Code On iPhoneDevLog">
</div>
<script type="text/javascript" charset="utf-8">
// The watch id references the current `watchAcceleration`
 var watchID = null;

// Wait for device API libraries to load
 document.addEventListener("deviceready", onDeviceReady, false);

// device APIs are available
 function onDeviceReady() {
 startWatch();
 }

// Start watching the acceleration, update every 3 seconds
 function startWatch() {
 var options = { frequency: 3000 };
watchID = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
 }

// Stop watching the acceleration
 function stopWatch() {
 if (watchID) {
 navigator.accelerometer.clearWatch(watchID);
 watchID = null;
 }
 }

// onSuccess: Get a snapshot of the current acceleration
 //
 function onSuccess(acceleration) {
 var element = document.getElementById('accelerometer');
 element.innerHTML = 'Acceleration X: ' + acceleration.x + '<br />' +
 'Acceleration Y: ' + acceleration.y + '<br />' +
 'Acceleration Z: ' + acceleration.z + '<br />' +
 'Timestamp: ' + acceleration.timestamp + '<br />';
 }

// onError: Failed to get the acceleration
 function onError() {
 alert('onError!');
 }
</script> 
<!-- ********************* Accelerometer end *********************** -->

6. In terminal, prepare the files:

cordova prepare android

7. Create the apk file:

cordova compile android

8. Navigate to /platforms/android/bin and copy the CordovaAPI-debug.apk file to your device to test. (I copy it to DropBox on my computer and retrieve it from the DropBox app on my device.)

9. With the device in hand and the app running, hold it parallel to the floor. The numbers change every 3 seconds.

Notice the Y number, then lift the top end so the device is perpendicular to the floor and see the number dramatically change. Mine went from 0.1 to 9.9.

Move it back to flat and notice the X number. Now turn the right edge up and watch the number change. Mine went from 0.1 to 9.8.

Move it back flat and notice the Z number, a positive number. Flip the device upside down over your head and it goes negative.

accelerometer

Camera

[Frankly, the following project isn’t very practical; it’s just an introduction. Some time later I did a more advanced, but practical, camera application. You can see it here: https://iphonedevlog.wordpress.com/2014/03/24/adding-cordova-apis-to-android-via-cli-camera-and-file-apis-shoot-picture-and-upload-to-server-folder-with-php/]

The camera API opens the device’s default camera application that allows users to snap pictures. Once the user snaps the photo, the camera application closes and the application is restored. Another script allows one to open the photo gallery and choose the captured image and display it onscreen in the app.

We’ll follow this page from the docs to set it up: http://docs.phonegap.com/en/3.3.0/cordova_camera_camera.md.html#Camera

According to this page, it works in Android versions before KitKat (4.4). Please review the page to gain an understanding of the steps we’ll be following.

1. Download the plugin in terminal:

cordova plugin add org.apache.cordova.camera

2. Make sure it’s downloaded:

cordova plugin ls

3. Open CordovaAPI/platforms/android/res/xml/config.xml in a text file and add the following to just above </widget> and save:

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

4. Open platforms/android/AndroidManifest.xml with a text editor and enter the following among the other “<uses-permission” entries:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

5. Copy the following into your index.html file right above the </body> tag:

<!-- ********************* Camera begin *********************** --> 
<div class="segment"><h2>Camera</h2>
 <p><em>Shoot photo with camera and display as thumbnail on this page.</em></p>

 <input type="button" class="buttonClass" onclick="capturePhotoEdit();" value="Capture Photo"> <br><input type="button" class="buttonClass" onclick="removeImages();" value="Remove thumbnail"><br> 
 <img style="display:none;width:60px;height:60px;" id="smallImage" src="">
 <p id="smTitle"></p>
 <p><em>Display the captured photo from gallery on this page:</em></p>
 <input type="button" class="buttonClass" value="Browse Gallery" onclick="getPhoto(pictureSource.PHOTOLIBRARY);"><br>
 <input type="button" class="buttonClass" onclick="removeLargeImage();" value="Remove below image"><br> 
 <img style="display:none;" id="largeImage" src="">

<p>&nbsp;</p>
<input type="button" class="buttonClass" onclick='window.location="https://iphonedevlog.wordpress.com/2014/01/31/adding-cordova-apis-to-android-via-cli-accelerometer-and-camera/"' value="View Code On iPhoneDevLog">
</div>

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

 var pictureSource; // picture source
 var destinationType; // sets the format of returned value

 // Wait for device API libraries to load
 document.addEventListener("deviceready",onDeviceReady,false);

 // device APIs are available
 function onDeviceReady() {
 pictureSource=navigator.camera.PictureSourceType;
 destinationType=navigator.camera.DestinationType;
 }

// ---------------- CAMERA

// STEP 2. Show thumbnail
 function onPhotoFileSuccess(imageData) {
 var note = document.getElementById('smTitle');
 note.innerHTML = "Image location:<br>" + JSON.stringify(imageData); // put name of file onscreen
 var smallImage = document.getElementById('smallImage');
 smallImage.style.display = 'block';
 smallImage.src = imageData; // Show thumbnail
 }

// STEP 1. Capture photo.
 function capturePhotoEdit() {
 navigator.camera.getPicture(onPhotoFileSuccess, onFail, { quality: 90, destinationType: Camera.DestinationType.FILE_URI,
 sourceType : Camera.PictureSourceType.CAMERA, 
 allowEdit : true,
 encodingType: Camera.EncodingType.JPEG,
 // targetWidth: 200, // capture it at this size
 // targetHeight: 200, // capture it at this size
 popoverOptions: CameraPopoverOptions,
 saveToPhotoAlbum: true // saves photo to internal memory, viewed in Gallery
 });
 }
 
// ---------------- PHOTO GALLERY

 // STEP b. Called when a photo is successfully retrieved - gallery
 function onPhotoURISuccess(imageURI) {
 // Get image handle
 var largeImage = document.getElementById('largeImage');
 // Unhide image elements
 largeImage.style.display = 'block';
 // Show the captured photo
 largeImage.src = imageURI;
 navigator.camera.cleanup( cameraSuccess, cameraError );
 }

 // STEP a. A button will call this function
 function getPhoto(source) {
 // Retrieve image file location from specified source
 navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 50,
 destinationType: destinationType.FILE_URI,
 sourceType: source });
 }
 
// ---------------- REMOVE IMAGES

 function removeImages() {
 var smallImage = document.getElementById('smallImage');
 smallImage.style.display = 'none';
 smallImage = null;
 }
 
 function removeLargeImage() {
 var largeImage = document.getElementById('largeImage');
 largeImage.style.display = 'none';
 largeImage = null;
 }

 // Called if something bad happens.
 function onFail(message) {
 alert('Response: ' + message);
 }
 </script>

<!-- ********************* Camera end *********************** -->

6. In Terminal, prepare the file:

cordova prepare android

7. Create the apk file:

cordova compile android

8. Navigate to /platforms/android/bin and copy the CordovaAPI-debug.apk and put the into your device to test.

9. With the device in hand and the app running, tap on Capture Photo and the camera app opens. Take the photo and tap done. See its thumbnail and file location in the device appear.

Click on Browse Gallery. I choose a photo. It appears in the app.

Exporting the captured images

What is curious is that I can see the image thumbnails in the gallery, but when I hook up the device to my PC, those images captured in the app show a zero byte count and are blank when opened. Fortunately, I found a way to export them.

1. I downloaded the Nexus Media Importer software to my Nexus 7 (free).

2. I plugged a USB thumbdrive into the USB end of my USB OTG cable and the other end into the Nexus 7.

3. The software recognized the cable. I selected the Export option (you can use this OTG cable to import files to the device), chose the images, and they were copied to the thumb drive.

4. I opened the images from the thumb drive on the PC and they were perfect.

Screenshot: Camera API

8 thoughts on “Adding Cordova APIs to Android via CLI: Accelerometer and Camera

  1. Errors: Accelerometer
    In “Set Up the Android Project” step 7, the error message indicated that the ant download was not included in OS X Mavericks (to which I had recently upgraded), so I needed to add it:

    A query on phonegap’s Google groups helped with this:
    a. I visited http://ant.apache.org/bindownload.cgi and selected the apache-ant-1.9.3-bin.tar.bz2 archive to download it.
    b. In /Downloads, I copied /apache-ant-1.9.3 and pasted it into /Developer/adt-bundle-mac-x86.
    c. I opened the hidden file .bash_profile in a text editor and added these two lines:
    export ANT_HOME=~/Developer/adt-bundle-mac-x86/apache-ant-1.9.3
    export PATH=$PATH:$ANT_HOME/bin
    f. I saved and closed the document, quit Terminal and reopened it and tested to see if ant was recognized:
    ant – version
    A long list of what’s possible showed success!

    7. I changed directories to the CordovaAPI folder and again entered:
    cordova platform add android

    I received another error notice:
    Error: Please install Android target 19 (the Android newest SDK). Make sure you have the latest Android tools installed as well. Run “android” from your command-line to install/update any missing SDKs or tools.

    A search on Google gave me several things to try:
    a. I checked that I had target 19 installed in Eclipse: Open Eclipse (I’m using ADT – Android Development Tools, which includes Eclipse) > Window > Android SDK Manager. It shows that I have API 19 installed.
    b. I checked the latest Android tools: the top of the SDK Manager (seen in step a) showed that several Android Build-tools were not installed. I selected them all and hit Install and accepted the license agreement for installation.
    c. Also did: Help > Check for Updates. A note indicated that it was “Unable to read repository at http://download.eclipse.org/releases/juno.” It also could not read a repository .jar on my hard drive either.
    d. I tried to reload step c through Eclipse > Preferences > Install/Update > Available Software Sites > Reload, but without success.
    e. I changed directories to the /adt-bundle-mac-x86/sdk/tools directory in terminal, then typed:
    android
    Files began downloading, then opened Eclipse and brought up the SDK dialog and waited for me to install and accept the license for 10 packages. Made sure everything for version 19 was selected, and install them.
    f. Still in the /adt-bundle-mac-x86/sdk/tools directory in terminal, I ran the follow and confirmed that version 19 was recognized:
    android list target

    These steps finally allowed “cordova platform add android” to work.

  2. D:\Test_Project\>cordova plugin add org.apache.cordova.splashs
    creen
    Current working directory is not a Cordova-based project.

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

Leave a comment

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