LocalNotification.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  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. package de.appplant.cordova.plugin.localnotification;
  22. import android.app.Activity;
  23. import org.apache.cordova.CallbackContext;
  24. import org.apache.cordova.CordovaInterface;
  25. import org.apache.cordova.CordovaPlugin;
  26. import org.apache.cordova.CordovaWebView;
  27. import org.apache.cordova.PluginResult;
  28. import org.json.JSONArray;
  29. import org.json.JSONException;
  30. import org.json.JSONObject;
  31. import java.lang.reflect.Method;
  32. import java.util.ArrayList;
  33. import java.util.List;
  34. import java.lang.Exception;
  35. import de.appplant.cordova.plugin.notification.Manager;
  36. import de.appplant.cordova.plugin.notification.Notification;
  37. import de.appplant.cordova.plugin.notification.Options;
  38. import de.appplant.cordova.plugin.notification.Request;
  39. // import de.appplant.cordova.plugin.notification.Manager;
  40. // import de.appplant.cordova.plugin.notification.Notification;
  41. /**
  42. * This plugin utilizes the Android AlarmManager in combination with local
  43. * notifications. When a local notification is scheduled the alarm manager takes
  44. * care of firing the event. When the event is processed, a notification is put
  45. * in the Android notification center and status bar.
  46. */
  47. public class LocalNotification extends CordovaPlugin {
  48. // Reference to the web view for static access
  49. private static CordovaWebView webView = null;
  50. // Indicates if the device is ready (to receive events)
  51. private static Boolean deviceready = false;
  52. // To inform the user about the state of the app in callbacks
  53. protected static Boolean isInBackground = true;
  54. // Queues all events before deviceready
  55. private static ArrayList<String> eventQueue = new ArrayList<String>();
  56. /**
  57. * Called after plugin construction and fields have been initialized.
  58. * Prefer to use pluginInitialize instead since there is no value in
  59. * having parameters on the initialize() function.
  60. *
  61. * pluginInitialize is not available for cordova 3.0-3.5 !
  62. */
  63. @Override
  64. public void initialize (CordovaInterface cordova, CordovaWebView webView) {
  65. LocalNotification.webView = super.webView;
  66. }
  67. /**
  68. * Called when the system is about to start resuming a previous activity.
  69. *
  70. * @param multitasking
  71. * Flag indicating if multitasking is turned on for app
  72. */
  73. @Override
  74. public void onPause(boolean multitasking) {
  75. super.onPause(multitasking);
  76. isInBackground = true;
  77. }
  78. /**
  79. * Called when the activity will start interacting with the user.
  80. *
  81. * @param multitasking
  82. * Flag indicating if multitasking is turned on for app
  83. */
  84. @Override
  85. public void onResume(boolean multitasking) {
  86. super.onResume(multitasking);
  87. isInBackground = false;
  88. deviceready();
  89. }
  90. /**
  91. * The final call you receive before your activity is destroyed.
  92. */
  93. @Override
  94. public void onDestroy() {
  95. deviceready = false;
  96. isInBackground = true;
  97. }
  98. /**
  99. * Executes the request.
  100. *
  101. * This method is called from the WebView thread. To do a non-trivial
  102. * amount of work, use:
  103. * cordova.getThreadPool().execute(runnable);
  104. *
  105. * To run on the UI thread, use:
  106. * cordova.getActivity().runOnUiThread(runnable);
  107. *
  108. * @param action
  109. * The action to execute.
  110. * @param args
  111. * The exec() arguments in JSON form.
  112. * @param command
  113. * The callback context used when calling back into JavaScript.
  114. * @return
  115. * Whether the action was valid.
  116. */
  117. @Override
  118. public boolean execute (final String action, final JSONArray args,
  119. final CallbackContext command) throws JSONException {
  120. cordova.getThreadPool().execute(new Runnable() {
  121. public void run() {
  122. if (action.equals("ready")) {
  123. deviceready();
  124. } else
  125. if (action.equalsIgnoreCase("check")) {
  126. check(command);
  127. } else
  128. if (action.equalsIgnoreCase("request")) {
  129. request(command);
  130. } else
  131. if (action.equalsIgnoreCase("schedule")) {
  132. schedule(args);
  133. command.success();
  134. }
  135. // if (action.equals("update")) {
  136. // update(args);
  137. // command.success();
  138. // } else
  139. // if (action.equals("cancel")) {
  140. // cancel(args);
  141. // command.success();
  142. // } else
  143. // if (action.equals("cancelAll")) {
  144. // cancelAll();
  145. // command.success();
  146. // } else
  147. // if (action.equals("clear")) {
  148. // clear(args);
  149. // command.success();
  150. // } else
  151. // if (action.equals("clearAll")) {
  152. // clearAll();
  153. // command.success();
  154. // } else
  155. // if (action.equals("isPresent")) {
  156. // isPresent(args.optInt(0), command);
  157. // } else
  158. // if (action.equals("isScheduled")) {
  159. // isScheduled(args.optInt(0), command);
  160. // } else
  161. // if (action.equals("isTriggered")) {
  162. // isTriggered(args.optInt(0), command);
  163. // } else
  164. // if (action.equals("getAllIds")) {
  165. // getAllIds(command);
  166. // } else
  167. // if (action.equals("getScheduledIds")) {
  168. // getScheduledIds(command);
  169. // } else
  170. // if (action.equals("getTriggeredIds")) {
  171. // getTriggeredIds(command);
  172. // } else
  173. // if (action.equals("getSingle")) {
  174. // getSingle(args, command);
  175. // } else
  176. // if (action.equals("getSingleScheduled")) {
  177. // getSingleScheduled(args, command);
  178. // } else
  179. // if (action.equals("getSingleTriggered")) {
  180. // getSingleTriggered(args, command);
  181. // } else
  182. // if (action.equals("getAll")) {
  183. // getAll(args, command);
  184. // } else
  185. // if (action.equals("getScheduled")) {
  186. // getScheduled(args, command);
  187. // } else
  188. // if (action.equals("getTriggered")) {
  189. // getTriggered(args, command);
  190. // }
  191. }
  192. });
  193. return true;
  194. }
  195. /**
  196. * Ask if user has enabled permission for local notifications.
  197. *
  198. * @param command The callback context used when calling back into
  199. * JavaScript.
  200. */
  201. private void check (CallbackContext command) {
  202. boolean allowed = getNotificationMgr().hasPermission();
  203. PluginResult result = new PluginResult(PluginResult.Status.OK, allowed);
  204. command.sendPluginResult(result);
  205. }
  206. /**
  207. * Request permission for local notifications.
  208. *
  209. * @param command The callback context used when calling back into
  210. * JavaScript.
  211. */
  212. private void request (CallbackContext command) {
  213. check(command);
  214. }
  215. /**
  216. * Schedule multiple local notifications.
  217. *
  218. * @param notifications The notifications to schedule.
  219. */
  220. private void schedule (JSONArray notifications) {
  221. Manager mgr = getNotificationMgr();
  222. for (int i = 0; i < notifications.length(); i++) {
  223. JSONObject dict = notifications.optJSONObject(i);
  224. Options options = new Options(dict);
  225. Request request = new Request(options);
  226. Notification notification =
  227. mgr.schedule(request, TriggerReceiver.class);
  228. fireEvent("schedule", notification);
  229. }
  230. }
  231. // /**
  232. // * Update multiple local notifications.
  233. // *
  234. // * @param updates
  235. // * Notification properties including their IDs
  236. // */
  237. // private void update (JSONArray updates) {
  238. // for (int i = 0; i < updates.length(); i++) {
  239. // JSONObject update = updates.optJSONObject(i);
  240. // int id = update.optInt("id", 0);
  241. // Notification notification =
  242. // getNotificationMgr().update(id, update, TriggerReceiver.class);
  243. // if (notification == null)
  244. // continue;
  245. // fireEvent("update", notification);
  246. // }
  247. // }
  248. // /**
  249. // * Cancel multiple local notifications.
  250. // *
  251. // * @param ids
  252. // * Set of local notification IDs
  253. // */
  254. // private void cancel (JSONArray ids) {
  255. // for (int i = 0; i < ids.length(); i++) {
  256. // int id = ids.optInt(i, 0);
  257. // Notification notification =
  258. // getNotificationMgr().cancel(id);
  259. // if (notification == null)
  260. // continue;
  261. // fireEvent("cancel", notification);
  262. // }
  263. // }
  264. // /**
  265. // * Cancel all scheduled notifications.
  266. // */
  267. // private void cancelAll() {
  268. // getNotificationMgr().cancelAll();
  269. // fireEvent("cancelall");
  270. // }
  271. // /**
  272. // * Clear multiple local notifications without canceling them.
  273. // *
  274. // * @param ids
  275. // * Set of local notification IDs
  276. // */
  277. // private void clear(JSONArray ids){
  278. // for (int i = 0; i < ids.length(); i++) {
  279. // int id = ids.optInt(i, 0);
  280. // Notification notification =
  281. // getNotificationMgr().clear(id);
  282. // if (notification == null)
  283. // continue;
  284. // fireEvent("clear", notification);
  285. // }
  286. // }
  287. // /**
  288. // * Clear all triggered notifications without canceling them.
  289. // */
  290. // private void clearAll() {
  291. // getNotificationMgr().clearAll();
  292. // fireEvent("clearall");
  293. // }
  294. // /**
  295. // * If a notification with an ID is present.
  296. // *
  297. // * @param id
  298. // * Notification ID
  299. // * @param command
  300. // * The callback context used when calling back into JavaScript.
  301. // */
  302. // private void isPresent (int id, CallbackContext command) {
  303. // boolean exist = getNotificationMgr().exist(id);
  304. // PluginResult result = new PluginResult(
  305. // PluginResult.Status.OK, exist);
  306. // command.sendPluginResult(result);
  307. // }
  308. // /**
  309. // * If a notification with an ID is scheduled.
  310. // *
  311. // * @param id
  312. // * Notification ID
  313. // * @param command
  314. // * The callback context used when calling back into JavaScript.
  315. // */
  316. // private void isScheduled (int id, CallbackContext command) {
  317. // boolean exist = getNotificationMgr().exist(
  318. // id, Notification.Type.SCHEDULED);
  319. // PluginResult result = new PluginResult(
  320. // PluginResult.Status.OK, exist);
  321. // command.sendPluginResult(result);
  322. // }
  323. // /**
  324. // * If a notification with an ID is triggered.
  325. // *
  326. // * @param id
  327. // * Notification ID
  328. // * @param command
  329. // * The callback context used when calling back into JavaScript.
  330. // */
  331. // private void isTriggered (int id, CallbackContext command) {
  332. // boolean exist = getNotificationMgr().exist(
  333. // id, Notification.Type.TRIGGERED);
  334. // PluginResult result = new PluginResult(
  335. // PluginResult.Status.OK, exist);
  336. // command.sendPluginResult(result);
  337. // }
  338. // /**
  339. // * Set of IDs from all existent notifications.
  340. // *
  341. // * @param command
  342. // * The callback context used when calling back into JavaScript.
  343. // */
  344. // private void getAllIds (CallbackContext command) {
  345. // List<Integer> ids = getNotificationMgr().getIds();
  346. // command.success(new JSONArray(ids));
  347. // }
  348. // /**
  349. // * Set of IDs from all scheduled notifications.
  350. // *
  351. // * @param command
  352. // * The callback context used when calling back into JavaScript.
  353. // */
  354. // private void getScheduledIds (CallbackContext command) {
  355. // List<Integer> ids = getNotificationMgr().getIdsByType(
  356. // Notification.Type.SCHEDULED);
  357. // command.success(new JSONArray(ids));
  358. // }
  359. // /**
  360. // * Set of IDs from all triggered notifications.
  361. // *
  362. // * @param command
  363. // * The callback context used when calling back into JavaScript.
  364. // */
  365. // private void getTriggeredIds (CallbackContext command) {
  366. // List<Integer> ids = getNotificationMgr().getIdsByType(
  367. // Notification.Type.TRIGGERED);
  368. // command.success(new JSONArray(ids));
  369. // }
  370. // /**
  371. // * Options from local notification.
  372. // *
  373. // * @param ids
  374. // * Set of local notification IDs
  375. // * @param command
  376. // * The callback context used when calling back into JavaScript.
  377. // */
  378. // private void getSingle (JSONArray ids, CallbackContext command) {
  379. // getOptions(ids.optString(0), Notification.Type.ALL, command);
  380. // }
  381. // /**
  382. // * Options from scheduled notification.
  383. // *
  384. // * @param ids
  385. // * Set of local notification IDs
  386. // * @param command
  387. // * The callback context used when calling back into JavaScript.
  388. // */
  389. // private void getSingleScheduled (JSONArray ids, CallbackContext command) {
  390. // getOptions(ids.optString(0), Notification.Type.SCHEDULED, command);
  391. // }
  392. // /**
  393. // * Options from triggered notification.
  394. // *
  395. // * @param ids
  396. // * Set of local notification IDs
  397. // * @param command
  398. // * The callback context used when calling back into JavaScript.
  399. // */
  400. // private void getSingleTriggered (JSONArray ids, CallbackContext command) {
  401. // getOptions(ids.optString(0), Notification.Type.TRIGGERED, command);
  402. // }
  403. // /**
  404. // * Set of options from local notification.
  405. // *
  406. // * @param ids
  407. // * Set of local notification IDs
  408. // * @param command
  409. // * The callback context used when calling back into JavaScript.
  410. // */
  411. // private void getAll (JSONArray ids, CallbackContext command) {
  412. // getOptions(ids, Notification.Type.ALL, command);
  413. // }
  414. // /**
  415. // * Set of options from scheduled notifications.
  416. // *
  417. // * @param ids
  418. // * Set of local notification IDs
  419. // * @param command
  420. // * The callback context used when calling back into JavaScript.
  421. // */
  422. // private void getScheduled (JSONArray ids, CallbackContext command) {
  423. // getOptions(ids, Notification.Type.SCHEDULED, command);
  424. // }
  425. // /**
  426. // * Set of options from triggered notifications.
  427. // *
  428. // * @param ids
  429. // * Set of local notification IDs
  430. // * @param command
  431. // * The callback context used when calling back into JavaScript.
  432. // */
  433. // private void getTriggered (JSONArray ids, CallbackContext command) {
  434. // getOptions(ids, Notification.Type.TRIGGERED, command);
  435. // }
  436. // /**
  437. // * Options from local notification.
  438. // *
  439. // * @param id
  440. // * Set of local notification IDs
  441. // * @param type
  442. // * The local notification life cycle type
  443. // * @param command
  444. // * The callback context used when calling back into JavaScript.
  445. // */
  446. // private void getOptions (String id, Notification.Type type,
  447. // CallbackContext command) {
  448. // JSONArray ids = new JSONArray().put(id);
  449. // PluginResult result;
  450. // List<JSONObject> options =
  451. // getNotificationMgr().getOptionsBy(type, toList(ids));
  452. // if (options.isEmpty()) {
  453. // // Status.NO_RESULT led to no callback invocation :(
  454. // // Status.OK led to no NPE and crash
  455. // result = new PluginResult(PluginResult.Status.NO_RESULT);
  456. // } else {
  457. // result = new PluginResult(PluginResult.Status.OK, options.get(0));
  458. // }
  459. // command.sendPluginResult(result);
  460. // }
  461. // /**
  462. // * Set of options from local notifications.
  463. // *
  464. // * @param ids
  465. // * Set of local notification IDs
  466. // * @param type
  467. // * The local notification life cycle type
  468. // * @param command
  469. // * The callback context used when calling back into JavaScript.
  470. // */
  471. // private void getOptions (JSONArray ids, Notification.Type type,
  472. // CallbackContext command) {
  473. // List<JSONObject> options;
  474. // if (ids.length() == 0) {
  475. // options = getNotificationMgr().getOptionsByType(type);
  476. // } else {
  477. // options = getNotificationMgr().getOptionsBy(type, toList(ids));
  478. // }
  479. // command.success(new JSONArray(options));
  480. // }
  481. /**
  482. * Call all pending callbacks after the deviceready event has been fired.
  483. */
  484. private static synchronized void deviceready () {
  485. isInBackground = false;
  486. deviceready = true;
  487. for (String js : eventQueue) {
  488. sendJavascript(js);
  489. }
  490. eventQueue.clear();
  491. }
  492. /**
  493. * Fire given event on JS side. Does inform all event listeners.
  494. *
  495. * @param event
  496. * The event name
  497. */
  498. private void fireEvent (String event) {
  499. fireEvent(event, null);
  500. }
  501. /**
  502. * Fire given event on JS side. Does inform all event listeners.
  503. *
  504. * @param event The event name
  505. * @param notification Optional notification to pass the id and properties.
  506. */
  507. static void fireEvent (String event, Notification notification) {
  508. String state = getApplicationState();
  509. String params = "\"" + state + "\"";
  510. if (notification != null) {
  511. params = notification.toString() + "," + params;
  512. }
  513. String js = "cordova.plugins.notification.local.core.fireEvent(" +
  514. "\"" + event + "\"," + params + ")";
  515. sendJavascript(js);
  516. }
  517. /**
  518. * Use this instead of deprecated sendJavascript
  519. *
  520. * @param js JS code snippet as string
  521. */
  522. private static synchronized void sendJavascript(final String js) {
  523. if (!deviceready) {
  524. eventQueue.add(js);
  525. return;
  526. }
  527. Runnable jsLoader = new Runnable() {
  528. public void run() {
  529. webView.loadUrl("javascript:" + js);
  530. }
  531. };
  532. try {
  533. Method post = webView.getClass().getMethod("post",Runnable.class);
  534. post.invoke(webView,jsLoader);
  535. } catch(Exception e) {
  536. ((Activity)(webView.getContext())).runOnUiThread(jsLoader);
  537. }
  538. }
  539. // /**
  540. // * Convert JSON array of integers to List.
  541. // *
  542. // * @param ary
  543. // * Array of integers
  544. // */
  545. // private List<Integer> toList (JSONArray ary) {
  546. // ArrayList<Integer> list = new ArrayList<Integer>();
  547. // for (int i = 0; i < ary.length(); i++) {
  548. // list.add(ary.optInt(i));
  549. // }
  550. // return list;
  551. // }
  552. /**
  553. * Current application state.
  554. *
  555. * @return "background" or "foreground"
  556. */
  557. static String getApplicationState() {
  558. return isInBackground ? "background" : "foreground";
  559. }
  560. /**
  561. * Notification manager instance.
  562. */
  563. private Manager getNotificationMgr() {
  564. return Manager.getInstance(cordova.getActivity());
  565. }
  566. }