local-notification.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. /*
  2. Copyright 2013-2014 appPlant UG
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing,
  12. software distributed under the License is distributed on an
  13. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. KIND, either express or implied. See the License for the
  15. specific language governing permissions and limitations
  16. under the License.
  17. */
  18. var exec = require('cordova/exec'),
  19. channel = require('cordova/channel');
  20. // Called after 'deviceready' event
  21. channel.deviceready.subscribe( function () {
  22. // Device is ready now, the listeners are registered
  23. // and all queued events can be executed.
  24. exec(null, null, 'LocalNotification', 'deviceready', []);
  25. });
  26. // Called before 'deviceready' event
  27. channel.onCordovaReady.subscribe( function () {
  28. // The cordova device plugin is ready now
  29. channel.onCordovaInfoReady.subscribe( function () {
  30. if (device.platform == 'Android') {
  31. channel.onPause.subscribe( function () {
  32. // Necessary to set the state to `background`
  33. exec(null, null, 'LocalNotification', 'pause', []);
  34. });
  35. channel.onResume.subscribe( function () {
  36. // Necessary to set the state to `foreground`
  37. exec(null, null, 'LocalNotification', 'resume', []);
  38. });
  39. // Necessary to set the state to `foreground`
  40. exec(null, null, 'LocalNotification', 'resume', []);
  41. }
  42. // Merges the platform specific properties into the default properties
  43. exports.applyPlatformSpecificOptions();
  44. });
  45. });
  46. /**
  47. * @private
  48. *
  49. * Default values.
  50. */
  51. exports._defaults = {
  52. message: '',
  53. title: '',
  54. autoCancel: false,
  55. badge: -1,
  56. id: '0',
  57. json: '',
  58. repeat: ''
  59. };
  60. /**
  61. * Returns the default settings
  62. *
  63. * @return {Object}
  64. */
  65. exports.getDefaults = function () {
  66. return this._defaults;
  67. };
  68. /**
  69. * Overwrite default settings
  70. *
  71. * @param {Object} defaults
  72. */
  73. exports.setDefaults = function (newDefaults) {
  74. var defaults = this.getDefaults();
  75. for (var key in defaults) {
  76. if (newDefaults[key] !== undefined) {
  77. defaults[key] = newDefaults[key];
  78. }
  79. }
  80. };
  81. /**
  82. * Add a new entry to the registry
  83. *
  84. * @param {Object} props
  85. * The notification properties
  86. * @param {Function} callback
  87. * A function to be called after the notification has been canceled
  88. * @param {Object} scope
  89. * The scope for the callback function
  90. *
  91. * @return {Number}
  92. * The notification's ID
  93. */
  94. exports.add = function (props, callback, scope) {
  95. var options = this.mergeWithDefaults(props),
  96. fn = this.createCallbackFn(callback, scope);
  97. this.convertOptions(options);
  98. if (['WinCE', 'Win32NT'].indexOf(device.platform) > -1) {
  99. fn = function (cmd) {
  100. eval(cmd);
  101. };
  102. }
  103. this.registerPermission(function(granted) {
  104. if (granted) {
  105. this.exec('add', options, callback, scope);
  106. }
  107. }, this);
  108. return options.id;
  109. };
  110. /**
  111. * Update existing notification specified by ID in options.
  112. *
  113. * @param {Object} options
  114. * The notification properties to update
  115. * @param {Function} callback
  116. * A function to be called after the notification has been updated
  117. * @param {Object} scope
  118. * The scope for the callback function
  119. */
  120. exports.update = function (options, callback, scope) {
  121. this.exec('update', options, callback, scope);
  122. };
  123. /**
  124. * Clears the specified notification.
  125. *
  126. * @param {String} id
  127. * The ID of the notification
  128. * @param {Function} callback
  129. * A function to be called after the notification has been cleared
  130. * @param {Object} scope
  131. * The scope for the callback function
  132. */
  133. exports.clear = function (id, callback, scope) {
  134. var notId = (id || '0').toString();
  135. this.exec('clear', notId, callback, scope);
  136. };
  137. /**
  138. * Clears all previously sheduled notifications.
  139. *
  140. * @param {Function} callback
  141. * A function to be called after all notifications have been cleared
  142. * @param {Object} scope
  143. * The scope for the callback function
  144. */
  145. exports.clearAll = function (callback, scope) {
  146. this.exec('clearAll', null, callback, scope);
  147. };
  148. /**
  149. * Cancels the specified notifications.
  150. *
  151. * @param {String[]} ids
  152. * The IDs of the notifications
  153. * @param {Function} callback
  154. * A function to be called after the notifications has been canceled
  155. * @param {Object} scope
  156. * The scope for the callback function
  157. */
  158. exports.cancel = function (ids, callback, scope) {
  159. ids = Array.isArray(ids) ? ids : [ids];
  160. for (var i = 0; i < ids.length; i++) {
  161. ids[i] = ids[i].toString();
  162. }
  163. if (device.platform != 'iOS') {
  164. ids = ids[0];
  165. }
  166. this.exec('cancel', ids, callback, scope);
  167. };
  168. /**
  169. * Removes all previously registered notifications.
  170. *
  171. * @param {Function} callback
  172. * A function to be called after all notifications have been canceled
  173. * @param {Object} scope
  174. * The scope for the callback function
  175. */
  176. exports.cancelAll = function (callback, scope) {
  177. this.exec('cancelAll', null, callback, scope);
  178. };
  179. /**
  180. * Retrieves a list with all currently pending notifications.
  181. *
  182. * @param {Function} callback
  183. * A callback function to be called with the list
  184. * @param {Object} scope
  185. * The scope for the callback function
  186. */
  187. exports.getScheduledIds = function (callback, scope) {
  188. this.exec('getScheduledIds', null, callback, scope);
  189. };
  190. /**
  191. * Checks wether a notification with an ID is scheduled.
  192. *
  193. * @param {String} id
  194. * The ID of the notification
  195. * @param {Function} callback
  196. * A callback function to be called with the list
  197. * @param {Object} scope
  198. * The scope for the callback function
  199. */
  200. exports.isScheduled = function (id, callback, scope) {
  201. var notId = (id || '0').toString();
  202. this.exec('isScheduled', notId, callback, scope);
  203. };
  204. /**
  205. * Retrieves a list with all triggered notifications.
  206. *
  207. * @param {Function} callback
  208. * A callback function to be called with the list
  209. * @param {Object} scope
  210. * The scope for the callback function
  211. */
  212. exports.getTriggeredIds = function (callback, scope) {
  213. this.exec('getTriggeredIds', null, callback, scope);
  214. };
  215. /**
  216. * Checks wether a notification with an ID was triggered.
  217. *
  218. * @param {String} id
  219. * The ID of the notification
  220. * @param {Function} callback
  221. * A callback function to be called with the list
  222. * @param {Object} scope
  223. * The scope for the callback function
  224. */
  225. exports.isTriggered = function (id, callback, scope) {
  226. var notId = (id || '0').toString();
  227. this.exec('isTriggered', notId, callback, scope);
  228. };
  229. /**
  230. * Informs if the app has the permission to show notifications.
  231. *
  232. * @param {Function} callback
  233. * The function to be exec as the callback
  234. * @param {Object?} scope
  235. * The callback function's scope
  236. */
  237. exports.hasPermission = function (callback, scope) {
  238. var fn = this.createCallbackFn(callback, scope);
  239. if (device.platform != 'iOS') {
  240. fn(true);
  241. return;
  242. }
  243. exec(fn, null, 'LocalNotification', 'hasPermission', []);
  244. };
  245. /**
  246. * Register permission to show notifications if not already granted.
  247. *
  248. * @param {Function} callback
  249. * The function to be exec as the callback
  250. * @param {Object?} scope
  251. * The callback function's scope
  252. */
  253. exports.registerPermission = function (callback, scope) {
  254. var fn = this.createCallbackFn(callback, scope);
  255. if (device.platform != 'iOS') {
  256. fn(true);
  257. return;
  258. }
  259. exec(fn, null, 'LocalNotification', 'registerPermission', []);
  260. };
  261. /**
  262. * @deprecated
  263. *
  264. * Register permission to show notifications if not already granted.
  265. *
  266. * @param {Function} callback
  267. * The function to be exec as the callback
  268. * @param {Object?} scope
  269. * The callback function's scope
  270. */
  271. exports.promptForPermission = function (callback, scope) {
  272. console.warn('Depreated: Please use `notification.local.registerPermission` instead.');
  273. exports.registerPermission.apply(this, arguments);
  274. };
  275. /**
  276. * Add new entries to the registry (more than one)
  277. *
  278. * @param {Object} options
  279. * The notification properties
  280. * @param {Function} callback
  281. * A function to be called after the notification has been added
  282. * @param {Object} scope
  283. * The scope for the callback function
  284. *
  285. * @return {Number}
  286. * The notification's ID
  287. */
  288. exports.addMultiple = function (notifications, callback, scope) {
  289. var length = notifications.length;
  290. var notificationsMerged = new Array(),
  291. callbackFn = this.createCallbackFn(callback, scope);
  292. for (var i=0;i<length;i++){
  293. var options = this.mergeWithDefaults(notifications[i]);
  294. if (options.id) {
  295. options.id = options.id.toString();
  296. }
  297. if (options.date === undefined) {
  298. options.date = new Date();
  299. }
  300. if (options.title) {
  301. options.title = options.title.toString();
  302. }
  303. if (options.message) {
  304. options.message = options.message.toString();
  305. }
  306. if (typeof options.date == 'object') {
  307. options.date = Math.round(options.date.getTime()/1000);
  308. }
  309. if (['WinCE', 'Win32NT'].indexOf(device.platform) > -1) {
  310. callbackFn = function (cmd) {
  311. eval(cmd);
  312. };
  313. }
  314. notificationsMerged.push(options);
  315. }
  316. cordova.exec(callbackFn, null, 'LocalNotification', 'addMultiple', notificationsMerged);
  317. return options.id;
  318. };
  319. /**
  320. * Clear the specified notifications (more than one).
  321. *
  322. * @param {String} id
  323. * The ID of the notification
  324. * @param {Function} callback
  325. * A function to be called after the notifications has been cleared.
  326. * @param {Object} scope
  327. * The scope for the callback function
  328. */
  329. exports.clearMultiple = function (ids, callback, scope) {
  330. var length = ids.length;
  331. var idArray = new Array(),
  332. callbackFn = this.createCallbackFn(callback, scope);
  333. for (var i=0;i<length;i++){
  334. var id = ids[i].toString();
  335. idArray.push(id);
  336. }
  337. var callbackFn = this.createCallbackFn(callback, scope);
  338. cordova.exec(callbackFn, null, 'LocalNotification', 'clearMultiple', [ids]);
  339. };
  340. /**
  341. * Cancel the specified notifications (more than one).
  342. *
  343. * @param {String} id
  344. * The ID of the notification
  345. * @param {Function} callback
  346. * A function to be called after the notifications has been canceled
  347. * @param {Object} scope
  348. * The scope for the callback function
  349. */
  350. exports.cancelMultiple = function (ids, callback, scope) {
  351. var length = ids.length;
  352. var idArray = new Array(),
  353. callbackFn = this.createCallbackFn(callback, scope);
  354. for (var i=0;i<length;i++){
  355. var id = ids[i].toString();
  356. idArray.push(id);
  357. }
  358. var callbackFn = this.createCallbackFn(callback, scope);
  359. cordova.exec(callbackFn, null, 'LocalNotification', 'cancelMultiple', [ids]);
  360. };
  361. /**
  362. * Occurs when a notification was added.
  363. *
  364. * @param {String} id
  365. * The ID of the notification
  366. * @param {String} state
  367. * Either "foreground" or "background"
  368. * @param {String} json
  369. * A custom (JSON) string
  370. * @param {Object} data
  371. * The notification properties
  372. */
  373. exports.onadd = function (id, state, json, data) {};
  374. /**
  375. * Occurs when the notification is triggered.
  376. *
  377. * @param {String} id
  378. * The ID of the notification
  379. * @param {String} state
  380. * Either "foreground" or "background"
  381. * @param {String} json
  382. * A custom (JSON) string
  383. * @param {Object} data
  384. * The notification properties
  385. */
  386. exports.ontrigger = function (id, state, json, data) {};
  387. /**
  388. * Fires after the notification was clicked.
  389. *
  390. * @param {String} id
  391. * The ID of the notification
  392. * @param {String} state
  393. * Either "foreground" or "background"
  394. * @param {String} json
  395. * A custom (JSON) string
  396. * @param {Object} data
  397. * The notification properties
  398. */
  399. exports.onclick = function (id, state, json, data) {};
  400. /**
  401. * Fires if the notification was canceled.
  402. *
  403. * @param {String} id
  404. * The ID of the notification
  405. * @param {String} state
  406. * Either "foreground" or "background"
  407. * @param {String} json
  408. * A custom (JSON) string
  409. * @param {Object} data
  410. * The notification properties
  411. */
  412. exports.oncancel = function (id, state, json, data) {};
  413. /**
  414. * Get fired when the notification was cleared.
  415. *
  416. * @param {String} id
  417. * The ID of the notification
  418. * @param {String} state
  419. * Either "foreground" or "background"
  420. * @param {String} json
  421. * A custom (JSON) string
  422. * @param {Object} data
  423. * The notification properties
  424. */
  425. exports.onclear = function (id, state, json, data) {};
  426. /**
  427. * @private
  428. *
  429. * Merges custom properties with the default values.
  430. *
  431. * @param {Object} options
  432. * Set of custom values
  433. *
  434. * @retrun {Object}
  435. * The merged property list
  436. */
  437. exports.mergeWithDefaults = function (options) {
  438. var defaults = this.getDefaults();
  439. for (var key in defaults) {
  440. if (options[key] === undefined) {
  441. options[key] = defaults[key];
  442. }
  443. }
  444. return options;
  445. };
  446. /**
  447. * @private
  448. *
  449. * Convert the passed values to their required type.
  450. *
  451. * @param {Object} options
  452. * Set of custom values
  453. *
  454. * @retrun {Object}
  455. * The converted property list
  456. */
  457. exports.convertOptions = function (options) {
  458. if (options.id) {
  459. options.id = options.id.toString();
  460. }
  461. if (options.date === undefined) {
  462. options.date = new Date();
  463. }
  464. if (options.title) {
  465. options.title = options.title.toString();
  466. }
  467. if (options.message) {
  468. options.message = options.message.toString();
  469. }
  470. if (options.text) {
  471. options.message = options.text.toString();
  472. }
  473. if (typeof options.date == 'object') {
  474. options.date = Math.round(options.date.getTime()/1000);
  475. }
  476. if (typeof options.json == 'object') {
  477. options.json = JSON.stringify(options.json);
  478. }
  479. return options;
  480. };
  481. /**
  482. * @private
  483. *
  484. * Merges the platform specific properties into the default properties.
  485. *
  486. * @return {Object}
  487. * The default properties for the platform
  488. */
  489. exports.applyPlatformSpecificOptions = function () {
  490. var defaults = this._defaults;
  491. switch (device.platform) {
  492. case 'Android':
  493. defaults.icon = 'icon';
  494. defaults.smallIcon = null;
  495. defaults.ongoing = false;
  496. defaults.led = 'FFFFFF'; /*RRGGBB*/
  497. defaults.sound = 'TYPE_NOTIFICATION'; break;
  498. case 'iOS':
  499. defaults.sound = ''; break;
  500. case 'WinCE': case 'Win32NT':
  501. defaults.smallImage = null;
  502. defaults.image = null;
  503. defaults.wideImage = null;
  504. }
  505. return defaults;
  506. };
  507. /**
  508. * @private
  509. *
  510. * Creates a callback, which will be executed within a specific scope.
  511. *
  512. * @param {Function} callbackFn
  513. * The callback function
  514. * @param {Object} scope
  515. * The scope for the function
  516. *
  517. * @return {Function}
  518. * The new callback function
  519. */
  520. exports.createCallbackFn = function (callbackFn, scope) {
  521. if (typeof callbackFn != 'function')
  522. return;
  523. return function () {
  524. callbackFn.apply(scope || this, arguments);
  525. };
  526. };
  527. /**
  528. * @private
  529. *
  530. * Executes the native counterpart.
  531. *
  532. * @param {String} action
  533. * The name of the action
  534. * @param args[]
  535. * Array of arguments
  536. * @param {Function} callback
  537. * The callback function
  538. * @param {Object} scope
  539. * The scope for the function
  540. */
  541. exports.exec = function (action, args, callback, scope) {
  542. var fn = this.createCallbackFn(callback, scope),
  543. params = args ? [args] : [];
  544. exec(fn, null, 'LocalNotification', action, params);
  545. };