diff --git a/framework/assets/js/device.js b/framework/assets/js/device.js index 17bd9bb8..450a0e32 100644 --- a/framework/assets/js/device.js +++ b/framework/assets/js/device.js @@ -1,59 +1,60 @@ /** - * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the + * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the * phone, etc. * @constructor */ function Device() { this.available = PhoneGap.available; this.platform = null; - this.version = null; - this.name = null; - this.gap = null; - this.uuid = null; - try { - if (window.DroidGap) { - this.available = true; - this.uuid = window.DroidGap.getUuid(); - this.version = window.DroidGap.getOSVersion(); - this.gapVersion = window.DroidGap.getVersion(); - this.platform = window.DroidGap.getPlatform(); - this.name = window.DroidGap.getProductName(); - this.line1Number = window.DroidGap.getLine1Number(); - this.deviceId = window.DroidGap.getDeviceId(); - this.simSerialNumber = window.DroidGap.getSimSerialNumber(); - this.subscriberId = window.DroidGap.getSubscriberId(); - } - } catch(e) { - this.available = false; - } + this.version = null; + this.name = null; + this.uuid = null; + this.phonegap = null; + + var me = this; + PhoneGap.execAsync( + function(info) { + me.available = true; + me.platform = info.platform; + me.version = info.version; + me.uuid = info.uuid; + me.phonegap = info.phonegap; + }, + function(e) { + me.available = false; + console.log("Error initializing PhoneGap: " + e); + alert("Error initializing PhoneGap: "+e); + }, + "Device", "getDeviceInfo", []); } /* - * You must explicitly override the back button. + * This is only for Android. + * + * You must explicitly override the back button. */ - -Device.prototype.overrideBackButton = function() -{ - BackButton.override(); +Device.prototype.overrideBackButton = function() { + BackButton.override(); } /* + * This is only for Android. + * * This resets the back button to the default behaviour */ - -Device.prototype.resetBackButton = function() -{ - BackButton.reset(); +Device.prototype.resetBackButton = function() { + BackButton.reset(); } /* + * This is only for Android. + * * This terminates the activity! */ -Device.prototype.exitApp = function() -{ - BackButton.exitApp(); +Device.prototype.exitApp = function() { + BackButton.exitApp(); } PhoneGap.addConstructor(function() { navigator.device = window.device = new Device(); -}); \ No newline at end of file +}); diff --git a/framework/assets/js/notification.js b/framework/assets/js/notification.js index 5a7c733b..e80c3e40 100644 --- a/framework/assets/js/notification.js +++ b/framework/assets/js/notification.js @@ -2,7 +2,6 @@ * This class provides access to notifications on the device. */ function Notification() { - } /** @@ -34,7 +33,7 @@ Notification.prototype.activityStop = function() { * @param {String} colour The colour of the light. */ Notification.prototype.blink = function(count, colour) { - + }; /** @@ -42,16 +41,17 @@ Notification.prototype.blink = function(count, colour) { * @param {Integer} mills The number of milliseconds to vibrate for. */ Notification.prototype.vibrate = function(mills) { - + PhoneGap.execAsync(null, null, "Device", "vibrate", [mills]); }; /** * Causes the device to beep. + * On Android, the default notification ringtone is played. + * * @param {Integer} count The number of beeps. - * @param {Integer} volume The volume of the beep. */ -Notification.prototype.beep = function(count, volume) { - +Notification.prototype.beep = function(count) { + PhoneGap.execAsync(null, null, "Device", "beep", [count]); }; // TODO: of course on Blackberry and Android there notifications in the UI as well @@ -60,18 +60,3 @@ PhoneGap.addConstructor(function() { if (typeof navigator.notification == "undefined") navigator.notification = new Notification(); }); -Notification.prototype.vibrate = function(mills) -{ - DroidGap.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) -{ - DroidGap.beep(count); -} diff --git a/framework/assets/js/phonegap.js.base b/framework/assets/js/phonegap.js.base index 49640d5d..b3a09655 100755 --- a/framework/assets/js/phonegap.js.base +++ b/framework/assets/js/phonegap.js.base @@ -219,6 +219,36 @@ document.addEventListener = function(evt, handler, capture) { } }; +/** + * If JSON not included, use our own stringify. (Android 1.6) + * The restriction on ours is that it must be an array of simple types. + * + * @param args + * @return + */ +PhoneGap.stringify = function(args) { + if (typeof JSON == "undefined") { + var s = "["; + for (var i=0; i 0) { + s = s + ","; + } + var type = typeof args[i]; + if ((type == "number") || (type == "boolean")) { + s = s + args[i]; + } + else { + s = s + '"' + args[i] + '"'; + } + } + s = s + "]"; + return s; + } + else { + return JSON.stringify(args); + } +}; + PhoneGap.callbackId = 0; PhoneGap.callbacks = {}; @@ -232,7 +262,7 @@ PhoneGap.callbacks = {}; PhoneGap.exec = function(clazz, action, args) { try { var callbackId = 0; - var r = PluginManager.exec(clazz, action, callbackId, JSON.stringify(args), false); + var r = PluginManager.exec(clazz, action, callbackId, this.stringify(args), false); eval("var v="+r+";"); // If status is OK, then return value back to caller @@ -256,10 +286,10 @@ PhoneGap.execAsync = function(success, fail, clazz, action, args) { if (success || fail) { PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; } - var r = PluginManager.exec(clazz, action, callbackId, JSON.stringify(args), true); + var r = PluginManager.exec(clazz, action, callbackId, this.stringify(args), true); // If a result was returned - if (r) { + if (typeof r == "string") { eval("var v="+r+";"); // If status is OK, then return value back to caller diff --git a/framework/src/com/phonegap/AccelListener.java b/framework/src/com/phonegap/AccelListener.java index 8896f018..4f4cae62 100755 --- a/framework/src/com/phonegap/AccelListener.java +++ b/framework/src/com/phonegap/AccelListener.java @@ -105,13 +105,18 @@ public class AccelListener implements SensorEventListener, Plugin{ return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START); } // Wait until running - while (this.status == STARTING) { + long timeout = 2000; + while ((this.status == STARTING) && (timeout > 0)) { + timeout = timeout - 100; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } + if (timeout == 0) { + return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START); + } } JSONObject r = new JSONObject(); r.put("x", this.x); diff --git a/framework/src/com/phonegap/CompassListener.java b/framework/src/com/phonegap/CompassListener.java index 2f3bf549..6ff6efe1 100755 --- a/framework/src/com/phonegap/CompassListener.java +++ b/framework/src/com/phonegap/CompassListener.java @@ -98,13 +98,18 @@ public class CompassListener implements SensorEventListener, Plugin{ return new PluginResult(PluginResult.Status.IO_EXCEPTION, ERROR_FAILED_TO_START); } // Wait until running - while (this.status == STARTING) { + long timeout = 2000; + while ((this.status == STARTING) && (timeout > 0)) { + timeout = timeout - 100; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } + if (timeout == 0) { + return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START); + } } float f = this.getHeading(); return new PluginResult(status, f); diff --git a/framework/src/com/phonegap/Device.java b/framework/src/com/phonegap/Device.java index 922fd01f..babd09fe 100644 --- a/framework/src/com/phonegap/Device.java +++ b/framework/src/com/phonegap/Device.java @@ -24,7 +24,15 @@ package com.phonegap; import java.util.TimeZone; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import com.phonegap.api.Plugin; +import com.phonegap.api.PluginResult; + import android.content.Context; +import android.content.Intent; import android.net.Uri; import android.os.Vibrator; import android.provider.Settings; @@ -33,76 +41,210 @@ import android.webkit.WebView; import android.media.Ringtone; import android.media.RingtoneManager; -public class Device{ +public class Device implements Plugin { - private static final String LOG_TAG = "PhoneGap"; - /* - * UUID, version and availability - */ - public boolean droid = true; - public static String version = "0.91"; - public static String platform = "Android"; - public static String uuid; - private Context mCtx; - private WebView mAppView; - AudioPlayer audio; + public static String phonegapVersion = "pre-0.92 EDGE"; // PhoneGap version + public static String platform = "Android"; // Device OS + public static String uuid; // Device UUID + private DroidGap ctx; // DroidGap object + @SuppressWarnings("unused") + private WebView webView; // Webview object - public Device(WebView appView, Context ctx) { - this.mCtx = ctx; - this.mAppView = appView; - uuid = getUuid(); + /** + * Constructor. + */ + public Device() { } - public void beep(long pattern) - { + /** + * Sets the context of the Command. This can then be used to do things like + * get file paths associated with the Activity. + * + * @param ctx The context of the main Activity. + */ + public void setContext(DroidGap ctx) { + this.ctx = ctx; + Device.uuid = getUuid(); + } + + /** + * Sets the main View of the application, this is the WebView within which + * a PhoneGap app runs. + * + * @param webView The PhoneGap WebView + */ + public void setView(WebView webView) { + this.webView = webView; + } + + /** + * Executes the request and returns CommandResult. + * + * @param action The command to execute. + * @param args JSONArry of arguments for the command. + * @return A CommandResult object with a status and message. + */ + public PluginResult execute(String action, JSONArray args) { + PluginResult.Status status = PluginResult.Status.OK; + String result = ""; + + try { + if (action.equals("getDeviceInfo")) { + JSONObject r = new JSONObject(); + r.put("uuid", Device.uuid); + r.put("version", this.getOSVersion()); + r.put("platform", Device.platform); + r.put("name", this.getProductName()); + r.put("phonegap", Device.phonegapVersion); + //JSONObject pg = new JSONObject(); + //pg.put("version", Device.phonegapVersion); + //r.put("phonegap", pg); + return new PluginResult(status, r); + } + else if (action.equals("beep")) { + this.beep(args.getLong(0)); + } + else if (action.equals("vibrate")) { + this.vibrate(args.getLong(0)); + } + return new PluginResult(status, result); + } catch (JSONException e) { + return new PluginResult(PluginResult.Status.JSON_EXCEPTION); + } + } + + /** + * Identifies if action to be executed returns a value and should be run synchronously. + * + * @param action The action to execute + * @return T=returns value + */ + public boolean isSynch(String action) { + if (action.equals("getDeviceInfo")) { + return true; + } + return false; + } + + /** + * Called when the system is about to start resuming a previous activity. + */ + public void onPause() { + } + + /** + * Called when the activity will start interacting with the user. + */ + public void onResume() { + } + + /** + * Called when the activity is to be shut down. + * Stop listener. + */ + public void onDestroy() { + } + + /** + * Called when an activity you launched exits, giving you the requestCode you started it with, + * the resultCode it returned, and any additional data from it. + * + * @param requestCode The request code originally supplied to startActivityForResult(), + * allowing you to identify who this result came from. + * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + */ + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + } + + //-------------------------------------------------------------------------- + // LOCAL METHODS + //-------------------------------------------------------------------------- + + /** + * Beep plays the default notification ringtone. + * + * @param count Number of times to play notification + */ + public void beep(long count) { Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); - Ringtone notification = RingtoneManager.getRingtone(mCtx, ringtone); - if (notification != null) { // This will be the case when the phone is set to silent for example - for (long i = 0; i < pattern; ++i) - { + Ringtone notification = RingtoneManager.getRingtone(this.ctx, ringtone); + + // If phone is not set to silent mode + if (notification != null) { + for (long i = 0; i < count; ++i) { notification.play(); + long timeout = 5000; + while (notification.isPlaying() && (timeout > 0)) { + timeout = timeout - 100; + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } } } } - public void vibrate(long pattern){ + /** + * Vibrates the device for the specified amount of time. + * + * @param time Time to vibrate in ms. + */ + public void vibrate(long time){ // 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); + if (time == 0) { + time = 500; + } + Vibrator vibrator = (Vibrator) this.ctx.getSystemService(Context.VIBRATOR_SERVICE); + vibrator.vibrate(time); } - public String getPlatform() - { - return this.platform; + /** + * Get the OS name. + * + * @return + */ + public String getPlatform() { + return Device.platform; } - public String getUuid() - { - //TelephonyManager operator = (TelephonyManager) mCtx.getSystemService(Context.TELEPHONY_SERVICE); - //String uuid = operator.getDeviceId(); - String uuid = Settings.Secure.getString(mCtx.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); + /** + * Get the device's Universally Unique Identifier (UUID). + * + * @return + */ + public String getUuid() { + String uuid = Settings.Secure.getString(this.ctx.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); return uuid; } + /** + * Get the PhoneGap version. + * + * @return + */ + public String getPhonegapVersion() { + return Device.phonegapVersion; + } + public String getLine1Number(){ - TelephonyManager operator = (TelephonyManager)mCtx.getSystemService(Context.TELEPHONY_SERVICE); + TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE); return operator.getLine1Number(); } public String getDeviceId(){ - TelephonyManager operator = (TelephonyManager)mCtx.getSystemService(Context.TELEPHONY_SERVICE); + TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE); return operator.getDeviceId(); } public String getSimSerialNumber(){ - TelephonyManager operator = (TelephonyManager)mCtx.getSystemService(Context.TELEPHONY_SERVICE); + TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE); return operator.getSimSerialNumber(); } public String getSubscriberId(){ - TelephonyManager operator = (TelephonyManager)mCtx.getSystemService(Context.TELEPHONY_SERVICE); + TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE); return operator.getSubscriberId(); } @@ -116,21 +258,23 @@ public class Device{ String productname = android.os.Build.PRODUCT; return productname; } - public String getOSVersion() - { + + /** + * Get the OS version. + * + * @return + */ + public String getOSVersion() { String osversion = android.os.Build.VERSION.RELEASE; return osversion; } + public String getSDKVersion() { String sdkversion = android.os.Build.VERSION.SDK; return sdkversion; } - public String getVersion() - { - return version; - } public String getTimeZoneID() { TimeZone tz = TimeZone.getDefault(); diff --git a/framework/src/com/phonegap/DroidGap.java b/framework/src/com/phonegap/DroidGap.java index 371d4d23..3fa921ed 100755 --- a/framework/src/com/phonegap/DroidGap.java +++ b/framework/src/com/phonegap/DroidGap.java @@ -83,7 +83,6 @@ public class DroidGap extends Activity { protected Boolean loadInWebView = false; private LinearLayout root; - private Device gap; private FileUtils fs; private BrowserKey mKey; public CallbackServer callbackServer; @@ -270,13 +269,11 @@ public class DroidGap extends Activity { private void bindBrowser(WebView appView) { this.callbackServer = new CallbackServer(); this.pluginManager = new PluginManager(appView, this); - this.gap = new Device(appView, this); this.fs = new FileUtils(appView, this); this.mKey = new BrowserKey(appView, this); // This creates the new javascript interfaces for PhoneGap appView.addJavascriptInterface(this.pluginManager, "PluginManager"); - appView.addJavascriptInterface(this.gap, "DroidGap"); appView.addJavascriptInterface(this.fs, "FileUtil"); appView.addJavascriptInterface(this.mKey, "BackButton"); @@ -295,6 +292,7 @@ public class DroidGap extends Activity { } + this.addService("Device", "com.phonegap.Device"); this.addService("Accelerometer", "com.phonegap.AccelListener"); this.addService("Compass", "com.phonegap.CompassListener"); this.addService("Media", "com.phonegap.AudioHandler");