Commit b9ba9ab7 by Sebastián Katzer

Revert "Minimize android-support-v4.jar to only include required classes"

This reverts commit 504b36cb.
parent cf9c64d3
...@@ -21,171 +21,352 @@ ...@@ -21,171 +21,352 @@
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import java.util.Calendar; import java.util.ArrayList;
import java.util.Random; import java.util.Map;
import java.util.Set;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.annotation.SuppressLint; import android.app.AlarmManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.*;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.content.SharedPreferences;
import android.graphics.BitmapFactory; import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
/** /**
* The alarm receiver is triggered when a scheduled alarm is fired. This class * This plugin utilizes the Android AlarmManager in combination with StatusBar
* reads the information in the intent and displays this information in the * notifications. When a local notification is scheduled the alarm manager takes
* Android notification bar. The notification uses the default notification * care of firing the event. When the event is processed, a notification is put
* sound and it vibrates the phone. * in the Android status bar.
*/ */
public class Receiver extends BroadcastReceiver { public class LocalNotification extends CordovaPlugin {
public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS"; protected final static String PLUGIN_NAME = "LocalNotification";
private Context context; private static CordovaWebView webView = null;
private Options options; private static Boolean deviceready = false;
protected static Context context = null;
protected static Boolean isInBackground = true;
private static ArrayList<String> eventQueue = new ArrayList<String>();
@Override @Override
public void onReceive (Context context, Intent intent) { public void initialize (CordovaInterface cordova, CordovaWebView webView) {
Options options = null; super.initialize(cordova, webView);
Bundle bundle = intent.getExtras();
JSONObject args;
try { LocalNotification.webView = super.webView;
args = new JSONObject(bundle.getString(OPTIONS)); LocalNotification.context = super.cordova.getActivity().getApplicationContext();
options = new Options(context).parse(args); }
} catch (JSONException e) {
return; @Override
public boolean execute (String action, final JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equalsIgnoreCase("add")) {
cordova.getThreadPool().execute( new Runnable() {
public void run() {
JSONObject arguments = args.optJSONObject(0);
Options options = new Options(context).parse(arguments);
persist(options.getId(), args);
add(options, true);
}
});
return true;
} }
this.context = context; if (action.equalsIgnoreCase("cancel")) {
this.options = options; cordova.getThreadPool().execute( new Runnable() {
public void run() {
String id = args.optString(0);
// The context may got lost if the app was not running before cancel(id);
LocalNotification.setContext(context); unpersist(id);
}
});
fireTriggerEvent(); return true;
}
if (options.getInterval() == 0) { if (action.equalsIgnoreCase("cancelAll")) {
LocalNotification.unpersist(options.getId()); cordova.getThreadPool().execute( new Runnable() {
} else if (isFirstAlarmInFuture()) { public void run() {
return; cancelAll();
} else { unpersistAll();
LocalNotification.add(options.moveDate(), false); }
});
return true;
}
if (action.equalsIgnoreCase("isScheduled")) {
String id = args.optString(0);
isScheduled(id, callbackContext);
return true;
}
if (action.equalsIgnoreCase("getScheduledIds")) {
getScheduledIds(callbackContext);
return true;
}
if (action.equalsIgnoreCase("deviceready")) {
cordova.getThreadPool().execute( new Runnable() {
public void run() {
deviceready();
}
});
return true;
}
if (action.equalsIgnoreCase("pause")) {
isInBackground = true;
return true;
} }
Builder notification = buildNotification(); if (action.equalsIgnoreCase("resume")) {
isInBackground = false;
return true;
}
showNotification(notification); // Returning false results in a "MethodNotFound" error.
return false;
} }
/* /**
* If you set a repeating alarm at 11:00 in the morning and it * Calls all pending callbacks after the deviceready event has been fired.
* should trigger every morning at 08:00 o'clock, it will
* immediately fire. E.g. Android tries to make up for the
* 'forgotten' reminder for that day. Therefore we ignore the event
* if Android tries to 'catch up'.
*/ */
private Boolean isFirstAlarmInFuture () { private static void deviceready () {
if (options.getInterval() > 0) { deviceready = true;
Calendar now = Calendar.getInstance();
Calendar alarm = options.getCalendar(); for (String js : eventQueue) {
webView.sendJavascript(js);
int alarmHour = alarm.get(Calendar.HOUR_OF_DAY);
int alarmMin = alarm.get(Calendar.MINUTE);
int currentHour = now.get(Calendar.HOUR_OF_DAY);
int currentMin = now.get(Calendar.MINUTE);
if (currentHour != alarmHour && currentMin != alarmMin) {
return true;
}
} }
return false; eventQueue.clear();
} }
/** /**
* Creates the notification. * Set an alarm.
*
* @param options
* The options that can be specified per alarm.
* @param doFireEvent
* If the onadd callback shall be called.
*/ */
@SuppressLint("NewApi") public static void add (Options options, boolean doFireEvent) {
private Builder buildNotification () { long triggerTime = options.getDate();
Bitmap icon = BitmapFactory.decodeResource(context.getResources(), options.getIcon());
Uri sound = options.getSound(); Intent intent = new Intent(context, Receiver.class)
.setAction("" + options.getId())
Builder notification = new NotificationCompat.Builder(context) .putExtra(Receiver.OPTIONS, options.getJSONObject().toString());
.setContentTitle(options.getTitle())
.setContentText(options.getMessage()) AlarmManager am = getAlarmManager();
.setNumber(options.getBadge()) PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
.setTicker(options.getMessage())
.setSmallIcon(options.getSmallIcon()) if (doFireEvent) {
.setLargeIcon(icon) fireEvent("add", options.getId(), options.getJSON());
.setAutoCancel(options.getAutoCancel())
.setOngoing(options.getOngoing());
if (sound != null) {
notification.setSound(sound);
} }
if (Build.VERSION.SDK_INT > 16) { am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
notification.setStyle(new NotificationCompat.BigTextStyle() }
.bigText(options.getMessage()));
/**
* Cancel a specific notification that was previously registered.
*
* @param notificationId
* The original ID of the notification that was used when it was
* registered using add()
*/
public static void cancel (String notificationId) {
/*
* Create an intent that looks similar, to the one that was registered
* using add. Making sure the notification id in the action is the same.
* Now we can search for such an intent using the 'getService' method
* and cancel it.
*/
Intent intent = new Intent(context, Receiver.class)
.setAction("" + notificationId);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = getAlarmManager();
NotificationManager nc = getNotificationManager();
am.cancel(pi);
try {
nc.cancel(Integer.parseInt(notificationId));
} catch (Exception e) {}
fireEvent("cancel", notificationId, "");
}
/**
* Cancel all notifications that were created by this plugin.
*
* Android can only unregister a specific alarm. There is no such thing
* as cancelAll. Therefore we rely on the Shared Preferences which holds
* all our alarms to loop through these alarms and unregister them one
* by one.
*/
public static void cancelAll() {
SharedPreferences settings = getSharedPreferences();
NotificationManager nc = getNotificationManager();
Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet();
for (String alarmId : alarmIds) {
cancel(alarmId);
} }
setClickEvent(notification); nc.cancelAll();
}
/**
* Checks wether a notification with an ID is scheduled.
*
* @param id
* The notification ID to be check.
* @param callbackContext
*/
public static void isScheduled (String id, CallbackContext callbackContext) {
SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll();
boolean isScheduled = alarms.containsKey(id);
PluginResult result = new PluginResult(PluginResult.Status.OK, isScheduled);
callbackContext.sendPluginResult(result);
}
/**
* Retrieves a list with all currently pending notifications.
*
* @param callbackContext
*/
public static void getScheduledIds (CallbackContext callbackContext) {
SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet();
JSONArray pendingIds = new JSONArray(alarmIds);
return notification; callbackContext.success(pendingIds);
} }
/** /**
* Adds an onclick handler to the notification * Persist the information of this alarm to the Android Shared Preferences.
* This will allow the application to restore the alarm upon device reboot.
* Also this is used by the cancelAll method.
*
* @param alarmId
* The Id of the notification that must be persisted.
* @param args
* The assumption is that parse has been called already.
*/ */
private Builder setClickEvent (Builder notification) { public static void persist (String alarmId, JSONArray args) {
Intent intent = new Intent(context, ReceiverActivity.class) Editor editor = getSharedPreferences().edit();
.putExtra(OPTIONS, options.getJSONObject().toString())
.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
int requestCode = new Random().nextInt(); if (alarmId != null) {
editor.putString(alarmId, args.toString());
editor.apply();
}
}
PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT); /**
* Remove a specific alarm from the Android shared Preferences.
*
* @param alarmId
* The Id of the notification that must be removed.
*/
public static void unpersist (String alarmId) {
Editor editor = getSharedPreferences().edit();
return notification.setContentIntent(contentIntent); if (alarmId != null) {
editor.remove(alarmId);
editor.apply();
}
} }
/** /**
* Shows the notification * Clear all alarms from the Android shared Preferences.
*/ */
@SuppressWarnings("deprecation") public static void unpersistAll () {
@SuppressLint("NewApi") Editor editor = getSharedPreferences().edit();
private void showNotification (Builder notification) {
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int id = 0;
try { editor.clear();
id = Integer.parseInt(options.getId()); editor.apply();
} catch (Exception e) {} }
if (Build.VERSION.SDK_INT<16) { /**
// build notification for HoneyComb to ICS * Fires the given event.
mgr.notify(id, notification.getNotification()); *
} else if (Build.VERSION.SDK_INT>15) { * @param {String} event The Name of the event
// Notification for Jellybean and above * @param {String} id The ID of the notification
mgr.notify(id, notification.build()); * @param {String} json A custom (JSON) string
*/
public static void fireEvent (String event, String id, String json) {
String state = getApplicationState();
String params = "\"" + id + "\",\"" + state + "\",\\'" + JSONObject.quote(json) + "\\'.replace(/(^\"|\"$)/g, \\'\\')";
String js = "setTimeout('plugin.notification.local.on" + event + "(" + params + ")',0)";
// webview may available, but callbacks needs to be executed
// after deviceready
if (deviceready == false) {
eventQueue.add(js);
} else {
webView.sendJavascript(js);
} }
} }
/** /**
* Fires ontrigger event. * Retrieves the application state
*
* @return {String}
* Either "background" or "foreground"
*/
protected static String getApplicationState () {
return isInBackground ? "background" : "foreground";
}
/**
* Set the application context if not already set.
*/
protected static void setContext (Context context) {
if (LocalNotification.context == null) {
LocalNotification.context = context;
}
}
/**
* The Local storage for the application.
*/
protected static SharedPreferences getSharedPreferences () {
return context.getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE);
}
/**
* The alarm manager for the application.
*/
protected static AlarmManager getAlarmManager () {
return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
/**
* The notification manager for the application.
*/ */
private void fireTriggerEvent () { protected static NotificationManager getNotificationManager () {
LocalNotification.fireEvent("trigger", options.getId(), options.getJSON()); return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment