Manager.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * Apache 2.0 License
  3. *
  4. * Copyright (c) Sebastian Katzer 2017
  5. *
  6. * This file contains Original Code and/or Modifications of Original Code
  7. * as defined in and that are subject to the Apache License
  8. * Version 2.0 (the 'License'). You may not use this file except in
  9. * compliance with the License. Please obtain a copy of the License at
  10. * http://opensource.org/licenses/Apache-2.0/ and read it before using this
  11. * file.
  12. *
  13. * The Original Code and all software distributed under the License are
  14. * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  15. * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  16. * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  18. * Please see the License for the specific language governing rights and
  19. * limitations under the License.
  20. */
  21. // codebeat:disable[TOO_MANY_FUNCTIONS]
  22. package de.appplant.cordova.plugin.notification;
  23. import android.annotation.SuppressLint;
  24. import android.app.NotificationChannel;
  25. import android.app.NotificationManager;
  26. import android.content.Context;
  27. import android.content.SharedPreferences;
  28. import android.service.notification.StatusBarNotification;
  29. import android.support.v4.app.NotificationManagerCompat;
  30. import org.json.JSONException;
  31. import org.json.JSONObject;
  32. import java.util.ArrayList;
  33. import java.util.List;
  34. import java.util.Set;
  35. import de.appplant.cordova.plugin.badge.BadgeImpl;
  36. import static android.os.Build.VERSION.SDK_INT;
  37. import static android.os.Build.VERSION_CODES.M;
  38. import static android.os.Build.VERSION_CODES.O;
  39. import static android.support.v4.app.NotificationManagerCompat.IMPORTANCE_DEFAULT;
  40. import static de.appplant.cordova.plugin.notification.Notification.PREF_KEY_ID;
  41. import static de.appplant.cordova.plugin.notification.Notification.Type.TRIGGERED;
  42. /**
  43. * Central way to access all or single local notifications set by specific
  44. * state like triggered or scheduled. Offers shortcut ways to schedule,
  45. * cancel or clear local notifications.
  46. */
  47. public final class Manager {
  48. // TODO: temporary
  49. static final String CHANNEL_ID = "default-channel-id";
  50. // TODO: temporary
  51. private static final CharSequence CHANNEL_NAME = "Default channel";
  52. // The application context
  53. private Context context;
  54. /**
  55. * Constructor
  56. *
  57. * @param context Application context
  58. */
  59. private Manager(Context context) {
  60. this.context = context;
  61. createDefaultChannel();
  62. }
  63. /**
  64. * Static method to retrieve class instance.
  65. *
  66. * @param context Application context
  67. */
  68. public static Manager getInstance(Context context) {
  69. return new Manager(context);
  70. }
  71. /**
  72. * Check if app has local notification permission.
  73. */
  74. public boolean hasPermission () {
  75. return getNotCompMgr().areNotificationsEnabled();
  76. }
  77. /**
  78. * Schedule local notification specified by request.
  79. *
  80. * @param request Set of notification options.
  81. * @param receiver Receiver to handle the trigger event.
  82. */
  83. public Notification schedule (Request request, Class<?> receiver) {
  84. Options options = request.getOptions();
  85. Notification toast = new Notification(context, options);
  86. toast.schedule(request, receiver);
  87. return toast;
  88. }
  89. /**
  90. * TODO: temporary
  91. */
  92. @SuppressLint("WrongConstant")
  93. private void createDefaultChannel() {
  94. NotificationManager mgr = getNotMgr();
  95. if (SDK_INT < O)
  96. return;
  97. NotificationChannel channel = mgr.getNotificationChannel(CHANNEL_ID);
  98. if (channel != null)
  99. return;
  100. channel = new NotificationChannel(
  101. CHANNEL_ID, CHANNEL_NAME, IMPORTANCE_DEFAULT);
  102. mgr.createNotificationChannel(channel);
  103. }
  104. /**
  105. * Update local notification specified by ID.
  106. *
  107. * @param id The notification ID.
  108. * @param updates JSON object with notification options.
  109. * @param receiver Receiver to handle the trigger event.
  110. */
  111. public Notification update (int id, JSONObject updates, Class<?> receiver) {
  112. Notification notification = get(id);
  113. if (notification == null)
  114. return null;
  115. notification.update(updates, receiver);
  116. return notification;
  117. }
  118. /**
  119. * Clear local notification specified by ID.
  120. *
  121. * @param id The notification ID.
  122. */
  123. public Notification clear (int id) {
  124. Notification toast = get(id);
  125. if (toast != null) {
  126. toast.clear();
  127. }
  128. return toast;
  129. }
  130. /**
  131. * Clear all local notifications.
  132. */
  133. public void clearAll () {
  134. List<Notification> toasts = getByType(TRIGGERED);
  135. for (Notification toast : toasts) {
  136. toast.clear();
  137. }
  138. getNotCompMgr().cancelAll();
  139. setBadge(0);
  140. }
  141. /**
  142. * Clear local notification specified by ID.
  143. *
  144. * @param id The notification ID
  145. */
  146. public Notification cancel (int id) {
  147. Notification toast = get(id);
  148. if (toast != null) {
  149. toast.cancel();
  150. }
  151. return toast;
  152. }
  153. /**
  154. * Cancel all local notifications.
  155. */
  156. public void cancelAll () {
  157. List<Notification> notifications = getAll();
  158. for (Notification notification : notifications) {
  159. notification.cancel();
  160. }
  161. getNotCompMgr().cancelAll();
  162. setBadge(0);
  163. }
  164. /**
  165. * All local notifications IDs.
  166. */
  167. public List<Integer> getIds() {
  168. Set<String> keys = getPrefs().getAll().keySet();
  169. List<Integer> ids = new ArrayList<Integer>();
  170. for (String key : keys) {
  171. try {
  172. ids.add(Integer.parseInt(key));
  173. } catch (NumberFormatException e) {
  174. e.printStackTrace();
  175. }
  176. }
  177. return ids;
  178. }
  179. /**
  180. * All local notification IDs for given type.
  181. *
  182. * @param type The notification life cycle type
  183. */
  184. public List<Integer> getIdsByType(Notification.Type type) {
  185. if (type == Notification.Type.ALL)
  186. return getIds();
  187. StatusBarNotification[] activeToasts = getActiveNotifications();
  188. List<Integer> activeIds = new ArrayList<Integer>();
  189. for (StatusBarNotification toast : activeToasts) {
  190. activeIds.add(toast.getId());
  191. }
  192. if (type == TRIGGERED)
  193. return activeIds;
  194. List<Integer> ids = getIds();
  195. ids.removeAll(activeIds);
  196. return ids;
  197. }
  198. /**
  199. * List of local notifications with matching ID.
  200. *
  201. * @param ids Set of notification IDs.
  202. */
  203. private List<Notification> getByIds(List<Integer> ids) {
  204. List<Notification> toasts = new ArrayList<Notification>();
  205. for (int id : ids) {
  206. Notification toast = get(id);
  207. if (toast != null) {
  208. toasts.add(toast);
  209. }
  210. }
  211. return toasts;
  212. }
  213. /**
  214. * List of all local notification.
  215. */
  216. public List<Notification> getAll() {
  217. return getByIds(getIds());
  218. }
  219. /**
  220. * List of local notifications from given type.
  221. *
  222. * @param type The notification life cycle type
  223. */
  224. private List<Notification> getByType(Notification.Type type) {
  225. if (type == Notification.Type.ALL)
  226. return getAll();
  227. List<Integer> ids = getIdsByType(type);
  228. return getByIds(ids);
  229. }
  230. /**
  231. * List of properties from all local notifications.
  232. */
  233. public List<JSONObject> getOptions() {
  234. return getOptionsById(getIds());
  235. }
  236. /**
  237. * List of properties from local notifications with matching ID.
  238. *
  239. * @param ids Set of notification IDs
  240. */
  241. public List<JSONObject> getOptionsById(List<Integer> ids) {
  242. List<JSONObject> toasts = new ArrayList<JSONObject>();
  243. for (int id : ids) {
  244. Options options = getOptions(id);
  245. if (options != null) {
  246. toasts.add(options.getDict());
  247. }
  248. }
  249. return toasts;
  250. }
  251. /**
  252. * List of properties from all local notifications from given type.
  253. *
  254. * @param type
  255. * The notification life cycle type
  256. */
  257. public List<JSONObject> getOptionsByType(Notification.Type type) {
  258. ArrayList<JSONObject> options = new ArrayList<JSONObject>();
  259. List<Notification> notifications = getByType(type);
  260. for (Notification notification : notifications) {
  261. options.add(notification.getOptions().getDict());
  262. }
  263. return options;
  264. }
  265. /**
  266. * Get local notification options.
  267. *
  268. * @param id Notification ID.
  269. *
  270. * @return null if could not found.
  271. */
  272. public Options getOptions(int id) {
  273. SharedPreferences prefs = getPrefs();
  274. String toastId = Integer.toString(id);
  275. if (!prefs.contains(toastId))
  276. return null;
  277. try {
  278. String json = prefs.getString(toastId, null);
  279. JSONObject dict = new JSONObject(json);
  280. return new Options(context, dict);
  281. } catch (JSONException e) {
  282. e.printStackTrace();
  283. return null;
  284. }
  285. }
  286. /**
  287. * Get existent local notification.
  288. *
  289. * @param id Notification ID.
  290. *
  291. * @return null if could not found.
  292. */
  293. public Notification get(int id) {
  294. Options options = getOptions(id);
  295. if (options == null)
  296. return null;
  297. return new Notification(context, options);
  298. }
  299. /**
  300. * Set the badge number of the app icon.
  301. *
  302. * @param badge The badge number.
  303. */
  304. public void setBadge (int badge) {
  305. if (badge == 0) {
  306. new BadgeImpl(context).clearBadge();
  307. } else {
  308. new BadgeImpl(context).setBadge(badge);
  309. }
  310. }
  311. /**
  312. * Get all active status bar notifications.
  313. */
  314. StatusBarNotification[] getActiveNotifications() {
  315. if (SDK_INT >= M) {
  316. return getNotMgr().getActiveNotifications();
  317. } else {
  318. return new StatusBarNotification[0];
  319. }
  320. }
  321. /**
  322. * Shared private preferences for the application.
  323. */
  324. private SharedPreferences getPrefs () {
  325. return context.getSharedPreferences(PREF_KEY_ID, Context.MODE_PRIVATE);
  326. }
  327. /**
  328. * Notification manager for the application.
  329. */
  330. private NotificationManager getNotMgr() {
  331. return (NotificationManager) context.getSystemService(
  332. Context.NOTIFICATION_SERVICE);
  333. }
  334. /**
  335. * Notification compat manager for the application.
  336. */
  337. private NotificationManagerCompat getNotCompMgr() {
  338. return NotificationManagerCompat.from(context);
  339. }
  340. }
  341. // codebeat:enable[TOO_MANY_FUNCTIONS]