Commit 0c0b1079 by Sebastián Katzer

Huge Android rework.

parent 7c94104d
...@@ -50,14 +50,14 @@ ...@@ -50,14 +50,14 @@
* Android notification bar. The notification uses the default notification * Android notification bar. The notification uses the default notification
* sound and it vibrates the phone. * sound and it vibrates the phone.
--> -->
<receiver android:name="de.appplant.cordova.plugin.localnotification.LocalNotificationReceiver" /> <receiver android:name="de.appplant.cordova.plugin.localnotification.Receiver" />
<!-- <!--
* This class is triggered upon reboot of the device. It needs to re-register * This class is triggered upon reboot of the device. It needs to re-register
* the alarms with the AlarmManager since these alarms are lost in case of * the alarms with the AlarmManager since these alarms are lost in case of
* reboot. * reboot.
--> -->
<receiver android:name="de.appplant.cordova.plugin.localnotification.LocalNotificationRestore" > <receiver android:name="de.appplant.cordova.plugin.localnotification.Restore" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> </intent-filter>
...@@ -66,12 +66,13 @@ ...@@ -66,12 +66,13 @@
<config-file target="AndroidManifest.xml" parent="/manifest"> <config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</config-file> </config-file>
<source-file src="src/android/LocalNotificationReceiver.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/LocalNotificationOptions.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/LocalNotificationRestore.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/LocalNotification.java" target-dir="src/de/appplant/cordova/plugin/localnotification" /> <source-file src="src/android/LocalNotification.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/Receiver.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/Options.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/Restore.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
</platform> </platform>
<!-- wp8 --> <!-- wp8 -->
......
/**
* Cordova LocalNotification Plugin
*
* Created by Sebastian Katzer (github.com/katzer).
* Copyright 2013 Sebastian Katzer. All rights reserved.
* LGPL v2.1 licensed
*/
package de.appplant.cordova.plugin.localnotification;
import java.util.Map;
import java.util.Set;
import org.json.JSONArray;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
public class Helper {
private Context context;
public Helper(Context context) {
this.context = context;
}
/**
* Set an alarm.
*
* @param options
* The options that can be specified per alarm.
*/
public void add (Options options) {
long triggerTime = options.getDate();
Intent intent = new Intent(context, Receiver.class);
intent.setAction("" + options.getId());
intent.putExtra(Receiver.OPTIONS, options.getJSONObject().toString());
AlarmManager am = getAlarmManager();
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (options.getInterval() > 0) {
am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, options.getInterval(), pi);
} else {
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 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);
intent.setAction("" + notificationId);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = getAlarmManager();
try {
am.cancel(pi);
} catch (Exception e) {}
}
/**
* 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 void cancelAll() {
SharedPreferences settings = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE);
Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet();
for (String alarmId : alarmIds) {
cancel(alarmId);
}
}
/**
* 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 args
* The assumption is that parse has been called already.
*/
public void persist (String alarmId, JSONArray args) {
Editor editor = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE).edit();
if (alarmId != null) {
editor.putString(alarmId, args.toString());
editor.commit();
}
}
/**
* Remove a specific alarm from the Android shared Preferences.
*
* @param alarmId
* The Id of the notification that must be removed.
*/
public void unpersist (String alarmId) {
Editor editor = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE).edit();
if (alarmId != null) {
editor.remove(alarmId);
editor.commit();
}
}
/**
* Clear all alarms from the Android shared Preferences.
*/
public void unpersistAll () {
Editor editor = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE).edit();
editor.clear();
editor.commit();
}
private AlarmManager getAlarmManager () {
return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
}
\ No newline at end of file
/** /**
* LocalNotification.java
* Cordova LocalNotification Plugin * Cordova LocalNotification Plugin
* *
* Created by Sebastian Katzer (github.com/katzer) on 31/08/2013. * Created by Sebastian Katzer (github.com/katzer).
* Copyright 2013 Sebastian Katzer. All rights reserved. * Copyright 2013 Sebastian Katzer. All rights reserved.
* GPL v2 licensed * LGPL v2.1 licensed
*/ */
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import java.util.Map;
import java.util.Set;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.content.Intent;
import android.content.Context; import android.content.Context;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext; import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
...@@ -39,15 +28,24 @@ public class LocalNotification extends CordovaPlugin { ...@@ -39,15 +28,24 @@ public class LocalNotification extends CordovaPlugin {
public static final String PLUGIN_NAME = "LocalNotification"; public static final String PLUGIN_NAME = "LocalNotification";
public static CordovaInterface cordova = null;
public static CordovaWebView webView = null; public static CordovaWebView webView = null;
public static Context context = null;
@Override @Override
public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException { public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
rememberCordovaVarsForStaticUse(); rememberCordovaVarsForStaticUse();
if (action.equalsIgnoreCase("add")) { if (action.equalsIgnoreCase("add")) {
addWithoutBlocking(args); JSONObject arguments = args.optJSONObject(0);
final Options options = new Options(context).parse(arguments);
persist(options.getId(), args);
cordova.getThreadPool().execute( new Runnable() {
public void run() {
add(options);
}
});
return true; return true;
} }
...@@ -72,40 +70,16 @@ public class LocalNotification extends CordovaPlugin { ...@@ -72,40 +70,16 @@ public class LocalNotification extends CordovaPlugin {
return false; return false;
} }
private static void addWithoutBlocking (final JSONArray args) {
cordova.getThreadPool().execute(new Runnable() {
public void run() {
JSONObject arguments = args.optJSONObject(0);
Activity activity = cordova.getActivity();
LocalNotificationOptions options = new LocalNotificationOptions(activity).parse(arguments);
persist(options.getId(), args);
add(options);
}
});
}
/** /**
* Set an alarm * Set an alarm.
* *
* @param options * @param options
* The options that can be specified per alarm. * The options that can be specified per alarm.
*/ */
public static void add (LocalNotificationOptions options) { public static void add (Options options) {
long triggerTime = options.getDate(); Helper helper = new Helper(context);
Intent intent = new Intent(cordova.getActivity(), LocalNotificationReceiver.class);
intent.setAction("" + options.getId());
intent.putExtra(LocalNotificationReceiver.OPTIONS, options.getJSONObject().toString());
AlarmManager am = getAlarmManager();
PendingIntent pi = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (options.getInterval() > 0) { helper.add(options);
am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, options.getInterval(), pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
}
} }
/** /**
...@@ -116,22 +90,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -116,22 +90,9 @@ public class LocalNotification extends CordovaPlugin {
* registered using add() * registered using add()
*/ */
public static void cancel (String notificationId) { public static void cancel (String notificationId) {
/* Helper helper = new Helper(context);
* 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. helper.cancel(notificationId);
* Now we can search for such an intent using the 'getService' method
* and cancel it.
*/
Intent intent = new Intent(cordova.getActivity(), LocalNotificationReceiver.class);
intent.setAction("" + notificationId);
PendingIntent pi = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = getAlarmManager();
try {
am.cancel(pi);
} catch (Exception e) {}
} }
/** /**
...@@ -143,13 +104,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -143,13 +104,9 @@ public class LocalNotification extends CordovaPlugin {
* by one. * by one.
*/ */
public static void cancelAll() { public static void cancelAll() {
SharedPreferences settings = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE); Helper helper = new Helper(context);
Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet();
for (String alarmId : alarmIds) { helper.cancelAll();
cancel(alarmId);
}
} }
/** /**
...@@ -161,12 +118,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -161,12 +118,9 @@ public class LocalNotification extends CordovaPlugin {
* The assumption is that parse has been called already. * The assumption is that parse has been called already.
*/ */
public static void persist (String alarmId, JSONArray args) { public static void persist (String alarmId, JSONArray args) {
Editor editor = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit(); Helper helper = new Helper(context);
if (alarmId != null) { helper.persist(alarmId, args);
editor.putString(alarmId, args.toString());
editor.commit();
}
} }
/** /**
...@@ -176,33 +130,25 @@ public class LocalNotification extends CordovaPlugin { ...@@ -176,33 +130,25 @@ public class LocalNotification extends CordovaPlugin {
* The Id of the notification that must be removed. * The Id of the notification that must be removed.
*/ */
public static void unpersist (String alarmId) { public static void unpersist (String alarmId) {
Editor editor = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit(); Helper helper = new Helper(context);
if (alarmId != null) { helper.unpersist(alarmId);
editor.remove(alarmId);
editor.commit();
}
} }
/** /**
* Clear all alarms from the Android shared Preferences. * Clear all alarms from the Android shared Preferences.
*/ */
public static void unpersistAll () { public static void unpersistAll () {
Editor editor = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit(); Helper helper = new Helper(context);
editor.clear();
editor.commit();
}
private static AlarmManager getAlarmManager () { helper.unpersistAll();
return (AlarmManager) cordova.getActivity().getSystemService(Context.ALARM_SERVICE);
} }
/** /**
* Save required Cordova specific variables for later use. * Save required Cordova specific variables for later use.
*/ */
private void rememberCordovaVarsForStaticUse () { private void rememberCordovaVarsForStaticUse () {
LocalNotification.cordova = super.cordova;
LocalNotification.webView = super.webView; LocalNotification.webView = super.webView;
LocalNotification.context = super.cordova.getActivity();
} }
} }
\ No newline at end of file
/** /**
* LocalNotificationOptions.java
* Cordova LocalNotification Plugin * Cordova LocalNotification Plugin
* *
* Created by Sebastian Katzer (github.com/katzer) on 31/08/2013. * Created by Sebastian Katzer (github.com/katzer).
* Copyright 2013 Sebastian Katzer. All rights reserved. * Copyright 2013 Sebastian Katzer. All rights reserved.
* GPL v2 licensed * LGPL v2.1 licensed
*/ */
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
...@@ -23,29 +22,26 @@ import android.net.Uri; ...@@ -23,29 +22,26 @@ import android.net.Uri;
/** /**
* Class that helps to store the options that can be specified per alarm. * Class that helps to store the options that can be specified per alarm.
*/ */
public class LocalNotificationOptions { public class Options {
/*
* Options that can be set when this plugin is invoked
*/
private JSONObject options = new JSONObject(); private JSONObject options = new JSONObject();
private String id = null; private String id = null;
private String packageName = null; private String packageName = null;
private long interval = 0; private long interval = 0;
private long date = 0; private long date = 0;
LocalNotificationOptions (Activity activity) { Options (Activity activity) {
packageName = activity.getPackageName(); packageName = activity.getPackageName();
} }
LocalNotificationOptions (Context context) { Options (Context context) {
packageName = context.getPackageName(); packageName = context.getPackageName();
} }
/** /**
* Parst die übergebenen Eigenschaften. * Parst die übergebenen Eigenschaften.
*/ */
public LocalNotificationOptions parse (JSONObject options) { public Options parse (JSONObject options) {
String repeat = options.optString("repeat"); String repeat = options.optString("repeat");
this.options = options; this.options = options;
......
/** /**
* LocalNotificationReceiver.java
* Cordova LocalNotification Plugin * Cordova LocalNotification Plugin
* *
* Created by Sebastian Katzer (github.com/katzer) on 31/08/2013. * Created by Sebastian Katzer (github.com/katzer).
* Copyright 2013 Sebastian Katzer. All rights reserved. * Copyright 2013 Sebastian Katzer. All rights reserved.
* GPL v2 licensed * LGPL v2.1 licensed
*/ */
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
...@@ -32,22 +31,22 @@ import android.os.Bundle; ...@@ -32,22 +31,22 @@ import android.os.Bundle;
* Android notification bar. The notification uses the default notification * Android notification bar. The notification uses the default notification
* sound and it vibrates the phone. * sound and it vibrates the phone.
*/ */
public class LocalNotificationReceiver extends BroadcastReceiver { public class Receiver extends BroadcastReceiver {
public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS"; public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
private Context context; private Context context;
private LocalNotificationOptions options; private Options options;
@Override @Override
public void onReceive (Context context, Intent intent) { public void onReceive (Context context, Intent intent) {
LocalNotificationOptions options = null; Options options = null;
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
JSONObject args; JSONObject args;
try { try {
args = new JSONObject(bundle.getString(OPTIONS)); args = new JSONObject(bundle.getString(OPTIONS));
options = new LocalNotificationOptions(context).parse(args); options = new Options(context).parse(args);
} catch (JSONException e) {} } catch (JSONException e) {}
this.context = context; this.context = context;
...@@ -62,8 +61,7 @@ public class LocalNotificationReceiver extends BroadcastReceiver { ...@@ -62,8 +61,7 @@ public class LocalNotificationReceiver extends BroadcastReceiver {
Builder notification = buildNotification(); Builder notification = buildNotification();
if (!isInBackground(context)) { if (!isInBackground(context)) {
// exec foreground callback invokeForegroundCallback();
invokeForegroundCallback(options);
} }
showNotification(notification); showNotification(notification);
...@@ -154,22 +152,26 @@ public class LocalNotificationReceiver extends BroadcastReceiver { ...@@ -154,22 +152,26 @@ public class LocalNotificationReceiver extends BroadcastReceiver {
/** /**
* Ruft die `foreground` Callback Funktion auf. * Ruft die `foreground` Callback Funktion auf.
*/ */
private void invokeForegroundCallback (LocalNotificationOptions options) { private void invokeForegroundCallback () {
String function = options.getForeground(); String function = options.getForeground();
if (function != null) { // after reboot, LocalNotification.webView is always null
LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")"); // may be call foreground callback later
} if (function != null && LocalNotification.webView != null) {
LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")");
}
} }
/** /**
* Ruft die `background` Callback Funktion auf. * Ruft die `background` Callback Funktion auf.
*/ */
private void invokeBackgroundCallback (LocalNotificationOptions options) { private void invokeBackgroundCallback () {
String function = options.getBackground(); String function = options.getBackground();
if (function != null) { // after reboot, LocalNotification.webView is always null
LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")"); // may be call background callback later
} if (function != null && LocalNotification.webView != null) {
LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")");
}
} }
} }
\ No newline at end of file
/** /**
* LocalNotificationRestore.java
* Cordova LocalNotification Plugin * Cordova LocalNotification Plugin
* *
* Created by Sebastian Katzer (github.com/katzer) on 31/08/2013. * Created by Sebastian Katzer (github.com/katzer).
* Copyright 2013 Sebastian Katzer. All rights reserved. * Copyright 2013 Sebastian Katzer. All rights reserved.
* GPL v2 licensed * LGPL v2.1 licensed
*/ */
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import java.util.Set; import java.util.Set;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
...@@ -24,16 +23,12 @@ import android.content.SharedPreferences; ...@@ -24,16 +23,12 @@ import android.content.SharedPreferences;
* the alarms with the AlarmManager since these alarms are lost in case of * the alarms with the AlarmManager since these alarms are lost in case of
* reboot. * reboot.
*/ */
public class LocalNotificationRestore extends BroadcastReceiver { public class Restore extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
String pluginName = LocalNotification.PLUGIN_NAME; String pluginName = LocalNotification.PLUGIN_NAME;
if (LocalNotification.cordova == null) {
return;
}
// Obtain alarm details form Shared Preferences // Obtain alarm details form Shared Preferences
SharedPreferences alarms = context.getSharedPreferences(pluginName, Context.MODE_PRIVATE); SharedPreferences alarms = context.getSharedPreferences(pluginName, Context.MODE_PRIVATE);
Set<String> alarmIds = alarms.getAll().keySet(); Set<String> alarmIds = alarms.getAll().keySet();
...@@ -43,14 +38,12 @@ public class LocalNotificationRestore extends BroadcastReceiver { ...@@ -43,14 +38,12 @@ public class LocalNotificationRestore extends BroadcastReceiver {
* the Alarm Manager * the Alarm Manager
*/ */
for (String alarmId : alarmIds) { for (String alarmId : alarmIds) {
LocalNotificationOptions options;
JSONObject args;
try { try {
args = new JSONObject(alarms.getString(alarmId, "")); JSONArray args = new JSONArray(alarms.getString(alarmId, ""));
options = new LocalNotificationOptions(context).parse(args); Options options = new Options(context).parse(args.getJSONObject(0));
LocalNotification.add(options); LocalNotification.add(options);
} catch (JSONException e) {} } catch (JSONException e) {}
} }
} }
......
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