produceconsumerobot


 

 


 


 


 

Week 4:

Programming an Android Phone

Using your Android phone to test your apps instead of the emulator is easy. You just need to follow these simple steps to set up your phone - http://developer.android.com/guide/developing/device.html

PhoneGap API

The PhoneGap API is how you communicate with the device's native funtions.
The AppLaud PhoneGap plugin that we're currently using creates projects with v1.3.0 of PhoneGap, so we'll look at the corresponding API - http://docs.phonegap.com/en/1.3.0/index.html

If you want to upgrade/downgrade to a different version of PhoneGap, you can simply download a different version of PhoneGap and replace the phonegap.jar and phonegap-1.3.0.js with the version you want:

Changing PhoneGap Versions

*** And change in your html file(s) the name of the phonegap-x.x.x.js you're looking for


<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
                        

Events

The events API sets up a number of listeners that callback to specified functions when your device triggers those events.

One you're already familiar with is the "deviceready" event.


var onDeviceReady = function() {
    document.getElementById("devready").innerHTML = "OnDeviceReady fired.";
};

function init() {
    document.addEventListener("deviceready", onDeviceReady, true);
} 

This event is of special importance because it means that the PhoneGap API has loaded and now you're ready to start calling other PhoneGap functions.

All of these events are very useful for controlling how your app responds to button presses on your device. A particularly useful event on Android phones is the backbutton event. All you have to do to take control of the back button is copy and paste this code into your app:


document.addEventListener("backbutton", onBackKeyDown, false);

function onBackKeyDown() {
    // Handle the back button
    console.log("what does back mean in YOUR app?");
		// navigator.app.exitApp(); // This would cause the back button to exit your app.
}

Connection

The connection API lets you detect how the device is connected to the interweb.


var onDeviceReady = function() {
	checkConnection();
};
 
function checkConnection() {
    var networkState = navigator.network.connection.type;

		if (networkState == Connection.WIFI) {
    	alert("Yay, fast interweb!");
    } else {
    	alert("slo, bro");
    }
}

Be sure to call checkConnection() after "deviceready" has fired.

Notifications

Notifications present device notifications to the user.

Using notification.alert and notification.confirm is typically better than using the javascript alert/confirm because you can customize the buttons more and it delivers the message in a platform specific presentation.


function onBackKeyDown() {
    console.log("what does back mean in YOUR app?")
    showConfirm();
}

function onConfirm(button) {
    alert('You selected button ' + button);
    navigator.notification.beep(button);
}

function showConfirm() {
    navigator.notification.confirm(
        'You are the winner!',  // message
        onConfirm,              // callback to invoke with index of button pressed
        'Game Over',            // title
        'Restart,Exit,Scary'    // buttonLabels
    );
}

Note that notification.confirm allows you to use 3 response buttons.

Device

The device API lets you get information about the device running your app. This can be useful if there are quirks about particular devices that you need to account for or if there are differences, e.g. between iPhone and Android that require different code to run.


function logDeviceInfo() {
  console.log('Device Name: '     + device.name);
  console.log('Device PhoneGap: ' + device.phonegap);
  console.log('Device Platform: ' + device.platform);
  console.log('Device UUID: '     + device.uuid );
  console.log('Device Version: '  + device.version);
}

Accelerometer & Geolocation

Accelerometer and geolocation are asynchronous API calls that give you information from the respective sensors.

There are a couple of ways to get the acceleration. You can get it once by calling:


navigator.accelerometer.getCurrentAcceleration(accelerometerSuccess, accelerometerError);

which will call the respective callback functions when it get the data or an error.

Alternatively, you can "watch" the acceleration, which will return with acceleration data at "frequency" millisecond intervals until you clear the watchID (called accelWatchID below). Basically, PhoneGap is giving you a single function that incorporates both setInterval and getCurrentAcceleration.


var accelWatchID = null;

var accelerometerSuccess = function(acceleration) {
  var accelp = document.getElementById("accelerometerData");
  accelp.textContent = "x:" + acceleration.x + "\ny:" + acceleration.y + "\nz:" + acceleration.z; 
  
  var body = document.getElementsByTagName("body");

  if ((acceleration.x > 9) && (acceleration.y < 9)) {
    body[0].style.backgroundColor = "red";
  } else if ((acceleration.x < 9) && (acceleration.y > 9)){
    body[0].style.backgroundColor = "blue";
  } else {
    body[0].style.backgroundColor = "green";
  }
}

var accelerometerError = function(acceleration) {
  var accelp = document.getElementById("accelerometerData");
  accelp.textContent = "Accelerometer Error"; 
}
var onDeviceReady = function() {
  document.getElementById("devready").innerHTML = "OnDeviceReady fired.";
  
  var options = { frequency: 250 }; // Frequency of update callback in milliseconds
  navigator.accelerometer.watchAcceleration(accelerometerSuccess,
     accelerometerError, options);
};

