├── .editorconfig
├── .github
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .jshintrc
├── .npmignore
├── CHANGELOG.md
├── MIT-LICENSE
├── README.md
├── docs
└── api.md
├── package.json
├── plugin.xml
├── src
├── android
│ ├── LocalNotifications.java
│ └── NotificationHandlerActivity.java
└── ios
│ ├── AppDelegate+LocalNotification.h
│ ├── AppDelegate+LocalNotification.m
│ ├── W3CLocalNotifications.h
│ └── W3CLocalNotifications.m
├── tests
├── plugin.xml
└── tests.js
└── www
└── notification.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style of different editors and IDEs.
2 | # editorconfig.org
3 |
4 | root = true
5 |
6 | [*]
7 | charset = utf-8
8 | end_of_line = lf
9 | indent_size = 4
10 | indent_style = space
11 | insert_final_newline = true
12 | trim_trailing_whitespace = true
13 |
14 | [*.json]
15 | indent_size = 2
16 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | We love pull requests from everyone.
4 |
5 | [Fork](https://help.github.com/articles/fork-a-repo/), then [clone](https://help.github.com/articles/cloning-a-repository/) the repo:
6 |
7 | ```
8 | git clone git@github.com:your-username/phonegap-plugin-local-notification.git
9 | ```
10 |
11 | Set up a branch for your feature or bugfix with a link to the original repo:
12 |
13 | ```
14 | git checkout -b my-awesome-new-feature
15 | git push --set-upstream origin my-awesome-new-feature
16 | git remote add upstream https://github.com/phonegap/phonegap-plugin-local-notification.git
17 | ```
18 |
19 | Set up the project:
20 |
21 | ```
22 | npm install
23 | ```
24 |
25 | Make sure the tests pass before changing anything:
26 |
27 | ```
28 | npm test
29 | ```
30 |
31 | Make your change. Add tests for your change. Make the tests pass:
32 |
33 | ```
34 | npm test
35 | ```
36 |
37 | Commit changes:
38 |
39 | ```
40 | git commit -m "Cool stuff"
41 | ```
42 |
43 | Consider starting the commit message with an applicable emoji:
44 | * :art: `:art:` when improving the format/structure of the code
45 | * :zap: `:zap:` when improving performance
46 | * :non-potable_water: `:non-potable_water:` when plugging memory leaks
47 | * :memo: `:memo:` when writing docs
48 | * :ambulance: `:ambulance:` a critical hotfix.
49 | * :sparkles: `:sparkles:` when introducing new features
50 | * :bookmark: `:bookmark:` when releasing / version tags
51 | * :rocket: `:rocket:` when deploying stuff
52 | * :penguin: `:penguin:` when fixing something on Android
53 | * :apple: `:apple:` when fixing something on iOS
54 | * :checkered_flag: `:checkered_flag:` when fixing something on Windows
55 | * :bug: `:bug:` when fixing a bug
56 | * :fire: `:fire:` when removing code or files
57 | * :green_heart: `:green_heart:` when fixing the CI build
58 | * :white_check_mark: `:white_check_mark:` when adding tests
59 | * :lock: `:lock:` when dealing with security
60 | * :arrow_up: `:arrow_up:` when upgrading dependencies
61 | * :arrow_down: `:arrow_down:` when downgrading dependencies
62 | * :shirt: `:shirt:` when removing linter warnings
63 | * :hammer: `:hammer:` when doing heavy refactoring
64 | * :heavy_minus_sign: `:heavy_minus_sign:` when removing a dependency.
65 | * :heavy_plus_sign: `:heavy_plus_sign:` when adding a dependency.
66 | * :wrench: `:wrench:` when changing configuration files.
67 | * :globe_with_meridians: `:globe_with_meridians:` when dealing with internationalization and localization.
68 | * :pencil2: `:pencil2:` when fixing typos.
69 | * :hankey: `:hankey:` when writing bad code that needs to be improved.
70 | * :package: `:package:` when updating compiled files or packages.
71 |
72 | Make sure your branch is up to date with the original repo:
73 |
74 | ```
75 | git fetch upstream
76 | git merge upstream/master
77 | ```
78 |
79 | Review your changes and any possible conflicts and push to your fork:
80 |
81 | ```
82 | git push origin
83 | ```
84 |
85 | [Submit a pull request](https://help.github.com/articles/creating-a-pull-request/).
86 |
87 | At this point you're waiting on us. We do our best to keep on top of all the pull requests. We may suggest some changes, improvements or alternatives.
88 |
89 | Some things that will increase the chance that your pull request is accepted:
90 |
91 | - Write tests.
92 | - Write a [good commit message](http://chris.beams.io/posts/git-commit/).
93 | - Make sure the PR merges cleanly with the latest master.
94 | - Describe your feature/bugfix and why it's needed/important in the pull request description.
95 |
96 |
97 | ## Editor Config
98 |
99 | The project uses [.editorconfig](http://editorconfig.org/) to define the coding
100 | style of each file. We recommend that you install the Editor Config extension
101 | for your preferred IDE. Consistency is key.
102 |
103 | ## JSHint
104 |
105 | The project uses [.jshint](http://jshint.com/docs) to define the JavaScript
106 | coding conventions. Most editors now have a JSHint add-on to provide on-save
107 | or on-edit linting.
108 |
109 | ### Install JSHint for vim
110 |
111 | 1. Install [jshint](https://www.npmjs.com/package/jshint).
112 | 1. Install [jshint.vim](https://github.com/wookiehangover/jshint.vim).
113 |
114 | ### Install JSHint for Sublime
115 |
116 | 1. Install [Package Control](https://packagecontrol.io/installation)
117 | 1. Restart Sublime
118 | 1. Type `CMD+SHIFT+P`
119 | 1. Type _Install Package_
120 | 1. Type _JSHint Gutter_
121 | 1. Sublime -> Preferences -> Package Settings -> JSHint Gutter
122 | 1. Set `lint_on_load` and `lint_on_save` to `true`
123 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Expected Behaviour
2 |
3 | ### Actual Behaviour
4 |
5 | ### Reproduce Scenario (including but not limited to)
6 |
7 | #### Steps to Reproduce
8 |
9 | #### Platform and Version (e.g. Android 5.0 or iOS 9.2.1)
10 |
11 | #### (Android) What device vendor (e.g. Samsung, HTC, Sony...)
12 |
13 | #### Cordova CLI version and cordova platform version
14 |
15 | cordova --version # e.g. 6.0.0
16 | cordova platform version android # e.g. 4.1.1
17 |
18 | #### Plugin version
19 |
20 | cordova plugin version | grep phonegap-plugin-local-notification # e.g. 1.5.3
21 |
22 | #### Sample Code that illustrates the problem
23 |
24 | #### Logs taken while reproducing problem
25 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Description
4 |
5 |
6 | ## Related Issue
7 |
8 |
9 |
10 |
11 |
12 | ## Motivation and Context
13 |
14 |
15 | ## How Has This Been Tested?
16 |
17 |
18 |
19 |
20 | ## Screenshots (if appropriate):
21 |
22 | ## Types of changes
23 |
24 | - [ ] Bug fix (non-breaking change which fixes an issue)
25 | - [ ] New feature (non-breaking change which adds functionality)
26 | - [ ] Breaking change (fix or feature that would cause existing functionality to change)
27 |
28 | ## Checklist:
29 |
30 |
31 | - [ ] My code follows the code style of this project.
32 | - [ ] My change requires a change to the documentation.
33 | - [ ] I have updated the documentation accordingly.
34 | - [ ] I have read the **CONTRIBUTING** document.
35 | - [ ] I have added tests to cover my changes.
36 | - [ ] All new and existing tests passed.
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea
3 | .DS_Store
4 | /node_modules/
5 | npm-debug.log
6 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "asi": false,
3 | "boss": false,
4 | "camelcase": true,
5 | "curly": true,
6 | "eqeqeq": true,
7 | "eqnull": false,
8 | "es5": false,
9 | "evil": false,
10 | "expr": false,
11 | "forin": true,
12 | "funcscope": false,
13 | "jasmine": true,
14 | "immed": true,
15 | "indent": 4,
16 | "latedef": true,
17 | "loopfunc": false,
18 | "maxerr": 7,
19 | "newcap": true,
20 | "node": true,
21 | "nonew": true,
22 | "plusplus": false,
23 | "quotmark": "single",
24 | "shadow": false,
25 | "strict": false,
26 | "supernew": false,
27 | "trailing": true,
28 | "undef": true,
29 | "white": true
30 | }
31 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | spec/
2 | tests/
3 | .vscode/
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## [v1.0.1](https://github.com/phonegap/phonegap-plugin-local-notification/tree/v1.0.1) (2017-04-25)
4 | [Full Changelog](https://github.com/phonegap/phonegap-plugin-local-notification/compare/v1.0.0...v1.0.1)
5 |
6 | - 1.0.1 [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/d2552f8e71f6050f05ebfe4bef702970a5237da3)
7 | - :bookmark: Bumping plugin version to 1.0.1 [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/c8815608e1d6273442e881aaa21802b8c46a1d4d)
8 | - :bug::penguin: Fix activity name [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/93af1a3cfd5f0fc52d41adcca55ba711e93c51af)
9 | - Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/727aa00c3536dd8ac059d332de836dcecf8205bf)
10 |
11 | ## [v1.0.0](https://github.com/phonegap/phonegap-plugin-local-notification/tree/v1.0.0) (2017-04-24)
12 | [Full Changelog](https://github.com/phonegap/phonegap-plugin-local-notification/compare/v0.0.1...v1.0.0)
13 |
14 | - 1.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/8885886b2a689b26231b7706db98fa0d3bc58ef1)
15 | - :bookmark: Bumping plugin version to 1.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/fe3a598f8512ee9078208a14f133c83430b76663)
16 | - :wrench: adding LICENSE file [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/f7646f9c214fc419b5be18ffdc11802768d44102)
17 | - :beer::memo: Issue #2: Instrument notification.js with jsdocs [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/afd2111b2f66490ed2fb1ddba34c66e80c880e1f)
18 | - :heavy_plus_sign: add js2docs package [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/5dc3ab5b07b89dcba9343b5ef000baac19526f38)
19 | - :hammer: cleaning up iOS code [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/0ee8cc57759ff7f725d89617ea869fb52ef96296)
20 | - :apple: Implement click event firing for iOS [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/c6ee0376cfd735b65f8da831f998302684f2d418)
21 | - :penguin: Implement click event firing [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/75747b93590f6deb66e4cac7acb52b56ea093fff)
22 | - :penguin: Implement show and close events for Android [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/043e8f07e524dfcc2450dc71649719a8f3467fb6)
23 | - :apple: Implement show, close and error events for iOS [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/8b5dbb654cbcba7221b36297bd2370456530d0ca)
24 | - :beer: Fire show, close, error and click events from JavaScript [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/1eb096794e02e1a7ca9acb725521342313a41b41)
25 | - :memo: Issue #6: Add github templates [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/162a82d3365c20a438d62f88a0a4cc64b661a3df)
26 | - :wrench: Issue #5: Add pluginpub to package.json [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/e9e789621b12e09e2ffe58386b1d0b0fdcb000e8)
27 | - :apple: implement show and close functionality [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/1f2d380c8d0cd1bd01b1afe3876dc6c99cb097ec)
28 | - :apple: implement requestPermission method [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/e7762331c10727033c1bc6f5539db484874e6d71)
29 | - :penguin: implement requestPermission method [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/19d2f3908462667fcb72ae45d179f2f2b335fabb)
30 | - :wrench: add a gitignore file [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/f1133b13a4f40f3ecc8525a26c99fbbaade93107)
31 | - :memo: update README [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/85bce1324d79f1325396a812319958185b4363ac)
32 | - :penguin: Implementation of show and close functionality [view commit](http://github.com/phonegap/phonegap-plugin-local-notification/commit/f37464874c699a8db7e37d0c4f1bfd8788eea6fd)
33 |
34 | undefined
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2012-2017 Adobe Systems
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | phonegap-plugin-local-notification
3 | ------------------------
4 |
5 | An implementation of the Web Notifications API for end-user notifications. The Local Notification plugin gives developers the ability to post notifications from their app that show up in the device’s notification area. The API for the local notification plugin follows the [W3C Web Notifications specification](https://www.w3.org/TR/notifications/).
6 |
7 | ## Platform Support
8 | - iOS
9 | - Android
10 |
11 | ## Installation
12 |
13 | After you have built your project, install the plugin in your project location:
14 | ```
15 | $ phonegap plugin add phonegap-plugin-local-notification
16 | ```
17 |
18 | (or)
19 | ```
20 | $ cordova plugin add phonegap-plugin-local-notification
21 | ```
22 |
23 | ## Usage
24 | Please read through the [full API documentation here](https://github.com/phonegap/phonegap-plugin-local-notification/blob/master/docs/api.md). To show a new local notification add this code to your application’s JavaScript:
25 |
26 | ```js
27 | if (“Notification” in window) {
28 | Notification.requestPermission(function (permission) {
29 | // If the user accepts, let’s create a notification
30 | if (permission === ‘granted’) {
31 | var notification = new Notification(“My title”, {
32 | tag: ‘message1’,
33 | body: “My body”
34 | });
35 | notification.onshow = function() { console.log(‘show’); };
36 | notification.onclose = function() { console.log(‘close’); };
37 | notification.onclick = function() { console.log(‘click’); };
38 | }
39 | });
40 | }
41 | ```
42 |
43 | To close a local notification make this call in your application’s JavaScript:
44 |
45 | ```js
46 | notification.close();
47 | ```
48 |
49 | ## Known Issues
50 | - iOS requires that you specify the body for the notification. Without a title and a body the notification will not be shown.
51 |
52 |
53 | ## Contact Us
54 | Your feedback is graciously accepted and appreciated!
55 | Please submit your pull requests and issues here.
56 |
--------------------------------------------------------------------------------
/docs/api.md:
--------------------------------------------------------------------------------
1 | ## Functions
2 |
3 |
4 | - Notification(title, options)
5 | A global object that lets you interact with the Notification API.
6 |
7 |
8 |
9 | ## Typedefs
10 |
11 |
12 | - callback :
function
13 | A callback to be used when the requestPermission method returns a value.
14 |
15 |
16 |
17 |
18 |
19 | ## Notification(title, options)
20 | A global object that lets you interact with the Notification API.
21 |
22 | **Kind**: global function
23 |
24 | | Param | Type | Description |
25 | | --- | --- | --- |
26 | | title | string
| of the local notification. |
27 | | options | Options
| An object containing optional property/value pairs. |
28 |
29 |
30 | * [Notification(title, options)](#Notification)
31 | * [.requestPermission(callback)](#Notification.requestPermission)
32 | * [.close()](#Notification.close)
33 |
34 |
35 |
36 | ### Notification.requestPermission(callback)
37 | requests permission from the user to show a local notification.
38 |
39 | **Kind**: static method of [Notification
](#Notification)
40 |
41 | | Param | Type | Description |
42 | | --- | --- | --- |
43 | | callback | [callback
](#callback) | See type definition. |
44 |
45 |
46 |
47 | ### Notification.close()
48 | closes an open notification.
49 |
50 | **Kind**: static method of [Notification
](#Notification)
51 |
52 |
53 | ## callback : function
54 | A callback to be used when the requestPermission method returns a value.
55 |
56 | **Kind**: global typedef
57 |
58 | | Param | Type | Description |
59 | | --- | --- | --- |
60 | | permission | string
| one of "default", "denied" or "granted" |
61 |
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "phonegap-plugin-local-notification",
3 | "description": "",
4 | "version": "1.0.1",
5 | "homepage": "http://github.com/phonegap/phonegap-plugin-local-notification#readme",
6 | "repository": {
7 | "type": "git",
8 | "url": "http://github.com/phonegap/phonegap-plugin-local-notification.git"
9 | },
10 | "bugs": {
11 | "url": "http://github.com/phonegap/phonegap-plugin-local-notification/issues"
12 | },
13 | "cordova": {
14 | "id": "phonegap-plugin-local-notification",
15 | "platforms": [
16 | "ios",
17 | "android",
18 | "windows"
19 | ]
20 | },
21 | "keywords": [
22 | "ecosystem:cordova",
23 | "ecosystem:phonegap"
24 | ],
25 | "engines": {
26 | "cordova": ">=3.0.0"
27 | },
28 | "author": "Adobe PhoneGap Team",
29 | "license": "MIT",
30 | "scripts": {
31 | "build": "npm run build:docs && npm test",
32 | "build:docs": "jsdoc2md www/notification.js > docs/api.md",
33 | "test": "jasmine-node --color spec"
34 | },
35 | "devDependencies": {
36 | "jasmine-node": "1.14.5",
37 | "jsdoc-to-markdown": "^3.0.0",
38 | "pluginpub": "^0.0.8"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | phonegap-plugin-local-notification
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/android/LocalNotifications.java:
--------------------------------------------------------------------------------
1 |
2 | package com.adobe.phonegap.notification;
3 |
4 | import org.apache.cordova.CallbackContext;
5 | import org.apache.cordova.CordovaPlugin;
6 | import org.apache.cordova.CordovaWebView;
7 | import org.apache.cordova.PluginResult;
8 | import org.json.JSONArray;
9 | import org.json.JSONException;
10 |
11 | import android.annotation.SuppressLint;
12 | import android.app.NotificationManager;
13 | import android.app.PendingIntent;
14 | import android.content.Context;
15 | import android.content.Intent;
16 | import android.graphics.Bitmap;
17 | import android.graphics.BitmapFactory;
18 | import android.support.v4.app.NotificationCompat;
19 | import android.util.Log;
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 | import java.net.HttpURLConnection;
24 | import java.net.URL;
25 | import java.util.Random;
26 |
27 | /**
28 | * This class exposes methods in Cordova that can be called from JavaScript.
29 | */
30 | public class LocalNotifications extends CordovaPlugin {
31 |
32 | private static final String TAG = "LocalNotifications";
33 |
34 | private static CallbackContext notificationContext;
35 |
36 | /**
37 | * Executes the request and returns PluginResult.
38 | *
39 | * @param action The action to execute.
40 | * @param args JSONArry of arguments for the plugin.
41 | * @param callbackContext The callback context from which we were invoked.
42 | */
43 | @SuppressLint("NewApi")
44 | public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
45 | Log.d(TAG, "in local notifications");
46 |
47 | if (action.equals("show")) {
48 | Log.d(TAG, "action show");
49 |
50 | notificationContext = callbackContext;
51 |
52 | showNotification(args);
53 |
54 | PluginResult result = new PluginResult(PluginResult.Status.OK, "show");
55 | result.setKeepCallback(true);
56 | notificationContext.sendPluginResult(result);
57 | } else if (action.equals("close")) {
58 | NotificationManager mNotificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
59 | mNotificationManager.cancel(args.getString(0), 0);
60 |
61 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
62 | } else if (action.equals("requestPermission")) {
63 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "granted"));
64 | } else {
65 | Log.d(TAG, "return false");
66 | return false;
67 | }
68 | return true;
69 | }
70 |
71 | private void showNotification(JSONArray args) throws JSONException {
72 | // Get args
73 | String title = args.getString(0);
74 | String dir = args.getString(1);
75 | String lang = args.getString(2);
76 | String body = args.getString(3);
77 | String tag = args.getString(4);
78 | String icon = args.getString(5);
79 |
80 | Context context = cordova.getActivity();
81 |
82 | Intent notificationIntent = new Intent(context, NotificationHandlerActivity.class);
83 | notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
84 | notificationIntent.putExtra("tag", tag);
85 |
86 | int requestCode = new Random().nextInt();
87 | PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
88 |
89 |
90 | // Build notifications
91 | NotificationCompat.Builder mBuilder =
92 | new NotificationCompat.Builder(context)
93 | .setWhen(System.currentTimeMillis())
94 | .setContentTitle(title)
95 | .setContentText(body)
96 | .setSmallIcon(context.getApplicationInfo().icon)
97 | .setContentIntent(contentIntent)
98 | .setAutoCancel(true);
99 |
100 | if (icon.startsWith("http://") || icon.startsWith("https://")) {
101 | Bitmap bitmap = getBitmapFromURL(icon);
102 | mBuilder.setLargeIcon(bitmap);
103 | }
104 |
105 | // Show notification
106 | NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
107 | mNotificationManager.notify(tag, 0, mBuilder.build());
108 | }
109 |
110 | private Bitmap getBitmapFromURL(String strURL) {
111 | try {
112 | URL url = new URL(strURL);
113 | HttpURLConnection connection = (HttpURLConnection) url.openConnection();
114 | connection.setConnectTimeout(15000);
115 | connection.setDoInput(true);
116 | connection.connect();
117 | InputStream input = connection.getInputStream();
118 | return BitmapFactory.decodeStream(input);
119 | } catch (IOException e) {
120 | e.printStackTrace();
121 | return null;
122 | }
123 | }
124 |
125 | public static void fireClickEvent(String tag) {
126 | PluginResult result = new PluginResult(PluginResult.Status.OK, "click");
127 | result.setKeepCallback(true);
128 | notificationContext.sendPluginResult(result);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/android/NotificationHandlerActivity.java:
--------------------------------------------------------------------------------
1 | package com.adobe.phonegap.notification;
2 |
3 | import android.app.Activity;
4 | import android.app.NotificationManager;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.pm.PackageManager;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.support.v4.app.RemoteInput;
11 |
12 | public class NotificationHandlerActivity extends Activity {
13 | private static String LOG_TAG = "LocalNotification_PushHandlerActivity";
14 |
15 | /*
16 | * this activity will be started if the user touches a notification that we own.
17 | * We send it's data off to the push plugin for processing.
18 | * If needed, we boot up the main activity to kickstart the application.
19 | * @see android.app.Activity#onCreate(android.os.Bundle)
20 | */
21 | @Override
22 | public void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 |
25 | Log.d(LOG_TAG, "in on create of pushhandleractivity");
26 |
27 | Intent intent = getIntent();
28 | String tag = intent.getExtras().getString("tag", "");
29 |
30 | NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
31 | notificationManager.cancel(tag, 0);
32 |
33 | LocalNotifications.fireClickEvent(tag);
34 |
35 | forceMainActivityReload();
36 |
37 | finish();
38 | }
39 |
40 | /**
41 | * Forces the main activity to re-launch if it's unloaded.
42 | */
43 | private void forceMainActivityReload() {
44 | PackageManager pm = getPackageManager();
45 | Intent launchIntent = pm.getLaunchIntentForPackage(getApplicationContext().getPackageName());
46 | startActivity(launchIntent);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/ios/AppDelegate+LocalNotification.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate+LocalNotification.h
3 | //
4 |
5 | #import "AppDelegate.h"
6 |
7 | @interface AppDelegate (notification)
8 | -(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
9 |
10 | @property (nonatomic, retain) NSDictionary *launchNotification;
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/src/ios/AppDelegate+LocalNotification.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate+LocalNotification.m
3 | //
4 |
5 | #import "AppDelegate+LocalNotification.h"
6 | #import "W3CLocalNotifications.h"
7 | #import
8 |
9 | static char launchNotificationKey;
10 |
11 | @implementation AppDelegate (notification)
12 |
13 | - (id) getCommandInstance:(NSString*)className
14 | {
15 | return [self.viewController getCommandInstance:className];
16 | }
17 |
18 | // its dangerous to override a method from within a category.
19 | // Instead we will use method swizzling. we set this up in the load call.
20 | + (void)load
21 | {
22 | static dispatch_once_t onceToken;
23 | dispatch_once(&onceToken, ^{
24 | Class class = [self class];
25 |
26 | SEL originalSelector = @selector(init);
27 | SEL swizzledSelector = @selector(notificationPluginSwizzledInit);
28 |
29 | Method original = class_getInstanceMethod(class, originalSelector);
30 | Method swizzled = class_getInstanceMethod(class, swizzledSelector);
31 |
32 | BOOL didAddMethod =
33 | class_addMethod(class,
34 | originalSelector,
35 | method_getImplementation(swizzled),
36 | method_getTypeEncoding(swizzled));
37 |
38 | if (didAddMethod) {
39 | class_replaceMethod(class,
40 | swizzledSelector,
41 | method_getImplementation(original),
42 | method_getTypeEncoding(original));
43 | } else {
44 | method_exchangeImplementations(original, swizzled);
45 | }
46 | });
47 | }
48 |
49 | - (AppDelegate *)notificationPluginSwizzledInit
50 | {
51 | [[NSNotificationCenter defaultCenter] addObserver:self
52 | selector:@selector(createNotificationChecker:)
53 | name:UIApplicationDidFinishLaunchingNotification
54 | object:nil];
55 | [[NSNotificationCenter defaultCenter]addObserver:self
56 | selector:@selector(pushPluginOnApplicationDidBecomeActive:)
57 | name:UIApplicationDidBecomeActiveNotification
58 | object:nil];
59 |
60 | // This actually calls the original init method over in AppDelegate. Equivilent to calling super
61 | // on an overrided method, this is not recursive, although it appears that way. neat huh?
62 | return [self notificationPluginSwizzledInit];
63 | }
64 |
65 | // This code will be called immediately after application:didFinishLaunchingWithOptions:. We need
66 | // to process notifications in cold-start situations
67 | - (void)createNotificationChecker:(NSNotification *)notification
68 | {
69 | NSLog(@"createNotificationChecker");
70 | }
71 |
72 | - (void)pushPluginOnApplicationDidBecomeActive:(NSNotification *)notification {
73 |
74 | NSLog(@"active");
75 | }
76 |
77 | -(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
78 | {
79 | NSLog(@"got local notification");
80 | W3CLocalNotifications *notificationHandler = [self getCommandInstance:@"LocalNotifications"];
81 | [notificationHandler notificationClicked];
82 |
83 | }
84 |
85 | // The accessors use an Associative Reference since you can't define a iVar in a category
86 | // http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocAssociativeReferences.html
87 | - (NSMutableArray *)launchNotification
88 | {
89 | return objc_getAssociatedObject(self, &launchNotificationKey);
90 | }
91 |
92 | - (void)setLaunchNotification:(NSDictionary *)aDictionary
93 | {
94 | objc_setAssociatedObject(self, &launchNotificationKey, aDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
95 | }
96 |
97 | - (void)dealloc
98 | {
99 | self.launchNotification = nil; // clear the association and release the object
100 | }
101 |
102 | @end
103 |
--------------------------------------------------------------------------------
/src/ios/W3CLocalNotifications.h:
--------------------------------------------------------------------------------
1 | //
2 | // W3CLocalNotifications.h
3 | //
4 |
5 | #import
6 | #import
7 |
8 | @interface W3CLocalNotifications : CDVPlugin
9 | {
10 | NSDictionary *notificationMessage;
11 | NSString *notificationCallbackId;
12 | }
13 |
14 | @property (nonatomic, copy) NSString *callbackId;
15 |
16 | - (void)show:(CDVInvokedUrlCommand*)command;
17 | - (void)close:(CDVInvokedUrlCommand*)command;
18 | - (void)requestPermission:(CDVInvokedUrlCommand*)command;
19 | - (void)notificationClicked;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/src/ios/W3CLocalNotifications.m:
--------------------------------------------------------------------------------
1 |
2 | @import UserNotifications;
3 |
4 | #import
5 | #import "W3CLocalNotifications.h"
6 |
7 | @implementation W3CLocalNotifications : CDVPlugin
8 |
9 | @synthesize callbackId;
10 |
11 | - (void)show:(CDVInvokedUrlCommand*)command {
12 | self.callbackId = command.callbackId;
13 |
14 | UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
15 |
16 | UNMutableNotificationContent *content = [UNMutableNotificationContent new];
17 | content.title = [command.arguments objectAtIndex:0];
18 | content.body = [command.arguments objectAtIndex:3];
19 |
20 | NSString *identifier = [command.arguments objectAtIndex:4];
21 |
22 | UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:nil];
23 |
24 | [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
25 | if (error != nil) {
26 | NSLog(@"Something went wrong: %@",error);
27 | CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
28 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
29 | } else {
30 | CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"show"];
31 | [pluginResult setKeepCallbackAsBool:YES];
32 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
33 | }
34 | }];
35 | }
36 |
37 | - (void)close:(CDVInvokedUrlCommand*)command {
38 | UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
39 |
40 | NSArray *identifiers = @[[command.arguments objectAtIndex:0]];
41 | [center removeDeliveredNotificationsWithIdentifiers:identifiers];
42 |
43 | CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
44 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
45 | }
46 |
47 | - (void)requestPermission:(CDVInvokedUrlCommand*)command {
48 | UNAuthorizationOptions options = UNAuthorizationOptionAlert + UNAuthorizationOptionSound;
49 | UNUserNotificationCenter *center = UNUserNotificationCenter.currentNotificationCenter;
50 | [center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError * _Nullable error) {
51 | if (granted) {
52 | CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"granted"];
53 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
54 | } else {
55 | CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"denied"];
56 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
57 | }
58 | }];
59 | }
60 |
61 | - (void)notificationClicked {
62 | NSLog(@"in plugin, local notification clicked");
63 | CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"click"];
64 | [pluginResult setKeepCallbackAsBool:YES];
65 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
66 | }
67 |
68 | @end
69 |
--------------------------------------------------------------------------------
/tests/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
26 | Phonegap Local Notification Plugin
27 | Apache 2.0
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/tests/tests.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
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 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 | /* jshint jasmine: true */
22 | /* global navigator, done, Notification */
23 | exports.defineAutoTests = function() {
24 |
25 | describe('Notification', function() {
26 | it('Notification should be defined', function() {
27 | expect(Notification).toBeDefined();
28 | expect(typeof Notification).toBe('function');
29 | expect(Notification.requestPermission).toBeDefined();
30 | expect(typeof Notification.requestPermission).toBe('function');
31 | });
32 |
33 | it('Notification instance should include default properties', function() {
34 | var notification = new Notification('title');
35 | expect(notification.permission).toBeDefined();
36 | expect(notification.title).toBeDefined();
37 | expect(notification.title).toBe('title');
38 | expect(notification.dir).toBeDefined();
39 | expect(notification.dir).toBe('auto');
40 | expect(notification.lang).toBeDefined();
41 | expect(notification.body).toBeDefined();
42 | expect(notification.tag).toBeDefined();
43 | expect(notification.icon).toBeDefined();
44 | expect(notification.close).toBeDefined();
45 | expect(typeof notification.close).toBe('function');
46 | });
47 |
48 | it('Notification instance should get properties from options object', function() {
49 | var notification = new Notification('title', {
50 | dir: 'ltr',
51 | lang: 'en-US',
52 | body: 'body',
53 | tag: 'tag',
54 | icon: 'icon'
55 | });
56 | expect(notification.permission).toBeDefined();
57 | expect(notification.title).toBeDefined();
58 | expect(notification.title).toBe('title');
59 | expect(notification.dir).toBeDefined();
60 | expect(notification.dir).toBe('ltr');
61 | expect(notification.lang).toBeDefined();
62 | expect(notification.lang).toBe('en-US');
63 | expect(notification.body).toBeDefined();
64 | expect(notification.body).toBe('body');
65 | expect(notification.tag).toBeDefined();
66 | expect(notification.tag).toBe('tag');
67 | expect(notification.icon).toBeDefined();
68 | expect(notification.icon).toBe('icon');
69 | expect(notification.close).toBeDefined();
70 | expect(typeof notification.close).toBe('function');
71 | });
72 |
73 | it('Notification instance should throw exception without title property', function() {
74 | expect(function() { var n = new Notification(); }).toThrow();
75 | });
76 | });
77 | };
78 |
--------------------------------------------------------------------------------
/www/notification.js:
--------------------------------------------------------------------------------
1 | /* global cordova:false */
2 | /* globals window */
3 |
4 | var argscheck = cordova.require('cordova/argscheck'),
5 | exec = cordova.require('cordova/exec'),
6 | utils = cordova.require('cordova/utils');
7 |
8 | /**
9 | * @description A global object that lets you interact with the Notification API.
10 | * @global
11 | * @param {!string} title of the local notification.
12 | * @param {?Options} options An object containing optional property/value pairs.
13 | */
14 | var Notification = function(title, options) {
15 | // require title parameter
16 | if (typeof title === 'undefined') {
17 | throw new Error('The title argument is required.');
18 | }
19 |
20 | options = options || {};
21 | var getValue = argscheck.getValue;
22 |
23 | this.permission = 'granted';
24 | this.title = getValue(title, '');
25 | this.dir = getValue(options.dir, 'auto');
26 | this.lang = getValue(options.lang, '');
27 | this.body = getValue(options.body, '');
28 | this.tag = getValue(options.tag, '');
29 | this.icon = getValue(options.icon, '');
30 | this.onclick = function() {};
31 | this.onshow = function() {};
32 | this.onerror = function() {};
33 | this.onclose = function() {};
34 |
35 | // triggered on click, show, error and close
36 | var that = this;
37 | var success = function(result) {
38 | if (!result) {
39 | return;
40 | }
41 |
42 | if (result === 'show') {
43 | that.onshow();
44 | } else if (result === 'click') {
45 | that.onclick();
46 | }
47 | };
48 |
49 | var failure = function() {
50 | that.onerror();
51 | };
52 |
53 | exec(success, failure, 'LocalNotifications', 'show', [this.title, this.dir, this.lang, this.body, this.tag, this.icon]);
54 | };
55 |
56 | /**
57 | * @description requests permission from the user to show a local notification.
58 | * @function requestPermission
59 | * @memberof Notification
60 | * @param {!callback} callback - See type definition.
61 | */
62 | Notification.requestPermission = function(callback) {
63 | if (!callback) { callback = function() {}; }
64 |
65 | if (typeof callback !== 'function') {
66 | console.log('Notification.requestPermission failure: callback parameter not a function');
67 | return;
68 | }
69 |
70 | exec(callback, function() {
71 | console.log('requestPermission error');
72 | }, 'LocalNotifications', 'requestPermission', []);
73 | };
74 |
75 | /**
76 | * @description closes an open notification.
77 | * @function close
78 | * @memberof Notification
79 | */
80 | Notification.prototype.close = function() {
81 | var that = this;
82 | exec(function() {
83 | that.onclose();
84 | }, function() {
85 | that.onerror();
86 | }, 'LocalNotifications', 'close', [this.tag]);
87 | };
88 |
89 | /**
90 | * @description A callback to be used when the requestPermission method returns a value.
91 | *
92 | * @callback callback
93 | * @param {string} permission - one of "default", "denied" or "granted"
94 | */
95 |
96 | /*
97 | * @typedef {Object} Options - An object for configuring Notification behavior.
98 | * @property {string} [dir='auto'] - Sets the direction of the notification. One of "auto", "ltr" or "rtl"
99 | * @property {string} [lang=''] - Sets the language of the notification
100 | * @property {string} [body=''] - Sets the body of the notification
101 | * @property {string} [tag=''] - Sets the identifying tag of the notification
102 | * @property {string} [icon=''] - Sets the icon of the notification
103 | */
104 |
105 | module.exports = Notification;
106 |
--------------------------------------------------------------------------------