diff --git a/config.xml b/config.xml
index d88e6ba..4d89f16 100644
--- a/config.xml
+++ b/config.xml
@@ -51,6 +51,7 @@
+
diff --git a/src/android/BackgroundFetchHeadlessTask.java b/src/android/BackgroundFetchHeadlessTask.java
new file mode 100644
index 0000000..12e2893
--- /dev/null
+++ b/src/android/BackgroundFetchHeadlessTask.java
@@ -0,0 +1,175 @@
+package com.transistorsoft.cordova.backgroundfetch;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+
+import com.netsyms.BusinessMobile.R;
+import com.transistorsoft.tsbackgroundfetch.BackgroundFetch;
+
+import android.graphics.Color;
+import android.os.Build;
+import android.provider.Settings;
+import android.support.v4.app.NotificationCompat;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONArray;
+
+public class BackgroundFetchHeadlessTask implements HeadlessTask {
+
+ private static final String PREFS_NAME = "NativeStorage";
+ private static final String KEY = "accounts";
+ private static String shownNotifications = "";
+ public final String NOTIFICATION_CHANNEL_ID = "background-channel-id";
+
+ public static String getValue(Context context, String key, String defaultValue) {
+ SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
+ return settings.getString(key, defaultValue);
+ }
+
+ /**
+ * https://stackoverflow.com/a/34691486
+ *
+ * @param urlString
+ * @return
+ * @throws IOException
+ */
+ public static String getStringFromURL(String urlString) throws IOException {
+ HttpURLConnection urlConnection = null;
+ URL url = new URL(urlString);
+ urlConnection = (HttpURLConnection) url.openConnection();
+ urlConnection.setRequestMethod("GET");
+ urlConnection.setReadTimeout(10000 /* milliseconds */);
+ urlConnection.setConnectTimeout(15000 /* milliseconds */);
+ urlConnection.setDoOutput(true);
+ urlConnection.connect();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
+ StringBuilder sb = new StringBuilder();
+
+ String line;
+ while ((line = br.readLine()) != null) {
+ sb.append(line + "\n");
+ }
+ br.close();
+
+ String jsonString = sb.toString();
+ return jsonString;
+ }
+
+ @Override
+ public void onFetch(Context context) {
+ Log.d(BackgroundFetch.TAG, "Notification Poller: onFetch");
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ String accountjson = getValue(context, KEY, null).replaceAll("\\\\", "");
+ accountjson = accountjson.substring(1, accountjson.length() - 1);
+ //Log.d(BackgroundFetch.TAG, "Notification Poller: Account JSON: " + accountjson);
+ try {
+ JSONArray accounts = new JSONArray(accountjson);
+
+ for (int i = 0; i < accounts.length(); i++) {
+ try {
+ JSONObject acct = accounts.getJSONObject(i);
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Account " + i + " URL: " + acct.getString("syncurl"));
+ String notificationString = getStringFromURL(acct.getString("syncurl") + "?key=" + acct.getString("key") + "&username=" + acct.getString("username") + "&action=checknotifications");
+ //Log.d(BackgroundFetch.TAG, "Notification Poller: Account " + i + " JSON: " + notificationString);
+ JSONArray notifications = new JSONObject(notificationString).getJSONArray("notifications");
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Account " + i + " JSON parsed: " + notifications.length() + " notifications");
+ for (int j = 0; j < notifications.length(); j++) {
+ JSONObject notif = notifications.getJSONObject(j);
+
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Procesing notification ID " + notif.getString("id") + " with title " + notif.getString("title"));
+
+ if (notif.getBoolean("seen") || shownNotifications.contains("|" + i + ":" + notif.getString("id") + "|")) {
+ continue;
+ }
+
+ Intent intent = new Intent(context, com.netsyms.BusinessMobile.MainActivity.class);
+ PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ NotificationCompat.Builder b = new NotificationCompat.Builder(context);
+
+ b.setAutoCancel(true)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .setSmallIcon(R.drawable.ic_notification)
+ .setContentTitle(notif.getString("title"))
+ .setContentText(notif.getString("content"))
+ .setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
+ .setContentIntent(contentIntent)
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PRIVATE);
+
+ // Create alternate notification for lockscreen
+ NotificationCompat.Builder lockb = new NotificationCompat.Builder(context);
+ if (notif.getBoolean("sensitive") == true) {
+ lockb
+ .setSmallIcon(R.drawable.ic_notification)
+ .setContentTitle("Contents hidden")
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT);
+ } else {
+ lockb
+ .setSmallIcon(R.drawable.ic_notification)
+ .setContentTitle(notif.getString("title"))
+ .setContentText(notif.getString("content"))
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT);
+ }
+
+ b.setPublicVersion(lockb.build());
+
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ CharSequence name = "Background Notifications";
+ int importance = NotificationManager.IMPORTANCE_DEFAULT;
+ NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance);
+ channel.enableLights(true);
+ channel.enableVibration(true);
+ channel.setLightColor(Color.rgb(33, 150, 243));
+ // Register the channel with the system; you can't change the importance
+ // or other notification behaviors after this
+ b.setChannelId(NOTIFICATION_CHANNEL_ID);
+ notificationManager.createNotificationChannel(channel);
+ }
+
+
+ notificationManager.notify(Integer.parseInt(notif.getString("id")), b.build());
+
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Shown notification " + notif.getString("id"));
+
+ shownNotifications += "|" + i + ":" + notif.getString("id") + "|";
+ }
+ } catch (Exception e) {
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Exception: " + e.getMessage());
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Stack trace: " + Log.getStackTraceString(e));
+ }
+ }
+ } catch (Exception e) {
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Exception: " + e.getMessage());
+ Log.d(BackgroundFetch.TAG, "Notification Poller: Stack trace: " + Log.getStackTraceString(e));
+ } finally {
+ BackgroundFetch.getInstance(context).finish();
+ }
+ }
+ }
+ );
+ thread.start();
+ }
+}
diff --git a/www/js/app.js b/www/js/app.js
index fabb41b..d870b54 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -219,7 +219,8 @@ function displayNotifications(callback) {
actions: [
{id: 'mark_read', title: "Mark Read"}
],
- id: n.id
+ id: n.id,
+ lockscreen: !n.sensitive
}]);
shown_notifications.push(n.id);
@@ -263,7 +264,9 @@ document.addEventListener("deviceready", function () {
}
cordova.plugins.notification.local.setDefaults({
- led: {color: '#2196F3'},
+ led: true,
+ color: '#2196F3',
+ vibrate: true,
smallIcon: "res://ic_notification"
});
cordova.plugins.notification.local.on("mark_read", function (notification) {