Geolocation

Geolocation is quite similar, but has a few more options parameters. Also take note of position.coords.accuracy that is returned by the geolocation API. While position.coords.latitude and position.coords.longitude return with units in degrees and decimals accuracy is returned in meters.

You can use a google API like the following to convert from lat/long in degrees and decimals to meters:


<script type="text/javascript" 
	src="http://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=true">
</script>
var currlatlng = new google.maps.LatLng(currentLocation.lat, currentLocation.lon);
var targetlatlng = new google.maps.LatLng(targetLocation.lat, targetLocation.lon);
var distance = google.maps.geometry.spherical.computeDistanceBetween(currlatlng, targetlatlng);

Camera

Using the PhoneGap camera API is quite simple and pretty straighforward from the PhoneGap Campera API - http://docs.phonegap.com/en/1.3.0/phonegap_camera_camera.md.html#Camera

You can similarly use the PhoneGap capture.captureImage API - http://docs.phonegap.com/en/1.3.0/phonegap_media_capture_capture.md.html#capture.captureImage

These two methods are practically very similar, but the captureImage function gives you a little more flexibility to specify multiple images coming back from your phone's default camera application via the "limit" parameter.

Note, however that there are some "quirks" about the captureImage function that PhoneGap is still working out.

** Always be sure to look at the "quirks" section for any PhoneGap API function you're thinking about implementing.

Audio

There are two ways to capture audio in PhoneGap. You can use the capture.captureAudio API - http://docs.phonegap.com/en/1.3.0/phonegap_media_capture_capture.md.html#capture.captureAudio

Similar to captureImage, this calls the default audio capture app on your device and returns a MediaFile object with information about your captured file (including name, path, etc.)

You can also use the Media API - http://docs.phonegap.com/en/1.3.0/phonegap_media_media.md.html#Media

The advantage of the media API is that the recording is taking place in your app. So as you're recording the file you can track how long the file is, stop the recording programatically, and style the record and stop buttons however you wish.

This drawback is that it requires you to keep track of extra variables and functions to properly manage recording the audio.

To familiarize you with both the captureAudio and Media APIs, lets take the following example that records an audio file to your phone with captureAudio and then plays it back with media.play().


<!DOCTYPE html>
<html>
<head>
  <title>Capture Audio</title>
  <script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
  <script type="text/javascript" charset="utf-8">
  var audioSrc = "http://produceconsumerobot.com/temp/lovid/content/1_voiceover.mp3";
  var mediaObj = null;
  
  // capture callback
  var captureSuccess = function(mediaFiles) {
    var i, path, len;
    for (i = 0, len = mediaFiles.length; i < len; i += 1) {
      //audioSrc = mediaFiles[i].fullPath;
      audioSrc = mediaFiles[i].name; // media.play looks in the default SDCARD directory so we don't need the full path
    }
  };
  
  // capture error callback
  var captureError = function(error) {
    navigator.notification.alert('Error code: ' + error.code, null, 'Capture Error');
  };
  var captureAudio = function () {
    // start audio capture
    navigator.device.capture.captureAudio(captureSuccess, captureError, {limit:1});
  }
  
  var playAudio = function () {
    console.log("playAudio();");
    console.log("audioSrc");
    if (audioSrc) {
      console.log(audioSrc);
      var mediaObj = new Media(audioSrc, mediaSuccess, mediaError);
      if (mediaObj) {
        mediaObj.play();
      } else {
        console.error("mediaObj is empty");
      }
    } else {
      navigator.notification.alert("No audio file found");
    }
  }
  
  // onSuccess Callback
  function mediaSuccess() {
    console.log("playAudio():Audio Success");
  }
  
  // onError Callback
  //
  function mediaError(error) {
    alert('code: '    + error.code    + '\n' + 
    'message: ' + error.message + '\n');
  }
  </script>
</head>
<body>
  <button onclick="captureAudio();">Capture Audio</button> <br>
  <button onclick="playAudio();">Play Audio</button><br/>
</body>
</html>

Video

Currently the PhoneGap API only supports video recording via external app calls using the captureVideo API - http://docs.phonegap.com/en/1.3.0/phonegap_media_capture_capture.md.html#capture.captureVideo

And does not support video playback, so for that you have to look into plugins - https://github.com/phonegap/phonegap-plugins/tree/master/Android/VideoPlayer

Presumably the reason that PhoneGap has a "Media" API rather than an "Audio" API is that they hope to incorporate this more difficult process in future versions of PhoneGap... so stay tuned!

But, until that time, you can look into plugins to serve these needs - https://github.com/phonegap/phonegap-plugins

 
produceconsumerobot