mirror of
https://github.com/purplecabbage/phonegap-plugins.git
synced 2026-04-24 03:00:11 -04:00
Improvements to Android status bar notifications
Several things here: - Add support for the W3C notifications spec, and rewrite the old API to call the new W3C one behind the scenes. - Notifications are now automatically cleared when the user clicks. - Clicking the notification brings the user to the same instance of the app as was already running (and not a new copy as by default in Android notifications). - Support for multiple notifications from one app using tags, as specified in the W3C spec and supported by Android. - Support for canceling a single notification by tag, as per W3C spec. Callbacks to Javascript when the user clicks are specified but not yet supported; I will add that assuming I can get Android to call some code in the plugin when the notification is clicked.
This commit is contained in:
@@ -1,110 +1,120 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2011 Dmitry Savchenko <dg.freak@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
*
|
||||
* Copyright (C) 2011 Dmitry Savchenko <dg.freak@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.phonegap.plugins.statusBarNotification;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.cordova.DroidGap;
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.apache.cordova.api.PluginResult.Status;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
public class StatusBarNotification extends Plugin {
|
||||
// Action to execute
|
||||
public static final String NOTIFY = "notify";
|
||||
public static final String CLEAR = "clear";
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult
|
||||
*
|
||||
* @param action Action to execute
|
||||
* @param data JSONArray of arguments to the plugin
|
||||
* @param callbackId The callback id used when calling back into JavaScript
|
||||
*
|
||||
* @return A PluginRequest object with a status
|
||||
* */
|
||||
@Override
|
||||
public PluginResult execute(String action, JSONArray data, String callbackId) {
|
||||
PluginResult result = null;
|
||||
if (NOTIFY.equals(action)) {
|
||||
try {
|
||||
// Action to execute
|
||||
public static final String NOTIFY = "notify";
|
||||
public static final String CLEAR = "clear";
|
||||
|
||||
String title = data.getString(0);
|
||||
String body = data.getString(1);
|
||||
Log.d("NotificationPlugin", "Notification: " + title + ", " + body);
|
||||
showNotification(title, body);
|
||||
result = new PluginResult(Status.OK);
|
||||
} catch (JSONException jsonEx) {
|
||||
Log.d("NotificationPlugin", "Got JSON Exception "
|
||||
+ jsonEx.getMessage());
|
||||
result = new PluginResult(Status.JSON_EXCEPTION);
|
||||
}
|
||||
} else if (CLEAR.equals(action)){
|
||||
clearNotification();
|
||||
} else {
|
||||
result = new PluginResult(Status.INVALID_ACTION);
|
||||
Log.d("NotificationPlugin", "Invalid action : "+action+" passed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays status bar notification
|
||||
*
|
||||
* @param contentTitle Notification title
|
||||
* @param contentText Notification text
|
||||
* */
|
||||
public void showNotification( CharSequence contentTitle, CharSequence contentText ) {
|
||||
String ns = Context.NOTIFICATION_SERVICE;
|
||||
mNotificationManager = (NotificationManager) cordova.getContext().getSystemService(ns);
|
||||
context = ctx.getApplicationContext();
|
||||
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
|
||||
if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||
Notification noti = new StatusNotificationBuilder().buildNotification(context, contentTitle, contentText);
|
||||
mNotificationManager.notify(1, noti);
|
||||
} else {
|
||||
Notification noti = new StatusNotificationIntent().buildNotification(context, contentTitle, contentText);
|
||||
mNotificationManager.notify(1, noti);
|
||||
/**
|
||||
* Executes the request and returns PluginResult
|
||||
*
|
||||
* @param action Action to execute
|
||||
* @param data JSONArray of arguments to the plugin
|
||||
* @param callbackId The callback id used when calling back into JavaScript
|
||||
*
|
||||
* @return A PluginRequest object with a status
|
||||
* */
|
||||
@Override
|
||||
public PluginResult execute(String action, JSONArray data, String callbackId) {
|
||||
PluginResult result = null;
|
||||
if (NOTIFY.equals(action)) {
|
||||
try {
|
||||
String tag = data.getString(0);
|
||||
String title = data.getString(1);
|
||||
String body = data.getString(2);
|
||||
Log.d("NotificationPlugin", "Notification: " + tag + ", " + title + ", " + body);
|
||||
showNotification(tag, title, body);
|
||||
result = new PluginResult(Status.OK);
|
||||
} catch (JSONException jsonEx) {
|
||||
Log.d("NotificationPlugin", "Got JSON Exception "
|
||||
+ jsonEx.getMessage());
|
||||
result = new PluginResult(Status.JSON_EXCEPTION);
|
||||
}
|
||||
} else if (CLEAR.equals(action)){
|
||||
try {
|
||||
String tag = data.getString(0);
|
||||
Log.d("NotificationPlugin", "Notification cancel: " + tag);
|
||||
clearNotification(tag);
|
||||
} catch (JSONException jsonEx) {
|
||||
Log.d("NotificationPlugin", "Got JSON Exception " + jsonEx.getMessage());
|
||||
result = new PluginResult(Status.JSON_EXCEPTION);
|
||||
}
|
||||
} else {
|
||||
result = new PluginResult(Status.INVALID_ACTION);
|
||||
Log.d("NotificationPlugin", "Invalid action : "+action+" passed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the Notification from status bar
|
||||
*/
|
||||
public void clearNotification() {
|
||||
mNotificationManager.cancelAll();
|
||||
}
|
||||
|
||||
private NotificationManager mNotificationManager;
|
||||
private Context context;
|
||||
|
||||
/**
|
||||
* Displays status bar notification
|
||||
*
|
||||
* @param tag Notification tag.
|
||||
* @param contentTitle Notification title
|
||||
* @param contentText Notification text
|
||||
* */
|
||||
public void showNotification( CharSequence tag, CharSequence contentTitle, CharSequence contentText ) {
|
||||
String ns = Context.NOTIFICATION_SERVICE;
|
||||
context = cordova.getActivity().getApplicationContext();
|
||||
mNotificationManager = (NotificationManager) context.getSystemService(ns);
|
||||
|
||||
Notification noti = StatusNotificationIntent.buildNotification(context, contentTitle, contentText);
|
||||
mNotificationManager.notify(tag.hashCode(), noti);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a single notification by tag.
|
||||
*
|
||||
* @param tag Notification tag to cancel.
|
||||
*/
|
||||
public void clearNotification(String tag) {
|
||||
mNotificationManager.cancel(tag.hashCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all Notifications from the status bar.
|
||||
*/
|
||||
public void clearAllNotifications() {
|
||||
mNotificationManager.cancelAll();
|
||||
}
|
||||
|
||||
private NotificationManager mNotificationManager;
|
||||
private Context context;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
// This class is used on all Androids below Honeycomb
|
||||
package com.phonegap.plugins.statusBarNotification;
|
||||
// import com.yourapp.R;
|
||||
|
||||
|
||||
import com.google.cordova.statusbarnotificationtest.R;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.util.Log;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
public class StatusNotificationIntent {
|
||||
public Notification buildNotification( Context ctx, CharSequence contentTitle, CharSequence contentText ) {
|
||||
int icon = R.drawable.notification;
|
||||
long when = System.currentTimeMillis();
|
||||
Notification noti = new Notification(icon, contentTitle, when);
|
||||
Intent notificationIntent = new Intent(ctx, ctx.getClass());
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0, notificationIntent, 0);
|
||||
noti.setLatestEventInfo(ctx, contentTitle, contentText, contentIntent);
|
||||
return noti;
|
||||
}
|
||||
public static Notification buildNotification( Context context, CharSequence contentTitle, CharSequence contentText ) {
|
||||
int icon = R.drawable.notification;
|
||||
long when = System.currentTimeMillis();
|
||||
Notification noti = new Notification(icon, contentTitle, when);
|
||||
noti.flags |= Notification.FLAG_AUTO_CANCEL;
|
||||
|
||||
PackageManager pm = context.getPackageManager();
|
||||
Intent notificationIntent = pm.getLaunchIntentForPackage(context.getPackageName());
|
||||
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
|
||||
noti.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
|
||||
return noti;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,23 +27,93 @@
|
||||
|
||||
var cordovaRef = window.PhoneGap || window.Cordova || window.cordova; // old to new fallbacks
|
||||
|
||||
/** @deprecated Use the W3C standard window.Notification API instead. */
|
||||
var NotificationMessenger = function() { }
|
||||
|
||||
/**
|
||||
* @param title Title of the notification
|
||||
* @param body Body of the notification
|
||||
* @deprecated Use the W3C standard window.Notification API instead.
|
||||
*/
|
||||
NotificationMessenger.prototype.notify = function(title, body) {
|
||||
return cordovaRef.exec(null, null, 'StatusBarNotification', 'notify', [title, body])
|
||||
if (window.Notification) {
|
||||
this.activeNotification = new window.Notification(title, {
|
||||
body: body
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the Notificaiton Bar
|
||||
* @deprecated Use the W3C standard window.Notification API instead.
|
||||
*/
|
||||
NotificationMessenger.prototype.clear = function() {
|
||||
return cordovaRef.exec(null, null, 'StatusBarNotification', 'clear', []);
|
||||
if (this.activeNotification) {
|
||||
this.activeNotification.close();
|
||||
this.activeNotification = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.plugins) window.plugins = {}
|
||||
if (!window.plugins.statusBarNotification) window.plugins.statusBarNotification = new NotificationMessenger()
|
||||
;
|
||||
if (!window.plugins.statusBarNotification) window.plugins.statusBarNotification = new NotificationMessenger();
|
||||
|
||||
|
||||
/*
|
||||
* The W3C standard API, window.Notification. See http://www.w3.org/TR/notifications/
|
||||
* This API should be used for new applications instead of the old plugin API above.
|
||||
*/
|
||||
if (typeof window.Notification == "undefined") {
|
||||
|
||||
/**
|
||||
* Creates and shows a new notification.
|
||||
* @param title
|
||||
* @param options
|
||||
*/
|
||||
window.Notification = function(title, options) {
|
||||
options = options || {};
|
||||
this.tag = options.tag || "defaultTag";
|
||||
|
||||
// May be undefined.
|
||||
this.onclick = options.onclick;
|
||||
this.onerror = options.onerror;
|
||||
this.onshow = options.onshow;
|
||||
this.onclose = options.onclose;
|
||||
|
||||
var content = title + (options.body ? "\n" + options.body : "");
|
||||
|
||||
cordova.exec(function() {
|
||||
if (this.onshow) {
|
||||
this.onshow();
|
||||
}
|
||||
}, function(error) {
|
||||
if (this.onerror) {
|
||||
this.onerror(error);
|
||||
}
|
||||
}, "StatusBarNotification", "notify", [this.tag, title, content]);
|
||||
};
|
||||
|
||||
// Permission is always granted on Android.
|
||||
window.Notification.permission = "granted";
|
||||
|
||||
window.Notification.requestPermission = function(callback) {
|
||||
callback('granted');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cancels a notification that has already been created and shown to the user.
|
||||
*/
|
||||
window.Notification.prototype.close = function() {
|
||||
cordova.exec(function() {
|
||||
if (this.onclose) {
|
||||
this.onclose();
|
||||
}
|
||||
}, function(error) {
|
||||
if (this.onerror) {
|
||||
this.onerror(error);
|
||||
}
|
||||
}, "StatusBarNotification", "clear", [this.tag]);
|
||||
};
|
||||
}
|
||||
|
||||
// vim: tabstop=4:softtabstop=4:shiftwidth=4:expandtab
|
||||
|
||||
Reference in New Issue
Block a user