+ Watch Accelerometer
+ Get Location
+ Call 411
+ Beep
+ Vibrate
+
+
+
\ No newline at end of file
diff --git a/assets/master.css b/assets/master.css
new file mode 100644
index 00000000..1d1bea20
--- /dev/null
+++ b/assets/master.css
@@ -0,0 +1,95 @@
+ body {
+ background:#222 none repeat scroll 0 0;
+ color:#666;
+ font-family:Helvetica;
+ font-size:72%;
+ line-height:1.5em;
+ margin:0;
+ border-top:1px solid #393939;
+ }
+
+ #info{
+ background:#ffa;
+ border: 1px solid #ffd324;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ clear:both;
+ margin:15px 6px 0;
+ width:295px;
+ padding:4px 0px 2px 10px;
+ }
+
+ #info > h4{
+ font-size:.95em;
+ margin:5px 0;
+ }
+
+ #stage.theme{
+ padding-top:3px;
+ }
+
+ /* Definition List */
+ #stage.theme > dl{
+ padding-top:10px;
+ clear:both;
+ margin:0;
+ list-style-type:none;
+ padding-left:10px;
+ overflow:auto;
+ }
+
+ #stage.theme > dl > dt{
+ font-weight:bold;
+ float:left;
+ margin-left:5px;
+ }
+
+ #stage.theme > dl > dd{
+ width:45px;
+ float:left;
+ color:#a87;
+ font-weight:bold;
+ }
+
+ /* Content Styling */
+ #stage.theme > h1, #stage.theme > h2, #stage.theme > p{
+ margin:1em 0 .5em 13px;
+ }
+
+ #stage.theme > h1{
+ color:#eee;
+ font-size:1.6em;
+ text-align:center;
+ margin:0;
+ margin-top:15px;
+ padding:0;
+ }
+
+ #stage.theme > h2{
+ clear:both;
+ margin:0;
+ padding:3px;
+ font-size:1em;
+ text-align:center;
+ }
+
+ /* Stage Buttons */
+ #stage.theme a.btn{
+ border: 1px solid #555;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ text-align:center;
+ display:block;
+ float:left;
+ background:#444;
+ width:150px;
+ color:#9ab;
+ font-size:1.1em;
+ text-decoration:none;
+ padding:1.2em 0;
+ margin:3px 0px 3px 5px;
+ }
+ #stage.theme a.btn.large{
+ width:308px;
+ padding:1.2em 0;
+ }
diff --git a/assets/phonegap.js b/assets/phonegap.js
new file mode 100644
index 00000000..493e61b8
--- /dev/null
+++ b/assets/phonegap.js
@@ -0,0 +1,604 @@
+
+ /**
+ * This class contains acceleration information
+ * @constructor
+ * @param {Number} x The force applied by the device in the x-axis.
+ * @param {Number} y The force applied by the device in the y-axis.
+ * @param {Number} z The force applied by the device in the z-axis.
+ */
+ function Acceleration(x, y, z) {
+ /**
+ * The force applied by the device in the x-axis.
+ */
+ this.x = x;
+ /**
+ * The force applied by the device in the y-axis.
+ */
+ this.y = y;
+ /**
+ * The force applied by the device in the z-axis.
+ */
+ this.z = z;
+ /**
+ * The time that the acceleration was obtained.
+ */
+ this.timestamp = new Date().getTime();
+ }
+
+ /**
+ * This class specifies the options for requesting acceleration data.
+ * @constructor
+ */
+ function AccelerationOptions() {
+ /**
+ * The timeout after which if acceleration data cannot be obtained the errorCallback
+ * is called.
+ */
+ this.timeout = 10000;
+ }
+
+
+ /**
+ * This class provides access to device accelerometer data.
+ * @constructor
+ */
+ function Accelerometer() {
+ /**
+ * The last known acceleration.
+ */
+ this.lastAcceleration = null;
+ }
+
+ /**
+ * Asynchronously aquires the current acceleration.
+ * @param {Function} successCallback The function to call when the acceleration
+ * data is available
+ * @param {Function} errorCallback The function to call when there is an error
+ * getting the acceleration data.
+ * @param {AccelerationOptions} options The options for getting the accelerometer data
+ * such as timeout.
+ */
+ Accelerometer.prototype.getCurrentAcceleration = function(successCallback, errorCallback, options) {
+ // If the acceleration is available then call success
+ // If the acceleration is not available then call error
+
+ // Created for iPhone, Iphone passes back _accel obj litteral
+ if (typeof successCallback == "function") {
+ var accel = new Acceleration(_accel.x,_accel.y,_accel.z);
+ Accelerometer.lastAcceleration = accel;
+ successCallback(accel);
+ }
+ }
+
+ /**
+ * Asynchronously aquires the acceleration repeatedly at a given interval.
+ * @param {Function} successCallback The function to call each time the acceleration
+ * data is available
+ * @param {Function} errorCallback The function to call when there is an error
+ * getting the acceleration data.
+ * @param {AccelerationOptions} options The options for getting the accelerometer data
+ * such as timeout.
+ */
+
+ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) {
+ this.getCurrentAcceleration(successCallback, errorCallback, options);
+ // TODO: add the interval id to a list so we can clear all watches
+ var frequency = (options != undefined)? options.frequency : 10000;
+ return setInterval(function() {
+ navigator.accelerometer.getCurrentAcceleration(successCallback, errorCallback, options);
+ }, frequency);
+ }
+
+ /**
+ * Clears the specified accelerometer watch.
+ * @param {String} watchId The ID of the watch returned from #watchAcceleration.
+ */
+ Accelerometer.prototype.clearWatch = function(watchId) {
+ clearInterval(watchId);
+ }
+
+ if (typeof navigator.accelerometer == "undefined") navigator.accelerometer = new Accelerometer();
+
+
+
+ /**
+ * This class provides access to the device media, interfaces to both sound and video
+ * @constructor
+ */
+ function Media(src) {
+ this.src = src;
+ }
+
+ Media.prototype.play = function() {
+ }
+
+ Media.prototype.pause = function() {
+ }
+
+ Media.prototype.stop = function() {
+ }
+
+
+ /**
+ * This class contains information about any Media errors.
+ * @constructor
+ */
+ function MediaError() {
+ this.code = null,
+ this.message = "";
+ }
+
+ MediaError.MEDIA_ERR_ABORTED = 1;
+ MediaError.MEDIA_ERR_NETWORK = 2;
+ MediaError.MEDIA_ERR_DECODE = 3;
+ MediaError.MEDIA_ERR_NONE_SUPPORTED = 4;
+
+
+ //if (typeof navigator.audio == "undefined") navigator.audio = new Media(src);
+
+
+ /**
+ * This class provides access to the device camera.
+ * @constructor
+ */
+ function Camera() {
+
+ }
+
+ /**
+ *
+ * @param {Function} successCallback
+ * @param {Function} errorCallback
+ * @param {Object} options
+ */
+ Camera.prototype.getPicture = function(successCallback, errorCallback, options) {
+
+ }
+
+ if (typeof navigator.camera == "undefined") navigator.camera = new Camera();
+
+
+ /**
+ * This class provides access to the device contacts.
+ * @constructor
+ */
+ function Contact() {
+ this.name = "";
+ this.phone = "";
+ this.address = "";
+ }
+
+ /**
+ *
+ * @param {Object} successCallback
+ * @param {Object} errorCallback
+ * @param {Object} options
+ */
+ Contact.prototype.get = function(successCallback, errorCallback, options) {
+
+ }
+
+
+ function ContactManager() {
+ // Dummy object to hold array of contacts
+ this.contacts = [];
+ this.timestap = new Date().getTime();
+ }
+
+ ContactManager.prototype.get = function(successCallback, errorCallback, options) {
+ // Interface
+ }
+
+ if (typeof navigator.ContactManager == "undefined") navigator.ContactManager = new ContactManager();
+
+
+ /**
+ * This class provides generic read and write access to the mobile device file system.
+ */
+ function File() {
+ /**
+ * The data of a file.
+ */
+ this.data = "";
+ /**
+ * The name of the file.
+ */
+ this.name = "";
+ }
+
+ /**
+ * Reads a file from the mobile device. This function is asyncronous.
+ * @param {String} fileName The name (including the path) to the file on the mobile device.
+ * The file name will likely be device dependant.
+ * @param {Function} successCallback The function to call when the file is successfully read.
+ * @param {Function} errorCallback The function to call when there is an error reading the file from the device.
+ */
+ File.prototype.read = function(fileName, successCallback, errorCallback) {
+
+ }
+
+ /**
+ * Writes a file to the mobile device.
+ * @param {File} file The file to write to the device.
+ */
+ File.prototype.write = function(file) {
+
+ }
+
+ if (typeof navigator.file == "undefined") navigator.file = new File();
+
+
+ /**
+ * This class provides access to device GPS data.
+ * @constructor
+ */
+ function Geolocation() {
+ /**
+ * The last known GPS position.
+ */
+ this.lastPosition = null;
+ }
+
+ /**
+ * Asynchronously aquires the current position.
+ * @param {Function} successCallback The function to call when the position
+ * data is available
+ * @param {Function} errorCallback The function to call when there is an error
+ * getting the position data.
+ * @param {PositionOptions} options The options for getting the position data
+ * such as timeout.
+ */
+ Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) {
+ // If the position is available then call success
+ // If the position is not available then call error
+ }
+
+ /**
+ * Asynchronously aquires the position repeatedly at a given interval.
+ * @param {Function} successCallback The function to call each time the position
+ * data is available
+ * @param {Function} errorCallback The function to call when there is an error
+ * getting the position data.
+ * @param {PositionOptions} options The options for getting the position data
+ * such as timeout and the frequency of the watch.
+ */
+ Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) {
+ // Invoke the appropriate callback with a new Position object every time the implementation
+ // determines that the position of the hosting device has changed.
+
+ this.getCurrentPosition(successCallback, errorCallback, options);
+ var frequency = (options != undefined)? options.frequency : 10000;
+
+ var that = this;
+ return setInterval(function() {
+ that.getCurrentPosition(successCallback, errorCallback, options);
+ //navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options);
+ }, frequency);
+ }
+
+
+ /**
+ * Clears the specified position watch.
+ * @param {String} watchId The ID of the watch returned from #watchPosition.
+ */
+ Geolocation.prototype.clearWatch = function(watchId) {
+ clearInterval(watchId);
+ }
+
+ if (typeof navigator.geolocation == "undefined") navigator.geolocation = new Geolocation();
+
+
+ /**
+ * This class provides access to native mapping applications on the device.
+ */
+ function Map() {
+
+ }
+
+ /**
+ * Shows a native map on the device with pins at the given positions.
+ * @param {Array} positions
+ */
+ Map.prototype.show = function(positions) {
+
+ }
+
+ if (typeof navigator.map == "undefined") navigator.map = new Map();
+
+
+ /**
+ * This class provides access to notifications on the device.
+ */
+ function Notification() {
+
+ }
+
+ /**
+ * Causes the device to blink a status LED.
+ * @param {Integer} count The number of blinks.
+ * @param {String} colour The colour of the light.
+ */
+ Notification.prototype.blink = function(count, colour) {
+
+ }
+
+ /**
+ * Causes the device to vibrate.
+ * @param {Integer} mills The number of milliseconds to vibrate for.
+ */
+ Notification.prototype.vibrate = function(mills) {
+
+ }
+
+ /**
+ * Causes the device to beep.
+ * @param {Integer} count The number of beeps.
+ * @param {Integer} volume The volume of the beep.
+ */
+ Notification.prototype.beep = function(count, volume) {
+
+ }
+
+ // TODO: of course on Blackberry and Android there notifications in the UI as well
+
+ if (typeof navigator.notification == "undefined") navigator.notification = new Notification();
+
+
+ /**
+ * This class provides access to the device orientation.
+ * @constructor
+ */
+ function Orientation() {
+ /**
+ * The last known orientation.
+ */
+ this.lastOrientation = null;
+ }
+
+ /**
+ * Asynchronously aquires the current orientation.
+ * @param {Function} successCallback The function to call when the orientation
+ * is known.
+ * @param {Function} errorCallback The function to call when there is an error
+ * getting the orientation.
+ */
+ Orientation.prototype.getCurrentOrientation = function(successCallback, errorCallback) {
+ // If the position is available then call success
+ // If the position is not available then call error
+ }
+
+ /**
+ * Asynchronously aquires the orientation repeatedly at a given interval.
+ * @param {Function} successCallback The function to call each time the orientation
+ * data is available.
+ * @param {Function} errorCallback The function to call when there is an error
+ * getting the orientation data.
+ */
+ Orientation.prototype.watchOrientation = function(successCallback, errorCallback) {
+ // Invoke the appropriate callback with a new Position object every time the implementation
+ // determines that the position of the hosting device has changed.
+ this.getCurrentPosition(successCallback, errorCallback);
+ return setInterval(function() {
+ navigator.orientation.getCurrentOrientation(successCallback, errorCallback);
+ }, 10000);
+ }
+
+ /**
+ * Clears the specified orientation watch.
+ * @param {String} watchId The ID of the watch returned from #watchOrientation.
+ */
+ Orientation.prototype.clearWatch = function(watchId) {
+ clearInterval(watchId);
+ }
+
+ if (typeof navigator.orientation == "undefined") navigator.orientation = new Orientation();
+
+
+ /**
+ * This class contains position information.
+ * @param {Object} lat
+ * @param {Object} lng
+ * @param {Object} acc
+ * @param {Object} alt
+ * @param {Object} altacc
+ * @param {Object} head
+ * @param {Object} vel
+ * @constructor
+ */
+ function Position(lat, lng, acc, alt, altacc, head, vel) {
+ /**
+ * The latitude of the position.
+ */
+ this.latitude = lat;
+ /**
+ * The longitude of the position,
+ */
+ this.longitude = lng;
+ /**
+ * The accuracy of the position.
+ */
+ this.accuracy = acc;
+ /**
+ * The altitude of the position.
+ */
+ this.altitude = alt;
+ /**
+ * The altitude accuracy of the position.
+ */
+ this.altitudeAccuracy = altacc;
+ /**
+ * The direction the device is moving at the position.
+ */
+ this.heading = head;
+ /**
+ * The velocity with which the device is moving at the position.
+ */
+ this.velocity = vel;
+ /**
+ * The time that the position was obtained.
+ */
+ this.timestamp = new Date().getTime();
+ }
+
+ /**
+ * This class specifies the options for requesting position data.
+ * @constructor
+ */
+ function PositionOptions() {
+ /**
+ * Specifies the desired position accuracy.
+ */
+ this.enableHighAccuracy = true;
+ /**
+ * The timeout after which if position data cannot be obtained the errorCallback
+ * is called.
+ */
+ this.timeout = 10000;
+ }
+
+ /**
+ * This class contains information about any GSP errors.
+ * @constructor
+ */
+ function PositionError() {
+ this.code = null;
+ this.message = "";
+ }
+
+ PositionError.UNKNOWN_ERROR = 0;
+ PositionError.PERMISSION_DENIED = 1;
+ PositionError.POSITION_UNAVAILABLE = 2;
+ PositionError.TIMEOUT = 3;
+
+
+
+ /**
+ * This class provides access to the device SMS functionality.
+ * @constructor
+ */
+ function Sms() {
+
+ }
+
+ /**
+ * Sends an SMS message.
+ * @param {Integer} number The phone number to send the message to.
+ * @param {String} message The contents of the SMS message to send.
+ * @param {Function} successCallback The function to call when the SMS message is sent.
+ * @param {Function} errorCallback The function to call when there is an error sending the SMS message.
+ * @param {PositionOptions} options The options for accessing the GPS location such as timeout and accuracy.
+ */
+ Sms.prototype.send = function(number, message, successCallback, errorCallback, options) {
+
+ }
+
+ if (typeof navigator.sms == "undefined") navigator.sms = new Sms();
+
+
+ /**
+ * This class provides access to the telephony features of the device.
+ * @constructor
+ */
+ function Telephony() {
+
+ }
+
+ /**
+ * Calls the specifed number.
+ * @param {Integer} number The number to be called.
+ */
+ Telephony.prototype.call = function(number) {
+
+ }
+
+ if (typeof navigator.telephony == "undefined") navigator.telephony = new Telephony();
+
+
+ // Android specific overrides here
+
+Notification.prototype.vibrate = function(mills)
+{
+ Device.vibrate(mills);
+}
+
+/*
+ * On the Android, we don't beep, we notify you with your
+ * notification! We shouldn't keep hammering on this, and should
+ * review what we want beep to do.
+ */
+
+Notification.prototype.beep = function(count, volume)
+{
+ Device.notify();
+}
+
+/*
+ * Since we can't guarantee that we will have the most recent, we just try our best!
+ *
+ * Also, the API doesn't specify which version is the best version of the API
+ */
+
+Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options)
+{
+ this.global_success = successCallback;
+ this.fail = errorCallback;
+ Geo.getCurrentLocation();
+}
+
+// Run the global callback
+Geolocation.prototype.gotCurrentPosition = function(lat, lng)
+{
+ alert('foo');
+ if (lat == 0 || lng == 0)
+ {
+ this.fail();
+ }
+ else
+ {
+ var p = { "lat" : lat, "lng": lng };
+ this.global_success(p);
+ }
+}
+
+
+/*
+ * This turns on the GeoLocator class, which has two listeners.
+ * The listeners have their own timeouts, and run independently of this process
+ * In this case, we return the key to the watch hash
+ */
+
+Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options)
+{
+ var frequency = (options != undefined)? options.frequency : 10000;
+
+ if (!this.listeners)
+ {
+ this.listeners = []
+ }
+
+ var key = this.listeners.push( {"success" : successCallback, "fail" : failCallback }) - 1;
+
+ // TO-DO: Get the names of the method and pass them as strings to the Java.
+ return Geolocation.start(frequency, key);
+}
+
+/*
+ * Retrieve and stop this listener from listening to the GPS
+ *
+ */
+Geolocation.prototype.success = function(key, lat, lng)
+{
+ this.listeners[key].success(lat,lng);
+}
+
+Geolocation.prototype.fail = function(key)
+{
+ this.listeners[key].fail();
+}
+
+Geolocation.prototype.clearWatch = function(watchId)
+{
+ Geo.stop(watchId);
+}
+
+
diff --git a/src/com/nitobi/phonegap/DroidGap.java b/src/com/nitobi/phonegap/DroidGap.java
index b1b7cdee..47bb26b3 100644
--- a/src/com/nitobi/phonegap/DroidGap.java
+++ b/src/com/nitobi/phonegap/DroidGap.java
@@ -91,8 +91,10 @@ public class DroidGap extends Activity {
{
// The PhoneGap class handles the Notification and Android Specific crap
PhoneGap gap = new PhoneGap(this, mHandler, appView);
- appView.addJavascriptInterface(gap, "Droid");
-
+ GeoBroker geo = new GeoBroker(appView, this);
+ // This creates the new javascript interfaces for PhoneGap
+ appView.addJavascriptInterface(gap, "Device");
+ appView.addJavascriptInterface(geo, "Geo");
}
/**
diff --git a/src/com/nitobi/phonegap/GeoBroker.java b/src/com/nitobi/phonegap/GeoBroker.java
index 28ad2757..dea01929 100644
--- a/src/com/nitobi/phonegap/GeoBroker.java
+++ b/src/com/nitobi/phonegap/GeoBroker.java
@@ -23,25 +23,9 @@ public class GeoBroker {
mAppView = view;
}
- public GeoTuple getCurrentLocation()
+ public void getCurrentLocation()
{
- GeoListener listener = new GeoListener("0", mCtx, 60000, mAppView);
- Location loc = listener.getCurrentLocation();
- GeoTuple geo = new GeoTuple();
- if (loc == null)
- {
- geo.lat = 0;
- geo.lng = 0;
- geo.ele = 0;
- }
- else
- {
- geo.lng = loc.getLongitude();
- geo.lat = loc.getLatitude();
- geo.ele = 0;
- }
- listener.stop();
- return geo;
+ GeoListener listener = new GeoListener("global", mCtx, 10000, mAppView);
}
public String start(int freq, String key)
diff --git a/src/com/nitobi/phonegap/GeoListener.java b/src/com/nitobi/phonegap/GeoListener.java
index 6281a817..623fe24c 100644
--- a/src/com/nitobi/phonegap/GeoListener.java
+++ b/src/com/nitobi/phonegap/GeoListener.java
@@ -30,7 +30,15 @@ public class GeoListener {
/*
* We only need to figure out what we do when we succeed!
*/
- mAppView.loadUrl("javascript:GeoLocation.success(" + id + ", " + loc.getLatitude() + ", " + loc.getLongitude() + ")");
+ if(id != "global")
+ {
+ mAppView.loadUrl("javascript:Geolocation.success(" + id + ", " + loc.getLatitude() + ", " + loc.getLongitude() + ")");
+ }
+ else
+ {
+ mAppView.loadUrl("javascript:Geolocation.gotCurrentPosition(" + loc.getLatitude() + ", " + loc.getLongitude() + ")");
+ this.stop();
+ }
}
void fail()
diff --git a/src/com/nitobi/phonegap/PhoneGap.java b/src/com/nitobi/phonegap/PhoneGap.java
index 249e03eb..02a445ea 100644
--- a/src/com/nitobi/phonegap/PhoneGap.java
+++ b/src/com/nitobi/phonegap/PhoneGap.java
@@ -42,13 +42,12 @@ public class PhoneGap{
* UUID, version and availability
*/
public boolean droid = true;
- private String version = "0.1";
- private Context mCtx;
+ public static String version = "0.2";
+ public static String platform = "Android";
+ public static String uuid;
+ private Context mCtx;
private Handler mHandler;
- private WebView mAppView;
- private GpsListener mGps;
- private NetworkListener mNetwork;
- protected LocationProvider provider;
+ private WebView mAppView;
SmsListener mSmsListener;
DirectoryManager fileManager;
AudioHandler audio;
@@ -61,6 +60,7 @@ public class PhoneGap{
mSmsListener = new SmsListener(ctx,mAppView);
fileManager = new DirectoryManager();
audio = new AudioHandler("/sdcard/tmprecording.mp3", ctx);
+ uuid = getUuid();
}
public void updateAccel(){
@@ -75,42 +75,14 @@ public class PhoneGap{
}
- public void takePhoto(){
- // TO-DO: Figure out what this should do
- }
-
- public void playSound(){
- // TO-DO: Figure out what this should do
- }
-
public void vibrate(long pattern){
- // Start the vibration
+ // Start the vibration, 0 defaults to half a second.
+ if (pattern == 0)
+ pattern = 500;
Vibrator vibrator = (Vibrator) mCtx.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(pattern);
}
- public void getLocation( ){
- mHandler.post(new Runnable() {
- public void run() {
- GeoTuple geoloc = new GeoTuple();
- Location loc = mGps.hasLocation() ? mGps.getLocation() : mNetwork.getLocation();
- if (loc != null)
- {
- geoloc.lat = loc.getLatitude();
- geoloc.lng = loc.getLongitude();
- geoloc.ele = loc.getAltitude();
- }
- else
- {
- geoloc.lat = 0;
- geoloc.lng = 0;
- geoloc.ele = 0;
- }
- mAppView.loadUrl("javascript:gotLocation(" + geoloc.lat + ", " + geoloc.lng + ")");
- }
- });
- }
-
public String getUuid()
{
@@ -119,6 +91,11 @@ public class PhoneGap{
return uuid;
}
+ public void init()
+ {
+ mAppView.loadUrl("javascript:Device.setData('Android','" + version + "','" + this.getUuid() + "')");
+ }
+
public String getModel()
{
String model = android.os.Build.MODEL;
@@ -145,6 +122,9 @@ public class PhoneGap{
return version;
}
+ // Old SMS code, figure out what to do with this!
+ // BTW: This is awesome!
+
public void notificationWatchPosition(String filter)
/**
* Starts the listener for incoming notifications of type filter