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 android.graphics.Color; import android.os.Build; import android.provider.Settings; import android.support.v4.app.NotificationCompat; import android.util.Log; import com.netsyms.apps.Mobile.MainActivity; import com.netsyms.apps.Mobile.R; import com.transistorsoft.tsbackgroundfetch.BackgroundFetch; import org.json.JSONArray; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; 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, 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(); } }