Commit e364b93b by PKnittel

Added getFunctions to request notifications arguments

Changed add-,cancel-, and clear function
Revised class-structure
parent e60af757
......@@ -100,10 +100,15 @@
<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" />
<source-file src="src/android/ReceiverActivity.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/DeleteIntentReceiver.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/notification/Options.java" target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file src="src/android/notification/Asset.java" target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file src="src/android/notification/Manager.java" target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file src="src/android/notification/NotificationBuilder.java" target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file src="src/android/notification/NotificationWrapper.java" target-dir="src/de/appplant/cordova/plugin/notification" />
</platform>
<!-- wp8 -->
......
......@@ -23,6 +23,7 @@ package de.appplant.cordova.plugin.localnotification;
import java.util.Date;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
......@@ -31,10 +32,15 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import de.appplant.cordova.plugin.notification.Options;
public class DeleteIntentReceiver extends BroadcastReceiver {
public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
/**
* Is called when a Notification is cleared manualy by the User
*/
@Override
public void onReceive(Context context, Intent intent) {
Options options = null;
......@@ -53,7 +59,8 @@ public class DeleteIntentReceiver extends BroadcastReceiver {
Date now = new Date();
if ((options.getInterval()!=0)){
LocalNotification.persist(options.getId(), setInitDate(args));
options.setInitDate();
LocalNotification.persist(options.getId(), options.getJSONObject());
}
else if((new Date(options.getDate()).before(now))){
LocalNotification.unpersist(options.getId());
......@@ -62,21 +69,12 @@ public class DeleteIntentReceiver extends BroadcastReceiver {
fireClearEvent(options);
}
private JSONObject setInitDate(JSONObject arguments){
long initialDate = arguments.optLong("date", 0) * 1000;
try {
arguments.put("initialDate", initialDate);
} catch (JSONException e) {
e.printStackTrace();
}
return arguments;
}
/**
* Fires onclear event.
*/
private void fireClearEvent (Options options) {
LocalNotification.fireEvent("clear", options.getId(), options.getJSON());
JSONArray data = new JSONArray().put(options.getJSONObject());
LocalNotification.fireEvent("clear", options.getId(), options.getJSON(),data);
}
}
......@@ -22,23 +22,18 @@
package de.appplant.cordova.plugin.localnotification;
import java.util.Calendar;
import java.util.Random;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
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.net.Uri;
import android.os.Build;
import android.os.Bundle;
import de.appplant.cordova.plugin.notification.*;
/**
* 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
......@@ -49,11 +44,12 @@ public class Receiver extends BroadcastReceiver {
public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
private Context context;
private Options options;
@Override
public void onReceive (Context context, Intent intent) {
NotificationWrapper nWrapper = new NotificationWrapper(context,
Receiver.class,LocalNotification.PLUGIN_NAME,OPTIONS);
Options options = null;
Bundle bundle = intent.getExtras();
JSONObject args;
......@@ -64,10 +60,11 @@ public class Receiver extends BroadcastReceiver {
} catch (JSONException e) {
return;
}
this.context = context;
this.options = options;
NotificationBuilder builder = new NotificationBuilder(options,context,OPTIONS,
DeleteIntentReceiver.class,ReceiverActivity.class);
// The context may got lost if the app was not running before
LocalNotification.setContext(context);
......@@ -77,18 +74,18 @@ public class Receiver extends BroadcastReceiver {
} else if (isFirstAlarmInFuture()) {
return;
} else {
LocalNotification.add(options.moveDate(), false);
nWrapper.schedule(options.moveDate());
}
if (!LocalNotification.isInBackground && options.getForegroundMode()){
if (options.getInterval() == 0) {
LocalNotification.unpersist(options.getId());
}
LocalNotification.showNotification(options.getTitle(), options.getMessage());
builder.showNotificationToast();
fireTriggerEvent();
} else {
Builder notification = buildNotification();
builder.buildNotification();
showNotification(notification);
builder.showNotification();
}
}
......@@ -118,85 +115,10 @@ public class Receiver extends BroadcastReceiver {
}
/**
* Creates the notification.
*/
@SuppressLint("NewApi")
private Builder buildNotification () {
Uri sound = options.getSound();
//DeleteIntent is called when the user clears a notification manually
Intent deleteIntent = new Intent(context, DeleteIntentReceiver.class)
.setAction("" + options.getId())
.putExtra(Receiver.OPTIONS, options.getJSONObject().toString());
PendingIntent dpi = PendingIntent.getBroadcast(context, 0, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Builder notification = new NotificationCompat.Builder(context)
.setDefaults(0) // Do not inherit any defaults
.setContentTitle(options.getTitle())
.setContentText(options.getMessage())
.setNumber(options.getBadge())
.setTicker(options.getMessage())
.setSmallIcon(options.getSmallIcon())
.setLargeIcon(options.getIcon())
.setAutoCancel(options.getAutoCancel())
.setOngoing(options.getOngoing())
.setLights(options.getColor(), 500, 500)
.setDeleteIntent(dpi);
if (sound != null) {
notification.setSound(sound);
}
if (Build.VERSION.SDK_INT > 16) {
notification.setStyle(new NotificationCompat.BigTextStyle()
.bigText(options.getMessage()));
}
setClickEvent(notification);
return notification;
}
/**
* Adds an onclick handler to the notification
*/
private Builder setClickEvent (Builder notification) {
Intent intent = new Intent(context, ReceiverActivity.class)
.putExtra(OPTIONS, options.getJSONObject().toString())
.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
int requestCode = new Random().nextInt();
PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return notification.setContentIntent(contentIntent);
}
/**
* Shows the notification
*/
@SuppressWarnings("deprecation")
private void showNotification (Builder notification) {
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int id = 0;
try {
id = Integer.parseInt(options.getId());
} catch (Exception e) {}
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());
}
}
/**
* Fires ontrigger event.
*/
private void fireTriggerEvent () {
LocalNotification.fireEvent("trigger", options.getId(), options.getJSON());
JSONArray data = new JSONArray().put(options.getJSONObject());
LocalNotification.fireEvent("trigger", options.getId(), options.getJSON(),data);
}
}
......@@ -23,12 +23,15 @@ package de.appplant.cordova.plugin.localnotification;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import de.appplant.cordova.plugin.notification.*;
public class ReceiverActivity extends Activity {
/** Called when the activity is first created. */
......@@ -65,10 +68,11 @@ public class ReceiverActivity extends Activity {
* Fires the onclick event.
*/
private void fireClickEvent (Options options) {
LocalNotification.fireEvent("click", options.getId(), options.getJSON());
JSONArray data = new JSONArray().put(options.getJSONObject());
LocalNotification.fireEvent("click", options.getId(), options.getJSON(),data);
if (options.getAutoCancel()) {
LocalNotification.fireEvent("cancel", options.getId(), options.getJSON());
LocalNotification.fireEvent("cancel", options.getId(), options.getJSON(),data);
}
}
}
......@@ -31,6 +31,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import de.appplant.cordova.plugin.notification.*;
/**
* 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
......@@ -42,6 +44,9 @@ public class Restore extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// The application context needs to be set as first
LocalNotification.setContext(context);
//Create NotificationWrapper
NotificationWrapper nWrapper = new NotificationWrapper(context,
Receiver.class,LocalNotification.PLUGIN_NAME,Receiver.OPTIONS);
// Obtain alarm details form Shared Preferences
SharedPreferences alarms = LocalNotification.getSharedPreferences();
......@@ -59,7 +64,7 @@ public class Restore extends BroadcastReceiver {
/*
* If the trigger date was in the past, the notification will be displayed immediately.
*/
LocalNotification.add(options, false);
nWrapper.schedule(options);
} catch (JSONException e) {}
}
......
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package de.appplant.cordova.plugin.notification;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.StrictMode;
import android.util.Log;
public class Asset {
private Activity activity;
protected final String STORAGE_FOLDER;
/**
* Constructor of Asset Class. Takes Applications Activity and a foldername for temporary saving.
*
*@param activity Applications Activity
*@param storageFolder foldername for temporary saving.
*/
public Asset(Activity activity,String storageFolder){
this.activity = activity;
this.STORAGE_FOLDER = storageFolder;
}
/**
* Parse given PathStrings to Uris
* @param notification Notifications JSONObject
* @return new Notification JSONObject with additional iconUri and soundUri
*/
public JSONObject parseURIs(JSONObject notification){
//sound
String sound = notification.optString("sound", null);
Uri soundUri = null;
if (sound != null) {
try {
int soundId = (Integer) RingtoneManager.class.getDeclaredField(sound).get(Integer.class);
soundUri = RingtoneManager.getDefaultUri(soundId);
} catch (Exception e) {
soundUri = getURIfromPath(sound);
}
}
if (soundUri!= null&&soundUri!=Uri.EMPTY){
try{
notification.put("soundUri", soundUri.toString());
} catch (JSONException jse){
jse.printStackTrace();
}
}
//image
String icon = notification.optString("icon", "icon");
Uri iconUri = null;
iconUri = getURIfromPath(icon);
if (iconUri != Uri.EMPTY&&iconUri != null){
try{
notification.put("iconUri", iconUri.toString());
} catch (JSONException jse){
jse.printStackTrace();
}
}
return notification;
}
/**
* The URI for a path.
*
* @param path The given path
*
* @return The URI pointing to the given path
*/
public Uri getURIfromPath(String path){
if (path.startsWith("res:")) {
return getUriForResourcePath(path);
} else if (path.startsWith("file:///")) {
return getUriForAbsolutePath(path);
} else if (path.startsWith("file://")) {
return getUriForAssetPath(path);
} else if (path.startsWith("http")){
return getUriForHTTP(path);
}
return Uri.parse(path);
}
/**
* The URI for a file.
*
* @param path
* The given absolute path
*
* @return The URI pointing to the given path
*/
private Uri getUriForAbsolutePath(String path) {
String absPath = path.replaceFirst("file://", "");
File file = new File(absPath);
if (!file.exists()) {
Log.e("Asset", "File not found: " + file.getAbsolutePath());
return Uri.EMPTY;
}
return Uri.fromFile(file);
}
/**
* The URI for an asset.
*
* @param path
* The given asset path
*
* @return The URI pointing to the given path
*/
private Uri getUriForAssetPath(String path) {
String resPath = path.replaceFirst("file:/", "www");
String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
File dir = activity.getExternalCacheDir();
if (dir == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
String storage = dir.toString() + STORAGE_FOLDER;
File file = new File(storage, fileName);
new File(storage).mkdir();
try {
AssetManager assets = activity.getAssets();
FileOutputStream outStream = new FileOutputStream(file);
InputStream inputStream = assets.open(resPath);
copyFile(inputStream, outStream);
outStream.flush();
outStream.close();
return Uri.fromFile(file);
} catch (Exception e) {
Log.e("Asset", "File not found: assets/" + resPath);
e.printStackTrace();
}
return Uri.EMPTY;
}
/**
* The URI for a resource.
*
* @param path
* The given relative path
*
* @return The URI pointing to the given path
*/
private Uri getUriForResourcePath(String path) {
String resPath = path.replaceFirst("res://", "");
String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
String resName = fileName.substring(0, fileName.lastIndexOf('.'));
String extension = resPath.substring(resPath.lastIndexOf('.'));
File dir = activity.getExternalCacheDir();
if (dir == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
String storage = dir.toString() + STORAGE_FOLDER;
int resId = getResId(resPath);
File file = new File(storage, resName + extension);
if (resId == 0) {
Log.e("Asset", "File not found: " + resPath);
return Uri.EMPTY;
}
new File(storage).mkdir();
try {
Resources res = activity.getResources();
FileOutputStream outStream = new FileOutputStream(file);
InputStream inputStream = res.openRawResource(resId);
copyFile(inputStream, outStream);
outStream.flush();
outStream.close();
return Uri.fromFile(file);
} catch (Exception e) {
e.printStackTrace();
}
return Uri.EMPTY;
}
/**
*Get Uri for HTTP Content
* @param path HTTP adress
* @return Uri of the downloaded file
*/
private Uri getUriForHTTP(String path) {
try {
URL url = new URL(path);
String fileName = path.substring(path.lastIndexOf('/') + 1);
String resName = fileName.substring(0, fileName.lastIndexOf('.'));
String extension = path.substring(path.lastIndexOf('.'));
File dir = activity.getExternalCacheDir();
if (dir == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
String storage = dir.toString() + STORAGE_FOLDER;
File file = new File(storage, resName + extension);
new File(storage).mkdir();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
FileOutputStream outStream = new FileOutputStream(file);
copyFile(input, outStream);
outStream.flush();
outStream.close();
return Uri.fromFile(file);
} catch (MalformedURLException e) {
Log.e("Asset", "Incorrect URL");
e.printStackTrace();
} catch (FileNotFoundException e) {
Log.e("Asset", "Failed to create new File from HTTP Content");
e.printStackTrace();
} catch (IOException e) {
Log.e("Asset", "No Input can be created from http Stream");
e.printStackTrace();
}
return Uri.EMPTY;
}
/**
* Writes an InputStream to an OutputStream
*
* @param in
* The input stream
* @param out
* The output stream
*/
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
/**
* @return The resource ID for the given resource.
*/
private int getResId(String resPath) {
Resources res = activity.getResources();
int resId;
String pkgName = getPackageName();
String dirName = "drawable";
String fileName = resPath;
if (resPath.contains("/")) {
dirName = resPath.substring(0, resPath.lastIndexOf('/'));
fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
}
String resName = fileName.substring(0, fileName.lastIndexOf('.'));
resId = res.getIdentifier(resName, dirName, pkgName);
if (resId == 0) {
resId = res.getIdentifier(resName, "drawable", pkgName);
}
return resId;
}
/**
* The name for the package.
*
* @return The package name
*/
private String getPackageName() {
return activity.getPackageName();
}
}
/*
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package de.appplant.cordova.plugin.notification;
import java.util.Random;
import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.widget.Toast;
public class NotificationBuilder {
private Options options;
private Context context;
private Builder notification;
private final String OPTIONS;
private Class<?> deleteIntentReceiver;
private Class<?> receiverActivity;
/**
* Constructor of NotificationBuilder
* @param options
* @param context
* @param OPTIONS
* @param deleteIntentReceiver
* @param receiverActivity
*/
public NotificationBuilder(Options options,Context context, String OPTIONS,
Class<?> deleteIntentReceiver, Class<?> receiverActivity){
this.options = options;
this.context = context;
this.OPTIONS = OPTIONS;
this.deleteIntentReceiver = deleteIntentReceiver;
this.receiverActivity = receiverActivity;
}
/**
* Creates the notification.
*/
@SuppressLint("NewApi")
public void buildNotification () {
Uri sound = options.getSound();
//DeleteIntent is called when the user clears a notification manually
Intent deleteIntent = new Intent(context, deleteIntentReceiver)
.setAction("" + options.getId())
.putExtra(OPTIONS, options.getJSONObject().toString());
PendingIntent dpi = PendingIntent.getBroadcast(context, 0, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
notification = new NotificationCompat.Builder(context)
.setDefaults(0) // Do not inherit any defaults
.setContentTitle(options.getTitle())
.setContentText(options.getMessage())
.setNumber(options.getBadge())
.setTicker(options.getMessage())
.setSmallIcon(options.getSmallIcon())
.setLargeIcon(options.getIcon())
.setAutoCancel(options.getAutoCancel())
.setOngoing(options.getOngoing())
.setLights(options.getColor(), 500, 500)
.setDeleteIntent(dpi);
if (sound != null) {
notification.setSound(sound);
}
if (Build.VERSION.SDK_INT > 16) {
notification.setStyle(new NotificationCompat.BigTextStyle()
.bigText(options.getMessage()));
}
setClickEvent(notification);
}
/**
* Adds an onclick handler to the notification
*/
private Builder setClickEvent (Builder notification) {
Intent intent = new Intent(context, receiverActivity)
.putExtra(OPTIONS, options.getJSONObject().toString())
.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
int requestCode = new Random().nextInt();
PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return notification.setContentIntent(contentIntent);
}
/**
* Shows the notification
*/
@SuppressWarnings("deprecation")
public void showNotification () {
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int id = 0;
try {
id = Integer.parseInt(options.getId());
} catch (Exception e) {}
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());
}
}
/**
* Show a notification as a Toast when App is runing in foreground
* @param title Title of the notification
* @param notification Notification to show
*/
public void showNotificationToast(){
String title = options.getTitle();
String message = options.getMessage();
int duration = Toast.LENGTH_LONG;
if(title.equals("")){
title = "Notification";
}
String text = title + " \n " + message;
Toast notificationToast = Toast.makeText(context, text, duration);
notificationToast.show();
}
}
......@@ -120,7 +120,7 @@ exports.add = function (props, callback, scope) {
this.convertProperties(properties);
}
if (device.platform != 'iOS') {
if (device.platform != 'iOS'&&device.platform != 'Android' ) {
notifications = notifications[0];
}
......@@ -152,10 +152,12 @@ exports.update = function (options, callback, scope) {
* @param {Object?} scope
* The scope for the callback function
*/
exports.clear = function (id, callback, scope) {
var notId = (id || '0').toString();
exports.clear = function (ids, callback, scope) {
ids = Array.isArray(ids) ? ids : [ids];
this.exec('clear', notId, callback, scope);
ids = this.convertIds(ids);
this.exec('clear', ids, callback, scope);
};
/**
......@@ -186,7 +188,7 @@ exports.cancel = function (ids, callback, scope) {
ids = this.convertIds(ids);
if (device.platform != 'iOS') {
if (device.platform != 'iOS'&&device.platform != 'Android' ) {
ids = ids[0];
}
......
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