LocalNotification.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. /*
  2. * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
  3. *
  4. * @APPPLANT_LICENSE_HEADER_START@
  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. * @APPPLANT_LICENSE_HEADER_END@
  22. */
  23. package de.appplant.cordova.plugin.localnotification;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import org.apache.cordova.CallbackContext;
  27. import org.apache.cordova.CordovaPlugin;
  28. import org.apache.cordova.CordovaWebView;
  29. import org.apache.cordova.PluginResult;
  30. import org.json.JSONArray;
  31. import org.json.JSONException;
  32. import org.json.JSONObject;
  33. import android.os.Build;
  34. import de.appplant.cordova.plugin.notification.*;
  35. /**
  36. * This plugin utilizes the Android AlarmManager in combination with local
  37. * notifications. When a local notification is scheduled the alarm manager takes
  38. * care of firing the event. When the event is processed, a notification is put
  39. * in the Android notification center and status bar.
  40. */
  41. public class LocalNotification extends CordovaPlugin {
  42. // Reference to the web view for static access
  43. private static CordovaWebView webView = null;
  44. // Indicates if the device is ready (to receive events)
  45. private static Boolean deviceready = false;
  46. // To inform the user about the state of the app in callbacks
  47. protected static Boolean isInBackground = true;
  48. // Queues all events before deviceready
  49. private static ArrayList<String> eventQueue = new ArrayList<String>();
  50. /**
  51. * Called after plugin construction and fields have been initialized.
  52. */
  53. @Override
  54. protected void pluginInitialize() {
  55. LocalNotification.webView = super.webView;
  56. }
  57. /**
  58. * Called when the system is about to start resuming a previous activity.
  59. *
  60. * @param multitasking
  61. * Flag indicating if multitasking is turned on for app
  62. */
  63. @Override
  64. public void onPause(boolean multitasking) {
  65. super.onPause(multitasking);
  66. isInBackground = true;
  67. }
  68. /**
  69. * Called when the activity will start interacting with the user.
  70. *
  71. * @param multitasking
  72. * Flag indicating if multitasking is turned on for app
  73. */
  74. @Override
  75. public void onResume(boolean multitasking) {
  76. super.onResume(multitasking);
  77. isInBackground = false;
  78. }
  79. /**
  80. * The final call you receive before your activity is destroyed.
  81. */
  82. @Override
  83. public void onDestroy() {
  84. deviceready = false;
  85. isInBackground = true;
  86. }
  87. /**
  88. * Executes the request.
  89. *
  90. * This method is called from the WebView thread. To do a non-trivial
  91. * amount of work, use:
  92. * cordova.getThreadPool().execute(runnable);
  93. *
  94. * To run on the UI thread, use:
  95. * cordova.getActivity().runOnUiThread(runnable);
  96. *
  97. * @param action
  98. * The action to execute.
  99. * @param args
  100. * The exec() arguments in JSON form.
  101. * @param command
  102. * The callback context used when calling back into JavaScript.
  103. * @return
  104. * Whether the action was valid.
  105. */
  106. @Override
  107. public boolean execute (final String action, final JSONArray args,
  108. final CallbackContext command) throws JSONException {
  109. Notification.setDefaultTriggerReceiver(TriggerReceiver.class);
  110. cordova.getThreadPool().execute(new Runnable() {
  111. public void run() {
  112. if (action.equals("schedule")) {
  113. schedule(args);
  114. command.success();
  115. }
  116. else if (action.equals("update")) {
  117. update(args);
  118. command.success();
  119. }
  120. else if (action.equals("cancel")) {
  121. cancel(args);
  122. command.success();
  123. }
  124. else if (action.equals("cancelAll")) {
  125. cancelAll();
  126. command.success();
  127. }
  128. else if (action.equals("clear")) {
  129. clear(args);
  130. command.success();
  131. }
  132. else if (action.equals("clearAll")) {
  133. clearAll();
  134. command.success();
  135. }
  136. else if (action.equals("isPresent")) {
  137. isPresent(args.optInt(0), command);
  138. }
  139. else if (action.equals("isScheduled")) {
  140. isScheduled(args.optInt(0), command);
  141. }
  142. else if (action.equals("isTriggered")) {
  143. isTriggered(args.optInt(0), command);
  144. }
  145. else if (action.equals("getAllIds")) {
  146. getAllIds(command);
  147. }
  148. else if (action.equals("getScheduledIds")) {
  149. getScheduledIds(command);
  150. }
  151. else if (action.equals("getTriggeredIds")) {
  152. getTriggeredIds(command);
  153. }
  154. else if (action.equals("getAll")) {
  155. getAll(args, command);
  156. }
  157. else if (action.equals("getScheduled")) {
  158. getScheduled(args, command);
  159. }
  160. else if (action.equals("getTriggered")) {
  161. getTriggered(args, command);
  162. }
  163. else if (action.equals("deviceready")) {
  164. deviceready();
  165. }
  166. }
  167. });
  168. return true;
  169. }
  170. /**
  171. * Schedule multiple local notifications.
  172. *
  173. * @param notifications
  174. * Properties for each local notification
  175. */
  176. private void schedule (JSONArray notifications) {
  177. for (int i = 0; i < notifications.length(); i++) {
  178. JSONObject options = notifications.optJSONObject(i);
  179. Notification notification =
  180. getNotificationMgr().schedule(options, TriggerReceiver.class);
  181. fireEvent("schedule", notification);
  182. }
  183. }
  184. /**
  185. * Update multiple local notifications.
  186. *
  187. * @param updates
  188. * Notification properties including their IDs
  189. */
  190. private void update (JSONArray updates) {
  191. for (int i = 0; i < updates.length(); i++) {
  192. JSONObject update = updates.optJSONObject(i);
  193. int id = update.optInt("id", 0);
  194. Notification notification =
  195. getNotificationMgr().update(id, update, TriggerReceiver.class);
  196. fireEvent("update", notification);
  197. }
  198. }
  199. /**
  200. * Cancel multiple local notifications.
  201. *
  202. * @param ids
  203. * Set of local notification IDs
  204. */
  205. private void cancel (JSONArray ids) {
  206. for (int i = 0; i < ids.length(); i++) {
  207. int id = ids.optInt(i, 0);
  208. Notification notification =
  209. getNotificationMgr().cancel(id);
  210. fireEvent("cancel", notification);
  211. }
  212. }
  213. /**
  214. * Cancel all scheduled notifications.
  215. */
  216. private void cancelAll() {
  217. getNotificationMgr().cancelAll();
  218. fireEvent("cancelall");
  219. }
  220. /**
  221. * Clear multiple local notifications without canceling them.
  222. *
  223. * @param ids
  224. * Set of local notification IDs
  225. */
  226. private void clear(JSONArray ids){
  227. for (int i = 0; i < ids.length(); i++) {
  228. int id = ids.optInt(i, 0);
  229. Notification notification =
  230. getNotificationMgr().clear(id);
  231. fireEvent("clear", notification);
  232. }
  233. }
  234. /**
  235. * Clear all triggered notifications without canceling them.
  236. */
  237. private void clearAll() {
  238. getNotificationMgr().clearAll();
  239. fireEvent("clearall");
  240. }
  241. /**
  242. * If a notification with an ID is present.
  243. *
  244. * @param id
  245. * Notification ID
  246. * @param command
  247. * The callback context used when calling back into JavaScript.
  248. */
  249. private void isPresent (int id, CallbackContext command) {
  250. boolean exist = getNotificationMgr().exist(id);
  251. PluginResult result = new PluginResult(
  252. PluginResult.Status.OK, exist);
  253. command.sendPluginResult(result);
  254. }
  255. /**
  256. * If a notification with an ID is scheduled.
  257. *
  258. * @param id
  259. * Notification ID
  260. * @param command
  261. * The callback context used when calling back into JavaScript.
  262. */
  263. private void isScheduled (int id, CallbackContext command) {
  264. boolean exist = getNotificationMgr().exist(
  265. id, Notification.Type.SCHEDULED);
  266. PluginResult result = new PluginResult(
  267. PluginResult.Status.OK, exist);
  268. command.sendPluginResult(result);
  269. }
  270. /**
  271. * If a notification with an ID is triggered.
  272. *
  273. * @param id
  274. * Notification ID
  275. * @param command
  276. * The callback context used when calling back into JavaScript.
  277. */
  278. private void isTriggered (int id, CallbackContext command) {
  279. boolean exist = getNotificationMgr().exist(
  280. id, Notification.Type.TRIGGERED);
  281. PluginResult result = new PluginResult(
  282. PluginResult.Status.OK, exist);
  283. command.sendPluginResult(result);
  284. }
  285. /**
  286. * Set of IDs from all existent notifications.
  287. *
  288. * @param command
  289. * The callback context used when calling back into JavaScript.
  290. */
  291. private void getAllIds (CallbackContext command) {
  292. List<Integer> ids = getNotificationMgr().getIds();
  293. command.success(new JSONArray(ids));
  294. }
  295. /**
  296. * Set of IDs from all scheduled notifications.
  297. *
  298. * @param command
  299. * The callback context used when calling back into JavaScript.
  300. */
  301. private void getScheduledIds (CallbackContext command) {
  302. List<Integer> ids = getNotificationMgr().getIdsByType(
  303. Notification.Type.SCHEDULED);
  304. command.success(new JSONArray(ids));
  305. }
  306. /**
  307. * Set of IDs from all triggered notifications.
  308. *
  309. * @param command
  310. * The callback context used when calling back into JavaScript.
  311. */
  312. private void getTriggeredIds (CallbackContext command) {
  313. List<Integer> ids = getNotificationMgr().getIdsByType(
  314. Notification.Type.TRIGGERED);
  315. command.success(new JSONArray(ids));
  316. }
  317. /**
  318. * Set of options from local notification.
  319. *
  320. * @param ids
  321. * Set of local notification IDs
  322. * @param command
  323. * The callback context used when calling back into JavaScript.
  324. */
  325. private void getAll (JSONArray ids, CallbackContext command) {
  326. List<JSONObject> options;
  327. if (ids.length() == 0) {
  328. options = getNotificationMgr().getOptions();
  329. } else {
  330. options = getNotificationMgr().getOptionsById(toList(ids));
  331. }
  332. command.success(new JSONArray(options));
  333. }
  334. /**
  335. * Set of options from scheduled notifications.
  336. *
  337. * @param ids
  338. * Set of local notification IDs
  339. * @param command
  340. * The callback context used when calling back into JavaScript.
  341. */
  342. private void getScheduled (JSONArray ids, CallbackContext command) {
  343. List<JSONObject> options;
  344. if (ids.length() == 0) {
  345. options = getNotificationMgr().getOptionsByType(Notification.Type.SCHEDULED);
  346. } else {
  347. options = getNotificationMgr().getOptionsBy(
  348. Notification.Type.SCHEDULED, toList(ids));
  349. }
  350. command.success(new JSONArray(options));
  351. }
  352. /**
  353. * Set of options from triggered notifications.
  354. *
  355. * @param ids
  356. * Set of local notification IDs
  357. * @param command
  358. * The callback context used when calling back into JavaScript.
  359. */
  360. private void getTriggered (JSONArray ids, CallbackContext command) {
  361. List<JSONObject> options;
  362. if (ids.length() == 0) {
  363. options = getNotificationMgr().getOptionsByType(Notification.Type.TRIGGERED);
  364. } else {
  365. options = getNotificationMgr().getOptionsBy(
  366. Notification.Type.TRIGGERED, toList(ids));
  367. }
  368. command.success(new JSONArray(options));
  369. }
  370. /**
  371. * Call all pending callbacks after the deviceready event has been fired.
  372. */
  373. private static synchronized void deviceready () {
  374. isInBackground = false;
  375. deviceready = true;
  376. for (String js : eventQueue) {
  377. sendJavascript(js);
  378. }
  379. eventQueue.clear();
  380. }
  381. /**
  382. * Fire given event on JS side. Does inform all event listeners.
  383. *
  384. * @param event
  385. * The event name
  386. */
  387. private void fireEvent (String event) {
  388. fireEvent(event, null);
  389. }
  390. /**
  391. * Fire given event on JS side. Does inform all event listeners.
  392. *
  393. * @param event
  394. * The event name
  395. * @param notification
  396. * Optional local notification to pass the id and properties.
  397. */
  398. static void fireEvent (String event, Notification notification) {
  399. String state = getApplicationState();
  400. String params = "\"" + state + "\"";
  401. if (notification != null) {
  402. params = notification.toString() + "," + params;
  403. }
  404. String js = "cordova.plugins.notification.local.fireEvent(" +
  405. "\"" + event + "\"," + params + ")";
  406. sendJavascript(js);
  407. }
  408. /**
  409. * Use this instead of deprecated sendJavascript
  410. *
  411. * @param js
  412. * JS code snippet as string
  413. */
  414. private static synchronized void sendJavascript(final String js) {
  415. if (!deviceready) {
  416. eventQueue.add(js);
  417. return;
  418. }
  419. webView.post(new Runnable(){
  420. public void run(){
  421. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  422. webView.evaluateJavascript(js, null);
  423. } else {
  424. webView.loadUrl("javascript:" + js);
  425. }
  426. }
  427. });
  428. }
  429. /**
  430. * Convert JSON array of integers to List.
  431. *
  432. * @param ary
  433. * Array of integers
  434. */
  435. private List<Integer> toList (JSONArray ary) {
  436. ArrayList<Integer> list = new ArrayList<Integer>();
  437. for (int i = 0; i < ary.length(); i++) {
  438. list.add(ary.optInt(i));
  439. }
  440. return list;
  441. }
  442. /**
  443. * Current application state.
  444. *
  445. * @return
  446. * "background" or "foreground"
  447. */
  448. static String getApplicationState () {
  449. return isInBackground ? "background" : "foreground";
  450. }
  451. /**
  452. * Notification manager instance.
  453. */
  454. private Manager getNotificationMgr() {
  455. return Manager.getInstance(cordova.getActivity());
  456. }
  457. }