Browse Source

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

Sebastián Katzer 11 năm trước cách đây
mục cha
commit
504b36cb09
2 tập tin đã thay đổi với 112 bổ sung293 xóa
  1. BIN
      libs/android/android-support-v4.jar
  2. 112 293
      src/android/LocalNotification.java

BIN
libs/android/android-support-v4.jar


+ 112 - 293
src/android/LocalNotification.java

@@ -21,352 +21,171 @@
 
 package de.appplant.cordova.plugin.localnotification;
 
-import java.util.ArrayList;
-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 java.util.Calendar;
+import java.util.Random;
+
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import android.app.AlarmManager;
+import android.annotation.SuppressLint;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationCompat.*;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
 
 /**
- * This plugin utilizes the Android AlarmManager in combination with StatusBar
- * notifications. When a local notification is scheduled the alarm manager takes
- * care of firing the event. When the event is processed, a notification is put
- * in the Android status bar.
+ * The alarm receiver is triggered when a scheduled alarm is fired. This class
+ * reads the information in the intent and displays this information in the
+ * Android notification bar. The notification uses the default notification
+ * sound and it vibrates the phone.
  */
-public class LocalNotification extends CordovaPlugin {
-
-    protected final static String PLUGIN_NAME = "LocalNotification";
+public class Receiver extends BroadcastReceiver {
 
-    private   static CordovaWebView webView = null;
-    private   static Boolean deviceready = false;
-    protected static Context context = null;
-    protected static Boolean isInBackground = true;
-    private   static ArrayList<String> eventQueue = new ArrayList<String>();
+    public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
 
-    @Override
-    public void initialize (CordovaInterface cordova, CordovaWebView webView) {
-        super.initialize(cordova, webView);
-
-        LocalNotification.webView = super.webView;
-        LocalNotification.context = super.cordova.getActivity().getApplicationContext();
-    }
+    private Context context;
+    private Options options;
 
     @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;
-        }
-
-        if (action.equalsIgnoreCase("cancel")) {
-            cordova.getThreadPool().execute( new Runnable() {
-                public void run() {
-                    String id = args.optString(0);
-
-                    cancel(id);
-                    unpersist(id);
-                }
-            });
-
-            return true;
-        }
+    public void onReceive (Context context, Intent intent) {
+        Options options = null;
+        Bundle bundle   = intent.getExtras();
+        JSONObject args;
 
-        if (action.equalsIgnoreCase("cancelAll")) {
-            cordova.getThreadPool().execute( new Runnable() {
-                public void run() {
-                    cancelAll();
-                    unpersistAll();
-                }
-            });
-
-            return true;
-        }
-
-        if (action.equalsIgnoreCase("isScheduled")) {
-            String id = args.optString(0);
-
-            isScheduled(id, callbackContext);
-
-            return true;
-        }
-
-        if (action.equalsIgnoreCase("getScheduledIds")) {
-            getScheduledIds(callbackContext);
-
-            return true;
+        try {
+            args    = new JSONObject(bundle.getString(OPTIONS));
+            options = new Options(context).parse(args);
+        } catch (JSONException e) {
+            return;
         }
 
-        if (action.equalsIgnoreCase("deviceready")) {
-            cordova.getThreadPool().execute( new Runnable() {
-                public void run() {
-                    deviceready();
-                }
-            });
+        this.context = context;
+        this.options = options;
 
-            return true;
-        }
+        // The context may got lost if the app was not running before
+        LocalNotification.setContext(context);
 
-        if (action.equalsIgnoreCase("pause")) {
-            isInBackground = true;
+        fireTriggerEvent();
 
-            return true;
+        if (options.getInterval() == 0) {
+            LocalNotification.unpersist(options.getId());
+        } else if (isFirstAlarmInFuture()) {
+            return;
+        } else {
+            LocalNotification.add(options.moveDate(), false);
         }
 
-        if (action.equalsIgnoreCase("resume")) {
-            isInBackground = false;
-
-            return true;
-        }
+        Builder notification = buildNotification();
 
-        // Returning false results in a "MethodNotFound" error.
-        return false;
+        showNotification(notification);
     }
 
-    /**
-     * Calls all pending callbacks after the deviceready event has been fired.
+    /*
+     * If you set a repeating alarm at 11:00 in the morning and it
+     * 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 static void deviceready () {
-        deviceready = true;
-
-        for (String js : eventQueue) {
-            webView.sendJavascript(js);
+    private Boolean isFirstAlarmInFuture () {
+        if (options.getInterval() > 0) {
+            Calendar now    = Calendar.getInstance();
+            Calendar alarm  = options.getCalendar();
+
+            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;
+            }
         }
 
-        eventQueue.clear();
+        return false;
     }
 
     /**
-     * Set an alarm.
-     *
-     * @param options
-     *            The options that can be specified per alarm.
-     * @param doFireEvent
-     *            If the onadd callback shall be called.
+     * Creates the notification.
      */
-    public static void add (Options options, boolean doFireEvent) {
-        long triggerTime = options.getDate();
-
-        Intent intent = new Intent(context, Receiver.class)
-            .setAction("" + options.getId())
-            .putExtra(Receiver.OPTIONS, options.getJSONObject().toString());
-
-        AlarmManager am  = getAlarmManager();
-        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-
-        if (doFireEvent) {
-            fireEvent("add", options.getId(), options.getJSON());
+    @SuppressLint("NewApi")
+    private Builder buildNotification () {
+        Bitmap icon = BitmapFactory.decodeResource(context.getResources(), options.getIcon());
+        Uri sound   = options.getSound();
+
+        Builder notification = new NotificationCompat.Builder(context)
+            .setContentTitle(options.getTitle())
+            .setContentText(options.getMessage())
+            .setNumber(options.getBadge())
+            .setTicker(options.getMessage())
+            .setSmallIcon(options.getSmallIcon())
+            .setLargeIcon(icon)
+            .setAutoCancel(options.getAutoCancel())
+            .setOngoing(options.getOngoing());
+
+        if (sound != null) {
+            notification.setSound(sound);
         }
 
-        am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
-    }
-
-    /**
-     * 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);
+        if (Build.VERSION.SDK_INT > 16) {
+            notification.setStyle(new NotificationCompat.BigTextStyle()
+                .bigText(options.getMessage()));
         }
 
-        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);
+        setClickEvent(notification);
 
-        callbackContext.success(pendingIds);
+        return 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.
+     * Adds an onclick handler to the notification
      */
-    public static void persist (String alarmId, JSONArray args) {
-        Editor editor = getSharedPreferences().edit();
+    private Builder setClickEvent (Builder notification) {
+        Intent intent = new Intent(context, ReceiverActivity.class)
+            .putExtra(OPTIONS, options.getJSONObject().toString())
+            .setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
 
-        if (alarmId != null) {
-            editor.putString(alarmId, args.toString());
-            editor.apply();
-        }
-    }
+        int requestCode = new Random().nextInt();
 
-    /**
-     * 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();
+        PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
 
-        if (alarmId != null) {
-            editor.remove(alarmId);
-            editor.apply();
-        }
+        return notification.setContentIntent(contentIntent);
     }
 
     /**
-     * Clear all alarms from the Android shared Preferences.
+     * Shows the notification
      */
-    public static void unpersistAll () {
-        Editor editor = getSharedPreferences().edit();
-
-        editor.clear();
-        editor.apply();
-    }
+    @SuppressWarnings("deprecation")
+    @SuppressLint("NewApi")
+    private void showNotification (Builder notification) {
+        NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        int id                  = 0;
 
-    /**
-     * Fires the given event.
-     *
-     * @param {String} event The Name of the event
-     * @param {String} id    The ID of the notification
-     * @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);
-        }
-    }
-
-    /**
-     * Retrieves the application state
-     *
-     * @return {String}
-     *      Either "background" or "foreground"
-     */
-    protected static String getApplicationState () {
-        return isInBackground ? "background" : "foreground";
-    }
+        try {
+            id = Integer.parseInt(options.getId());
+        } catch (Exception e) {}
 
-    /**
-     * Set the application context if not already set.
-     */
-    protected static void setContext (Context context) {
-        if (LocalNotification.context == null) {
-            LocalNotification.context = context;
+        if (Build.VERSION.SDK_INT<16) {
+            // build notification for HoneyComb to ICS
+            mgr.notify(id, notification.getNotification());
+        } else if (Build.VERSION.SDK_INT>15) {
+            // Notification for Jellybean and above
+            mgr.notify(id, notification.build());
         }
     }
 
     /**
-     * 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.
+     * Fires ontrigger event.
      */
-    protected static NotificationManager getNotificationManager () {
-        return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+    private void fireTriggerEvent () {
+        LocalNotification.fireEvent("trigger", options.getId(), options.getJSON());
     }
-}
+}