From 50ab0e083487fd9602e9edb3bf28c68e96737d14 Mon Sep 17 00:00:00 2001 From: Bryce Curtis Date: Fri, 8 Oct 2010 09:18:10 -0500 Subject: [PATCH] Add confirm, start/stopActivity, start/stopProgress to notification service. Add "application loading" spinner that user can optionally show when app is starting. --- framework/assets/js/notification.js | 69 ++++-- framework/assets/js/phonegap.js.base | 3 + framework/src/com/phonegap/DroidGap.java | 2 +- framework/src/com/phonegap/Notification.java | 223 ++++++++++++++++++- 4 files changed, 280 insertions(+), 17 deletions(-) diff --git a/framework/assets/js/notification.js b/framework/assets/js/notification.js index 2d783211..92934ccb 100755 --- a/framework/assets/js/notification.js +++ b/framework/assets/js/notification.js @@ -6,40 +6,85 @@ function Notification() { /** * Open a native alert dialog, with a customizable title and button text. - * @param {String} message Message to print in the body of the alert - * @param {String} [title="Alert"] Title of the alert dialog (default: Alert) - * @param {String} [buttonLabel="OK"] Label of the close button (default: OK) + * + * @param {String} message Message to print in the body of the alert + * @param {String} title Title of the alert dialog (default: Alert) + * @param {String} buttonLabel Label of the close button (default: OK) */ Notification.prototype.alert = function(message, title, buttonLabel) { - var _title = (title || "Alert"); - var _buttonLabel = (buttonLabel || "OK"); + var _title = (title || "Alert"); + var _buttonLabel = (buttonLabel || "OK"); PhoneGap.execAsync(null, null, "Notification", "alert", [message,_title,_buttonLabel]); }; +/** + * Open a native confirm dialog, with a customizable title and button text. + * + * @param {String} message Message to print in the body of the alert + * @param {String} title Title of the alert dialog (default: Confirm) + * @param {String} buttonLabels Comma separated list of the labels of the buttons (default: 'OK,Cancel') + * @return {Number} The index of the button clicked + */ +Notification.prototype.confirm = function(message, title, buttonLabels) { + var _title = (title || "Confirm"); + var _buttonLabels = (buttonLabels || "OK,Cancel"); + return PhoneGap.execAsync(null, null, "Notification", "confirm", [message,_title,_buttonLabels]); +}; + /** * Start spinning the activity indicator on the statusbar */ Notification.prototype.activityStart = function() { + PhoneGap.execAsync(null, null, "Notification", "activityStart", ["Busy","Please wait..."]); }; /** * Stop spinning the activity indicator on the statusbar, if it's currently spinning */ Notification.prototype.activityStop = function() { + PhoneGap.execAsync(null, null, "Notification", "activityStop", []); +}; + +/** + * Display a progress dialog with progress bar that goes from 0 to 100. + * + * @param {String} title Title of the progress dialog. + * @param {String} message Message to display in the dialog. + */ +Notification.prototype.progressStart = function(title, message) { + PhoneGap.execAsync(null, null, "Notification", "progressStart", [title, message]); +}; + +/** + * Set the progress dialog value. + * + * @param {Number} value 0-100 + */ +Notification.prototype.progressValue = function(value) { + PhoneGap.execAsync(null, null, "Notification", "progressValue", [value]); +}; + +/** + * Close the progress dialog. + */ +Notification.prototype.progressStop = function() { + PhoneGap.execAsync(null, null, "Notification", "progressStop", []); }; /** * Causes the device to blink a status LED. - * @param {Integer} count The number of blinks. - * @param {String} colour The colour of the light. + * + * @param {Integer} count The number of blinks. + * @param {String} colour The colour of the light. */ Notification.prototype.blink = function(count, colour) { - + // NOT IMPLEMENTED }; /** * Causes the device to vibrate. - * @param {Integer} mills The number of milliseconds to vibrate for. + * + * @param {Integer} mills The number of milliseconds to vibrate for. */ Notification.prototype.vibrate = function(mills) { PhoneGap.execAsync(null, null, "Notification", "vibrate", [mills]); @@ -47,16 +92,14 @@ Notification.prototype.vibrate = function(mills) { /** * Causes the device to beep. - * On Android, the default notification ringtone is played. + * On Android, the default notification ringtone is played "count" times. * - * @param {Integer} count The number of beeps. + * @param {Integer} count The number of beeps. */ Notification.prototype.beep = function(count) { PhoneGap.execAsync(null, null, "Notification", "beep", [count]); }; -// TODO: of course on Blackberry and Android there notifications in the UI as well - PhoneGap.addConstructor(function() { if (typeof navigator.notification == "undefined") navigator.notification = new Notification(); }); diff --git a/framework/assets/js/phonegap.js.base b/framework/assets/js/phonegap.js.base index ab71d3d7..59401348 100755 --- a/framework/assets/js/phonegap.js.base +++ b/framework/assets/js/phonegap.js.base @@ -245,6 +245,9 @@ PhoneGap.Channel.join(function() { * received from native side. */ PhoneGap.Channel.join(function() { + // Turn off app loading dialog + navigator.notification.activityStop(); + PhoneGap.onDeviceReady.fire(); // Fire the onresume event, since first one happens before JavaScript is loaded diff --git a/framework/src/com/phonegap/DroidGap.java b/framework/src/com/phonegap/DroidGap.java index 3c7cabc6..46697229 100755 --- a/framework/src/com/phonegap/DroidGap.java +++ b/framework/src/com/phonegap/DroidGap.java @@ -84,7 +84,7 @@ public class DroidGap extends Activity { private BrowserKey mKey; public CallbackServer callbackServer; - private PluginManager pluginManager; + protected PluginManager pluginManager; private String url; // The initial URL for our app private String baseUrl; // The base of the initial URL for our app diff --git a/framework/src/com/phonegap/Notification.java b/framework/src/com/phonegap/Notification.java index 3d76366f..95874a0e 100755 --- a/framework/src/com/phonegap/Notification.java +++ b/framework/src/com/phonegap/Notification.java @@ -5,6 +5,7 @@ import org.json.JSONException; import com.phonegap.api.Plugin; import com.phonegap.api.PluginResult; import android.app.AlertDialog; +import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.media.Ringtone; @@ -16,7 +17,11 @@ import android.os.Vibrator; * This class provides access to notifications on the device. */ public class Notification extends Plugin { - + + public int confirmResult = -1; + public ProgressDialog spinnerDialog = null; + public ProgressDialog progressDialog = null; + /** * Constructor. */ @@ -45,6 +50,25 @@ public class Notification extends Plugin { else if (action.equals("alert")) { this.alert(args.getString(0),args.getString(1),args.getString(2)); } + else if (action.equals("confirm")) { + int i = this.confirm(args.getString(0),args.getString(1),args.getString(2)); + return new PluginResult(status, i); + } + else if (action.equals("activityStart")) { + this.activityStart(args.getString(0),args.getString(1)); + } + else if (action.equals("activityStop")) { + this.activityStop(); + } + else if (action.equals("progressStart")) { + this.progressStart(args.getString(0),args.getString(1)); + } + else if (action.equals("progressValue")) { + this.progressValue(args.getInt(0)); + } + else if (action.equals("progressStop")) { + this.progressStop(); + } return new PluginResult(status, result); } catch (JSONException e) { return new PluginResult(PluginResult.Status.JSON_EXCEPTION); @@ -58,10 +82,30 @@ public class Notification extends Plugin { * @return T=returns value */ public boolean isSynch(String action) { - if(action.equals("alert")) + if (action.equals("alert")) { return true; - else + } + else if (action.equals("confirm")) { + return true; + } + else if (action.equals("activityStart")) { + return true; + } + else if (action.equals("activityStop")) { + return true; + } + else if (action.equals("progressStart")) { + return true; + } + else if (action.equals("progressValue")) { + return true; + } + else if (action.equals("progressStop")) { + return true; + } + else { return false; + } } //-------------------------------------------------------------------------- @@ -128,4 +172,177 @@ public class Notification extends Plugin { dlg.show(); } + /** + * Builds and shows a native Android confirm dialog with given title, message, buttons. + * This dialog only shows up to 3 buttons. Any labels after that will be ignored. + * + * @param message The message the dialog should display + * @param title The title of the dialog + * @param buttonLabels A comma separated list of button labels (Up to 3 buttons) + * @return The index of the button clicked (1,2 or 3) + */ + public synchronized int confirm(final String message, final String title, String buttonLabels) { + + // Create dialog on UI thread + final DroidGap ctx = this.ctx; + final Notification notification = this; + final String[] fButtons = buttonLabels.split(","); + Runnable runnable = new Runnable() { + public void run() { + AlertDialog.Builder dlg = new AlertDialog.Builder(ctx); + dlg.setMessage(message); + dlg.setTitle(title); + dlg.setCancelable(false); + + // First button + if (fButtons.length > 0) { + dlg.setPositiveButton(fButtons[0], + new AlertDialog.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + synchronized(notification) { + notification.confirmResult = 1; + notification.notifyAll(); + } + } + }); + } + + // Second button + if (fButtons.length > 1) { + dlg.setNeutralButton(fButtons[1], + new AlertDialog.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + synchronized(notification) { + notification.confirmResult = 2; + notification.notifyAll(); + } + } + }); + } + + // Third button + if (fButtons.length > 2) { + dlg.setNegativeButton(fButtons[2], + new AlertDialog.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + synchronized(notification) { + notification.confirmResult = 3; + notification.notifyAll(); + } + } + } + ); + } + + dlg.create(); + dlg.show(); + } + }; + this.ctx.runOnUiThread(runnable); + + // Wait for dialog to close + synchronized(runnable) { + try { + this.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return this.confirmResult; + } + + /** + * Show the spinner. + * + * @param title Title of the dialog + * @param message The message of the dialog + */ + public synchronized void activityStart(final String title, final String message) { + if (this.spinnerDialog != null) { + this.spinnerDialog.dismiss(); + this.spinnerDialog = null; + } + final Notification notification = this; + final DroidGap ctx = this.ctx; + Runnable runnable = new Runnable() { + public void run() { + notification.spinnerDialog = ProgressDialog.show(ctx, title , message, true, true, + new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + notification.spinnerDialog = null; + } + }); + } + }; + this.ctx.runOnUiThread(runnable); + } + + /** + * Stop spinner. + */ + public synchronized void activityStop() { + if (this.spinnerDialog != null) { + this.spinnerDialog.dismiss(); + this.spinnerDialog = null; + } + } + + /** + * Show the progress dialog. + * + * @param title Title of the dialog + * @param message The message of the dialog + */ + public synchronized void progressStart(final String title, final String message) { + if (this.progressDialog != null) { + this.progressDialog.dismiss(); + this.progressDialog = null; + } + final Notification notification = this; + final DroidGap ctx = this.ctx; + Runnable runnable = new Runnable() { + public void run() { + notification.progressDialog = new ProgressDialog(ctx); + notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + notification.progressDialog.setTitle(title); + notification.progressDialog.setMessage(message); + notification.progressDialog.setCancelable(true); + notification.progressDialog.setMax(100); + notification.progressDialog.setProgress(0); + notification.progressDialog.setOnCancelListener( + new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + notification.progressDialog = null; + } + }); + notification.progressDialog.show(); + } + }; + this.ctx.runOnUiThread(runnable); + } + + /** + * Set value of progress bar. + * + * @param value 0-100 + */ + public synchronized void progressValue(int value) { + if (this.progressDialog != null) { + this.progressDialog.setProgress(value); + } + } + + /** + * Stop progress dialog. + */ + public synchronized void progressStop() { + if (this.progressDialog != null) { + this.progressDialog.dismiss(); + this.progressDialog = null; + } + } + }