Commit 331227c6 by Sebastián Katzer

Halbwegs funktionsfähiger Android Support

parent 8eda6a2d
package de.appplant.cordova.plugin;
import java.util.Calendar;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* 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.
*
* @author dvtoever
*/
public class AlarmReceiver extends BroadcastReceiver {
public static final String TITLE = "ALARM_TITLE";
public static final String SUBTITLE = "ALARM_SUBTITLE";
public static final String TICKER_TEXT = "ALARM_TICKER";
public static final String NOTIFICATION_ID = "NOTIFICATION_ID";
/* Contains time in 24hour format 'HH:mm' e.g. '04:30' or '18:23' */
public static final String HOUR_OF_DAY = "HOUR_OF_DAY";
public static final String MINUTE = "MINUTES";
@Override
public void onReceive(Context context, Intent intent) {
Log.d("AlarmReceiver", "AlarmReceiver invoked!");
final Bundle bundle = intent.getExtras();
final Object systemService = context.getSystemService(Context.NOTIFICATION_SERVICE);
// Retrieve notification details from the intent
final String tickerText = bundle.getString(TICKER_TEXT);
final String notificationTitle = bundle.getString(TITLE);
final String notificationSubText = bundle.getString(SUBTITLE);
int notificationId = 0;
try {
notificationId = Integer.parseInt(bundle.getString(NOTIFICATION_ID));
} catch (Exception e) {
Log.d("AlarmReceiver", "Unable to process alarm with id: " + bundle.getString(NOTIFICATION_ID));
}
Calendar currentCal = Calendar.getInstance();
int alarmHour = bundle.getInt(HOUR_OF_DAY);
int alarmMin = bundle.getInt(MINUTE);
int currentHour = currentCal.get(Calendar.HOUR_OF_DAY);
int currentMin = currentCal.get(Calendar.MINUTE);
if (currentHour != alarmHour && currentMin != alarmMin) {
/*
* 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'.
*/
Log.d(LocalNotification.PLUGIN_NAME, "AlarmReceiver, ignoring alarm since it is due");
return;
}
// Construct the notification and notificationManager objects
final NotificationManager notificationMgr = (NotificationManager) systemService;
final Notification notification = new Notification(R.drawable.ic_launcher, tickerText,
System.currentTimeMillis());
final PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
notification.defaults |= Notification.DEFAULT_SOUND;
notification.vibrate = new long[] { 0, 100, 200, 300 };
notification.setLatestEventInfo(context, notificationTitle, notificationSubText, contentIntent);
/*
* If you want all reminders to stay in the notification bar, you should
* generate a random ID. If you want do replace an existing
* notification, make sure the ID below matches the ID that you store in
* the alarm intent.
*/
notificationMgr.notify(notificationId, notification);
}
}
\ No newline at end of file
package de.appplant.cordova.plugin;
import java.util.Calendar;
import java.util.Map;
import java.util.Set;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
/**
* 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
* reboot.
*
* @author dvtoever
*/
public class AlarmRestoreOnBoot extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String pluginName = LocalNotification.PLUGIN_NAME;
// Obtain alarm details form Shared Preferences
final SharedPreferences alarmSettings = context.getSharedPreferences(pluginName, Context.MODE_PRIVATE);
final Map<String, ?> allAlarms = alarmSettings.getAll();
final Set<String> alarmIds = allAlarms.keySet();
/*
* For each alarm, parse its alarm options and register is again with
* the Alarm Manager
*/
for (String alarmId : alarmIds) {
try {
final AlarmHelper alarm = new AlarmHelper(context);
final JSONArray alarmDetails = new JSONArray(alarmSettings.getString(alarmId, ""));
final AlarmOptions options = new AlarmOptions();
options.parseOptions(alarmDetails);
final boolean daily = options.isRepeatDaily();
final String title = options.getAlarmTitle();
final String subTitle = options.getAlarmSubTitle();
final String ticker = options.getAlarmTicker();
final String id = options.getNotificationId();
final Calendar cal = options.getCal();
alarm.addAlarm(daily, title, subTitle, ticker, id, cal);
} catch (JSONException e) {
Log.d(pluginName,
"AlarmRestoreOnBoot: Error while restoring alarm details after reboot: " + e.toString());
}
Log.d(pluginName, "AlarmRestoreOnBoot: Successfully restored alarms upon reboot");
}
}
}
\ No newline at end of file
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
package de.appplant.cordova.plugin; package de.appplant.cordova.plugin;
import java.util.Calendar;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -40,14 +39,14 @@ public class LocalNotification extends CordovaPlugin { ...@@ -40,14 +39,14 @@ public class LocalNotification extends CordovaPlugin {
@Override @Override
public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException { public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
JSONObject arguments = args.getJSONObject(0); JSONObject arguments = args.getJSONObject(0);
LocalNotificationOptions options = new LocalNotificationOptions(); LocalNotificationOptions options = new LocalNotificationOptions(arguments);
options.parse(arguments); String alarmId = options.getId();
String alarmId = options.getNotificationId();
if (action.equalsIgnoreCase("add")) { if (action.equalsIgnoreCase("add")) {
if (alarmId != null)
persist(alarmId, args); persist(alarmId, args);
add(options); add(options);
return true; return true;
...@@ -58,10 +57,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -58,10 +57,9 @@ public class LocalNotification extends CordovaPlugin {
cancel(alarmId); cancel(alarmId);
return true; return true;
} }
if (action.equalsIgnoreCase("cancelall")) { if (action.equalsIgnoreCase("cancelAll")) {
unpersistAll(); unpersistAll();
cancelAll(); cancelAll();
...@@ -78,27 +76,18 @@ public class LocalNotification extends CordovaPlugin { ...@@ -78,27 +76,18 @@ public class LocalNotification extends CordovaPlugin {
* @param options * @param options
* The options that can be specified per alarm. * The options that can be specified per alarm.
*/ */
public void add(LocalNotificationOptions options) { private void add (LocalNotificationOptions options) {
Calendar calendar = options.getCalendar(); long triggerTime = options.getDate();
long triggerTime = calendar.getTimeInMillis(); Intent intent = new Intent(cordova.getActivity(), LocalNotificationReceiver.class);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int min = calendar.get(Calendar.MINUTE); intent.setAction("" + options.getId());
intent.putExtra(LocalNotificationReceiver.OPTIONS, options.getJSONObject().toString());
Intent intent = new Intent(cordova.getActivity(), AlarmReceiver.class);
intent.setAction("" + options.getNotificationId());
intent.putExtra(AlarmReceiver.TITLE, options.getTitle());
intent.putExtra(AlarmReceiver.SUBTITLE, options.getSubTitle());
intent.putExtra(AlarmReceiver.TICKER_TEXT, options.getTicker());
intent.putExtra(AlarmReceiver.NOTIFICATION_ID, options.getNotificationId());
intent.putExtra(AlarmReceiver.HOUR_OF_DAY, hour);
intent.putExtra(AlarmReceiver.MINUTE, min);
PendingIntent sender = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
/* Get the AlarmManager service */ /* Get the AlarmManager service */
AlarmManager am = getAlarmManager(); AlarmManager am = getAlarmManager();
PendingIntent sender = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (options.isRepeatDaily()) { if (options.getInterval() > 0) {
am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, AlarmManager.INTERVAL_DAY, sender); am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, AlarmManager.INTERVAL_DAY, sender);
} else { } else {
am.set(AlarmManager.RTC_WAKEUP, triggerTime, sender); am.set(AlarmManager.RTC_WAKEUP, triggerTime, sender);
...@@ -112,14 +101,14 @@ public class LocalNotification extends CordovaPlugin { ...@@ -112,14 +101,14 @@ public class LocalNotification extends CordovaPlugin {
* The original ID of the notification that was used when it was * The original ID of the notification that was used when it was
* registered using add() * registered using add()
*/ */
public void cancel (String notificationId) { private void cancel (String notificationId) {
/* /*
* Create an intent that looks similar, to the one that was registered * 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. * 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 * Now we can search for such an intent using the 'getService' method
* and cancel it. * and cancel it.
*/ */
Intent intent = new Intent(cordova.getActivity(), AlarmReceiver.class); Intent intent = new Intent(cordova.getActivity(), LocalNotificationReceiver.class);
intent.setAction("" + notificationId); intent.setAction("" + notificationId);
...@@ -139,7 +128,7 @@ public class LocalNotification extends CordovaPlugin { ...@@ -139,7 +128,7 @@ public class LocalNotification extends CordovaPlugin {
* all our alarms to loop through these alarms and unregister them one * all our alarms to loop through these alarms and unregister them one
* by one. * by one.
*/ */
public void cancelAll() { private void cancelAll() {
SharedPreferences settings = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE); SharedPreferences settings = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE);
Map<String, ?> alarms = settings.getAll(); Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet(); Set<String> alarmIds = alarms.keySet();
......
...@@ -9,10 +9,10 @@ ...@@ -9,10 +9,10 @@
package de.appplant.cordova.plugin; package de.appplant.cordova.plugin;
import java.util.Calendar;
import org.json.JSONObject; import org.json.JSONObject;
import android.R;
/** /**
* 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.
*/ */
...@@ -21,93 +21,84 @@ public class LocalNotificationOptions { ...@@ -21,93 +21,84 @@ public class LocalNotificationOptions {
/* /*
* Options that can be set when this plugin is invoked * Options that can be set when this plugin is invoked
*/ */
private Calendar calendar = Calendar.getInstance(); private JSONObject options = new JSONObject();
private String title = null;
private String subTitle = null;
private String sound = null;
private long interval = 0;
private String foreground = null;
private String background = null;
private int icon = -1;
private int badge = 0;
private String id = null; private String id = null;
private long interval = 0;
private long date = 0;
/** /**
* Parse options passed from javascript part of this plugin. * Parse options passed from javascript part of this plugin.
*/ */
public void parse (JSONObject options) { LocalNotificationOptions (JSONObject options) {
String date = options.optString("date"); this.options = options;
String message = options.optString("message"); date = options.optLong("date") * 1000;
//interval = options.optString("repeat");
if (!"".equals(date)) { id = options.optString("id");
calendar.setTimeInMillis(1000*Long.parseLong(date));
} }
if (!"".equals(message)) { /**
String lines[] = message.split("\\r?\\n"); * Gibt die Eigenschaften als JSONObjekt an.
*/
title = lines[0]; public JSONObject getJSONObject() {
return options;
if (lines.length > 1)
subTitle = lines[1];
} }
sound = options.optString("sound"); /**
icon = options.optInt("icon"); * Gibt die Zeit in Sekunden an, wann die Notification aufpoppen soll.
//interval = options.optString("repeat"); */
foreground = options.optString("foreground"); public long getDate() {
background = options.optString("background"); return date;
badge = options.optInt("badge");
id = options.optString("id");
} }
/** /**
* Gibt den Kalender mit dem Datum der nächsten Notification an. * Gibt die Nachricht der Notification an.
*/ */
public Calendar getCalendar() { public String getMessage () {
return calendar; return options.optString("message");
} }
/** /**
* Gibt den Titel der Notification an. * Gibt den Titel der Notification an.
*/ */
public String getTitle () { public String getTitle () {
return title; return getMessage().split("\\r?\\n")[0];
} }
/** /**
* Gibt den Untertitel der Notification an. * Gibt den Untertitel der Notification an.
*/ */
public String getSubTitle () { public String getSubTitle () {
return subTitle; String[] lines = getMessage().split("\\r?\\n");
return (lines.length > 1) ? lines[1] : "";
} }
/** /**
* Gibt den Pfad zum Sound der Notification an. * Gibt den Pfad zum Sound der Notification an.
*/ */
public String getSound () { public String getSound () {
return sound; return options.optString("sound", null);
} }
/** /**
* Gibt den Pfad zum Icon der Notification an. * Gibt den Pfad zum Icon der Notification an.
*/ */
public int getIcon () { public int getIcon () {
return icon; return options.optInt("icon", R.drawable.ic_menu_info_details);
} }
/** /**
* Gibt den Pfad zur Callback-Funktion der Notification an. * Gibt den Pfad zur Callback-Funktion der Notification an.
*/ */
public String getForeground () { public String getForeground () {
return foreground; return options.optString("foreground", null);
} }
/** /**
* Gibt den Pfad zur Callback-Funktion der Notification an. * Gibt den Pfad zur Callback-Funktion der Notification an.
*/ */
public String getBackground () { public String getBackground () {
return background; return options.optString("background", null);
} }
/** /**
...@@ -121,7 +112,7 @@ public class LocalNotificationOptions { ...@@ -121,7 +112,7 @@ public class LocalNotificationOptions {
* Gibt die Badge-Nummer der Notification an. * Gibt die Badge-Nummer der Notification an.
*/ */
public int getBadge () { public int getBadge () {
return badge; return options.optInt("badge", 0);
} }
/** /**
......
/**
* LocalNotificationReceiver.java
* Cordova LocalNotification Plugin
*
* Created by Sebastian Katzer (github.com/katzer) on 31/08/2013.
* Copyright 2013 Sebastian Katzer. All rights reserved.
* GPL v2 licensed
*/
package de.appplant.cordova.plugin;
import java.util.Calendar;
import org.json.JSONException;
import org.json.JSONObject;
import android.R;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
/**
* 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.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class LocalNotificationReceiver extends BroadcastReceiver {
public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
@Override
public void onReceive (Context context, Intent intent) {
NotificationManager notificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
LocalNotificationOptions options = null;
Bundle bundle = intent.getExtras();
int id = 0;
JSONObject args;
try {
args = new JSONObject(bundle.getString(OPTIONS));
options = new LocalNotificationOptions(args);
} catch (JSONException e) {}
try {
id = Integer.parseInt(options.getId());
} catch (Exception e) {}
/*
* 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'.
*/
if (options.getInterval() > 0) {
Calendar now = Calendar.getInstance();
int alarmHour = 0;//bundle.getInt(HOUR_OF_DAY);
int alarmMin = 0;//bundle.getInt(MINUTE);
int currentHour = now.get(Calendar.HOUR_OF_DAY);
int currentMin = now.get(Calendar.MINUTE);
if (currentHour != alarmHour && currentMin != alarmMin) {
return;
}
}
Builder notification = new Notification.Builder(context)
.setContentTitle(options.getTitle())
.setContentText(options.getSubTitle())
//.setVibrate(new long[] { 0, 100, 200, 300 })
.setDefaults(Notification.DEFAULT_SOUND)
.setNumber(0)
.setSmallIcon(options.getIcon());
/*
* If you want all reminders to stay in the notification bar, you should
* generate a random ID. If you want do replace an existing
* notification, make sure the ID below matches the ID that you store in
* the alarm intent.
*/
notificationMgr.notify(id, notification.build());
}
}
\ 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