├── screencasts
├── 1.png
└── 2.png
├── index.js
├── .npmignore
├── .gitignore
├── ios
├── RCTLocalNotifications.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
└── RCTLocalNotifications
│ ├── AppDelegate+APPRegisterUserNotificationSettings.h
│ ├── APPLocalNotificationOptions.h
│ ├── AppDelegate+APPRegisterUserNotificationSettings.m
│ ├── UILocalNotification+APPLocalNotification.h
│ ├── UIApplication+APPLocalNotification.h
│ ├── APPLocalNotification.h
│ ├── APPLocalNotificationOptions.m
│ ├── UILocalNotification+APPLocalNotification.m
│ ├── UIApplication+APPLocalNotification.m
│ └── APPLocalNotification.m
├── android
├── build.gradle
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── remobile
│ │ └── localNotifications
│ │ ├── RCTLocalNotificationsPackage.java
│ │ ├── notification
│ │ ├── ClearReceiver.java
│ │ ├── ClickActivity.java
│ │ ├── TriggerReceiver.java
│ │ ├── AbstractClearReceiver.java
│ │ ├── AbstractRestoreReceiver.java
│ │ ├── AbstractClickActivity.java
│ │ ├── AbstractTriggerReceiver.java
│ │ ├── Builder.java
│ │ ├── Options.java
│ │ ├── Notification.java
│ │ ├── AssetUtil.java
│ │ └── Manager.java
│ │ ├── ClearReceiver.java
│ │ ├── RestoreReceiver.java
│ │ ├── ClickActivity.java
│ │ ├── TriggerReceiver.java
│ │ └── LocalNotification.java
│ └── AndroidManifest.xml
├── package.json
├── LICENSE
├── README.md
└── libs
├── local-notification-util.js
├── local-notification.js
└── local-notification-core.js
/screencasts/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remobile/react-native-local-notifications/HEAD/screencasts/1.png
--------------------------------------------------------------------------------
/screencasts/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remobile/react-native-local-notifications/HEAD/screencasts/2.png
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const LocalNotification = require('./libs/local-notification.js');
4 |
5 | module.exports = LocalNotification;
6 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | .DS_Store
3 | *Thumbs.db
4 | .gradle
5 | .idea
6 | *.iml
7 | npm-debug.log
8 | node_modules
9 | /android/build
10 | /ios/**/*xcuserdata*
11 | /ios/**/*xcshareddata*
12 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.[aod]
2 | *.DS_Store
3 | .DS_Store
4 | *Thumbs.db
5 | *.iml
6 | .gradle
7 | .idea
8 | node_modules
9 | npm-debug.log
10 | /android/build
11 | /ios/**/*xcuserdata*
12 | /ios/**/*xcshareddata*
13 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 16
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | sourceSets {
20 | main {
21 | jniLibs.srcDirs = ['libs']
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | compile fileTree(dir: 'libs', include: ['*.jar'])
28 | compile 'com.android.support:appcompat-v7:23.0.1'
29 | compile 'com.facebook.react:react-native:+'
30 | compile project(':react-native-cordova')
31 | }
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@remobile/react-native-local-notifications",
3 | "version": "1.0.4",
4 | "description": "A cordova local notifications for react-native",
5 | "main": "index.js",
6 | "author": {
7 | "name": "YunJiang.Fang",
8 | "email": "42550564@qq.com"
9 | },
10 | "license": "MIT",
11 | "keywords": [
12 | "react-native",
13 | "react-component",
14 | "ios",
15 | "android",
16 | "local-notifications",
17 | "push",
18 | "notifications",
19 | "contact",
20 | "save",
21 | "find",
22 | "remobile",
23 | "mobile"
24 | ],
25 | "homepage": "https://github.com/remobile/react-native-local-notifications",
26 | "bugs": {
27 | "url": "https://github.com/remobile/react-native-local-notifications/issues"
28 | },
29 | "repository": {
30 | "type": "git",
31 | "url": "git://github.com/remobile/react-native-local-notifications.git"
32 | },
33 | "peerDependencies": {
34 | "@remobile/react-native-cordova": "^1.1.1"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/RCTLocalNotificationsPackage.java:
--------------------------------------------------------------------------------
1 | package com.remobile.localNotifications;
2 |
3 | import java.util.Arrays;
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | import com.facebook.react.ReactPackage;
8 | import com.facebook.react.bridge.JavaScriptModule;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 |
13 | public class RCTLocalNotificationsPackage implements ReactPackage {
14 | @Override
15 | public List createNativeModules(ReactApplicationContext reactContext) {
16 | return Arrays.asList(
17 | new LocalNotification(reactContext)
18 | );
19 | }
20 |
21 | public List> createJSModules() {
22 | return Collections.emptyList();
23 | }
24 |
25 | @Override
26 | public List createViewManagers(ReactApplicationContext reactContext) {
27 | return Arrays.asList();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (c) 2015-2016 YunJiang.Fang <42550564@qq.com>
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | 'Software'), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/AppDelegate+APPRegisterUserNotificationSettings.h:
--------------------------------------------------------------------------------
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 |
24 | #import "AppDelegate.h"
25 | #import
26 | #import
27 |
28 | extern NSString* const UIApplicationRegisterUserNotificationSettings;
29 |
30 | @interface AppDelegate (APPRegisterUserNotificationSettings)
31 |
32 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
33 | // Tells the delegate what types of notifications may be used
34 | - (void) application:(UIApplication*)application
35 | didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings;
36 | #endif
37 |
38 | @end
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/ClearReceiver.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | /**
27 | * The clear intent receiver is triggered when the user clears a
28 | * notification manually. It un-persists the cleared notification from the
29 | * shared preferences.
30 | */
31 | public class ClearReceiver extends AbstractClearReceiver {
32 |
33 | /**
34 | * Called when a local notification was cleared from outside of the app.
35 | *
36 | * @param notification
37 | * Wrapper around the local notification
38 | */
39 | @Override
40 | public void onClear (Notification notification) {
41 | notification.clear();
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/APPLocalNotificationOptions.h:
--------------------------------------------------------------------------------
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 | #import
24 | #import
25 | @interface APPLocalNotificationOptions : NSObject
26 |
27 | - (id) initWithDict:(NSDictionary*)dict;
28 |
29 | @property (readonly, getter=id) NSNumber* id;
30 | @property (readonly, getter=badgeNumber) NSInteger badgeNumber;
31 | @property (readonly, getter=alertBody) NSString* alertBody;
32 | @property (readonly, getter=soundName) NSString* soundName;
33 | @property (readonly, getter=fireDate) NSDate* fireDate;
34 | @property (readonly, getter=repeatInterval) NSCalendarUnit repeatInterval;
35 | @property (readonly, getter=userInfo) NSDictionary* userInfo;
36 |
37 | // If it's a repeating notification
38 | - (BOOL) isRepeating;
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/ClearReceiver.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications;
25 |
26 | import com.remobile.localNotifications.notification.Notification;
27 |
28 |
29 | /**
30 | * The clear intent receiver is triggered when the user clears a
31 | * notification manually. It un-persists the cleared notification from the
32 | * shared preferences.
33 | */
34 | public class ClearReceiver extends com.remobile.localNotifications.notification.ClearReceiver {
35 |
36 | /**
37 | * Called when a local notification was cleared from outside of the app.
38 | *
39 | * @param notification
40 | * Wrapper around the local notification
41 | */
42 | @Override
43 | public void onClear (Notification notification) {
44 | super.onClear(notification);
45 | LocalNotification.fireEvent("clear", notification);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/AppDelegate+APPRegisterUserNotificationSettings.m:
--------------------------------------------------------------------------------
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 | #import "AppDelegate+APPRegisterUserNotificationSettings.h"
24 | #import
25 |
26 | NSString* const UIApplicationRegisterUserNotificationSettings = @"UIApplicationRegisterUserNotificationSettings";
27 |
28 | @implementation AppDelegate (APPRegisterUserNotificationSettings)
29 |
30 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
31 | /**
32 | * Tells the delegate what types of notifications may be used
33 | * to get the user’s attention.
34 | */
35 | - (void) application:(UIApplication*)application
36 | didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings
37 | {
38 | NSNotificationCenter* center = [NSNotificationCenter
39 | defaultCenter];
40 |
41 | // re-post (broadcast)
42 | [center postNotificationName:UIApplicationRegisterUserNotificationSettings
43 | object:settings];
44 | }
45 | #endif
46 |
47 | @end
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/ClickActivity.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | /**
27 | * The receiver activity is triggered when a notification is clicked by a user.
28 | * The activity calls the background callback and brings the launch intent
29 | * up to foreground.
30 | */
31 | public class ClickActivity extends AbstractClickActivity {
32 |
33 | /**
34 | * Called when local notification was clicked by the user. Will
35 | * move the app to foreground.
36 | *
37 | * @param notification
38 | * Wrapper around the local notification
39 | */
40 | @Override
41 | public void onClick(Notification notification) {
42 | launchApp();
43 |
44 | if (notification.isRepeating()) {
45 | notification.clear();
46 | } else {
47 | notification.cancel();
48 | }
49 | }
50 |
51 | /**
52 | * Build notification specified by options.
53 | *
54 | * @param builder
55 | * Notification builder
56 | */
57 | public Notification buildNotification (Builder builder) {
58 | return builder.build();
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/UILocalNotification+APPLocalNotification.h:
--------------------------------------------------------------------------------
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 |
24 | #import "APPLocalNotificationOptions.h"
25 |
26 | typedef NS_ENUM(NSUInteger, APPLocalNotificationType) {
27 | NotifcationTypeAll = 0,
28 | NotifcationTypeScheduled = 1,
29 | NotifcationTypeTriggered = 2
30 | };
31 |
32 | @interface UILocalNotification (APPLocalNotification)
33 |
34 | // Initialize a new local notification
35 | - (id) initWithOptions:(NSDictionary*)dict;
36 | // The options provided by the plug-in
37 | - (APPLocalNotificationOptions*) options;
38 | // Timeinterval since last trigger date
39 | - (double) timeIntervalSinceLastTrigger;
40 | // Timeinterval since fire date
41 | - (double) timeIntervalSinceFireDate;
42 | // If the fire date was in the past
43 | - (BOOL) wasInThePast;
44 | // If the notification was already scheduled
45 | - (BOOL) isScheduled;
46 | // If the notification was already triggered
47 | - (BOOL) isTriggered;
48 | // If the notification was updated
49 | - (BOOL) wasUpdated;
50 | // If it's a repeating notification
51 | - (BOOL) isRepeating;
52 | // Notifciation type
53 | - (APPLocalNotificationType) type;
54 | // Encode the user info dict to JSON
55 | - (NSString*) encodeToJSON;
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/TriggerReceiver.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | /**
27 | * The alarm receiver is triggered when a scheduled alarm is fired. This class
28 | * reads the information in the intent and displays this information in the
29 | * Android notification bar. The notification uses the default notification
30 | * sound and it vibrates the phone.
31 | */
32 | public class TriggerReceiver extends AbstractTriggerReceiver {
33 |
34 | /**
35 | * Called when a local notification was triggered. Does present the local
36 | * notification and re-schedule the alarm if necessary.
37 | *
38 | * @param notification
39 | * Wrapper around the local notification
40 | * @param updated
41 | * If an update has triggered or the original
42 | */
43 | @Override
44 | public void onTrigger (Notification notification, boolean updated) {
45 | notification.show();
46 | }
47 |
48 | /**
49 | * Build notification specified by options.
50 | *
51 | * @param builder
52 | * Notification builder
53 | */
54 | @Override
55 | public Notification buildNotification (Builder builder) {
56 | return builder.build();
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/RestoreReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-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 |
24 | package com.remobile.localNotifications;
25 |
26 | import com.remobile.localNotifications.notification.AbstractRestoreReceiver;
27 | import com.remobile.localNotifications.notification.Builder;
28 | import com.remobile.localNotifications.notification.Notification;
29 |
30 | /**
31 | * This class is triggered upon reboot of the device. It needs to re-register
32 | * the alarms with the AlarmManager since these alarms are lost in case of
33 | * reboot.
34 | */
35 | public class RestoreReceiver extends AbstractRestoreReceiver {
36 |
37 | /**
38 | * Called when a local notification need to be restored.
39 | *
40 | * @param notification
41 | * Wrapper around the local notification
42 | */
43 | @Override
44 | public void onRestore (Notification notification) {
45 | if (notification.isScheduled()) {
46 | notification.schedule();
47 | }
48 | }
49 |
50 | /**
51 | * Build notification specified by options.
52 | *
53 | * @param builder
54 | * Notification builder
55 | */
56 | @Override
57 | public Notification buildNotification (Builder builder) {
58 | return builder
59 | .setTriggerReceiver(TriggerReceiver.class)
60 | .setClearReceiver(ClearReceiver.class)
61 | .setClickActivity(ClickActivity.class)
62 | .build();
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/ClickActivity.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications;
25 |
26 | import com.remobile.localNotifications.notification.Builder;
27 | import com.remobile.localNotifications.notification.Notification;
28 | import com.remobile.localNotifications.notification.TriggerReceiver;
29 |
30 | /**
31 | * The receiver activity is triggered when a notification is clicked by a user.
32 | * The activity calls the background callback and brings the launch intent
33 | * up to foreground.
34 | */
35 | public class ClickActivity extends com.remobile.localNotifications.notification.ClickActivity {
36 |
37 | /**
38 | * Called when local notification was clicked by the user.
39 | *
40 | * @param notification
41 | * Wrapper around the local notification
42 | */
43 | @Override
44 | public void onClick(Notification notification) {
45 | LocalNotification.fireEvent("click", notification);
46 |
47 | super.onClick(notification);
48 |
49 | if (notification.getOptions().isOngoing())
50 | return;
51 |
52 | String event = notification.isRepeating() ? "clear" : "cancel";
53 | LocalNotification.fireEvent(event, notification);
54 | }
55 |
56 | /**
57 | * Build notification specified by options.
58 | *
59 | * @param builder
60 | * Notification builder
61 | */
62 | @Override
63 | public Notification buildNotification (Builder builder) {
64 | return builder
65 | .setTriggerReceiver(TriggerReceiver.class)
66 | .build();
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/AbstractClearReceiver.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.content.BroadcastReceiver;
27 | import android.content.Context;
28 | import android.content.Intent;
29 | import android.os.Bundle;
30 |
31 | import org.json.JSONException;
32 | import org.json.JSONObject;
33 |
34 | /**
35 | * Abstract delete receiver for local notifications. Creates the local
36 | * notification and calls the event functions for further proceeding.
37 | */
38 | abstract public class AbstractClearReceiver extends BroadcastReceiver {
39 |
40 | /**
41 | * Called when the notification was cleared from the notification center.
42 | *
43 | * @param context
44 | * Application context
45 | * @param intent
46 | * Received intent with content data
47 | */
48 | @Override
49 | public void onReceive(Context context, Intent intent) {
50 | Bundle bundle = intent.getExtras();
51 | JSONObject options;
52 |
53 | try {
54 | String data = bundle.getString(Options.EXTRA);
55 | options = new JSONObject(data);
56 | } catch (JSONException e) {
57 | e.printStackTrace();
58 | return;
59 | }
60 |
61 | Notification notification =
62 | new Builder(context, options).build();
63 |
64 | onClear(notification);
65 | }
66 |
67 | /**
68 | * Called when a local notification was cleared from outside of the app.
69 | *
70 | * @param notification
71 | * Wrapper around the local notification
72 | */
73 | abstract public void onClear (Notification notification);
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/TriggerReceiver.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications;
25 |
26 | import com.remobile.localNotifications.notification.Builder;
27 | import com.remobile.localNotifications.notification.Notification;
28 |
29 | /**
30 | * The alarm receiver is triggered when a scheduled alarm is fired. This class
31 | * reads the information in the intent and displays this information in the
32 | * Android notification bar. The notification uses the default notification
33 | * sound and it vibrates the phone.
34 | */
35 | public class TriggerReceiver extends com.remobile.localNotifications.notification.TriggerReceiver {
36 |
37 | /**
38 | * Called when a local notification was triggered. Does present the local
39 | * notification, re-schedule the alarm if necessary and fire trigger event.
40 | *
41 | * @param notification
42 | * Wrapper around the local notification
43 | * @param updated
44 | * If an update has triggered or the original
45 | */
46 | @Override
47 | public void onTrigger (Notification notification, boolean updated) {
48 | super.onTrigger(notification, updated);
49 |
50 | if (!updated) {
51 | LocalNotification.fireEvent("trigger", notification);
52 | }
53 | }
54 |
55 | /**
56 | * Build notification specified by options.
57 | *
58 | * @param builder
59 | * Notification builder
60 | */
61 | @Override
62 | public Notification buildNotification (Builder builder) {
63 | return builder
64 | .setTriggerReceiver(TriggerReceiver.class)
65 | .setClickActivity(ClickActivity.class)
66 | .setClearReceiver(ClearReceiver.class)
67 | .build();
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/AbstractRestoreReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.content.BroadcastReceiver;
27 | import android.content.Context;
28 | import android.content.Intent;
29 |
30 | import org.json.JSONObject;
31 |
32 | import java.util.List;
33 |
34 | /**
35 | * This class is triggered upon reboot of the device. It needs to re-register
36 | * the alarms with the AlarmManager since these alarms are lost in case of
37 | * reboot.
38 | */
39 | abstract public class AbstractRestoreReceiver extends BroadcastReceiver {
40 |
41 | /**
42 | * Called on device reboot.
43 | *
44 | * @param context
45 | * Application context
46 | * @param intent
47 | * Received intent with content data
48 | */
49 | @Override
50 | public void onReceive (Context context, Intent intent) {
51 | Manager notificationMgr =
52 | Manager.getInstance(context);
53 |
54 | List options =
55 | notificationMgr.getOptions();
56 |
57 | for (JSONObject data : options) {
58 | Builder builder = new Builder(context, data);
59 |
60 | Notification notification =
61 | buildNotification(builder);
62 |
63 | onRestore(notification);
64 | }
65 | }
66 |
67 | /**
68 | * Called when a local notification need to be restored.
69 | *
70 | * @param notification
71 | * Wrapper around the local notification
72 | */
73 | abstract public void onRestore (Notification notification);
74 |
75 | /**
76 | * Build notification specified by options.
77 | *
78 | * @param builder
79 | * Notification builder
80 | */
81 | abstract public Notification buildNotification (Builder builder);
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/UIApplication+APPLocalNotification.h:
--------------------------------------------------------------------------------
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 |
24 | #import "UILocalNotification+APPLocalNotification.h"
25 |
26 | @interface UIApplication (APPLocalNotification)
27 |
28 | @property (readonly, getter=localNotifications) NSArray* localNotifications;
29 | @property (readonly, getter=localNotificationIds) NSArray* localNotificationIds;
30 |
31 | // If the app has the permission to schedule local notifications
32 | - (BOOL) hasPermissionToScheduleLocalNotifications;
33 | // Ask for permission to schedule local notifications
34 | - (void) registerPermissionToScheduleLocalNotifications;
35 |
36 | // List of all local notification IDs from given type
37 | - (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type;
38 |
39 | // If local notification with ID exists
40 | - (BOOL) localNotificationExist:(NSNumber*)id;
41 | // If local notification with ID and type exists
42 | - (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type;
43 |
44 | // Local notification by ID
45 | - (UILocalNotification*) localNotificationWithId:(NSNumber*)id;
46 | // Local notification by ID and type
47 | - (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type;
48 |
49 | // Property list from all local notifications
50 | - (NSArray*) localNotificationOptions;
51 | // Property list from given local notifications
52 | - (NSArray*) localNotificationOptionsById:(NSArray*)ids;
53 | // Property list from all local notifications with type constraint
54 | - (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type;
55 | // Property list from given local notifications with type constraint
56 | - (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids;
57 |
58 | // Clear single local notfications
59 | - (void) clearLocalNotification:(UILocalNotification*)notification;
60 | // Clear all local notfications
61 | - (void) clearAllLocalNotifications;
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/APPLocalNotification.h:
--------------------------------------------------------------------------------
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 |
24 | #import
25 | #import "CDVPlugin.h"
26 |
27 | @interface APPLocalNotification : CDVPlugin
28 |
29 | // Execute all queued events
30 | - (void) deviceready:(CDVInvokedUrlCommand*)command;
31 |
32 | // Inform if the app has the permission to show notifications
33 | - (void) hasPermission:(CDVInvokedUrlCommand*)command;
34 | // Register permission to show notifications
35 | - (void) registerPermission:(CDVInvokedUrlCommand*)command;
36 |
37 | // Schedule set of notifications
38 | - (void) schedule:(CDVInvokedUrlCommand*)command;
39 | // Update set of notifications
40 | - (void) update:(CDVInvokedUrlCommand*)command;
41 | // Cancel set of notifications
42 | - (void) cancel:(CDVInvokedUrlCommand*)command;
43 | // Cancel all notifications
44 | - (void) cancelAll:(CDVInvokedUrlCommand*)command;
45 | // Clear set of notifications
46 | - (void) clear:(CDVInvokedUrlCommand*)command;
47 | // Clear all notifications
48 | - (void) clearAll:(CDVInvokedUrlCommand*)command;
49 |
50 | // If a notification with an ID is present
51 | - (void) isPresent:(CDVInvokedUrlCommand*)command;
52 | // If a notification with an ID is scheduled
53 | - (void) isScheduled:(CDVInvokedUrlCommand*)command;
54 | // If a notification with an ID is triggered
55 | - (void) isTriggered:(CDVInvokedUrlCommand*)command;
56 |
57 | // List all ids from all local notifications
58 | - (void) getAllIds:(CDVInvokedUrlCommand*)command;
59 | // List all ids from all pending notifications
60 | - (void) getScheduledIds:(CDVInvokedUrlCommand*)command;
61 | // List all ids from all triggered notifications
62 | - (void) getTriggeredIds:(CDVInvokedUrlCommand*)command;
63 |
64 | // Propertys for given local notification
65 | - (void) getSingle:(CDVInvokedUrlCommand*)command;
66 | // Propertya for given scheduled notification
67 | - (void) getSingleScheduled:(CDVInvokedUrlCommand*)command;
68 | // Propertys for given triggered notification
69 | - (void) getSingleTriggered:(CDVInvokedUrlCommand*)command;
70 |
71 | // Property list for given local notifications
72 | - (void) getAll:(CDVInvokedUrlCommand*)command;
73 | // Property list for given scheduled notifications
74 | - (void) getScheduled:(CDVInvokedUrlCommand*)command;
75 | // Property list for given triggered notifications
76 | - (void) getTriggered:(CDVInvokedUrlCommand*)command;
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/AbstractClickActivity.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.app.Activity;
27 | import android.content.Context;
28 | import android.content.Intent;
29 | import android.os.Bundle;
30 |
31 | import org.json.JSONException;
32 | import org.json.JSONObject;
33 |
34 | /**
35 | * Abstract content receiver activity for local notifications. Creates the
36 | * local notification and calls the event functions for further proceeding.
37 | */
38 | abstract public class AbstractClickActivity extends Activity {
39 |
40 | /**
41 | * Called when local notification was clicked to launch the main intent.
42 | *
43 | * @param state
44 | * Saved instance state
45 | */
46 | @Override
47 | public void onCreate (Bundle state) {
48 | super.onCreate(state);
49 |
50 | Intent intent = getIntent();
51 | Bundle bundle = intent.getExtras();
52 | Context context = getApplicationContext();
53 |
54 | try {
55 | String data = bundle.getString(Options.EXTRA);
56 | JSONObject options = new JSONObject(data);
57 |
58 | Builder builder =
59 | new Builder(context, options);
60 |
61 | Notification notification =
62 | buildNotification(builder);
63 |
64 | onClick(notification);
65 | } catch (JSONException e) {
66 | e.printStackTrace();
67 | }
68 | }
69 |
70 | /**
71 | * Fixes "Unable to resume activity" error.
72 | * Theme_NoDisplay: Activities finish themselves before being resumed.
73 | */
74 | @Override
75 | protected void onResume() {
76 | super.onResume();
77 | finish();
78 | }
79 |
80 | /**
81 | * Called when local notification was clicked by the user.
82 | *
83 | * @param notification
84 | * Wrapper around the local notification
85 | */
86 | abstract public void onClick (Notification notification);
87 |
88 | /**
89 | * Build notification specified by options.
90 | *
91 | * @param builder
92 | * Notification builder
93 | */
94 | abstract public Notification buildNotification (Builder builder);
95 |
96 | /**
97 | * Launch main intent from package.
98 | */
99 | public void launchApp() {
100 | Context context = getApplicationContext();
101 | String pkgName = context.getPackageName();
102 |
103 | Intent intent = context
104 | .getPackageManager()
105 | .getLaunchIntentForPackage(pkgName);
106 |
107 | intent.addFlags(
108 | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
109 |
110 | context.startActivity(intent);
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/AbstractTriggerReceiver.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.content.BroadcastReceiver;
27 | import android.content.Context;
28 | import android.content.Intent;
29 | import android.os.Bundle;
30 |
31 | import org.json.JSONException;
32 | import org.json.JSONObject;
33 |
34 | import java.util.Calendar;
35 |
36 | /**
37 | * Abstract broadcast receiver for local notifications. Creates the
38 | * notification options and calls the event functions for further proceeding.
39 | */
40 | abstract public class AbstractTriggerReceiver extends BroadcastReceiver {
41 |
42 | /**
43 | * Called when an alarm was triggered.
44 | *
45 | * @param context
46 | * Application context
47 | * @param intent
48 | * Received intent with content data
49 | */
50 | @Override
51 | public void onReceive(Context context, Intent intent) {
52 | Bundle bundle = intent.getExtras();
53 | Options options;
54 |
55 | try {
56 | String data = bundle.getString(Options.EXTRA);
57 | JSONObject dict = new JSONObject(data);
58 |
59 | options = new Options(context).parse(dict);
60 | } catch (JSONException e) {
61 | e.printStackTrace();
62 | return;
63 | }
64 |
65 | if (options == null)
66 | return;
67 |
68 | if (isFirstAlarmInFuture(options))
69 | return;
70 |
71 | Builder builder = new Builder(options);
72 | Notification notification = buildNotification(builder);
73 | boolean updated = notification.isUpdate(false);
74 |
75 | onTrigger(notification, updated);
76 | }
77 |
78 | /**
79 | * Called when a local notification was triggered.
80 | *
81 | * @param notification
82 | * Wrapper around the local notification
83 | * @param updated
84 | * If an update has triggered or the original
85 | */
86 | abstract public void onTrigger (Notification notification, boolean updated);
87 |
88 | /**
89 | * Build notification specified by options.
90 | *
91 | * @param builder
92 | * Notification builder
93 | */
94 | abstract public Notification buildNotification (Builder builder);
95 |
96 | /*
97 | * If you set a repeating alarm at 11:00 in the morning and it
98 | * should trigger every morning at 08:00 o'clock, it will
99 | * immediately fire. E.g. Android tries to make up for the
100 | * 'forgotten' reminder for that day. Therefore we ignore the event
101 | * if Android tries to 'catch up'.
102 | */
103 | private Boolean isFirstAlarmInFuture (Options options) {
104 | Notification notification = new Builder(options).build();
105 |
106 | if (!notification.isRepeating())
107 | return false;
108 |
109 | Calendar now = Calendar.getInstance();
110 | Calendar alarm = Calendar.getInstance();
111 |
112 | alarm.setTime(notification.getOptions().getTriggerDate());
113 |
114 | int alarmHour = alarm.get(Calendar.HOUR_OF_DAY);
115 | int alarmMin = alarm.get(Calendar.MINUTE);
116 | int currentHour = now.get(Calendar.HOUR_OF_DAY);
117 | int currentMin = now.get(Calendar.MINUTE);
118 |
119 | return (currentHour != alarmHour && currentMin != alarmMin);
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native LocalNotifications (remobile)
2 | A cordova local-notifications for react-native, supprt for ios and android
3 |
4 | ## Installation
5 | ```sh
6 | npm install @remobile/react-native-local-notifications --save
7 | ```
8 | ### Installation (iOS)
9 | * Drag RCTLocalNotifications.xcodeproj to your project on Xcode.
10 | * Click on your main project file (the one that represents the .xcodeproj) select Build Phases and drag libRCTLocalNotifications.a from the Products folder inside the RCTLocalNotifications.xcodeproj.
11 | * Look for Header Search Paths and make sure it contains $(SRCROOT)/../../../react-native/React as recursive.
12 | * Look for Header Search Paths and make sure it contains $(SRCROOT)/../../react-native-cordova/ios/RCTCordova.
13 | * Look for Header Search Paths and make sure it contains $(SRCROOT)/../../../../ios/${your main project}.
14 |
15 | * register didReceiveLocalNotification (in AppDelegate.m)
16 |
17 | ```obj-c
18 | // repost all remote and local notification using the default NSNotificationCenter so multiple plugins may respond
19 | - (void) application:(UIApplication*)application
20 | didReceiveLocalNotification:(UILocalNotification*)notification
21 | {
22 | // re-post ( broadcast )
23 | [[NSNotificationCenter defaultCenter] postNotificationName:@"CDVLocalNotification" object:notification];
24 | }
25 | ```
26 |
27 | ### Installation (Android)
28 | ```gradle
29 | ...
30 | include ':react-native-local-notifications'
31 | project(':react-native-local-notifications').projectDir = new File(settingsDir, '../node_modules/@remobile/react-native-local-notifications/android')
32 | ```
33 |
34 | * In `android/app/build.gradle`
35 |
36 | ```gradle
37 | ...
38 | dependencies {
39 | ...
40 | compile project(':react-native-local-notifications')
41 | }
42 | ```
43 |
44 | * register module (in MainApplication.java)
45 |
46 | ```java
47 | ......
48 | import com.remobile.localNotifications.RCTLocalNotificationsPackage; // <--- import
49 |
50 | ......
51 |
52 | @Override
53 | protected List getPackages() {
54 | ......
55 | new RCTLocalNotificationsPackage(), // <------ add here
56 | ......
57 | }
58 |
59 | ```
60 |
61 | ### Screencasts
62 | 
63 | 
64 |
65 | ## Usage
66 |
67 | ### Example
68 | ```js
69 | 'use strict';
70 |
71 | var React = require('react');
72 | var ReactNative = require('react-native');
73 | var {
74 | AppRegistry,
75 | StyleSheet,
76 | Text,
77 | View,
78 | } = ReactNative;
79 |
80 |
81 | var Button = require('@remobile/react-native-simple-button');
82 | var LocalNotification = require('@remobile/react-native-local-notifications');
83 |
84 | module.exports = React.createClass({
85 | test() {
86 | var now = new Date().getTime(),
87 | _n_sec_from_now = new Date(now + 10*1000);
88 |
89 | LocalNotification.schedule({
90 | id: 10,
91 | title: "Meeting in 15 minutes!",
92 | text: "Jour fixe Produktionsbesprechung",
93 | at: _n_sec_from_now,
94 | data: { meetingId:"#123FG8" }
95 | });
96 | LocalNotification.on("click", function (notification) {
97 | if (notification.id == 10) {
98 | joinMeeting(notification.data.meetingId);
99 | }
100 | });
101 |
102 | // Notification has reached its trigger time (Tomorrow at 8:45 AM)
103 | LocalNotification.on("trigger", function (notification) {
104 | if (notification.id != 10)
105 | return;
106 | // After 5 seconds update notification's title
107 | setTimeout(function () {
108 | LocalNotification.update({
109 | id: 10,
110 | title: "Meeting in 10 minutes!"
111 | });
112 | }, 5000);
113 | });
114 | },
115 | render: function() {
116 | return (
117 |
118 |
121 |
122 | );
123 | }
124 | });
125 |
126 | var styles = StyleSheet.create({
127 | container: {
128 | flex: 1,
129 | justifyContent: 'center',
130 | alignItems: 'center',
131 | backgroundColor: '#fff',
132 | paddingVertical: 20,
133 | },
134 | });
135 | ```
136 |
137 | ### HELP
138 | * look https://github.com/katzer/cordova-plugin-local-notifications/wiki
139 |
140 |
141 | ### thanks
142 | * this project come from https://github.com/katzer/cordova-plugin-local-notifications
143 |
144 | ### see detail use
145 | * https://github.com/remobile/react-native-template
146 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/Builder.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.app.PendingIntent;
27 | import android.content.Context;
28 | import android.content.Intent;
29 | import android.net.Uri;
30 | import android.support.v4.app.NotificationCompat;
31 |
32 | import org.json.JSONObject;
33 |
34 | import java.util.Random;
35 |
36 | /**
37 | * Builder class for local notifications. Build fully configured local
38 | * notification specified by JSON object passed from JS side.
39 | */
40 | public class Builder {
41 |
42 | // Application context passed by constructor
43 | private final Context context;
44 |
45 | // Notification options passed by JS
46 | private final Options options;
47 |
48 | // Receiver to handle the trigger event
49 | private Class> triggerReceiver;
50 |
51 | // Receiver to handle the clear event
52 | private Class> clearReceiver = ClearReceiver.class;
53 |
54 | // Activity to handle the click event
55 | private Class> clickActivity = ClickActivity.class;
56 |
57 | /**
58 | * Constructor
59 | *
60 | * @param context
61 | * Application context
62 | * @param options
63 | * Notification options
64 | */
65 | public Builder(Context context, JSONObject options) {
66 | this.context = context;
67 | this.options = new Options(context).parse(options);
68 | }
69 |
70 | /**
71 | * Constructor
72 | *
73 | * @param options
74 | * Notification options
75 | */
76 | public Builder(Options options) {
77 | this.context = options.getContext();
78 | this.options = options;
79 | }
80 |
81 | /**
82 | * Set trigger receiver.
83 | *
84 | * @param receiver
85 | * Broadcast receiver
86 | */
87 | public Builder setTriggerReceiver(Class> receiver) {
88 | this.triggerReceiver = receiver;
89 | return this;
90 | }
91 |
92 | /**
93 | * Set clear receiver.
94 | *
95 | * @param receiver
96 | * Broadcast receiver
97 | */
98 | public Builder setClearReceiver(Class> receiver) {
99 | this.clearReceiver = receiver;
100 | return this;
101 | }
102 |
103 | /**
104 | * Set click activity.
105 | *
106 | * @param activity
107 | * Activity
108 | */
109 | public Builder setClickActivity(Class> activity) {
110 | this.clickActivity = activity;
111 | return this;
112 | }
113 |
114 | /**
115 | * Creates the notification with all its options passed through JS.
116 | */
117 | public Notification build() {
118 | Uri sound = options.getSoundUri();
119 | int smallIcon = options.getSmallIcon();
120 | NotificationCompat.Builder builder;
121 |
122 | builder = new NotificationCompat.Builder(context)
123 | .setDefaults(0)
124 | .setContentTitle(options.getTitle())
125 | .setContentText(options.getText())
126 | .setNumber(options.getBadgeNumber())
127 | .setTicker(options.getText())
128 | .setAutoCancel(options.isAutoClear())
129 | .setOngoing(options.isOngoing())
130 | .setLights(options.getLedColor(), 500, 500);
131 |
132 | if (sound != null) {
133 | builder.setSound(sound);
134 | }
135 |
136 | if (smallIcon == 0) {
137 | builder.setSmallIcon(options.getIcon());
138 | } else {
139 | builder.setSmallIcon(options.getSmallIcon());
140 | builder.setLargeIcon(options.getIconBitmap());
141 | }
142 |
143 | applyDeleteReceiver(builder);
144 | applyContentReceiver(builder);
145 |
146 | return new Notification(context, options, builder, triggerReceiver);
147 | }
148 |
149 | /**
150 | * Set intent to handle the delete event. Will clean up some persisted
151 | * preferences.
152 | *
153 | * @param builder
154 | * Local notification builder instance
155 | */
156 | private void applyDeleteReceiver(NotificationCompat.Builder builder) {
157 |
158 | if (clearReceiver == null)
159 | return;
160 |
161 | Intent intent = new Intent(context, clearReceiver)
162 | .setAction(options.getIdStr())
163 | .putExtra(Options.EXTRA, options.toString());
164 |
165 | PendingIntent deleteIntent = PendingIntent.getBroadcast(
166 | context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
167 |
168 | builder.setDeleteIntent(deleteIntent);
169 | }
170 |
171 | /**
172 | * Set intent to handle the click event. Will bring the app to
173 | * foreground.
174 | *
175 | * @param builder
176 | * Local notification builder instance
177 | */
178 | private void applyContentReceiver(NotificationCompat.Builder builder) {
179 |
180 | if (clickActivity == null)
181 | return;
182 |
183 | Intent intent = new Intent(context, clickActivity)
184 | .putExtra(Options.EXTRA, options.toString())
185 | .setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
186 |
187 | int reqCode = new Random().nextInt();
188 |
189 | PendingIntent contentIntent = PendingIntent.getActivity(
190 | context, reqCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
191 |
192 | builder.setContentIntent(contentIntent);
193 | }
194 |
195 | }
196 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/APPLocalNotificationOptions.m:
--------------------------------------------------------------------------------
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 |
24 | #import "APPLocalNotificationOptions.h"
25 |
26 | // Default sound ressource path
27 | NSString* const DEFAULT_SOUND = @"res://platform_default";
28 |
29 | @interface APPLocalNotificationOptions ()
30 |
31 | // The dictionary which contains all notification properties
32 | @property(nonatomic, retain) NSDictionary* dict;
33 |
34 | @end
35 |
36 | @implementation APPLocalNotificationOptions
37 |
38 | @synthesize dict;
39 |
40 | #pragma mark -
41 | #pragma mark Initialization
42 |
43 | /**
44 | * Initialize the object with the given options when calling on JS side:
45 | * notification.local.add(options)
46 | */
47 | - (id) initWithDict:(NSDictionary*)dictionary
48 | {
49 | self = [self init];
50 |
51 | self.dict = dictionary;
52 |
53 | return self;
54 | }
55 |
56 | #pragma mark -
57 | #pragma mark Attributes
58 |
59 | /**
60 | * The notification's ID.
61 | */
62 | - (NSNumber*) id
63 | {
64 | NSInteger id = [[dict objectForKey:@"id"] integerValue];
65 |
66 | return [NSNumber numberWithInteger:id];
67 | }
68 |
69 | /**
70 | * The notification's title.
71 | */
72 | - (NSString*) title
73 | {
74 | return [dict objectForKey:@"title"];
75 | }
76 |
77 | /**
78 | * The notification's message.
79 | */
80 | - (NSString*) text
81 | {
82 | return [dict objectForKey:@"text"];
83 | }
84 |
85 | /**
86 | * The notification's badge number.
87 | */
88 | - (NSInteger) badgeNumber
89 | {
90 | return [[dict objectForKey:@"badge"] intValue];
91 | }
92 |
93 | #pragma mark -
94 | #pragma mark Complex Attributes
95 |
96 | /**
97 | * The notification's alert body.
98 | */
99 | - (NSString*) alertBody
100 | {
101 | NSString* title = [self title];
102 | NSString* msg = [self text];
103 |
104 | NSString* alertBody = msg;
105 |
106 | if (![self stringIsNullOrEmpty:title])
107 | {
108 | alertBody = [NSString stringWithFormat:@"%@\n%@",
109 | title, msg];
110 | }
111 |
112 | return alertBody;
113 | }
114 |
115 | /**
116 | * The notification's sound path.
117 | */
118 | - (NSString*) soundName
119 | {
120 | NSString* path = [dict objectForKey:@"sound"];
121 |
122 | if ([self stringIsNullOrEmpty:path])
123 | return NULL;
124 |
125 | if ([path isEqualToString:DEFAULT_SOUND])
126 | return UILocalNotificationDefaultSoundName;
127 |
128 | if ([path hasPrefix:@"file:/"])
129 | return [self soundNameForAsset:path];
130 |
131 | if ([path hasPrefix:@"res:"])
132 | return [self soundNameForResource:path];
133 |
134 | return NULL;
135 | }
136 |
137 | /**
138 | * The notification's fire date.
139 | */
140 | - (NSDate*) fireDate
141 | {
142 | double timestamp = [[dict objectForKey:@"at"]
143 | doubleValue];
144 |
145 | return [NSDate dateWithTimeIntervalSince1970:timestamp];
146 | }
147 |
148 | /**
149 | * The notification's repeat interval.
150 | */
151 | - (NSCalendarUnit) repeatInterval
152 | {
153 | NSString* interval = [dict objectForKey:@"every"];
154 |
155 | if ([self stringIsNullOrEmpty:interval]) {
156 | return NSCalendarUnitEra;
157 | }
158 | else if ([interval isEqualToString:@"second"]) {
159 | return NSCalendarUnitSecond;
160 | }
161 | else if ([interval isEqualToString:@"minute"]) {
162 | return NSCalendarUnitMinute;
163 | }
164 | else if ([interval isEqualToString:@"hour"]) {
165 | return NSCalendarUnitHour;
166 | }
167 | else if ([interval isEqualToString:@"day"]) {
168 | return NSCalendarUnitDay;
169 | }
170 | else if ([interval isEqualToString:@"week"]) {
171 | return NSCalendarUnitWeekOfYear;
172 | }
173 | else if ([interval isEqualToString:@"month"]) {
174 | return NSCalendarUnitMonth;
175 | }
176 | else if ([interval isEqualToString:@"quarter"]) {
177 | return NSCalendarUnitQuarter;
178 | }
179 | else if ([interval isEqualToString:@"year"]) {
180 | return NSCalendarUnitYear;
181 | }
182 |
183 | return NSCalendarUnitEra;
184 | }
185 |
186 | #pragma mark -
187 | #pragma mark Methods
188 |
189 | /**
190 | * The notification's user info dict.
191 | */
192 | - (NSDictionary*) userInfo
193 | {
194 | if ([dict objectForKey:@"updatedAt"]) {
195 | NSMutableDictionary* data = [dict mutableCopy];
196 |
197 | [data removeObjectForKey:@"updatedAt"];
198 |
199 | return data;
200 | }
201 |
202 | return dict;
203 | }
204 |
205 | /**
206 | * If it's a repeating notification.
207 | */
208 | - (BOOL) isRepeating
209 | {
210 | NSCalendarUnit interval = self.repeatInterval;
211 |
212 | return !(interval == NSCalendarUnitEra || interval == 0);
213 | }
214 |
215 | #pragma mark -
216 | #pragma mark Helpers
217 |
218 | /**
219 | * Convert relative path to valid sound name attribute.
220 | */
221 | - (NSString*) soundNameForAsset:(NSString*)path
222 | {
223 | return [path stringByReplacingOccurrencesOfString:@"file:/"
224 | withString:@"www"];
225 | }
226 |
227 | /**
228 | * Convert resource path to valid sound name attribute.
229 | */
230 | - (NSString*) soundNameForResource:(NSString*)path
231 | {
232 | return [path pathComponents].lastObject;
233 | }
234 |
235 | /**
236 | * If the string is empty.
237 | */
238 | - (BOOL) stringIsNullOrEmpty:(NSString*)str
239 | {
240 | if (str == (NSString*)[NSNull null])
241 | return YES;
242 |
243 | if ([str isEqualToString:@""])
244 | return YES;
245 |
246 | return NO;
247 | }
248 |
249 | @end
250 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/UILocalNotification+APPLocalNotification.m:
--------------------------------------------------------------------------------
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 |
24 | #import "UILocalNotification+APPLocalNotification.h"
25 | #import "APPLocalNotificationOptions.h"
26 | #import
27 |
28 | static char optionsKey;
29 |
30 | NSInteger const APPLocalNotificationTypeScheduled = 1;
31 | NSInteger const APPLocalNotificationTypeTriggered = 2;
32 |
33 | @implementation UILocalNotification (APPLocalNotification)
34 |
35 | #pragma mark -
36 | #pragma mark Init
37 |
38 | /**
39 | * Initialize a local notification with the given options when calling on JS side:
40 | * notification.local.add(options)
41 | */
42 | - (id) initWithOptions:(NSDictionary*)dict
43 | {
44 | self = [self init];
45 |
46 | [self setUserInfo:dict];
47 | [self __init];
48 |
49 | return self;
50 | }
51 |
52 | /**
53 | * Applies the given options when calling on JS side:
54 | * notification.local.add(options)
55 |
56 | */
57 | - (void) __init
58 | {
59 | APPLocalNotificationOptions* options = self.options;
60 |
61 | self.fireDate = options.fireDate;
62 | self.timeZone = [NSTimeZone defaultTimeZone];
63 | self.applicationIconBadgeNumber = options.badgeNumber;
64 | self.repeatInterval = options.repeatInterval;
65 | self.alertBody = options.alertBody;
66 | self.soundName = options.soundName;
67 |
68 | if ([self wasInThePast]) {
69 | self.fireDate = [NSDate date];
70 | }
71 | }
72 |
73 | #pragma mark -
74 | #pragma mark Methods
75 |
76 | /**
77 | * The options provided by the plug-in.
78 | */
79 | - (APPLocalNotificationOptions*) options
80 | {
81 | APPLocalNotificationOptions* options = [self getOptions];
82 |
83 | if (!options) {
84 | options = [[APPLocalNotificationOptions alloc]
85 | initWithDict:[self userInfo]];
86 |
87 | [self setOptions:options];
88 | }
89 |
90 | return options;
91 | }
92 |
93 | /**
94 | * Get associated option object
95 | */
96 | - (APPLocalNotificationOptions*) getOptions
97 | {
98 | return objc_getAssociatedObject(self, &optionsKey);
99 | }
100 |
101 | /**
102 | * Set associated option object
103 | */
104 | - (void) setOptions:(APPLocalNotificationOptions*)options
105 | {
106 | objc_setAssociatedObject(self, &optionsKey,
107 | options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
108 | }
109 |
110 | /**
111 | * The repeating interval in seconds.
112 | */
113 | - (int) repeatIntervalInSeconds
114 | {
115 | switch (self.repeatInterval) {
116 | case NSCalendarUnitMinute:
117 | return 60;
118 |
119 | case NSCalendarUnitHour:
120 | return 60000;
121 |
122 | case NSCalendarUnitDay:
123 | case NSCalendarUnitWeekOfYear:
124 | case NSCalendarUnitMonth:
125 | case NSCalendarUnitYear:
126 | return 86400;
127 |
128 | default:
129 | return 1;
130 | }
131 | }
132 |
133 | /**
134 | * Timeinterval since fire date.
135 | */
136 | - (double) timeIntervalSinceFireDate
137 | {
138 | NSDate* now = [NSDate date];
139 | NSDate* fireDate = self.fireDate;
140 |
141 | int timespan = [now timeIntervalSinceDate:fireDate];
142 |
143 | return timespan;
144 | }
145 |
146 | /**
147 | * Timeinterval since last trigger date.
148 | */
149 | - (double) timeIntervalSinceLastTrigger
150 | {
151 | int timespan = [self timeIntervalSinceFireDate];
152 |
153 | if ([self isRepeating]) {
154 | timespan = timespan % [self repeatIntervalInSeconds];
155 | }
156 |
157 | return timespan;
158 | }
159 |
160 | /**
161 | * Encode the user info dict to JSON.
162 | */
163 | - (NSString*) encodeToJSON
164 | {
165 | NSString* json;
166 | NSData* data;
167 | NSMutableDictionary* obj = [self.userInfo mutableCopy];
168 |
169 | [obj removeObjectForKey:@"updatedAt"];
170 |
171 | if (obj == NULL || obj.count == 0)
172 | return json;
173 |
174 | data = [NSJSONSerialization dataWithJSONObject:obj
175 | options:NSJSONWritingPrettyPrinted
176 | error:NULL];
177 |
178 | json = [[NSString alloc] initWithData:data
179 | encoding:NSUTF8StringEncoding];
180 |
181 | return [json stringByReplacingOccurrencesOfString:@"\n"
182 | withString:@""];
183 | }
184 |
185 | #pragma mark -
186 | #pragma mark State
187 |
188 | /**
189 | * If the fire date was in the past.
190 | */
191 | - (BOOL) wasInThePast
192 | {
193 | return [self timeIntervalSinceLastTrigger] > 0;
194 | }
195 |
196 | // If the notification was already scheduled
197 | - (BOOL) isScheduled
198 | {
199 | return [self isRepeating] || ![self wasInThePast];
200 | }
201 |
202 | /**
203 | * If the notification was already triggered.
204 | */
205 | - (BOOL) isTriggered
206 | {
207 | NSDate* now = [NSDate date];
208 | NSDate* fireDate = self.fireDate;
209 |
210 | bool isLaterThanFireDate = !([now compare:fireDate] == NSOrderedAscending);
211 |
212 | return isLaterThanFireDate;
213 | }
214 |
215 | /**
216 | * If the notification was updated.
217 | */
218 | - (BOOL) wasUpdated
219 | {
220 | NSDate* now = [NSDate date];
221 | NSDate* updatedAt = [self.userInfo objectForKey:@"updatedAt"];
222 |
223 | if (updatedAt == NULL)
224 | return NO;
225 |
226 | int timespan = [now timeIntervalSinceDate:updatedAt];
227 |
228 | return timespan < 1;
229 | }
230 |
231 | /**
232 | * If it's a repeating notification.
233 | */
234 | - (BOOL) isRepeating
235 | {
236 | return [self.options isRepeating];
237 | }
238 |
239 | /**
240 | * Process state type of the local notification.
241 | */
242 | - (APPLocalNotificationType) type
243 | {
244 | return [self isTriggered] ? NotifcationTypeTriggered : NotifcationTypeScheduled;
245 | }
246 |
247 | @end
248 |
--------------------------------------------------------------------------------
/libs/local-notification-util.js:
--------------------------------------------------------------------------------
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 |
24 | const exec = require('@remobile/react-native-cordova').exec;
25 | const { Platform } = require('react-native');
26 |
27 | /***********
28 | * MEMBERS *
29 | ***********/
30 |
31 | // Default values
32 | exports._defaults = Platform.OS === 'android' ? {
33 | icon: 'res://ic_popup_reminder',
34 | smallIcon: undefined,
35 | ongoing: false,
36 | autoClear: true,
37 | led: 'FFFFFF',
38 | text: '',
39 | title: '',
40 | sound: 'res://platform_default',
41 | badge: 0,
42 | id: 0,
43 | data: undefined,
44 | every: undefined,
45 | at: undefined,
46 | } : {
47 | text: '',
48 | title: '',
49 | sound: 'res://platform_default',
50 | badge: 0,
51 | id: 0,
52 | data: undefined,
53 | every: undefined,
54 | at: undefined,
55 | };
56 |
57 | // listener
58 | exports._listener = {};
59 | exports._subscription = {};
60 |
61 | /********
62 | * UTIL *
63 | ********/
64 |
65 | /**
66 | * Merge custom properties with the default values.
67 | *
68 | * @param {Object} options
69 | * Set of custom values
70 | *
71 | * @retrun {Object}
72 | * The merged property list
73 | */
74 | exports.mergeWithDefaults = function (options) {
75 | const defaults = this.getDefaults();
76 |
77 | options.at = this.getValueFor(options, 'at', 'firstAt', 'date');
78 | options.text = this.getValueFor(options, 'text', 'message');
79 | options.data = this.getValueFor(options, 'data', 'json');
80 |
81 | if (defaults.hasOwnProperty('autoClear')) {
82 | options.autoClear = this.getValueFor(options, 'autoClear', 'autoCancel');
83 | }
84 |
85 | if (options.autoClear !== true && options.ongoing) {
86 | options.autoClear = false;
87 | }
88 |
89 | if (options.at === undefined || options.at === null) {
90 | options.at = new Date();
91 | }
92 |
93 | let key;
94 | for (key in defaults) {
95 | if (options[key] === null || options[key] === undefined) {
96 | if (options.hasOwnProperty(key) && ['data', 'sound'].indexOf(key) > -1) {
97 | options[key] = undefined;
98 | } else {
99 | options[key] = defaults[key];
100 | }
101 | }
102 | }
103 |
104 | for (key in options) {
105 | if (!defaults.hasOwnProperty(key)) {
106 | delete options[key];
107 | console.warn('Unknown property: ' + key);
108 | }
109 | }
110 |
111 | return options;
112 | };
113 |
114 | /**
115 | * Convert the passed values to their required type.
116 | *
117 | * @param {Object} options
118 | * Set of custom values
119 | *
120 | * @retrun {Object}
121 | * The converted property list
122 | */
123 | exports.convertProperties = function (options) {
124 | if (options.id) {
125 | if (isNaN(options.id)) {
126 | options.id = this.getDefaults().id;
127 | console.warn('Id is not a number: ' + options.id);
128 | } else {
129 | options.id = Number(options.id);
130 | }
131 | }
132 |
133 | if (options.title) {
134 | options.title = options.title.toString();
135 | }
136 |
137 | if (options.text) {
138 | options.text = options.text.toString();
139 | }
140 |
141 | if (options.badge) {
142 | if (isNaN(options.badge)) {
143 | options.badge = this.getDefaults().badge;
144 | console.warn('Badge number is not a number: ' + options.id);
145 | } else {
146 | options.badge = Number(options.badge);
147 | }
148 | }
149 |
150 | if (options.at) {
151 | if (typeof options.at == 'object') {
152 | options.at = options.at.getTime();
153 | }
154 |
155 | options.at = Math.round(options.at / 1000);
156 | }
157 |
158 | if (typeof options.data == 'object') {
159 | options.data = JSON.stringify(options.data);
160 | }
161 |
162 | return options;
163 | };
164 |
165 | /**
166 | * Create callback, which will be executed within a specific scope.
167 | *
168 | * @param {Function} callbackFn
169 | * The callback function
170 | * @param {Object} scope
171 | * The scope for the function
172 | *
173 | * @return {Function}
174 | * The new callback function
175 | */
176 | exports.createCallbackFn = function (callbackFn, scope) {
177 | if (typeof callbackFn != 'function') { return; }
178 |
179 | return function () {
180 | callbackFn.apply(scope || this, arguments);
181 | };
182 | };
183 |
184 | /**
185 | * Convert the IDs to numbers.
186 | *
187 | * @param {String/Number[]} ids
188 | *
189 | * @return Array of Numbers
190 | */
191 | exports.convertIds = function (ids) {
192 | const convertedIds = [];
193 |
194 | for (let i = 0; i < ids.length; i++) {
195 | convertedIds.push(Number(ids[i]));
196 | }
197 |
198 | return convertedIds;
199 | };
200 |
201 | /**
202 | * First found value for the given keys.
203 | *
204 | * @param {Object} options
205 | * Object with key-value properties
206 | * @param {String[]} keys*
207 | * Key list
208 | */
209 | exports.getValueFor = function (options) {
210 | const keys = Array.apply(null, arguments).slice(1);
211 |
212 | for (let i = 0; i < keys.length; i++) {
213 | const key = keys[i];
214 |
215 | if (options.hasOwnProperty(key)) {
216 | return options[key];
217 | }
218 | }
219 | };
220 |
221 | /**
222 | * Fire event with given arguments.
223 | *
224 | * @param {String} event
225 | * The event's name
226 | * @param {args*}
227 | * The callback's arguments
228 | */
229 | exports.fireEvent = function (event) {
230 | const args = Array.apply(null, arguments).slice(1),
231 | listener = this._listener[event];
232 |
233 | if (!listener) { return; }
234 |
235 | for (let i = 0; i < listener.length; i++) {
236 | const fn = listener[i][0],
237 | scope = listener[i][1];
238 |
239 | fn.apply(scope, args);
240 | }
241 | };
242 |
243 | /**
244 | * Execute the native counterpart.
245 | *
246 | * @param {String} action
247 | * The name of the action
248 | * @param args[]
249 | * Array of arguments
250 | * @param {Function} callback
251 | * The callback function
252 | * @param {Object} scope
253 | * The scope for the function
254 | */
255 | exports.exec = function (action, args, callback, scope) {
256 | const fn = this.createCallbackFn(callback, scope);
257 | let params = [];
258 |
259 | if (Array.isArray(args)) {
260 | params = args;
261 | } else if (args) {
262 | params.push(args);
263 | }
264 |
265 | exec(fn, null, 'LocalNotification', action, params);
266 | };
267 |
268 | /*********
269 | * HOOKS *
270 | *********/
271 | exec(null, null, 'LocalNotification', 'deviceready', []);
272 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/Options.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.app.AlarmManager;
27 | import android.content.Context;
28 | import android.graphics.Bitmap;
29 | import android.net.Uri;
30 |
31 | import org.json.JSONException;
32 | import org.json.JSONObject;
33 |
34 | import java.util.Date;
35 |
36 | /**
37 | * Wrapper around the JSON object passed through JS which contains all
38 | * possible option values. Class provides simple readers and more advanced
39 | * methods to convert independent values into platform specific values.
40 | */
41 | public class Options {
42 |
43 | // Key name for bundled extras
44 | static final String EXTRA = "NOTIFICATION_OPTIONS";
45 |
46 | // The original JSON object
47 | private JSONObject options = new JSONObject();
48 |
49 | // Repeat interval
50 | private long interval = 0;
51 |
52 | // Application context
53 | private final Context context;
54 |
55 | // Asset util instance
56 | private final AssetUtil assets;
57 |
58 |
59 | /**
60 | * Constructor
61 | *
62 | * @param context
63 | * Application context
64 | */
65 | public Options(Context context){
66 | this.context = context;
67 | this.assets = AssetUtil.getInstance(context);
68 | }
69 |
70 | /**
71 | * Parse given JSON properties.
72 | *
73 | * @param options
74 | * JSON properties
75 | */
76 | public Options parse (JSONObject options) {
77 | this.options = options;
78 |
79 | parseInterval();
80 | parseAssets();
81 |
82 | return this;
83 | }
84 |
85 | /**
86 | * Parse repeat interval.
87 | */
88 | private void parseInterval() {
89 | String every = options.optString("every").toLowerCase();
90 |
91 | if (every.isEmpty()) {
92 | interval = 0;
93 | } else
94 | if (every.equals("second")) {
95 | interval = 1000;
96 | } else
97 | if (every.equals("minute")) {
98 | interval = AlarmManager.INTERVAL_FIFTEEN_MINUTES / 15;
99 | } else
100 | if (every.equals("hour")) {
101 | interval = AlarmManager.INTERVAL_HOUR;
102 | } else
103 | if (every.equals("day")) {
104 | interval = AlarmManager.INTERVAL_DAY;
105 | } else
106 | if (every.equals("week")) {
107 | interval = AlarmManager.INTERVAL_DAY * 7;
108 | } else
109 | if (every.equals("month")) {
110 | interval = AlarmManager.INTERVAL_DAY * 31;
111 | } else
112 | if (every.equals("quarter")) {
113 | interval = AlarmManager.INTERVAL_HOUR * 2190;
114 | } else
115 | if (every.equals("year")) {
116 | interval = AlarmManager.INTERVAL_DAY * 365;
117 | } else {
118 | try {
119 | interval = Integer.parseInt(every) * 60000;
120 | } catch (Exception e) {
121 | e.printStackTrace();
122 | }
123 | }
124 | }
125 |
126 | /**
127 | * Parse asset URIs.
128 | */
129 | private void parseAssets() {
130 |
131 | if (options.has("iconUri"))
132 | return;
133 |
134 | Uri iconUri = assets.parse(options.optString("icon", "icon"));
135 | Uri soundUri = assets.parseSound(options.optString("sound", null));
136 |
137 | try {
138 | options.put("iconUri", iconUri.toString());
139 | options.put("soundUri", soundUri.toString());
140 | } catch (JSONException e) {
141 | e.printStackTrace();
142 | }
143 | }
144 |
145 | /**
146 | * Application context.
147 | */
148 | public Context getContext () {
149 | return context;
150 | }
151 |
152 | /**
153 | * Wrapped JSON object.
154 | */
155 | JSONObject getDict () {
156 | return options;
157 | }
158 |
159 | /**
160 | * Text for the local notification.
161 | */
162 | public String getText() {
163 | return options.optString("text", "");
164 | }
165 |
166 | /**
167 | * Repeat interval (day, week, month, year, aso.)
168 | */
169 | public long getRepeatInterval() {
170 | return interval;
171 | }
172 |
173 | /**
174 | * Badge number for the local notification.
175 | */
176 | public int getBadgeNumber() {
177 | return options.optInt("badge", 0);
178 | }
179 |
180 | /**
181 | * ongoing flag for local notifications.
182 | */
183 | public Boolean isOngoing() {
184 | return options.optBoolean("ongoing", false);
185 | }
186 |
187 | /**
188 | * autoClear flag for local notifications.
189 | */
190 | public Boolean isAutoClear() {
191 | return options.optBoolean("autoClear", false);
192 | }
193 |
194 | /**
195 | * ID for the local notification as a number.
196 | */
197 | public Integer getId() {
198 | return options.optInt("id", 0);
199 | }
200 |
201 | /**
202 | * ID for the local notification as a string.
203 | */
204 | public String getIdStr() {
205 | return getId().toString();
206 | }
207 |
208 | /**
209 | * Trigger date.
210 | */
211 | public Date getTriggerDate() {
212 | return new Date(getTriggerTime());
213 | }
214 |
215 | /**
216 | * Trigger date in milliseconds.
217 | */
218 | public long getTriggerTime() {
219 | //return Math.max(
220 | // System.currentTimeMillis(),
221 | return options.optLong("at", 0) * 1000;
222 | //);
223 | }
224 |
225 | /**
226 | * Title for the local notification.
227 | */
228 | public String getTitle() {
229 | String title = options.optString("title", "");
230 |
231 | if (title.isEmpty()) {
232 | title = context.getApplicationInfo().loadLabel(
233 | context.getPackageManager()).toString();
234 | }
235 |
236 | return title;
237 | }
238 |
239 | /**
240 | * @return
241 | * The notification color for LED
242 | */
243 | public int getLedColor() {
244 | String hex = options.optString("led", "000000");
245 | int aRGB = Integer.parseInt(hex,16);
246 |
247 | aRGB += 0xFF000000;
248 |
249 | return aRGB;
250 | }
251 |
252 | /**
253 | * Sound file path for the local notification.
254 | */
255 | public Uri getSoundUri() {
256 | Uri uri = null;
257 |
258 | try{
259 | uri = Uri.parse(options.optString("soundUri"));
260 | } catch (Exception e){
261 | e.printStackTrace();
262 | }
263 |
264 | return uri;
265 | }
266 |
267 | /**
268 | * Icon bitmap for the local notification.
269 | */
270 | public Bitmap getIconBitmap() {
271 | Bitmap bmp;
272 |
273 | try {
274 | Uri uri = Uri.parse(options.optString("iconUri"));
275 | bmp = assets.getIconFromUri(uri);
276 | } catch (Exception e){
277 | e.printStackTrace();
278 | bmp = assets.getIconFromDrawable("icon");
279 | }
280 |
281 | return bmp;
282 | }
283 |
284 | /**
285 | * Icon resource ID for the local notification.
286 | */
287 | public int getIcon () {
288 | String icon = options.optString("icon", "");
289 |
290 | int resId = assets.getResIdForDrawable(icon);
291 |
292 | if (resId == 0) {
293 | resId = getSmallIcon();
294 | }
295 |
296 | if (resId == 0) {
297 | resId = android.R.drawable.ic_popup_reminder;
298 | }
299 |
300 | return resId;
301 | }
302 |
303 | /**
304 | * Small icon resource ID for the local notification.
305 | */
306 | public int getSmallIcon () {
307 | String icon = options.optString("smallIcon", "");
308 |
309 | return assets.getResIdForDrawable(icon);
310 | }
311 |
312 | /**
313 | * JSON object as string.
314 | */
315 | public String toString() {
316 | return options.toString();
317 | }
318 |
319 | }
320 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/UIApplication+APPLocalNotification.m:
--------------------------------------------------------------------------------
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 |
24 | #import "UIApplication+APPLocalNotification.h"
25 | #import "UILocalNotification+APPLocalNotification.h"
26 |
27 | @implementation UIApplication (APPLocalNotification)
28 |
29 | #pragma mark -
30 | #pragma mark Permissions
31 |
32 | /**
33 | * If the app has the permission to schedule local notifications.
34 | */
35 | - (BOOL) hasPermissionToScheduleLocalNotifications
36 | {
37 | if ([[UIApplication sharedApplication]
38 | respondsToSelector:@selector(registerUserNotificationSettings:)])
39 | {
40 | UIUserNotificationType types;
41 | UIUserNotificationSettings *settings;
42 |
43 | settings = [[UIApplication sharedApplication]
44 | currentUserNotificationSettings];
45 |
46 | types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
47 |
48 | return (settings.types & types);
49 | } else {
50 | return YES;
51 | }
52 | }
53 |
54 | /**
55 | * Ask for permission to schedule local notifications.
56 | */
57 | - (void) registerPermissionToScheduleLocalNotifications
58 | {
59 | if ([[UIApplication sharedApplication]
60 | respondsToSelector:@selector(registerUserNotificationSettings:)])
61 | {
62 | UIUserNotificationType types;
63 | UIUserNotificationSettings *settings;
64 |
65 | settings = [[UIApplication sharedApplication]
66 | currentUserNotificationSettings];
67 |
68 | types = settings.types|UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
69 |
70 | settings = [UIUserNotificationSettings settingsForTypes:types
71 | categories:nil];
72 |
73 | [[UIApplication sharedApplication]
74 | registerUserNotificationSettings:settings];
75 | }
76 | }
77 |
78 | #pragma mark -
79 | #pragma mark LocalNotifications
80 |
81 | /**
82 | * List of all local notifications which have been added
83 | * but not yet removed from the notification center.
84 | */
85 | - (NSArray*) localNotifications
86 | {
87 | NSArray* scheduledNotifications = self.scheduledLocalNotifications;
88 | NSMutableArray* notifications = [[NSMutableArray alloc] init];
89 |
90 | for (UILocalNotification* notification in scheduledNotifications)
91 | {
92 | if (notification) {
93 | [notifications addObject:notification];
94 | }
95 | }
96 |
97 | return notifications;
98 | }
99 |
100 | /**
101 | * List of all triggered local notifications which have been scheduled
102 | * and not yet removed the notification center.
103 | */
104 | - (NSArray*) triggeredLocalNotifications
105 | {
106 | NSArray* notifications = self.localNotifications;
107 | NSMutableArray* triggeredNotifications = [[NSMutableArray alloc] init];
108 |
109 | for (UILocalNotification* notification in notifications)
110 | {
111 | if ([notification isTriggered]) {
112 | [triggeredNotifications addObject:notification];
113 | }
114 | }
115 |
116 | return triggeredNotifications;
117 | }
118 |
119 | /**
120 | * List of all local notifications IDs.
121 | */
122 | - (NSArray*) localNotificationIds
123 | {
124 | NSArray* notifications = self.localNotifications;
125 | NSMutableArray* ids = [[NSMutableArray alloc] init];
126 |
127 | for (UILocalNotification* notification in notifications)
128 | {
129 | [ids addObject:notification.options.id];
130 | }
131 |
132 | return ids;
133 | }
134 |
135 | /**
136 | * List of all local notifications IDs from given type.
137 | *
138 | * @param type
139 | * Notification life cycle type
140 | */
141 | - (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type
142 | {
143 | NSArray* notifications = self.localNotifications;
144 | NSMutableArray* ids = [[NSMutableArray alloc] init];
145 |
146 | for (UILocalNotification* notification in notifications)
147 | {
148 | if (notification.type == type) {
149 | [ids addObject:notification.options.id];
150 | }
151 | }
152 |
153 | return ids;
154 | }
155 |
156 | /*
157 | * If local notification with ID exists.
158 | *
159 | * @param id
160 | * Notification ID
161 | */
162 | - (BOOL) localNotificationExist:(NSNumber*)id
163 | {
164 | return [self localNotificationWithId:id] != NULL;
165 | }
166 |
167 | /* If local notification with ID and type exists
168 | *
169 | * @param id
170 | * Notification ID
171 | * @param type
172 | * Notification life cycle type
173 | */
174 | - (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type
175 | {
176 | return [self localNotificationWithId:id andType:type] != NULL;
177 | }
178 |
179 | /**
180 | * Get local notification with ID.
181 | *
182 | * @param id
183 | * Notification ID
184 | */
185 | - (UILocalNotification*) localNotificationWithId:(NSNumber*)id
186 | {
187 | NSArray* notifications = self.localNotifications;
188 |
189 | for (UILocalNotification* notification in notifications)
190 | {
191 | if ([notification.options.id isEqualToNumber:id]) {
192 | return notification;
193 | }
194 | }
195 |
196 | return NULL;
197 | }
198 |
199 | /*
200 | * Get local notification with ID and type.
201 | *
202 | * @param id
203 | * Notification ID
204 | * @param type
205 | * Notification life cycle type
206 | */
207 | - (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type
208 | {
209 | UILocalNotification* notification = [self localNotificationWithId:id];
210 |
211 | if (notification && notification.type == type)
212 | return notification;
213 |
214 | return NULL;
215 | }
216 |
217 | /**
218 | * List of properties from all notifications.
219 | */
220 | - (NSArray*) localNotificationOptions
221 | {
222 | NSArray* notifications = self.localNotifications;
223 | NSMutableArray* options = [[NSMutableArray alloc] init];
224 |
225 | for (UILocalNotification* notification in notifications)
226 | {
227 | [options addObject:notification.options.userInfo];
228 | }
229 |
230 | return options;
231 | }
232 |
233 | /**
234 | * List of properties from all local notifications from given type.
235 | *
236 | * @param type
237 | * Notification life cycle type
238 | */
239 | - (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type
240 | {
241 | NSArray* notifications = self.localNotifications;
242 | NSMutableArray* options = [[NSMutableArray alloc] init];
243 |
244 | for (UILocalNotification* notification in notifications)
245 | {
246 | if (notification.type == type) {
247 | [options addObject:notification.options.userInfo];
248 | }
249 | }
250 |
251 | return options;
252 | }
253 |
254 | /**
255 | * List of properties from given local notifications.
256 | *
257 | * @param ids
258 | * Notification IDs
259 | */
260 | - (NSArray*) localNotificationOptionsById:(NSArray*)ids
261 | {
262 | UILocalNotification* notification;
263 | NSMutableArray* options = [[NSMutableArray alloc] init];
264 |
265 | for (NSNumber* id in ids)
266 | {
267 | notification = [self localNotificationWithId:id];
268 |
269 | if (notification) {
270 | [options addObject:notification.options.userInfo];
271 | }
272 | }
273 |
274 | return options;
275 | }
276 |
277 | /**
278 | * List of properties from given local notifications.
279 | *
280 | * @param type
281 | * Notification life cycle type
282 | * @param ids
283 | * Notification IDs
284 | */
285 | - (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids
286 | {
287 | UILocalNotification* notification;
288 | NSMutableArray* options = [[NSMutableArray alloc] init];
289 |
290 | for (NSNumber* id in ids)
291 | {
292 | notification = [self localNotificationWithId:id];
293 |
294 | if (notification && notification.type == type) {
295 | [options addObject:notification.options.userInfo];
296 | }
297 | }
298 |
299 | return options;
300 | }
301 |
302 | /*
303 | * Clear all local notfications.
304 | */
305 | - (void) clearAllLocalNotifications
306 | {
307 | NSArray* notifications = self.triggeredLocalNotifications;
308 |
309 | for (UILocalNotification* notification in notifications) {
310 | [self clearLocalNotification:notification];
311 | }
312 | }
313 |
314 | /*
315 | * Clear single local notfication.
316 | *
317 | * @param notification
318 | * The local notification object
319 | */
320 | - (void) clearLocalNotification:(UILocalNotification*)notification
321 | {
322 | [self cancelLocalNotification:notification];
323 |
324 | if ([notification isRepeating]) {
325 | notification.fireDate = notification.options.fireDate;
326 |
327 | [self scheduleLocalNotification:notification];
328 | };
329 | }
330 |
331 | @end
332 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/Notification.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 |
27 | import android.app.AlarmManager;
28 | import android.app.NotificationManager;
29 | import android.app.PendingIntent;
30 | import android.content.Context;
31 | import android.content.Intent;
32 | import android.content.SharedPreferences;
33 | import android.os.Build;
34 | import android.support.v4.app.NotificationCompat;
35 |
36 | import org.json.JSONException;
37 | import org.json.JSONObject;
38 |
39 | import java.util.Date;
40 |
41 | /**
42 | * Wrapper class around OS notification class. Handles basic operations
43 | * like show, delete, cancel for a single local notification instance.
44 | */
45 | public class Notification {
46 |
47 | // Used to differ notifications by their life cycle state
48 | public enum Type {
49 | ALL, SCHEDULED, TRIGGERED
50 | }
51 |
52 | // Default receiver to handle the trigger event
53 | private static Class> defaultReceiver = TriggerReceiver.class;
54 |
55 | // Key for private preferences
56 | static final String PREF_KEY = "LocalNotification";
57 |
58 | // Application context passed by constructor
59 | private final Context context;
60 |
61 | // Notification options passed by JS
62 | private final Options options;
63 |
64 | // Builder with full configuration
65 | private final NotificationCompat.Builder builder;
66 |
67 | // Receiver to handle the trigger event
68 | private Class> receiver = defaultReceiver;
69 |
70 | /**
71 | * Constructor
72 | *
73 | * @param context
74 | * Application context
75 | * @param options
76 | * Parsed notification options
77 | * @param builder
78 | * Pre-configured notification builder
79 | */
80 | protected Notification (Context context, Options options,
81 | NotificationCompat.Builder builder, Class> receiver) {
82 |
83 | this.context = context;
84 | this.options = options;
85 | this.builder = builder;
86 |
87 | this.receiver = receiver != null ? receiver : defaultReceiver;
88 | }
89 |
90 | /**
91 | * Get application context.
92 | */
93 | public Context getContext () {
94 | return context;
95 | }
96 |
97 | /**
98 | * Get notification options.
99 | */
100 | public Options getOptions () {
101 | return options;
102 | }
103 |
104 | /**
105 | * Get notification ID.
106 | */
107 | public int getId () {
108 | return options.getId();
109 | }
110 |
111 | /**
112 | * If it's a repeating notification.
113 | */
114 | public boolean isRepeating () {
115 | return getOptions().getRepeatInterval() > 0;
116 | }
117 |
118 | /**
119 | * If the notification was in the past.
120 | */
121 | public boolean wasInThePast () {
122 | return new Date().after(options.getTriggerDate());
123 | }
124 |
125 | /**
126 | * If the notification is scheduled.
127 | */
128 | public boolean isScheduled () {
129 | return isRepeating() || !wasInThePast();
130 | }
131 |
132 | /**
133 | * If the notification is triggered.
134 | */
135 | public boolean isTriggered () {
136 | return wasInThePast();
137 | }
138 |
139 | /**
140 | * If the notification is an update.
141 | *
142 | * @param keepFlag
143 | * Set to false to remove the flag from the option map
144 | */
145 | protected boolean isUpdate (boolean keepFlag) {
146 | boolean updated = options.getDict().optBoolean("updated", false);
147 |
148 | if (!keepFlag) {
149 | options.getDict().remove("updated");
150 | }
151 |
152 | return updated;
153 | }
154 |
155 | /**
156 | * Notification type can be one of pending or scheduled.
157 | */
158 | public Type getType () {
159 | return isTriggered() ? Type.TRIGGERED : Type.SCHEDULED;
160 | }
161 |
162 | /**
163 | * Schedule the local notification.
164 | */
165 | public void schedule() {
166 | long triggerTime = options.getTriggerTime();
167 |
168 | persist();
169 |
170 | // Intent gets called when the Notification gets fired
171 | Intent intent = new Intent(context, receiver)
172 | .setAction(options.getIdStr())
173 | .putExtra(Options.EXTRA, options.toString());
174 |
175 | PendingIntent pi = PendingIntent.getBroadcast(
176 | context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
177 |
178 | if (isRepeating()) {
179 | getAlarmMgr().setRepeating(AlarmManager.RTC_WAKEUP,
180 | triggerTime, options.getRepeatInterval(), pi);
181 | } else {
182 | getAlarmMgr().set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
183 | }
184 | }
185 |
186 | /**
187 | * Clear the local notification without canceling repeating alarms.
188 | */
189 | public void clear () {
190 |
191 | if (!isRepeating() && wasInThePast())
192 | unpersist();
193 |
194 | if (!isRepeating())
195 | getNotMgr().cancel(getId());
196 | }
197 |
198 | /**
199 | * Cancel the local notification.
200 | *
201 | * Create an intent that looks similar, to the one that was registered
202 | * using schedule. Making sure the notification id in the action is the
203 | * same. Now we can search for such an intent using the 'getService'
204 | * method and cancel it.
205 | */
206 | public void cancel() {
207 | Intent intent = new Intent(context, receiver)
208 | .setAction(options.getIdStr());
209 |
210 | PendingIntent pi = PendingIntent.
211 | getBroadcast(context, 0, intent, 0);
212 |
213 | getAlarmMgr().cancel(pi);
214 | getNotMgr().cancel(options.getId());
215 |
216 | unpersist();
217 | }
218 |
219 | /**
220 | * Present the local notification to user.
221 | */
222 | public void show () {
223 | // TODO Show dialog when in foreground
224 | showNotification();
225 | }
226 |
227 | /**
228 | * Show as local notification when in background.
229 | */
230 | @SuppressWarnings("deprecation")
231 | private void showNotification () {
232 | int id = getOptions().getId();
233 |
234 | if (Build.VERSION.SDK_INT <= 15) {
235 | // Notification for HoneyComb to ICS
236 | getNotMgr().notify(id, builder.getNotification());
237 | } else {
238 | // Notification for Jellybean and above
239 | getNotMgr().notify(id, builder.build());
240 | }
241 | }
242 |
243 | /**
244 | * Count of triggers since schedule.
245 | */
246 | public int getTriggerCountSinceSchedule() {
247 | long now = System.currentTimeMillis();
248 | long triggerTime = options.getTriggerTime();
249 |
250 | if (!wasInThePast())
251 | return 0;
252 |
253 | if (!isRepeating())
254 | return 1;
255 |
256 | return (int) ((now - triggerTime) / options.getRepeatInterval());
257 | }
258 |
259 | /**
260 | * Encode options to JSON.
261 | */
262 | public String toString() {
263 | JSONObject dict = options.getDict();
264 | JSONObject json = new JSONObject();
265 |
266 | try {
267 | json = new JSONObject(dict.toString());
268 | } catch (JSONException e) {
269 | e.printStackTrace();
270 | }
271 |
272 | json.remove("firstAt");
273 | json.remove("updated");
274 | json.remove("soundUri");
275 | json.remove("iconUri");
276 |
277 | return json.toString();
278 | }
279 |
280 | /**
281 | * Persist the information of this notification to the Android Shared
282 | * Preferences. This will allow the application to restore the notification
283 | * upon device reboot, app restart, retrieve notifications, aso.
284 | */
285 | private void persist () {
286 | SharedPreferences.Editor editor = getPrefs().edit();
287 |
288 | editor.putString(options.getIdStr(), options.toString());
289 |
290 | if (Build.VERSION.SDK_INT < 9) {
291 | editor.commit();
292 | } else {
293 | editor.apply();
294 | }
295 | }
296 |
297 | /**
298 | * Remove the notification from the Android shared Preferences.
299 | */
300 | private void unpersist () {
301 | SharedPreferences.Editor editor = getPrefs().edit();
302 |
303 | editor.remove(options.getIdStr());
304 |
305 | if (Build.VERSION.SDK_INT < 9) {
306 | editor.commit();
307 | } else {
308 | editor.apply();
309 | }
310 | }
311 |
312 | /**
313 | * Shared private preferences for the application.
314 | */
315 | private SharedPreferences getPrefs () {
316 | return context.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);
317 | }
318 |
319 | /**
320 | * Notification manager for the application.
321 | */
322 | private NotificationManager getNotMgr () {
323 | return (NotificationManager) context
324 | .getSystemService(Context.NOTIFICATION_SERVICE);
325 | }
326 |
327 | /**
328 | * Alarm manager for the application.
329 | */
330 | private AlarmManager getAlarmMgr () {
331 | return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
332 | }
333 |
334 | /**
335 | * Set default receiver to handle the trigger event.
336 | *
337 | * @param receiver
338 | * broadcast receiver
339 | */
340 | public static void setDefaultTriggerReceiver (Class> receiver) {
341 | defaultReceiver = receiver;
342 | }
343 |
344 | }
345 |
--------------------------------------------------------------------------------
/libs/local-notification.js:
--------------------------------------------------------------------------------
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 |
24 | /*************
25 | * INTERFACE *
26 | *************/
27 |
28 | const core = require('./local-notification-core.js');
29 | /**
30 | * Returns the default settings.
31 | *
32 | * @return {Object}
33 | */
34 | exports.getDefaults = function () {
35 | return core.getDefaults();
36 | };
37 |
38 | /**
39 | * Overwrite default settings.
40 | *
41 | * @param {Object} defaults
42 | */
43 | exports.setDefaults = function (defaults) {
44 | core.setDefaults(defaults);
45 | };
46 |
47 | /**
48 | * Schedule a new local notification.
49 | *
50 | * @param {Object} opts
51 | * The notification properties
52 | * @param {Function} callback
53 | * A function to be called after the notification has been canceled
54 | * @param {Object?} scope
55 | * The scope for the callback function
56 | */
57 | exports.schedule = function (opts, callback, scope) {
58 | core.schedule(opts, callback, scope);
59 | };
60 |
61 | /**
62 | * Update existing notifications specified by IDs in options.
63 | *
64 | * @param {Object} options
65 | * The notification properties to update
66 | * @param {Function} callback
67 | * A function to be called after the notification has been updated
68 | * @param {Object?} scope
69 | * The scope for the callback function
70 | */
71 | exports.update = function (opts, callback, scope) {
72 | core.update(opts, callback, scope);
73 | };
74 |
75 | /**
76 | * Clear the specified notification.
77 | *
78 | * @param {String} id
79 | * The ID of the notification
80 | * @param {Function} callback
81 | * A function to be called after the notification has been cleared
82 | * @param {Object?} scope
83 | * The scope for the callback function
84 | */
85 | exports.clear = function (ids, callback, scope) {
86 | core.clear(ids, callback, scope);
87 | };
88 |
89 | /**
90 | * Clear all previously sheduled notifications.
91 | *
92 | * @param {Function} callback
93 | * A function to be called after all notifications have been cleared
94 | * @param {Object?} scope
95 | * The scope for the callback function
96 | */
97 | exports.clearAll = function (callback, scope) {
98 | core.clearAll(callback, scope);
99 | };
100 |
101 | /**
102 | * Cancel the specified notifications.
103 | *
104 | * @param {String[]} ids
105 | * The IDs of the notifications
106 | * @param {Function} callback
107 | * A function to be called after the notifications has been canceled
108 | * @param {Object?} scope
109 | * The scope for the callback function
110 | */
111 | exports.cancel = function (ids, callback, scope) {
112 | core.cancel(ids, callback, scope);
113 | };
114 |
115 | /**
116 | * Remove all previously registered notifications.
117 | *
118 | * @param {Function} callback
119 | * A function to be called after all notifications have been canceled
120 | * @param {Object?} scope
121 | * The scope for the callback function
122 | */
123 | exports.cancelAll = function (callback, scope) {
124 | core.cancelAll(callback, scope);
125 | };
126 |
127 | /**
128 | * Check if a notification with an ID is present.
129 | *
130 | * @param {String} id
131 | * The ID of the notification
132 | * @param {Function} callback
133 | * A callback function to be called with the list
134 | * @param {Object?} scope
135 | * The scope for the callback function
136 | */
137 | exports.isPresent = function (id, callback, scope) {
138 | core.isPresent(id, callback, scope);
139 | };
140 |
141 | /**
142 | * Check if a notification with an ID is scheduled.
143 | *
144 | * @param {String} id
145 | * The ID of the notification
146 | * @param {Function} callback
147 | * A callback function to be called with the list
148 | * @param {Object?} scope
149 | * The scope for the callback function
150 | */
151 | exports.isScheduled = function (id, callback, scope) {
152 | core.isScheduled(id, callback, scope);
153 | };
154 |
155 | /**
156 | * Check if a notification with an ID was triggered.
157 | *
158 | * @param {String} id
159 | * The ID of the notification
160 | * @param {Function} callback
161 | * A callback function to be called with the list
162 | * @param {Object?} scope
163 | * The scope for the callback function
164 | */
165 | exports.isTriggered = function (id, callback, scope) {
166 | core.isTriggered(id, callback, scope);
167 | };
168 |
169 | /**
170 | * List all local notification IDs.
171 | *
172 | * @param {Function} callback
173 | * A callback function to be called with the list
174 | * @param {Object?} scope
175 | * The scope for the callback function
176 | */
177 | exports.getAllIds = function (callback, scope) {
178 | core.getAllIds(callback, scope);
179 | };
180 |
181 | /**
182 | * Alias for `getAllIds`.
183 | */
184 | exports.getIds = function () {
185 | this.getAllIds.apply(this, arguments);
186 | };
187 |
188 | /**
189 | * List all scheduled notification IDs.
190 | *
191 | * @param {Function} callback
192 | * A callback function to be called with the list
193 | * @param {Object?} scope
194 | * The scope for the callback function
195 | */
196 | exports.getScheduledIds = function (callback, scope) {
197 | core.getScheduledIds(callback, scope);
198 | };
199 |
200 | /**
201 | * List all triggered notification IDs.
202 | *
203 | * @param {Function} callback
204 | * A callback function to be called with the list
205 | * @param {Object?} scope
206 | * The scope for the callback function
207 | */
208 | exports.getTriggeredIds = function (callback, scope) {
209 | core.getTriggeredIds(callback, scope);
210 | };
211 |
212 | /**
213 | * Property list for given local notifications.
214 | * If called without IDs, all notification will be returned.
215 | *
216 | * @param {Number[]?} ids
217 | * Set of notification IDs
218 | * @param {Function} callback
219 | * A callback function to be called with the list
220 | * @param {Object?} scope
221 | * The scope for the callback function
222 | */
223 | exports.get = function () {
224 | core.get.apply(core, arguments);
225 | };
226 |
227 | /**
228 | * Property list for all local notifications.
229 | *
230 | * @param {Function} callback
231 | * A callback function to be called with the list
232 | * @param {Object?} scope
233 | * The scope for the callback function
234 | */
235 | exports.getAll = function (callback, scope) {
236 | core.getAll(callback, scope);
237 | };
238 |
239 | /**
240 | * Property list for given scheduled notifications.
241 | * If called without IDs, all notification will be returned.
242 | *
243 | * @param {Number[]?} ids
244 | * Set of notification IDs
245 | * @param {Function} callback
246 | * A callback function to be called with the list
247 | * @param {Object?} scope
248 | * The scope for the callback function
249 | */
250 | exports.getScheduled = function () {
251 | core.getScheduled.apply(core, arguments);
252 | };
253 |
254 | /**
255 | * Property list for all scheduled notifications.
256 | *
257 | * @param {Function} callback
258 | * A callback function to be called with the list
259 | * @param {Object?} scope
260 | * The scope for the callback function
261 | */
262 | exports.getAllScheduled = function (callback, scope) {
263 | core.getAllScheduled(callback, scope);
264 | };
265 |
266 | /**
267 | * Property list for given triggered notifications.
268 | * If called without IDs, all notification will be returned.
269 | *
270 | * @param {Number[]?} ids
271 | * Set of notification IDs
272 | * @param {Function} callback
273 | * A callback function to be called with the list
274 | * @param {Object?} scope
275 | * The scope for the callback function
276 | */
277 | exports.getTriggered = function () {
278 | core.getTriggered.apply(core, arguments);
279 | };
280 |
281 | /**
282 | * Property list for all triggered notifications.
283 | *
284 | * @param {Function} callback
285 | * A callback function to be called with the list
286 | * @param {Object?} scope
287 | * The scope for the callback function
288 | */
289 | exports.getAllTriggered = function (callback, scope) {
290 | core.getAllTriggered(callback, scope);
291 | };
292 |
293 | /**
294 | * Informs if the app has the permission to show notifications.
295 | *
296 | * @param {Function} callback
297 | * The function to be exec as the callback
298 | * @param {Object?} scope
299 | * The callback function's scope
300 | */
301 | exports.hasPermission = function (callback, scope) {
302 | core.hasPermission(callback, scope);
303 | };
304 |
305 | /**
306 | * Register permission to show notifications if not already granted.
307 | *
308 | * @param {Function} callback
309 | * The function to be exec as the callback
310 | * @param {Object?} scope
311 | * The callback function's scope
312 | */
313 | exports.registerPermission = function (callback, scope) {
314 | core.registerPermission(callback, scope);
315 | };
316 |
317 | /****************
318 | * DEPRECATIONS *
319 | ****************/
320 |
321 | /**
322 | * Schedule a new local notification.
323 | */
324 | exports.add = function () {
325 | console.warn('Depreated: Please use `notification.local.schedule` instead.');
326 |
327 | this.schedule.apply(this, arguments);
328 | };
329 |
330 | /**
331 | * Register permission to show notifications
332 | * if not already granted.
333 | */
334 | exports.promptForPermission = function () {
335 | console.warn('Depreated: Please use `notification.local.registerPermission` instead.');
336 |
337 | this.registerPermission.apply(this, arguments);
338 | };
339 |
340 | /**********
341 | * EVENTS *
342 | **********/
343 |
344 | /**
345 | * Register callback for given event.
346 | *
347 | * @param {String} event
348 | * The event's name
349 | * @param {Function} callback
350 | * The function to be exec as callback
351 | * @param {Object?} scope
352 | * The callback function's scope
353 | */
354 | exports.on = function (event, callback, scope) {
355 | core.on(event, callback, scope);
356 | };
357 |
358 | /**
359 | * Unregister callback for given event.
360 | *
361 | * @param {String} event
362 | * The event's name
363 | * @param {Function} callback
364 | * The function to be exec as callback
365 | */
366 | exports.un = function (event, callback) {
367 | core.un(event, callback);
368 | };
369 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 32C0ED761C2A9835009E47A9 /* APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0ED6E1C2A9835009E47A9 /* APPLocalNotification.m */; };
11 | 32C0ED771C2A9835009E47A9 /* APPLocalNotificationOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0ED701C2A9835009E47A9 /* APPLocalNotificationOptions.m */; };
12 | 32C0ED781C2A9835009E47A9 /* UIApplication+APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0ED721C2A9835009E47A9 /* UIApplication+APPLocalNotification.m */; };
13 | 32C0ED791C2A9835009E47A9 /* UILocalNotification+APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0ED741C2A9835009E47A9 /* UILocalNotification+APPLocalNotification.m */; };
14 | 32C0EDF11C2B9565009E47A9 /* AppDelegate+APPRegisterUserNotificationSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0EDF01C2B9565009E47A9 /* AppDelegate+APPRegisterUserNotificationSettings.m */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXCopyFilesBuildPhase section */
18 | 32308DD41C16B5E900A2ED29 /* CopyFiles */ = {
19 | isa = PBXCopyFilesBuildPhase;
20 | buildActionMask = 2147483647;
21 | dstPath = "include/$(PRODUCT_NAME)";
22 | dstSubfolderSpec = 16;
23 | files = (
24 | );
25 | runOnlyForDeploymentPostprocessing = 0;
26 | };
27 | /* End PBXCopyFilesBuildPhase section */
28 |
29 | /* Begin PBXFileReference section */
30 | 32308DD61C16B5E900A2ED29 /* libRCTLocalNotifications.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTLocalNotifications.a; sourceTree = BUILT_PRODUCTS_DIR; };
31 | 32C0ED6D1C2A9835009E47A9 /* APPLocalNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APPLocalNotification.h; sourceTree = ""; };
32 | 32C0ED6E1C2A9835009E47A9 /* APPLocalNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APPLocalNotification.m; sourceTree = ""; };
33 | 32C0ED6F1C2A9835009E47A9 /* APPLocalNotificationOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APPLocalNotificationOptions.h; sourceTree = ""; };
34 | 32C0ED701C2A9835009E47A9 /* APPLocalNotificationOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APPLocalNotificationOptions.m; sourceTree = ""; };
35 | 32C0ED711C2A9835009E47A9 /* UIApplication+APPLocalNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIApplication+APPLocalNotification.h"; sourceTree = ""; };
36 | 32C0ED721C2A9835009E47A9 /* UIApplication+APPLocalNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIApplication+APPLocalNotification.m"; sourceTree = ""; };
37 | 32C0ED731C2A9835009E47A9 /* UILocalNotification+APPLocalNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UILocalNotification+APPLocalNotification.h"; sourceTree = ""; };
38 | 32C0ED741C2A9835009E47A9 /* UILocalNotification+APPLocalNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UILocalNotification+APPLocalNotification.m"; sourceTree = ""; };
39 | 32C0EDEF1C2B9565009E47A9 /* AppDelegate+APPRegisterUserNotificationSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AppDelegate+APPRegisterUserNotificationSettings.h"; sourceTree = ""; };
40 | 32C0EDF01C2B9565009E47A9 /* AppDelegate+APPRegisterUserNotificationSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AppDelegate+APPRegisterUserNotificationSettings.m"; sourceTree = ""; };
41 | /* End PBXFileReference section */
42 |
43 | /* Begin PBXFrameworksBuildPhase section */
44 | 32308DD31C16B5E900A2ED29 /* Frameworks */ = {
45 | isa = PBXFrameworksBuildPhase;
46 | buildActionMask = 2147483647;
47 | files = (
48 | );
49 | runOnlyForDeploymentPostprocessing = 0;
50 | };
51 | /* End PBXFrameworksBuildPhase section */
52 |
53 | /* Begin PBXGroup section */
54 | 32308DCD1C16B5E900A2ED29 = {
55 | isa = PBXGroup;
56 | children = (
57 | 32308DD81C16B5E900A2ED29 /* RCTLocalNotifications */,
58 | 32308DD71C16B5E900A2ED29 /* Products */,
59 | );
60 | sourceTree = "";
61 | };
62 | 32308DD71C16B5E900A2ED29 /* Products */ = {
63 | isa = PBXGroup;
64 | children = (
65 | 32308DD61C16B5E900A2ED29 /* libRCTLocalNotifications.a */,
66 | );
67 | name = Products;
68 | sourceTree = "";
69 | };
70 | 32308DD81C16B5E900A2ED29 /* RCTLocalNotifications */ = {
71 | isa = PBXGroup;
72 | children = (
73 | 32C0EDEF1C2B9565009E47A9 /* AppDelegate+APPRegisterUserNotificationSettings.h */,
74 | 32C0EDF01C2B9565009E47A9 /* AppDelegate+APPRegisterUserNotificationSettings.m */,
75 | 32C0ED6D1C2A9835009E47A9 /* APPLocalNotification.h */,
76 | 32C0ED6E1C2A9835009E47A9 /* APPLocalNotification.m */,
77 | 32C0ED6F1C2A9835009E47A9 /* APPLocalNotificationOptions.h */,
78 | 32C0ED701C2A9835009E47A9 /* APPLocalNotificationOptions.m */,
79 | 32C0ED711C2A9835009E47A9 /* UIApplication+APPLocalNotification.h */,
80 | 32C0ED721C2A9835009E47A9 /* UIApplication+APPLocalNotification.m */,
81 | 32C0ED731C2A9835009E47A9 /* UILocalNotification+APPLocalNotification.h */,
82 | 32C0ED741C2A9835009E47A9 /* UILocalNotification+APPLocalNotification.m */,
83 | );
84 | path = RCTLocalNotifications;
85 | sourceTree = "";
86 | };
87 | /* End PBXGroup section */
88 |
89 | /* Begin PBXNativeTarget section */
90 | 32308DD51C16B5E900A2ED29 /* RCTLocalNotifications */ = {
91 | isa = PBXNativeTarget;
92 | buildConfigurationList = 32308DEA1C16B5E900A2ED29 /* Build configuration list for PBXNativeTarget "RCTLocalNotifications" */;
93 | buildPhases = (
94 | 32308DD21C16B5E900A2ED29 /* Sources */,
95 | 32308DD31C16B5E900A2ED29 /* Frameworks */,
96 | 32308DD41C16B5E900A2ED29 /* CopyFiles */,
97 | );
98 | buildRules = (
99 | );
100 | dependencies = (
101 | );
102 | name = RCTLocalNotifications;
103 | productName = RCTLocalNotifications;
104 | productReference = 32308DD61C16B5E900A2ED29 /* libRCTLocalNotifications.a */;
105 | productType = "com.apple.product-type.library.static";
106 | };
107 | /* End PBXNativeTarget section */
108 |
109 | /* Begin PBXProject section */
110 | 32308DCE1C16B5E900A2ED29 /* Project object */ = {
111 | isa = PBXProject;
112 | attributes = {
113 | LastUpgradeCheck = 0640;
114 | ORGANIZATIONNAME = remobile;
115 | TargetAttributes = {
116 | 32308DD51C16B5E900A2ED29 = {
117 | CreatedOnToolsVersion = 6.4;
118 | };
119 | };
120 | };
121 | buildConfigurationList = 32308DD11C16B5E900A2ED29 /* Build configuration list for PBXProject "RCTLocalNotifications" */;
122 | compatibilityVersion = "Xcode 3.2";
123 | developmentRegion = English;
124 | hasScannedForEncodings = 0;
125 | knownRegions = (
126 | en,
127 | );
128 | mainGroup = 32308DCD1C16B5E900A2ED29;
129 | productRefGroup = 32308DD71C16B5E900A2ED29 /* Products */;
130 | projectDirPath = "";
131 | projectRoot = "";
132 | targets = (
133 | 32308DD51C16B5E900A2ED29 /* RCTLocalNotifications */,
134 | );
135 | };
136 | /* End PBXProject section */
137 |
138 | /* Begin PBXSourcesBuildPhase section */
139 | 32308DD21C16B5E900A2ED29 /* Sources */ = {
140 | isa = PBXSourcesBuildPhase;
141 | buildActionMask = 2147483647;
142 | files = (
143 | 32C0ED761C2A9835009E47A9 /* APPLocalNotification.m in Sources */,
144 | 32C0ED771C2A9835009E47A9 /* APPLocalNotificationOptions.m in Sources */,
145 | 32C0EDF11C2B9565009E47A9 /* AppDelegate+APPRegisterUserNotificationSettings.m in Sources */,
146 | 32C0ED781C2A9835009E47A9 /* UIApplication+APPLocalNotification.m in Sources */,
147 | 32C0ED791C2A9835009E47A9 /* UILocalNotification+APPLocalNotification.m in Sources */,
148 | );
149 | runOnlyForDeploymentPostprocessing = 0;
150 | };
151 | /* End PBXSourcesBuildPhase section */
152 |
153 | /* Begin XCBuildConfiguration section */
154 | 32308DE81C16B5E900A2ED29 /* Debug */ = {
155 | isa = XCBuildConfiguration;
156 | buildSettings = {
157 | ALWAYS_SEARCH_USER_PATHS = NO;
158 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
159 | CLANG_CXX_LIBRARY = "libc++";
160 | CLANG_ENABLE_MODULES = YES;
161 | CLANG_ENABLE_OBJC_ARC = YES;
162 | CLANG_WARN_BOOL_CONVERSION = YES;
163 | CLANG_WARN_CONSTANT_CONVERSION = YES;
164 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
165 | CLANG_WARN_EMPTY_BODY = YES;
166 | CLANG_WARN_ENUM_CONVERSION = YES;
167 | CLANG_WARN_INT_CONVERSION = YES;
168 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
169 | CLANG_WARN_UNREACHABLE_CODE = YES;
170 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
171 | COPY_PHASE_STRIP = NO;
172 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
173 | ENABLE_STRICT_OBJC_MSGSEND = YES;
174 | GCC_C_LANGUAGE_STANDARD = gnu99;
175 | GCC_DYNAMIC_NO_PIC = NO;
176 | GCC_NO_COMMON_BLOCKS = YES;
177 | GCC_OPTIMIZATION_LEVEL = 0;
178 | GCC_PREPROCESSOR_DEFINITIONS = (
179 | "DEBUG=1",
180 | "$(inherited)",
181 | );
182 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
185 | GCC_WARN_UNDECLARED_SELECTOR = YES;
186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
187 | GCC_WARN_UNUSED_FUNCTION = YES;
188 | GCC_WARN_UNUSED_VARIABLE = YES;
189 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
190 | MTL_ENABLE_DEBUG_INFO = YES;
191 | ONLY_ACTIVE_ARCH = YES;
192 | SDKROOT = iphoneos;
193 | };
194 | name = Debug;
195 | };
196 | 32308DE91C16B5E900A2ED29 /* Release */ = {
197 | isa = XCBuildConfiguration;
198 | buildSettings = {
199 | ALWAYS_SEARCH_USER_PATHS = NO;
200 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
201 | CLANG_CXX_LIBRARY = "libc++";
202 | CLANG_ENABLE_MODULES = YES;
203 | CLANG_ENABLE_OBJC_ARC = YES;
204 | CLANG_WARN_BOOL_CONVERSION = YES;
205 | CLANG_WARN_CONSTANT_CONVERSION = YES;
206 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
207 | CLANG_WARN_EMPTY_BODY = YES;
208 | CLANG_WARN_ENUM_CONVERSION = YES;
209 | CLANG_WARN_INT_CONVERSION = YES;
210 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
211 | CLANG_WARN_UNREACHABLE_CODE = YES;
212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
213 | COPY_PHASE_STRIP = NO;
214 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
215 | ENABLE_NS_ASSERTIONS = NO;
216 | ENABLE_STRICT_OBJC_MSGSEND = YES;
217 | GCC_C_LANGUAGE_STANDARD = gnu99;
218 | GCC_NO_COMMON_BLOCKS = YES;
219 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
220 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
221 | GCC_WARN_UNDECLARED_SELECTOR = YES;
222 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
223 | GCC_WARN_UNUSED_FUNCTION = YES;
224 | GCC_WARN_UNUSED_VARIABLE = YES;
225 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
226 | MTL_ENABLE_DEBUG_INFO = NO;
227 | SDKROOT = iphoneos;
228 | VALIDATE_PRODUCT = YES;
229 | };
230 | name = Release;
231 | };
232 | 32308DEB1C16B5E900A2ED29 /* Debug */ = {
233 | isa = XCBuildConfiguration;
234 | buildSettings = {
235 | HEADER_SEARCH_PATHS = (
236 | "$(inherited)",
237 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
238 | "$(SRCROOT)/../../react-native-cordova/ios/RCTCordova",
239 | "$(SRCROOT)/../../../../../ios/JFBSample",
240 | );
241 | OTHER_LDFLAGS = "-ObjC";
242 | PRODUCT_NAME = "$(TARGET_NAME)";
243 | SKIP_INSTALL = YES;
244 | };
245 | name = Debug;
246 | };
247 | 32308DEC1C16B5E900A2ED29 /* Release */ = {
248 | isa = XCBuildConfiguration;
249 | buildSettings = {
250 | HEADER_SEARCH_PATHS = (
251 | "$(inherited)",
252 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
253 | "$(SRCROOT)/../../react-native-cordova/ios/RCTCordova",
254 | "$(SRCROOT)/../../../../../ios/JFBSample",
255 | );
256 | OTHER_LDFLAGS = "-ObjC";
257 | PRODUCT_NAME = "$(TARGET_NAME)";
258 | SKIP_INSTALL = YES;
259 | };
260 | name = Release;
261 | };
262 | /* End XCBuildConfiguration section */
263 |
264 | /* Begin XCConfigurationList section */
265 | 32308DD11C16B5E900A2ED29 /* Build configuration list for PBXProject "RCTLocalNotifications" */ = {
266 | isa = XCConfigurationList;
267 | buildConfigurations = (
268 | 32308DE81C16B5E900A2ED29 /* Debug */,
269 | 32308DE91C16B5E900A2ED29 /* Release */,
270 | );
271 | defaultConfigurationIsVisible = 0;
272 | defaultConfigurationName = Release;
273 | };
274 | 32308DEA1C16B5E900A2ED29 /* Build configuration list for PBXNativeTarget "RCTLocalNotifications" */ = {
275 | isa = XCConfigurationList;
276 | buildConfigurations = (
277 | 32308DEB1C16B5E900A2ED29 /* Debug */,
278 | 32308DEC1C16B5E900A2ED29 /* Release */,
279 | );
280 | defaultConfigurationIsVisible = 0;
281 | defaultConfigurationName = Release;
282 | };
283 | /* End XCConfigurationList section */
284 | };
285 | rootObject = 32308DCE1C16B5E900A2ED29 /* Project object */;
286 | }
287 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/AssetUtil.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.content.Context;
27 | import android.content.res.AssetManager;
28 | import android.content.res.Resources;
29 | import android.graphics.Bitmap;
30 | import android.graphics.BitmapFactory;
31 | import android.media.RingtoneManager;
32 | import android.net.Uri;
33 | import android.os.StrictMode;
34 | import android.util.Log;
35 |
36 | import java.io.File;
37 | import java.io.FileNotFoundException;
38 | import java.io.FileOutputStream;
39 | import java.io.IOException;
40 | import java.io.InputStream;
41 | import java.io.OutputStream;
42 | import java.net.HttpURLConnection;
43 | import java.net.MalformedURLException;
44 | import java.net.URL;
45 | import java.util.UUID;
46 |
47 | /**
48 | * Util class to map unified asset URIs to native URIs. URIs like file:///
49 | * map to absolute paths while file:// point relatively to the www folder
50 | * within the asset resources. And res:// means a resource from the native
51 | * res folder. Remote assets are accessible via http:// for example.
52 | */
53 | class AssetUtil {
54 |
55 | // Name of the storage folder
56 | private static final String STORAGE_FOLDER = "/localnotification";
57 |
58 | // Placeholder URI for default sound
59 | private static final String DEFAULT_SOUND = "res://platform_default";
60 |
61 | // Ref to the context passed through the constructor to access the
62 | // resources and app directory.
63 | private final Context context;
64 |
65 | /**
66 | * Constructor
67 | *
68 | * @param context
69 | * Application context
70 | */
71 | private AssetUtil(Context context) {
72 | this.context = context;
73 | }
74 |
75 | /**
76 | * Static method to retrieve class instance.
77 | *
78 | * @param context
79 | * Application context
80 | */
81 | static AssetUtil getInstance(Context context) {
82 | return new AssetUtil(context);
83 | }
84 |
85 | /**
86 | * Parse path path to native URI.
87 | *
88 | * @param path
89 | * Path to path file
90 | */
91 | Uri parseSound (String path) {
92 |
93 | if (path == null || path.isEmpty())
94 | return Uri.EMPTY;
95 |
96 | if (path.equalsIgnoreCase(DEFAULT_SOUND)) {
97 | return RingtoneManager.getDefaultUri(RingtoneManager
98 | .TYPE_NOTIFICATION);
99 | }
100 |
101 | return parse(path);
102 | }
103 |
104 | /**
105 | * The URI for a path.
106 | *
107 | * @param path
108 | * The given path
109 | */
110 | Uri parse (String path) {
111 |
112 | if (path.startsWith("res:")) {
113 | return getUriForResourcePath(path);
114 | } else if (path.startsWith("file:///")) {
115 | return getUriFromPath(path);
116 | } else if (path.startsWith("file://")) {
117 | return getUriFromAsset(path);
118 | } else if (path.startsWith("http")){
119 | return getUriFromRemote(path);
120 | }
121 |
122 | return Uri.EMPTY;
123 | }
124 |
125 | /**
126 | * URI for a file.
127 | *
128 | * @param path
129 | * Absolute path like file:///...
130 | *
131 | * @return
132 | * URI pointing to the given path
133 | */
134 | private Uri getUriFromPath(String path) {
135 | String absPath = path.replaceFirst("file://", "");
136 | File file = new File(absPath);
137 |
138 | if (!file.exists()) {
139 | Log.e("Asset", "File not found: " + file.getAbsolutePath());
140 | return Uri.EMPTY;
141 | }
142 |
143 | return Uri.fromFile(file);
144 | }
145 |
146 | /**
147 | * URI for an asset.
148 | *
149 | * @param path
150 | * Asset path like file://...
151 | *
152 | * @return
153 | * URI pointing to the given path
154 | */
155 | private Uri getUriFromAsset(String path) {
156 | String resPath = path.replaceFirst("file:/", "www");
157 | String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
158 | File file = getTmpFile(fileName);
159 |
160 | if (file == null) {
161 | Log.e("Asset", "Missing external cache dir");
162 | return Uri.EMPTY;
163 | }
164 |
165 | try {
166 | AssetManager assets = context.getAssets();
167 | FileOutputStream outStream = new FileOutputStream(file);
168 | InputStream inputStream = assets.open(resPath);
169 |
170 | copyFile(inputStream, outStream);
171 |
172 | outStream.flush();
173 | outStream.close();
174 |
175 | return Uri.fromFile(file);
176 |
177 | } catch (Exception e) {
178 | Log.e("Asset", "File not found: assets/" + resPath);
179 | e.printStackTrace();
180 | }
181 |
182 | return Uri.EMPTY;
183 | }
184 |
185 | /**
186 | * The URI for a resource.
187 | *
188 | * @param path
189 | * The given relative path
190 | *
191 | * @return
192 | * URI pointing to the given path
193 | */
194 | private Uri getUriForResourcePath(String path) {
195 | String resPath = path.replaceFirst("res://", "");
196 | int resId = getResIdForDrawable(resPath);
197 | File file = getTmpFile();
198 |
199 | if (resId == 0) {
200 | Log.e("Asset", "File not found: " + resPath);
201 | return Uri.EMPTY;
202 | }
203 |
204 | if (file == null) {
205 | Log.e("Asset", "Missing external cache dir");
206 | return Uri.EMPTY;
207 | }
208 |
209 | try {
210 | Resources res = context.getResources();
211 | FileOutputStream outStream = new FileOutputStream(file);
212 | InputStream inputStream = res.openRawResource(resId);
213 | copyFile(inputStream, outStream);
214 |
215 | outStream.flush();
216 | outStream.close();
217 |
218 | return Uri.fromFile(file);
219 |
220 | } catch (Exception e) {
221 | e.printStackTrace();
222 | }
223 |
224 | return Uri.EMPTY;
225 | }
226 |
227 | /**
228 | * Uri from remote located content.
229 | *
230 | * @param path
231 | * Remote address
232 | *
233 | * @return
234 | * Uri of the downloaded file
235 | */
236 | private Uri getUriFromRemote(String path) {
237 | File file = getTmpFile();
238 |
239 | if (file == null) {
240 | Log.e("Asset", "Missing external cache dir");
241 | return Uri.EMPTY;
242 | }
243 |
244 | try {
245 | URL url = new URL(path);
246 | HttpURLConnection connection = (HttpURLConnection) url.openConnection();
247 |
248 | StrictMode.ThreadPolicy policy =
249 | new StrictMode.ThreadPolicy.Builder().permitAll().build();
250 |
251 | StrictMode.setThreadPolicy(policy);
252 |
253 | connection.setRequestProperty("Connection", "close");
254 | connection.setConnectTimeout(5000);
255 | connection.connect();
256 |
257 | InputStream input = connection.getInputStream();
258 | FileOutputStream outStream = new FileOutputStream(file);
259 |
260 | copyFile(input, outStream);
261 |
262 | outStream.flush();
263 | outStream.close();
264 |
265 | return Uri.fromFile(file);
266 |
267 | } catch (MalformedURLException e) {
268 | Log.e("Asset", "Incorrect URL");
269 | e.printStackTrace();
270 | } catch (FileNotFoundException e) {
271 | Log.e("Asset", "Failed to create new File from HTTP Content");
272 | e.printStackTrace();
273 | } catch (IOException e) {
274 | Log.e("Asset", "No Input can be created from http Stream");
275 | e.printStackTrace();
276 | }
277 |
278 | return Uri.EMPTY;
279 | }
280 |
281 | /**
282 | * Copy content from input stream into output stream.
283 | *
284 | * @param in
285 | * The input stream
286 | * @param out
287 | * The output stream
288 | */
289 | private void copyFile(InputStream in, OutputStream out) throws IOException {
290 | byte[] buffer = new byte[1024];
291 | int read;
292 |
293 | while ((read = in.read(buffer)) != -1) {
294 | out.write(buffer, 0, read);
295 | }
296 | }
297 |
298 | /**
299 | * Resource ID for drawable.
300 | *
301 | * @param resPath
302 | * Resource path as string
303 | */
304 | int getResIdForDrawable(String resPath) {
305 | int resId = getResIdForDrawable(getPkgName(), resPath);
306 |
307 | if (resId == 0) {
308 | resId = getResIdForDrawable("android", resPath);
309 | }
310 |
311 | return resId;
312 | }
313 |
314 | /**
315 | * Resource ID for drawable.
316 | *
317 | * @param clsName
318 | * Relative package or global android name space
319 | * @param resPath
320 | * Resource path as string
321 | */
322 | int getResIdForDrawable(String clsName, String resPath) {
323 | String drawable = getBaseName(resPath);
324 | int resId = 0;
325 |
326 | try {
327 | Class> cls = Class.forName(clsName + ".R$drawable");
328 |
329 | resId = (Integer) cls.getDeclaredField(drawable).get(Integer.class);
330 | } catch (Exception ignore) {}
331 |
332 | return resId;
333 | }
334 |
335 | /**
336 | * Convert drawable resource to bitmap.
337 | *
338 | * @param drawable
339 | * Drawable resource name
340 | */
341 | Bitmap getIconFromDrawable (String drawable) {
342 | Resources res = context.getResources();
343 | int iconId;
344 |
345 | iconId = getResIdForDrawable(getPkgName(), drawable);
346 |
347 | if (iconId == 0) {
348 | iconId = getResIdForDrawable("android", drawable);
349 | }
350 |
351 | if (iconId == 0) {
352 | iconId = android.R.drawable.screen_background_dark_transparent;
353 | }
354 |
355 | return BitmapFactory.decodeResource(res, iconId);
356 | }
357 |
358 | /**
359 | * Convert URI to Bitmap.
360 | *
361 | * @param uri
362 | * Internal image URI
363 | */
364 | Bitmap getIconFromUri (Uri uri) throws IOException {
365 | InputStream input = context.getContentResolver().openInputStream(uri);
366 |
367 | return BitmapFactory.decodeStream(input);
368 | }
369 |
370 | /**
371 | * Extract name of drawable resource from path.
372 | *
373 | * @param resPath
374 | * Resource path as string
375 | */
376 | private String getBaseName (String resPath) {
377 | String drawable = resPath;
378 |
379 | if (drawable.contains("/")) {
380 | drawable = drawable.substring(drawable.lastIndexOf('/') + 1);
381 | }
382 |
383 | if (resPath.contains(".")) {
384 | drawable = drawable.substring(0, drawable.lastIndexOf('.'));
385 | }
386 |
387 | return drawable;
388 | }
389 |
390 | /**
391 | * Returns a file located under the external cache dir of that app.
392 | *
393 | * @return
394 | * File with a random UUID name
395 | */
396 | private File getTmpFile () {
397 | // If random UUID is not be enough see
398 | // https://github.com/LukePulverenti/cordova-plugin-local-notifications/blob/267170db14044cbeff6f4c3c62d9b766b7a1dd62/src/android/notification/AssetUtil.java#L255
399 | return getTmpFile(UUID.randomUUID().toString());
400 | }
401 |
402 | /**
403 | * Returns a file located under the external cache dir of that app.
404 | *
405 | * @param name
406 | * The name of the file
407 | * @return
408 | * File with the provided name
409 | */
410 | private File getTmpFile (String name) {
411 | File dir = context.getExternalCacheDir();
412 |
413 | if (dir == null) {
414 | Log.e("Asset", "Missing external cache dir");
415 | return null;
416 | }
417 |
418 | String storage = dir.toString() + STORAGE_FOLDER;
419 |
420 | //noinspection ResultOfMethodCallIgnored
421 | new File(storage).mkdir();
422 |
423 | return new File(storage, name);
424 | }
425 |
426 | /**
427 | * Package name specified by context.
428 | */
429 | private String getPkgName () {
430 | return context.getPackageName();
431 | }
432 |
433 | }
434 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/notification/Manager.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications.notification;
25 |
26 | import android.app.NotificationManager;
27 | import android.content.Context;
28 | import android.content.SharedPreferences;
29 |
30 | import org.json.JSONException;
31 | import org.json.JSONObject;
32 |
33 | import java.util.ArrayList;
34 | import java.util.Iterator;
35 | import java.util.List;
36 | import java.util.Map;
37 | import java.util.Set;
38 |
39 | import static com.remobile.localNotifications.notification.Notification.PREF_KEY;
40 |
41 | /**
42 | * Central way to access all or single local notifications set by specific
43 | * state like triggered or scheduled. Offers shortcut ways to schedule,
44 | * cancel or clear local notifications.
45 | */
46 | public class Manager {
47 |
48 | // Context passed through constructor and used for notification builder.
49 | private Context context;
50 |
51 | /**
52 | * Constructor
53 | *
54 | * @param context
55 | * Application context
56 | */
57 | private Manager(Context context){
58 | this.context = context;
59 | }
60 |
61 | /**
62 | * Static method to retrieve class instance.
63 | *
64 | * @param context
65 | * Application context
66 | */
67 | public static Manager getInstance(Context context) {
68 | return new Manager(context);
69 | }
70 |
71 | /**
72 | * Schedule local notification specified by JSON object.
73 | *
74 | * @param options
75 | * JSON object with set of options
76 | * @param receiver
77 | * Receiver to handle the trigger event
78 | */
79 | public Notification schedule (JSONObject options, Class> receiver) {
80 | return schedule(new Options(context).parse(options), receiver);
81 | }
82 |
83 | /**
84 | * Schedule local notification specified by options object.
85 | *
86 | * @param options
87 | * Set of notification options
88 | * @param receiver
89 | * Receiver to handle the trigger event
90 | */
91 | public Notification schedule (Options options, Class> receiver) {
92 | Notification notification = new Builder(options)
93 | .setTriggerReceiver(receiver)
94 | .build();
95 |
96 | notification.schedule();
97 |
98 | return notification;
99 | }
100 |
101 | /**
102 | * Clear local notification specified by ID.
103 | *
104 | * @param id
105 | * The notification ID
106 | * @param updates
107 | * JSON object with notification options
108 | * @param receiver
109 | * Receiver to handle the trigger event
110 | */
111 | public Notification update (int id, JSONObject updates, Class> receiver) {
112 | Notification notification = get(id);
113 |
114 | if (notification == null)
115 | return null;
116 |
117 | notification.cancel();
118 |
119 | JSONObject options = mergeJSONObjects(
120 | notification.getOptions().getDict(), updates);
121 |
122 | try {
123 | options.putOpt("updated", true);
124 | } catch (JSONException ignore) {}
125 |
126 | return schedule(options, receiver);
127 | }
128 |
129 | /**
130 | * Clear local notification specified by ID.
131 | *
132 | * @param id
133 | * The notification ID
134 | */
135 | public Notification clear (int id) {
136 | Notification notification = get(id);
137 |
138 | if (notification != null) {
139 | notification.clear();
140 | }
141 |
142 | return notification;
143 | }
144 |
145 | /**
146 | * Clear local notification specified by ID.
147 | *
148 | * @param id
149 | * The notification ID
150 | */
151 | public Notification cancel (int id) {
152 | Notification notification = get(id);
153 |
154 | if (notification != null) {
155 | notification.cancel();
156 | }
157 |
158 | return notification;
159 | }
160 |
161 | /**
162 | * Clear all local notifications.
163 | */
164 | public void clearAll () {
165 | List notifications = getAll();
166 |
167 | for (Notification notification : notifications) {
168 | notification.clear();
169 | }
170 |
171 | getNotMgr().cancelAll();
172 | }
173 |
174 | /**
175 | * Cancel all local notifications.
176 | */
177 | public void cancelAll () {
178 | List notifications = getAll();
179 |
180 | for (Notification notification : notifications) {
181 | notification.cancel();
182 | }
183 |
184 | getNotMgr().cancelAll();
185 | }
186 |
187 | /**
188 | * All local notifications IDs.
189 | */
190 | public List getIds() {
191 | Set keys = getPrefs().getAll().keySet();
192 | ArrayList ids = new ArrayList();
193 |
194 | for (String key : keys) {
195 | try {
196 | ids.add(Integer.parseInt(key));
197 | } catch (NumberFormatException e) {
198 | e.printStackTrace();
199 | }
200 | }
201 |
202 | return ids;
203 | }
204 |
205 | /**
206 | * All local notification IDs for given type.
207 | *
208 | * @param type
209 | * The notification life cycle type
210 | */
211 | public List getIdsByType(Notification.Type type) {
212 | List notifications = getAll();
213 | ArrayList ids = new ArrayList();
214 |
215 | for (Notification notification : notifications) {
216 | if (notification.getType() == type) {
217 | ids.add(notification.getId());
218 | }
219 | }
220 |
221 | return ids;
222 | }
223 |
224 | /**
225 | * List of local notifications with matching ID.
226 | *
227 | * @param ids
228 | * Set of notification IDs
229 | */
230 | public List getByIds(List ids) {
231 | ArrayList notifications = new ArrayList();
232 |
233 | for (int id : ids) {
234 | Notification notification = get(id);
235 |
236 | if (notification != null) {
237 | notifications.add(notification);
238 | }
239 | }
240 |
241 | return notifications;
242 | }
243 |
244 | /**
245 | * List of all local notification.
246 | */
247 | public List getAll() {
248 | return getByIds(getIds());
249 | }
250 |
251 | /**
252 | * List of local notifications from given type.
253 | *
254 | * @param type
255 | * The notification life cycle type
256 | */
257 | public List getByType(Notification.Type type) {
258 | List notifications = getAll();
259 | ArrayList list = new ArrayList();
260 |
261 | if (type == Notification.Type.ALL)
262 | return notifications;
263 |
264 | for (Notification notification : notifications) {
265 | if (notification.getType() == type) {
266 | list.add(notification);
267 | }
268 | }
269 |
270 | return list;
271 | }
272 |
273 | /**
274 | * List of local notifications with matching ID from given type.
275 | *
276 | * @param type
277 | * The notification life cycle type
278 | * @param ids
279 | * Set of notification IDs
280 | */
281 | @SuppressWarnings("UnusedDeclaration")
282 | public List getBy(Notification.Type type, List ids) {
283 | ArrayList notifications = new ArrayList();
284 |
285 | for (int id : ids) {
286 | Notification notification = get(id);
287 |
288 | if (notification != null && notification.isScheduled()) {
289 | notifications.add(notification);
290 | }
291 | }
292 |
293 | return notifications;
294 | }
295 |
296 | /**
297 | * If a notification with an ID exists.
298 | *
299 | * @param id
300 | * Notification ID
301 | */
302 | public boolean exist (int id) {
303 | return get(id) != null;
304 | }
305 |
306 | /**
307 | * If a notification with an ID and type exists.
308 | *
309 | * @param id
310 | * Notification ID
311 | * @param type
312 | * Notification type
313 | */
314 | public boolean exist (int id, Notification.Type type) {
315 | Notification notification = get(id);
316 |
317 | return notification != null && notification.getType() == type;
318 | }
319 |
320 | /**
321 | * List of properties from all local notifications.
322 | */
323 | public List getOptions() {
324 | return getOptionsById(getIds());
325 | }
326 |
327 | /**
328 | * List of properties from local notifications with matching ID.
329 | *
330 | * @param ids
331 | * Set of notification IDs
332 | */
333 | public List getOptionsById(List ids) {
334 | ArrayList options = new ArrayList();
335 |
336 | for (int id : ids) {
337 | Notification notification = get(id);
338 |
339 | if (notification != null) {
340 | options.add(notification.getOptions().getDict());
341 | }
342 | }
343 |
344 | return options;
345 | }
346 |
347 | /**
348 | * List of properties from all local notifications from given type.
349 | *
350 | * @param type
351 | * The notification life cycle type
352 | */
353 | public List getOptionsByType(Notification.Type type) {
354 | ArrayList options = new ArrayList();
355 | List notifications = getByType(type);
356 |
357 | for (Notification notification : notifications) {
358 | options.add(notification.getOptions().getDict());
359 | }
360 |
361 | return options;
362 | }
363 |
364 | /**
365 | * List of properties from local notifications with matching ID from
366 | * given type.
367 | *
368 | * @param type
369 | * The notification life cycle type
370 | * @param ids
371 | * Set of notification IDs
372 | */
373 | public List getOptionsBy(Notification.Type type,
374 | List ids) {
375 |
376 | if (type == Notification.Type.ALL)
377 | return getOptionsById(ids);
378 |
379 | ArrayList options = new ArrayList();
380 | List notifications = getByIds(ids);
381 |
382 | for (Notification notification : notifications) {
383 | if (notification.getType() == type) {
384 | options.add(notification.getOptions().getDict());
385 | }
386 | }
387 |
388 | return options;
389 | }
390 |
391 | /**
392 | * Get existent local notification.
393 | *
394 | * @param id
395 | * Notification ID
396 | */
397 | public Notification get(int id) {
398 | Map alarms = getPrefs().getAll();
399 | String notId = Integer.toString(id);
400 | JSONObject options;
401 |
402 | if (!alarms.containsKey(notId))
403 | return null;
404 |
405 |
406 | try {
407 | String json = alarms.get(notId).toString();
408 | options = new JSONObject(json);
409 | } catch (JSONException e) {
410 | e.printStackTrace();
411 | return null;
412 | }
413 |
414 | Builder builder = new Builder(context, options);
415 |
416 | return builder.build();
417 | }
418 |
419 | /**
420 | * Merge two JSON objects.
421 | *
422 | * @param obj1
423 | * JSON object
424 | * @param obj2
425 | * JSON object with new options
426 | */
427 | private JSONObject mergeJSONObjects (JSONObject obj1, JSONObject obj2) {
428 | Iterator it = obj2.keys();
429 |
430 | while (it.hasNext()) {
431 | try {
432 | String key = (String)it.next();
433 |
434 | obj1.put(key, obj2.opt(key));
435 | } catch (JSONException e) {
436 | e.printStackTrace();
437 | }
438 | }
439 |
440 | return obj1;
441 | }
442 |
443 | /**
444 | * Shared private preferences for the application.
445 | */
446 | private SharedPreferences getPrefs () {
447 | return context.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);
448 | }
449 |
450 | /**
451 | * Notification manager for the application.
452 | */
453 | private NotificationManager getNotMgr () {
454 | return (NotificationManager) context
455 | .getSystemService(Context.NOTIFICATION_SERVICE);
456 | }
457 |
458 | }
459 |
--------------------------------------------------------------------------------
/libs/local-notification-core.js:
--------------------------------------------------------------------------------
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 |
24 | const exec = require('@remobile/react-native-cordova').exec;
25 | const util = require('./local-notification-util.js');
26 | const { NativeAppEventEmitter, DeviceEventEmitter, Platform } = require('react-native');
27 | const EventEmitter = Platform.OS === 'android' ? DeviceEventEmitter : NativeAppEventEmitter;
28 | exports = Object.assign(exports, util);
29 |
30 | /********
31 | * CORE *
32 | ********/
33 |
34 | /**
35 | * Returns the default settings.
36 | *
37 | * @return {Object}
38 | */
39 | exports.getDefaults = function () {
40 | return this._defaults;
41 | };
42 |
43 | /**
44 | * Overwrite default settings.
45 | *
46 | * @param {Object} defaults
47 | */
48 | exports.setDefaults = function (newDefaults) {
49 | const defaults = this.getDefaults();
50 |
51 | for (const key in defaults) {
52 | if (newDefaults.hasOwnProperty(key)) {
53 | defaults[key] = newDefaults[key];
54 | }
55 | }
56 | };
57 |
58 | /**
59 | * Schedule a new local notification.
60 | *
61 | * @param {Object} opts
62 | * The notification properties
63 | * @param {Function} callback
64 | * A function to be called after the notification has been canceled
65 | * @param {Object?} scope
66 | * The scope for the callback function
67 | */
68 | exports.schedule = function (opts, callback, scope) {
69 | this.registerPermission(function (granted) {
70 | if (!granted) { return; }
71 |
72 | const notifications = Array.isArray(opts) ? opts : [opts];
73 |
74 | for (let i = 0; i < notifications.length; i++) {
75 | const properties = notifications[i];
76 |
77 | this.mergeWithDefaults(properties);
78 | this.convertProperties(properties);
79 | }
80 |
81 | this.exec('schedule', notifications, callback, scope);
82 | }, this);
83 | };
84 |
85 | /**
86 | * Update existing notifications specified by IDs in options.
87 | *
88 | * @param {Object} options
89 | * The notification properties to update
90 | * @param {Function} callback
91 | * A function to be called after the notification has been updated
92 | * @param {Object?} scope
93 | * The scope for the callback function
94 | */
95 | exports.update = function (opts, callback, scope) {
96 | const notifications = Array.isArray(opts) ? opts : [opts];
97 |
98 | for (let i = 0; i < notifications.length; i++) {
99 | const properties = notifications[i];
100 |
101 | this.convertProperties(properties);
102 | }
103 |
104 | this.exec('update', notifications, callback, scope);
105 | };
106 |
107 | /**
108 | * Clear the specified notification.
109 | *
110 | * @param {String} id
111 | * The ID of the notification
112 | * @param {Function} callback
113 | * A function to be called after the notification has been cleared
114 | * @param {Object?} scope
115 | * The scope for the callback function
116 | */
117 | exports.clear = function (ids, callback, scope) {
118 | ids = Array.isArray(ids) ? ids : [ids];
119 | ids = this.convertIds(ids);
120 |
121 | this.exec('clear', ids, callback, scope);
122 | };
123 |
124 | /**
125 | * Clear all previously sheduled notifications.
126 | *
127 | * @param {Function} callback
128 | * A function to be called after all notifications have been cleared
129 | * @param {Object?} scope
130 | * The scope for the callback function
131 | */
132 | exports.clearAll = function (callback, scope) {
133 | this.exec('clearAll', null, callback, scope);
134 | };
135 |
136 | /**
137 | * Cancel the specified notifications.
138 | *
139 | * @param {String[]} ids
140 | * The IDs of the notifications
141 | * @param {Function} callback
142 | * A function to be called after the notifications has been canceled
143 | * @param {Object?} scope
144 | * The scope for the callback function
145 | */
146 | exports.cancel = function (ids, callback, scope) {
147 | ids = Array.isArray(ids) ? ids : [ids];
148 | ids = this.convertIds(ids);
149 |
150 | this.exec('cancel', ids, callback, scope);
151 | };
152 |
153 | /**
154 | * Remove all previously registered notifications.
155 | *
156 | * @param {Function} callback
157 | * A function to be called after all notifications have been canceled
158 | * @param {Object?} scope
159 | * The scope for the callback function
160 | */
161 | exports.cancelAll = function (callback, scope) {
162 | this.exec('cancelAll', null, callback, scope);
163 | };
164 |
165 | /**
166 | * Check if a notification with an ID is present.
167 | *
168 | * @param {String} id
169 | * The ID of the notification
170 | * @param {Function} callback
171 | * A callback function to be called with the list
172 | * @param {Object?} scope
173 | * The scope for the callback function
174 | */
175 | exports.isPresent = function (id, callback, scope) {
176 | this.exec('isPresent', id || 0, callback, scope);
177 | };
178 |
179 | /**
180 | * Check if a notification with an ID is scheduled.
181 | *
182 | * @param {String} id
183 | * The ID of the notification
184 | * @param {Function} callback
185 | * A callback function to be called with the list
186 | * @param {Object?} scope
187 | * The scope for the callback function
188 | */
189 | exports.isScheduled = function (id, callback, scope) {
190 | this.exec('isScheduled', id || 0, callback, scope);
191 | };
192 |
193 | /**
194 | * Check if a notification with an ID was triggered.
195 | *
196 | * @param {String} id
197 | * The ID of the notification
198 | * @param {Function} callback
199 | * A callback function to be called with the list
200 | * @param {Object?} scope
201 | * The scope for the callback function
202 | */
203 | exports.isTriggered = function (id, callback, scope) {
204 | this.exec('isTriggered', id || 0, callback, scope);
205 | };
206 |
207 | /**
208 | * List all local notification IDs.
209 | *
210 | * @param {Function} callback
211 | * A callback function to be called with the list
212 | * @param {Object?} scope
213 | * The scope for the callback function
214 | */
215 | exports.getAllIds = function (callback, scope) {
216 | this.exec('getAllIds', null, callback, scope);
217 | };
218 |
219 | /**
220 | * Alias for `getAllIds`.
221 | */
222 | exports.getIds = function () {
223 | this.getAllIds.apply(this, arguments);
224 | };
225 |
226 | /**
227 | * List all scheduled notification IDs.
228 | *
229 | * @param {Function} callback
230 | * A callback function to be called with the list
231 | * @param {Object?} scope
232 | * The scope for the callback function
233 | */
234 | exports.getScheduledIds = function (callback, scope) {
235 | this.exec('getScheduledIds', null, callback, scope);
236 | };
237 |
238 | /**
239 | * List all triggered notification IDs.
240 | *
241 | * @param {Function} callback
242 | * A callback function to be called with the list
243 | * @param {Object?} scope
244 | * The scope for the callback function
245 | */
246 | exports.getTriggeredIds = function (callback, scope) {
247 | this.exec('getTriggeredIds', null, callback, scope);
248 | };
249 |
250 | /**
251 | * Property list for given local notifications.
252 | * If called without IDs, all notification will be returned.
253 | *
254 | * @param {Number[]?} ids
255 | * Set of notification IDs
256 | * @param {Function} callback
257 | * A callback function to be called with the list
258 | * @param {Object?} scope
259 | * The scope for the callback function
260 | */
261 | exports.get = function () {
262 | const args = Array.apply(null, arguments);
263 |
264 | if (typeof args[0] == 'function') {
265 | args.unshift([]);
266 | }
267 |
268 | let ids = args[0],
269 | callback = args[1],
270 | scope = args[2];
271 |
272 | if (!Array.isArray(ids)) {
273 | this.exec('getSingle', Number(ids), callback, scope);
274 | return;
275 | }
276 |
277 | ids = this.convertIds(ids);
278 |
279 | this.exec('getAll', ids, callback, scope);
280 | };
281 |
282 | /**
283 | * Property list for all local notifications.
284 | *
285 | * @param {Function} callback
286 | * A callback function to be called with the list
287 | * @param {Object?} scope
288 | * The scope for the callback function
289 | */
290 | exports.getAll = function (callback, scope) {
291 | this.exec('getAll', null, callback, scope);
292 | };
293 |
294 | /**
295 | * Property list for given scheduled notifications.
296 | * If called without IDs, all notification will be returned.
297 | *
298 | * @param {Number[]?} ids
299 | * Set of notification IDs
300 | * @param {Function} callback
301 | * A callback function to be called with the list
302 | * @param {Object?} scope
303 | * The scope for the callback function
304 | */
305 | exports.getScheduled = function () {
306 | const args = Array.apply(null, arguments);
307 |
308 | if (typeof args[0] == 'function') {
309 | args.unshift([]);
310 | }
311 |
312 | let ids = args[0],
313 | callback = args[1],
314 | scope = args[2];
315 |
316 | if (!Array.isArray(ids)) {
317 | ids = [ids];
318 | }
319 |
320 | if (!Array.isArray(ids)) {
321 | this.exec('getSingleScheduled', Number(ids), callback, scope);
322 | return;
323 | }
324 |
325 | ids = this.convertIds(ids);
326 |
327 | this.exec('getScheduled', ids, callback, scope);
328 | };
329 |
330 | /**
331 | * Property list for all scheduled notifications.
332 | *
333 | * @param {Function} callback
334 | * A callback function to be called with the list
335 | * @param {Object?} scope
336 | * The scope for the callback function
337 | */
338 | exports.getAllScheduled = function (callback, scope) {
339 | this.exec('getScheduled', null, callback, scope);
340 | };
341 |
342 | /**
343 | * Property list for given triggered notifications.
344 | * If called without IDs, all notification will be returned.
345 | *
346 | * @param {Number[]?} ids
347 | * Set of notification IDs
348 | * @param {Function} callback
349 | * A callback function to be called with the list
350 | * @param {Object?} scope
351 | * The scope for the callback function
352 | */
353 | exports.getTriggered = function () {
354 | const args = Array.apply(null, arguments);
355 |
356 | if (typeof args[0] == 'function') {
357 | args.unshift([]);
358 | }
359 |
360 | let ids = args[0],
361 | callback = args[1],
362 | scope = args[2];
363 |
364 | if (!Array.isArray(ids)) {
365 | ids = [ids];
366 | }
367 |
368 | if (!Array.isArray(ids)) {
369 | this.exec('getSingleTriggered', Number(ids), callback, scope);
370 | return;
371 | }
372 |
373 | ids = this.convertIds(ids);
374 |
375 | this.exec('getTriggered', ids, callback, scope);
376 | };
377 |
378 | /**
379 | * Property list for all triggered notifications.
380 | *
381 | * @param {Function} callback
382 | * A callback function to be called with the list
383 | * @param {Object?} scope
384 | * The scope for the callback function
385 | */
386 | exports.getAllTriggered = function (callback, scope) {
387 | this.exec('getTriggered', null, callback, scope);
388 | };
389 |
390 | /**
391 | * Informs if the app has the permission to show notifications.
392 | *
393 | * @param {Function} callback
394 | * The function to be exec as the callback
395 | * @param {Object?} scope
396 | * The callback function's scope
397 | */
398 | exports.hasPermission = function (callback, scope) {
399 | const fn = this.createCallbackFn(callback, scope);
400 |
401 | if (Platform.OS != 'ios') {
402 | fn(true);
403 | return;
404 | }
405 |
406 | exec(fn, null, 'LocalNotification', 'hasPermission', []);
407 | };
408 |
409 | /**
410 | * Register permission to show notifications if not already granted.
411 | *
412 | * @param {Function} callback
413 | * The function to be exec as the callback
414 | * @param {Object?} scope
415 | * The callback function's scope
416 | */
417 | exports.registerPermission = function (callback, scope) {
418 | const fn = this.createCallbackFn(callback, scope);
419 |
420 | if (Platform.OS != 'ios') {
421 | fn(true);
422 | return;
423 | }
424 |
425 | exec(fn, null, 'LocalNotification', 'registerPermission', []);
426 | };
427 |
428 | /**********
429 | * EVENTS *
430 | **********/
431 |
432 | /**
433 | * Register callback for given event.
434 | *
435 | * @param {String} event
436 | * The event's name
437 | * @param {Function} callback
438 | * The function to be exec as callback
439 | * @param {Object?} scope
440 | * The callback function's scope
441 | */
442 | exports.on = function (event, callback, scope) {
443 | if (!this._subscription[event]) {
444 | this._subscription[event] = EventEmitter.addListener('RCT-LOCAL-NOTIFICATION-' + event, function (params) {
445 | console.log('[========]', event, params);
446 | exports.fireEvent(event, params);
447 | });
448 | }
449 |
450 | if (!this._listener[event]) {
451 | this._listener[event] = [];
452 | }
453 |
454 | const item = [callback, scope];
455 |
456 | this._listener[event].push(item);
457 | };
458 |
459 | /**
460 | * Unregister callback for given event.
461 | *
462 | * @param {String} event
463 | * The event's name
464 | * @param {Function} callback
465 | * The function to be exec as callback
466 | */
467 | exports.un = function (event, callback) {
468 | const listener = this._listener[event];
469 | const subscription = this._subscription[event];
470 | if (subscription) {
471 | subscription.remove();
472 | delete this._subscription[event];
473 | }
474 |
475 | if (!listener) { return; }
476 |
477 | for (let i = 0; i < listener.length; i++) {
478 | const fn = listener[i][0];
479 |
480 | if (fn == callback) {
481 | listener.splice(i, 1);
482 | break;
483 | }
484 | }
485 | };
486 |
--------------------------------------------------------------------------------
/ios/RCTLocalNotifications/APPLocalNotification.m:
--------------------------------------------------------------------------------
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 |
24 | #import "APPLocalNotification.h"
25 | #import "APPLocalNotificationOptions.h"
26 | #import "UIApplication+APPLocalNotification.h"
27 | #import "UILocalNotification+APPLocalNotification.h"
28 | #import "AppDelegate+APPRegisterUserNotificationSettings.h"
29 |
30 | NSString* const CDVLocalNotification = @"CDVLocalNotification";
31 |
32 | @interface APPLocalNotification ()
33 |
34 | // Retrieves the application state
35 | @property (readonly, getter=applicationState) NSString* applicationState;
36 | // All events will be queued until deviceready has been fired
37 | @property (readwrite, assign) BOOL deviceready;
38 | // Event queue
39 | @property (readonly, nonatomic, strong) NSMutableDictionary* eventQueue;
40 | // Needed when calling `registerPermission`
41 | @property (nonatomic, strong) CDVInvokedUrlCommand* command;
42 |
43 | @end
44 |
45 | @implementation APPLocalNotification
46 |
47 | @synthesize deviceready, eventQueue;
48 | @synthesize bridge = _bridge;
49 |
50 | RCT_EXPORT_MODULE(LocalNotification)
51 |
52 | - (id)init {
53 | self = [super init];
54 | if (self) {
55 | [self pluginInitialize];
56 | }
57 | return self;
58 | }
59 |
60 | RCT_EXPORT_CORDOVA_METHOD(deviceready);
61 | RCT_EXPORT_CORDOVA_METHOD(hasPermission);
62 | RCT_EXPORT_CORDOVA_METHOD(registerPermission);
63 | RCT_EXPORT_CORDOVA_METHOD(schedule);
64 | RCT_EXPORT_CORDOVA_METHOD(update);
65 | RCT_EXPORT_CORDOVA_METHOD(cancel);
66 | RCT_EXPORT_CORDOVA_METHOD(cancelAll);
67 | RCT_EXPORT_CORDOVA_METHOD(clear);
68 | RCT_EXPORT_CORDOVA_METHOD(clearAll);
69 | RCT_EXPORT_CORDOVA_METHOD(isPresent);
70 | RCT_EXPORT_CORDOVA_METHOD(isScheduled);
71 | RCT_EXPORT_CORDOVA_METHOD(isTriggered);
72 | RCT_EXPORT_CORDOVA_METHOD(getAllIds);
73 | RCT_EXPORT_CORDOVA_METHOD(getScheduledIds);
74 | RCT_EXPORT_CORDOVA_METHOD(getTriggeredIds);
75 | RCT_EXPORT_CORDOVA_METHOD(getSingle);
76 | RCT_EXPORT_CORDOVA_METHOD(getSingleScheduled);
77 | RCT_EXPORT_CORDOVA_METHOD(getSingleTriggered);
78 | RCT_EXPORT_CORDOVA_METHOD(getAll);
79 | RCT_EXPORT_CORDOVA_METHOD(getScheduled);
80 | RCT_EXPORT_CORDOVA_METHOD(getTriggered);
81 |
82 | - (void) sendJSEvent:(NSString *)event withParams:(NSString *)params {
83 | [self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"RCT-LOCAL-NOTIFICATION-%@", event] body:params];
84 | }
85 |
86 | #pragma mark -
87 | #pragma mark Interface
88 |
89 | /**
90 | * Execute all queued events.
91 | */
92 | - (void) deviceready:(CDVInvokedUrlCommand*)command
93 | {
94 | deviceready = YES;
95 |
96 | for (NSString* event in eventQueue) {
97 | NSString *params = eventQueue[event];
98 | [self sendJSEvent:event withParams:params];
99 | }
100 |
101 | [eventQueue removeAllObjects];
102 | }
103 |
104 | /**
105 | * Schedule a set of notifications.
106 | *
107 | * @param properties
108 | * A dict of properties for each notification
109 | */
110 | - (void) schedule:(CDVInvokedUrlCommand*)command
111 | {
112 | NSArray* notifications = command.arguments;
113 |
114 | [self.commandDelegate runInBackground:^{
115 | for (NSDictionary* options in notifications) {
116 | UILocalNotification* notification;
117 |
118 | notification = [[UILocalNotification alloc]
119 | initWithOptions:options];
120 |
121 | [self scheduleLocalNotification:[notification copy]];
122 | [self fireEvent:@"schedule" notification:notification];
123 |
124 | if (notifications.count > 1) {
125 | [NSThread sleepForTimeInterval:0.01];
126 | }
127 | }
128 |
129 | [self execCallback:command];
130 | }];
131 | }
132 |
133 | /**
134 | * Update a set of notifications.
135 | *
136 | * @param properties
137 | * A dict of properties for each notification
138 | */
139 | - (void) update:(CDVInvokedUrlCommand*)command
140 | {
141 | NSArray* notifications = command.arguments;
142 |
143 | [self.commandDelegate runInBackground:^{
144 | for (NSDictionary* options in notifications) {
145 | NSNumber* id = [options objectForKey:@"id"];
146 | UILocalNotification* notification;
147 |
148 | notification = [self.app localNotificationWithId:id];
149 |
150 | if (!notification)
151 | continue;
152 |
153 | [self updateLocalNotification:[notification copy]
154 | withOptions:options];
155 |
156 | [self fireEvent:@"update" notification:notification];
157 |
158 | if (notifications.count > 1) {
159 | [NSThread sleepForTimeInterval:0.01];
160 | }
161 | }
162 |
163 | [self execCallback:command];
164 | }];
165 | }
166 |
167 | /**
168 | * Cancel a set of notifications.
169 | *
170 | * @param ids
171 | * The IDs of the notifications
172 | */
173 | - (void) cancel:(CDVInvokedUrlCommand*)command
174 | {
175 | [self.commandDelegate runInBackground:^{
176 | for (NSNumber* id in command.arguments) {
177 | UILocalNotification* notification;
178 |
179 | notification = [self.app localNotificationWithId:id];
180 |
181 | if (!notification)
182 | continue;
183 |
184 | [self.app cancelLocalNotification:notification];
185 | [self fireEvent:@"cancel" notification:notification];
186 | }
187 |
188 | [self execCallback:command];
189 | }];
190 | }
191 |
192 | /**
193 | * Cancel all local notifications.
194 | */
195 | - (void) cancelAll:(CDVInvokedUrlCommand*)command
196 | {
197 | [self.commandDelegate runInBackground:^{
198 | [self cancelAllLocalNotifications];
199 | [self fireEvent:@"cancelall"];
200 | [self execCallback:command];
201 | }];
202 | }
203 |
204 | /**
205 | * Clear a set of notifications.
206 | *
207 | * @param ids
208 | * The IDs of the notifications
209 | */
210 | - (void) clear:(CDVInvokedUrlCommand*)command
211 | {
212 | [self.commandDelegate runInBackground:^{
213 | for (NSNumber* id in command.arguments) {
214 | UILocalNotification* notification;
215 |
216 | notification = [self.app localNotificationWithId:id];
217 |
218 | if (!notification)
219 | continue;
220 |
221 | [self.app clearLocalNotification:notification];
222 | [self fireEvent:@"clear" notification:notification];
223 | }
224 |
225 | [self execCallback:command];
226 | }];
227 | }
228 |
229 | /**
230 | * Clear all local notifications.
231 | */
232 | - (void) clearAll:(CDVInvokedUrlCommand*)command
233 | {
234 | [self.commandDelegate runInBackground:^{
235 | [self clearAllLocalNotifications];
236 | [self fireEvent:@"clearall"];
237 | [self execCallback:command];
238 | }];
239 | }
240 |
241 | /**
242 | * If a notification by ID is present.
243 | *
244 | * @param id
245 | * The ID of the notification
246 | */
247 | - (void) isPresent:(CDVInvokedUrlCommand *)command
248 | {
249 | [self isPresent:command type:NotifcationTypeAll];
250 | }
251 |
252 | /**
253 | * If a notification by ID is scheduled.
254 | *
255 | * @param id
256 | * The ID of the notification
257 | */
258 | - (void) isScheduled:(CDVInvokedUrlCommand*)command
259 | {
260 | [self isPresent:command type:NotifcationTypeScheduled];
261 | }
262 |
263 | /**
264 | * Check if a notification with an ID is triggered.
265 | *
266 | * @param id
267 | * The ID of the notification
268 | */
269 | - (void) isTriggered:(CDVInvokedUrlCommand*)command
270 | {
271 | [self isPresent:command type:NotifcationTypeTriggered];
272 | }
273 |
274 | /**
275 | * Check if a notification with an ID exists.
276 | *
277 | * @param type
278 | * The notification life cycle type
279 | */
280 | - (void) isPresent:(CDVInvokedUrlCommand*)command
281 | type:(APPLocalNotificationType)type;
282 | {
283 | [self.commandDelegate runInBackground:^{
284 | NSNumber* id = [command argumentAtIndex:0];
285 | BOOL exist;
286 |
287 | CDVPluginResult* result;
288 |
289 | if (type == NotifcationTypeAll) {
290 | exist = [self.app localNotificationExist:id];
291 | } else {
292 | exist = [self.app localNotificationExist:id type:type];
293 | }
294 |
295 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
296 | messageAsBool:exist];
297 |
298 | [self.commandDelegate sendPluginResult:result
299 | callbackId:command.callbackId];
300 | }];
301 | }
302 |
303 | /**
304 | * List all ids from all local notifications.
305 | */
306 | - (void) getAllIds:(CDVInvokedUrlCommand*)command
307 | {
308 | [self getIds:command byType:NotifcationTypeAll];
309 | }
310 |
311 | /**
312 | * List all ids from all pending notifications.
313 | */
314 | - (void) getScheduledIds:(CDVInvokedUrlCommand*)command
315 | {
316 | [self getIds:command byType:NotifcationTypeScheduled];
317 | }
318 |
319 | /**
320 | * List all ids from all triggered notifications.
321 | */
322 | - (void) getTriggeredIds:(CDVInvokedUrlCommand*)command
323 | {
324 | [self getIds:command byType:NotifcationTypeTriggered];
325 | }
326 |
327 | /**
328 | * List of ids for given local notifications.
329 | *
330 | * @param type
331 | * Notification life cycle type
332 | * @param ids
333 | * The IDs of the notifications
334 | */
335 | - (void) getIds:(CDVInvokedUrlCommand*)command
336 | byType:(APPLocalNotificationType)type;
337 | {
338 | [self.commandDelegate runInBackground:^{
339 | CDVPluginResult* result;
340 | NSArray* ids;
341 |
342 | if (type == NotifcationTypeAll) {
343 | ids = [self.app localNotificationIds];
344 | } else {
345 | ids = [self.app localNotificationIdsByType:type];
346 | }
347 |
348 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
349 | messageAsArray:ids];
350 |
351 | [self.commandDelegate sendPluginResult:result
352 | callbackId:command.callbackId];
353 | }];
354 | }
355 |
356 | /**
357 | * Propertys for given local notification.
358 | */
359 | - (void) getSingle:(CDVInvokedUrlCommand*)command
360 | {
361 | [self getOption:command byType:NotifcationTypeAll];
362 | }
363 |
364 | /**
365 | * Propertya for given scheduled notification.
366 | */
367 | - (void) getSingleScheduled:(CDVInvokedUrlCommand*)command
368 | {
369 | [self getOption:command byType:NotifcationTypeScheduled];
370 | }
371 |
372 | // Propertys for given triggered notification
373 | - (void) getSingleTriggered:(CDVInvokedUrlCommand*)command
374 | {
375 | [self getOption:command byType:NotifcationTypeTriggered];
376 | }
377 |
378 | /**
379 | * Property list for given local notifications.
380 | *
381 | * @param ids
382 | * The IDs of the notifications
383 | */
384 | - (void) getAll:(CDVInvokedUrlCommand*)command
385 | {
386 | [self getOptions:command byType:NotifcationTypeAll];
387 | }
388 |
389 | /**
390 | * Property list for given scheduled notifications.
391 | *
392 | * @param ids
393 | * The IDs of the notifications
394 | */
395 | - (void) getScheduled:(CDVInvokedUrlCommand*)command
396 | {
397 | [self getOptions:command byType:NotifcationTypeScheduled];
398 | }
399 |
400 | /**
401 | * Property list for given triggered notifications.
402 | *
403 | * @param ids
404 | * The IDs of the notifications
405 | */
406 | - (void) getTriggered:(CDVInvokedUrlCommand *)command
407 | {
408 | [self getOptions:command byType:NotifcationTypeTriggered];
409 | }
410 |
411 | /**
412 | * Propertys for given triggered notification.
413 | *
414 | * @param type
415 | * Notification life cycle type
416 | * @param ids
417 | * The ID of the notification
418 | */
419 | - (void) getOption:(CDVInvokedUrlCommand*)command
420 | byType:(APPLocalNotificationType)type;
421 | {
422 | [self.commandDelegate runInBackground:^{
423 | NSArray* ids = command.arguments;
424 | NSArray* notifications;
425 | CDVPluginResult* result;
426 |
427 | if (type == NotifcationTypeAll) {
428 | notifications = [self.app localNotificationOptionsById:ids];
429 | }
430 | else {
431 | notifications = [self.app localNotificationOptionsByType:type
432 | andId:ids];
433 | }
434 |
435 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
436 | messageAsDictionary:[notifications firstObject]];
437 |
438 | [self.commandDelegate sendPluginResult:result
439 | callbackId:command.callbackId];
440 | }];
441 | }
442 |
443 | /**
444 | * Property list for given triggered notifications.
445 | *
446 | * @param type
447 | * Notification life cycle type
448 | * @param ids
449 | * The IDs of the notifications
450 | */
451 | - (void) getOptions:(CDVInvokedUrlCommand*)command
452 | byType:(APPLocalNotificationType)type;
453 | {
454 | [self.commandDelegate runInBackground:^{
455 | NSArray* ids = command.arguments;
456 | NSArray* notifications;
457 | CDVPluginResult* result;
458 |
459 | if (type == NotifcationTypeAll && ids.count == 0) {
460 | notifications = [self.app localNotificationOptions];
461 | }
462 | else if (type == NotifcationTypeAll) {
463 | notifications = [self.app localNotificationOptionsById:ids];
464 | }
465 | else if (ids.count == 0) {
466 | notifications = [self.app localNotificationOptionsByType:type];
467 | }
468 | else {
469 | notifications = [self.app localNotificationOptionsByType:type
470 | andId:ids];
471 | }
472 |
473 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
474 | messageAsArray:notifications];
475 |
476 | [self.commandDelegate sendPluginResult:result
477 | callbackId:command.callbackId];
478 | }];
479 | }
480 |
481 | /**
482 | * Inform if the app has the permission to show
483 | * badges and local notifications.
484 | */
485 | - (void) hasPermission:(CDVInvokedUrlCommand*)command
486 | {
487 | [self.commandDelegate runInBackground:^{
488 | CDVPluginResult* result;
489 | BOOL hasPermission;
490 |
491 | hasPermission = [self.app hasPermissionToScheduleLocalNotifications];
492 |
493 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
494 | messageAsBool:hasPermission];
495 |
496 | [self.commandDelegate sendPluginResult:result
497 | callbackId:command.callbackId];
498 | }];
499 | }
500 |
501 | /**
502 | * Ask for permission to show badges.
503 | */
504 | - (void) registerPermission:(CDVInvokedUrlCommand*)command
505 | {
506 | if ([[UIApplication sharedApplication]
507 | respondsToSelector:@selector(registerUserNotificationSettings:)])
508 | {
509 | _command = command;
510 |
511 | [self.commandDelegate runInBackground:^{
512 | [self.app registerPermissionToScheduleLocalNotifications];
513 | }];
514 | } else {
515 | [self hasPermission:command];
516 | }
517 | }
518 |
519 | #pragma mark -
520 | #pragma mark Core Logic
521 |
522 | /**
523 | * Schedule the local notification.
524 | */
525 | - (void) scheduleLocalNotification:(UILocalNotification*)notification
526 | {
527 | [self cancelForerunnerLocalNotification:notification];
528 | [self.app scheduleLocalNotification:notification];
529 | }
530 |
531 | /**
532 | * Update the local notification.
533 | */
534 | - (void) updateLocalNotification:(UILocalNotification*)notification
535 | withOptions:(NSDictionary*)newOptions
536 | {
537 | NSMutableDictionary* options = [notification.userInfo mutableCopy];
538 |
539 | [options addEntriesFromDictionary:newOptions];
540 | [options setObject:[NSDate date] forKey:@"updatedAt"];
541 |
542 | notification = [[UILocalNotification alloc]
543 | initWithOptions:options];
544 |
545 | [self scheduleLocalNotification:notification];
546 | }
547 |
548 | /**
549 | * Cancel all local notifications.
550 | */
551 | - (void) cancelAllLocalNotifications
552 | {
553 | [self.app cancelAllLocalNotifications];
554 | [self.app setApplicationIconBadgeNumber:0];
555 | }
556 |
557 | /**
558 | * Clear all local notifications.
559 | */
560 | - (void) clearAllLocalNotifications
561 | {
562 | [self.app clearAllLocalNotifications];
563 | [self.app setApplicationIconBadgeNumber:0];
564 | }
565 |
566 | /**
567 | * Cancel a maybe given forerunner with the same ID.
568 | */
569 | - (void) cancelForerunnerLocalNotification:(UILocalNotification*)notification
570 | {
571 | NSNumber* id = notification.options.id;
572 | UILocalNotification* forerunner;
573 |
574 | forerunner = [self.app localNotificationWithId:id];
575 |
576 | if (!forerunner)
577 | return;
578 |
579 | [self.app cancelLocalNotification:forerunner];
580 | }
581 |
582 | /**
583 | * Cancels all non-repeating local notification older then
584 | * a specific amount of seconds
585 | */
586 | - (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds
587 | {
588 | NSArray* notifications;
589 |
590 | notifications = [self.app localNotifications];
591 |
592 | for (UILocalNotification* notification in notifications)
593 | {
594 | if (![notification isRepeating]
595 | && notification.timeIntervalSinceFireDate > seconds)
596 | {
597 | [self.app cancelLocalNotification:notification];
598 | [self fireEvent:@"cancel" notification:notification];
599 | }
600 | }
601 | }
602 |
603 | #pragma mark -
604 | #pragma mark Delegates
605 |
606 | /**
607 | * Calls the cancel or trigger event after a local notification was received.
608 | * Cancels the local notification if autoCancel was set to true.
609 | */
610 | - (void) didReceiveLocalNotification:(NSNotification*)localNotification
611 | {
612 | UILocalNotification* notification = [localNotification object];
613 |
614 | if ([notification userInfo] == NULL || [notification wasUpdated] )
615 | return;
616 |
617 | NSTimeInterval timeInterval = [notification timeIntervalSinceLastTrigger];
618 |
619 | NSString* event = (timeInterval <= 1 && deviceready) ? @"trigger" : @"click";
620 |
621 | [self fireEvent:event notification:notification];
622 |
623 | if (![event isEqualToString:@"click"])
624 | return;
625 |
626 | if ([notification isRepeating]) {
627 | [self fireEvent:@"clear" notification:notification];
628 | } else {
629 | [self.app cancelLocalNotification:notification];
630 | [self fireEvent:@"cancel" notification:notification];
631 | }
632 | }
633 |
634 | /**
635 | * Called when app has started
636 | * (by clicking on a local notification).
637 | */
638 | - (void) didFinishLaunchingWithOptions:(NSNotification*)notification
639 | {
640 | NSDictionary* launchOptions = [notification userInfo];
641 |
642 | UILocalNotification* localNotification;
643 |
644 | localNotification = [launchOptions objectForKey:
645 | UIApplicationLaunchOptionsLocalNotificationKey];
646 |
647 | if (localNotification) {
648 | [self didReceiveLocalNotification:
649 | [NSNotification notificationWithName:CDVLocalNotification
650 | object:localNotification]];
651 | }
652 | }
653 |
654 | /**
655 | * Called on otification settings registration is completed.
656 | */
657 | - (void) didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings
658 | {
659 | if (_command)
660 | {
661 | [self hasPermission:_command];
662 | _command = NULL;
663 | }
664 | }
665 |
666 | #pragma mark -
667 | #pragma mark Life Cycle
668 |
669 | /**
670 | * Registers obervers after plugin was initialized.
671 | */
672 | - (void) pluginInitialize
673 | {
674 | NSNotificationCenter* center = [NSNotificationCenter
675 | defaultCenter];
676 |
677 | eventQueue = [[NSMutableDictionary alloc] init];
678 |
679 | [center addObserver:self
680 | selector:@selector(didReceiveLocalNotification:)
681 | name:CDVLocalNotification
682 | object:nil];
683 |
684 | [center addObserver:self
685 | selector:@selector(didFinishLaunchingWithOptions:)
686 | name:UIApplicationDidFinishLaunchingNotification
687 | object:nil];
688 |
689 | [center addObserver:self
690 | selector:@selector(didRegisterUserNotificationSettings:)
691 | name:UIApplicationRegisterUserNotificationSettings
692 | object:nil];
693 | }
694 |
695 | /**
696 | * Clears all single repeating notifications which are older then 5 days
697 | * before the app terminates.
698 | */
699 | - (void) onAppTerminate
700 | {
701 | [self cancelAllNotificationsWhichAreOlderThen:432000];
702 | }
703 |
704 | #pragma mark -
705 | #pragma mark Helper
706 |
707 | /**
708 | * Retrieves the application state
709 | *
710 | * @return
711 | * Either "background" or "foreground"
712 | */
713 | - (NSString*) applicationState
714 | {
715 | UIApplicationState state = [self.app applicationState];
716 |
717 | bool isActive = state == UIApplicationStateActive;
718 |
719 | return isActive ? @"foreground" : @"background";
720 | }
721 |
722 | /**
723 | * Simply invokes the callback without any parameter.
724 | */
725 | - (void) execCallback:(CDVInvokedUrlCommand*)command
726 | {
727 | CDVPluginResult *result = [CDVPluginResult
728 | resultWithStatus:CDVCommandStatus_OK];
729 |
730 | [self.commandDelegate sendPluginResult:result
731 | callbackId:command.callbackId];
732 | }
733 |
734 | /**
735 | * Short hand for shared application instance.
736 | */
737 | - (UIApplication*) app
738 | {
739 | return [UIApplication sharedApplication];
740 | }
741 |
742 | /**
743 | * Fire general event.
744 | */
745 | - (void) fireEvent:(NSString*)event
746 | {
747 | [self fireEvent:event notification:NULL];
748 | }
749 |
750 | /**
751 | * Fire event for local notification.
752 | */
753 | - (void) fireEvent:(NSString*)event notification:(UILocalNotification*)notification
754 | {
755 | NSString* params = [NSString stringWithFormat:
756 | @"\"%@\"", self.applicationState];
757 |
758 | if (notification) {
759 | NSString* args = [notification encodeToJSON];
760 |
761 | params = [NSString stringWithFormat:
762 | @"%@,'%@'",
763 | args, self.applicationState];
764 | }
765 |
766 | if (deviceready) {
767 | [self sendJSEvent:event withParams:params];
768 | } else {
769 | [self.eventQueue setObject:params forKey:event];
770 | }
771 | }
772 |
773 | @end
774 |
--------------------------------------------------------------------------------
/android/src/main/java/com/remobile/localNotifications/LocalNotification.java:
--------------------------------------------------------------------------------
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 |
24 | package com.remobile.localNotifications;
25 |
26 | import android.app.Activity;
27 |
28 | import org.json.JSONArray;
29 | import org.json.JSONException;
30 | import org.json.JSONObject;
31 |
32 | import java.util.ArrayList;
33 | import java.util.HashMap;
34 | import java.util.List;
35 | import java.util.Map;
36 |
37 | import com.facebook.common.logging.FLog;
38 | import com.facebook.react.modules.core.DeviceEventManagerModule;
39 | import com.remobile.localNotifications.notification.Manager;
40 | import com.remobile.localNotifications.notification.Notification;
41 | import com.remobile.cordova.*;
42 | import com.facebook.react.bridge.*;
43 |
44 | /**
45 | * This plugin utilizes the Android AlarmManager in combination with local
46 | * notifications. When a local notification is scheduled the alarm manager takes
47 | * care of firing the event. When the event is processed, a notification is put
48 | * in the Android notification center and status bar.
49 | */
50 | public class LocalNotification extends CordovaPlugin {
51 | private static final String LOG_TAG = "LocalNotification";
52 | private static LocalNotification self = null;
53 |
54 | // Indicates if the device is ready (to receive events)
55 | private static Boolean deviceready = false;
56 |
57 | // To inform the user about the state of the app in callbacks
58 | protected static Boolean isInBackground = true;
59 |
60 | // Queues all events before deviceready
61 | private static Map eventQueue = new HashMap();
62 |
63 | /**
64 | * Constructor.
65 | */
66 | public LocalNotification(ReactApplicationContext reactContext) {
67 | super(reactContext);
68 | self = this;
69 | }
70 |
71 | @Override
72 | public String getName() {
73 | return "LocalNotification";
74 | }
75 |
76 | @ReactMethod
77 | public void schedule(ReadableArray args, Callback success, Callback error) {
78 | executeReactMethod("schedule", args, success, error);
79 | }
80 | @ReactMethod
81 | public void update(ReadableArray args, Callback success, Callback error) {
82 | executeReactMethod("update", args, success, error);
83 | }
84 | @ReactMethod
85 | public void cancel(ReadableArray args, Callback success, Callback error) {
86 | executeReactMethod("cancel", args, success, error);
87 | }
88 | @ReactMethod
89 | public void cancelAll(ReadableArray args, Callback success, Callback error) {
90 | executeReactMethod("cancelAll", args, success, error);
91 | }
92 | @ReactMethod
93 | public void clear(ReadableArray args, Callback success, Callback error) {
94 | executeReactMethod("clear", args, success, error);
95 | }
96 | @ReactMethod
97 | public void clearAll(ReadableArray args, Callback success, Callback error) {
98 | executeReactMethod("clearAll", args, success, error);
99 | }
100 | @ReactMethod
101 | public void isPresent(ReadableArray args, Callback success, Callback error) {
102 | executeReactMethod("isPresent", args, success, error);
103 | }
104 | @ReactMethod
105 | public void isScheduled(ReadableArray args, Callback success, Callback error) {
106 | executeReactMethod("isScheduled", args, success, error);
107 | }
108 | @ReactMethod
109 | public void isTriggered(ReadableArray args, Callback success, Callback error) {
110 | executeReactMethod("isTriggered", args, success, error);
111 | }
112 | @ReactMethod
113 | public void getAllIds(ReadableArray args, Callback success, Callback error) {
114 | executeReactMethod("getAllIds", args, success, error);
115 | }
116 | @ReactMethod
117 | public void getScheduledIds(ReadableArray args, Callback success, Callback error) {
118 | executeReactMethod("getScheduledIds", args, success, error);
119 | }
120 | @ReactMethod
121 | public void getTriggeredIds(ReadableArray args, Callback success, Callback error) {
122 | executeReactMethod("getTriggeredIds", args, success, error);
123 | }
124 | @ReactMethod
125 | public void getSingle(ReadableArray args, Callback success, Callback error) {
126 | executeReactMethod("getSingle", args, success, error);
127 | }
128 | @ReactMethod
129 | public void getSingleScheduled(ReadableArray args, Callback success, Callback error) {
130 | executeReactMethod("getSingleScheduled", args, success, error);
131 | }
132 | @ReactMethod
133 | public void getSingleTriggered(ReadableArray args, Callback success, Callback error) {
134 | executeReactMethod("getSingleTriggered", args, success, error);
135 | }
136 | @ReactMethod
137 | public void getAll(ReadableArray args, Callback success, Callback error) {
138 | executeReactMethod("getAll", args, success, error);
139 | }
140 | @ReactMethod
141 | public void getScheduled(ReadableArray args, Callback success, Callback error) {
142 | executeReactMethod("getScheduled", args, success, error);
143 | }
144 | @ReactMethod
145 | public void getTriggered(ReadableArray args, Callback success, Callback error) {
146 | executeReactMethod("getTriggered", args, success, error);
147 | }
148 | @ReactMethod
149 | public void deviceready(ReadableArray args, Callback success, Callback error) {
150 | executeReactMethod("deviceready", args, success, error);
151 | }
152 |
153 | /**
154 | * Called when the system is about to start resuming a previous activity.
155 | *
156 | * Flag indicating if multitasking is turned on for app
157 | */
158 | @Override
159 | public void onPause() {
160 | isInBackground = true;
161 | }
162 |
163 | /**
164 | * Called when the activity will start interacting with the user.
165 | *
166 | * Flag indicating if multitasking is turned on for app
167 | */
168 | @Override
169 | public void onResume() {
170 | isInBackground = false;
171 | deviceready();
172 | }
173 |
174 | /**
175 | * The final call you receive before your activity is destroyed.
176 | */
177 | @Override
178 | public void onDestroy() {
179 | deviceready = false;
180 | isInBackground = true;
181 | }
182 |
183 | /**
184 | * Executes the request.
185 | *
186 | * This method is called from the WebView thread. To do a non-trivial
187 | * amount of work, use:
188 | * cordova.getThreadPool().execute(runnable);
189 | *
190 | * To run on the UI thread, use:
191 | * cordova.getActivity().runOnUiThread(runnable);
192 | *
193 | * @param action
194 | * The action to execute.
195 | * @param args
196 | * The exec() arguments in JSON form.
197 | * @param command
198 | * The callback context used when calling back into JavaScript.
199 | * @return
200 | * Whether the action was valid.
201 | */
202 | public boolean execute (final String action, final JSONArray args,
203 | final CallbackContext command) throws JSONException {
204 |
205 | Notification.setDefaultTriggerReceiver(TriggerReceiver.class);
206 |
207 | cordova.getThreadPool().execute(new Runnable() {
208 | public void run() {
209 | if (action.equals("schedule")) {
210 | schedule(args);
211 | command.success();
212 | }
213 | else if (action.equals("update")) {
214 | update(args);
215 | command.success();
216 | }
217 | else if (action.equals("cancel")) {
218 | cancel(args);
219 | command.success();
220 | }
221 | else if (action.equals("cancelAll")) {
222 | cancelAll();
223 | command.success();
224 | }
225 | else if (action.equals("clear")) {
226 | clear(args);
227 | command.success();
228 | }
229 | else if (action.equals("clearAll")) {
230 | clearAll();
231 | command.success();
232 | }
233 | else if (action.equals("isPresent")) {
234 | isPresent(args.optInt(0), command);
235 | }
236 | else if (action.equals("isScheduled")) {
237 | isScheduled(args.optInt(0), command);
238 | }
239 | else if (action.equals("isTriggered")) {
240 | isTriggered(args.optInt(0), command);
241 | }
242 | else if (action.equals("getAllIds")) {
243 | getAllIds(command);
244 | }
245 | else if (action.equals("getScheduledIds")) {
246 | getScheduledIds(command);
247 | }
248 | else if (action.equals("getTriggeredIds")) {
249 | getTriggeredIds(command);
250 | }
251 | else if (action.equals("getSingle")) {
252 | getSingle(args, command);
253 | }
254 | else if (action.equals("getSingleScheduled")) {
255 | getSingleScheduled(args, command);
256 | }
257 | else if (action.equals("getSingleTriggered")) {
258 | getSingleTriggered(args, command);
259 | }
260 | else if (action.equals("getAll")) {
261 | getAll(args, command);
262 | }
263 | else if (action.equals("getScheduled")) {
264 | getScheduled(args, command);
265 | }
266 | else if (action.equals("getTriggered")) {
267 | getTriggered(args, command);
268 | }
269 | else if (action.equals("deviceready")) {
270 | deviceready();
271 | }
272 | }
273 | });
274 |
275 | return true;
276 | }
277 |
278 | /**
279 | * Schedule multiple local notifications.
280 | *
281 | * @param notifications
282 | * Properties for each local notification
283 | */
284 | private void schedule (JSONArray notifications) {
285 | for (int i = 0; i < notifications.length(); i++) {
286 | JSONObject options = notifications.optJSONObject(i);
287 |
288 | Notification notification =
289 | getNotificationMgr().schedule(options, TriggerReceiver.class);
290 |
291 | fireEvent("schedule", notification);
292 | }
293 | }
294 |
295 | /**
296 | * Update multiple local notifications.
297 | *
298 | * @param updates
299 | * Notification properties including their IDs
300 | */
301 | private void update (JSONArray updates) {
302 | for (int i = 0; i < updates.length(); i++) {
303 | JSONObject update = updates.optJSONObject(i);
304 | int id = update.optInt("id", 0);
305 |
306 | Notification notification =
307 | getNotificationMgr().update(id, update, TriggerReceiver.class);
308 |
309 | if (notification == null)
310 | continue;
311 |
312 | fireEvent("update", notification);
313 | }
314 | }
315 |
316 | /**
317 | * Cancel multiple local notifications.
318 | *
319 | * @param ids
320 | * Set of local notification IDs
321 | */
322 | private void cancel (JSONArray ids) {
323 | for (int i = 0; i < ids.length(); i++) {
324 | int id = ids.optInt(i, 0);
325 |
326 | Notification notification =
327 | getNotificationMgr().cancel(id);
328 |
329 | if (notification == null)
330 | continue;
331 |
332 | fireEvent("cancel", notification);
333 | }
334 | }
335 |
336 | /**
337 | * Cancel all scheduled notifications.
338 | */
339 | private void cancelAll() {
340 | getNotificationMgr().cancelAll();
341 | fireEvent("cancelall");
342 | }
343 |
344 | /**
345 | * Clear multiple local notifications without canceling them.
346 | *
347 | * @param ids
348 | * Set of local notification IDs
349 | */
350 | private void clear(JSONArray ids){
351 | for (int i = 0; i < ids.length(); i++) {
352 | int id = ids.optInt(i, 0);
353 |
354 | Notification notification =
355 | getNotificationMgr().clear(id);
356 |
357 | if (notification == null)
358 | continue;
359 |
360 | fireEvent("clear", notification);
361 | }
362 | }
363 |
364 | /**
365 | * Clear all triggered notifications without canceling them.
366 | */
367 | private void clearAll() {
368 | getNotificationMgr().clearAll();
369 | fireEvent("clearall");
370 | }
371 |
372 | /**
373 | * If a notification with an ID is present.
374 | *
375 | * @param id
376 | * Notification ID
377 | * @param command
378 | * The callback context used when calling back into JavaScript.
379 | */
380 | private void isPresent (int id, CallbackContext command) {
381 | boolean exist = getNotificationMgr().exist(id);
382 |
383 | PluginResult result = new PluginResult(
384 | PluginResult.Status.OK, exist);
385 |
386 | command.sendPluginResult(result);
387 | }
388 |
389 | /**
390 | * If a notification with an ID is scheduled.
391 | *
392 | * @param id
393 | * Notification ID
394 | * @param command
395 | * The callback context used when calling back into JavaScript.
396 | */
397 | private void isScheduled (int id, CallbackContext command) {
398 | boolean exist = getNotificationMgr().exist(
399 | id, Notification.Type.SCHEDULED);
400 |
401 | PluginResult result = new PluginResult(
402 | PluginResult.Status.OK, exist);
403 |
404 | command.sendPluginResult(result);
405 | }
406 |
407 | /**
408 | * If a notification with an ID is triggered.
409 | *
410 | * @param id
411 | * Notification ID
412 | * @param command
413 | * The callback context used when calling back into JavaScript.
414 | */
415 | private void isTriggered (int id, CallbackContext command) {
416 | boolean exist = getNotificationMgr().exist(
417 | id, Notification.Type.TRIGGERED);
418 |
419 | PluginResult result = new PluginResult(
420 | PluginResult.Status.OK, exist);
421 |
422 | command.sendPluginResult(result);
423 | }
424 |
425 | /**
426 | * Set of IDs from all existent notifications.
427 | *
428 | * @param command
429 | * The callback context used when calling back into JavaScript.
430 | */
431 | private void getAllIds (CallbackContext command) {
432 | List ids = getNotificationMgr().getIds();
433 |
434 | command.success(new JSONArray(ids));
435 | }
436 |
437 | /**
438 | * Set of IDs from all scheduled notifications.
439 | *
440 | * @param command
441 | * The callback context used when calling back into JavaScript.
442 | */
443 | private void getScheduledIds (CallbackContext command) {
444 | List ids = getNotificationMgr().getIdsByType(
445 | Notification.Type.SCHEDULED);
446 |
447 | command.success(new JSONArray(ids));
448 | }
449 |
450 | /**
451 | * Set of IDs from all triggered notifications.
452 | *
453 | * @param command
454 | * The callback context used when calling back into JavaScript.
455 | */
456 | private void getTriggeredIds (CallbackContext command) {
457 | List ids = getNotificationMgr().getIdsByType(
458 | Notification.Type.TRIGGERED);
459 |
460 | command.success(new JSONArray(ids));
461 | }
462 |
463 | /**
464 | * Options from local notification.
465 | *
466 | * @param ids
467 | * Set of local notification IDs
468 | * @param command
469 | * The callback context used when calling back into JavaScript.
470 | */
471 | private void getSingle (JSONArray ids, CallbackContext command) {
472 | getOptions(ids.optString(0), Notification.Type.ALL, command);
473 | }
474 |
475 | /**
476 | * Options from scheduled notification.
477 | *
478 | * @param ids
479 | * Set of local notification IDs
480 | * @param command
481 | * The callback context used when calling back into JavaScript.
482 | */
483 | private void getSingleScheduled (JSONArray ids, CallbackContext command) {
484 | getOptions(ids.optString(0), Notification.Type.SCHEDULED, command);
485 | }
486 |
487 | /**
488 | * Options from triggered notification.
489 | *
490 | * @param ids
491 | * Set of local notification IDs
492 | * @param command
493 | * The callback context used when calling back into JavaScript.
494 | */
495 | private void getSingleTriggered (JSONArray ids, CallbackContext command) {
496 | getOptions(ids.optString(0), Notification.Type.TRIGGERED, command);
497 | }
498 |
499 | /**
500 | * Set of options from local notification.
501 | *
502 | * @param ids
503 | * Set of local notification IDs
504 | * @param command
505 | * The callback context used when calling back into JavaScript.
506 | */
507 | private void getAll (JSONArray ids, CallbackContext command) {
508 | getOptions(ids, Notification.Type.ALL, command);
509 | }
510 |
511 | /**
512 | * Set of options from scheduled notifications.
513 | *
514 | * @param ids
515 | * Set of local notification IDs
516 | * @param command
517 | * The callback context used when calling back into JavaScript.
518 | */
519 | private void getScheduled (JSONArray ids, CallbackContext command) {
520 | getOptions(ids, Notification.Type.SCHEDULED, command);
521 | }
522 |
523 | /**
524 | * Set of options from triggered notifications.
525 | *
526 | * @param ids
527 | * Set of local notification IDs
528 | * @param command
529 | * The callback context used when calling back into JavaScript.
530 | */
531 | private void getTriggered (JSONArray ids, CallbackContext command) {
532 | getOptions(ids, Notification.Type.TRIGGERED, command);
533 | }
534 |
535 | /**
536 | * Options from local notification.
537 | *
538 | * @param id
539 | * Set of local notification IDs
540 | * @param type
541 | * The local notification life cycle type
542 | * @param command
543 | * The callback context used when calling back into JavaScript.
544 | */
545 | private void getOptions (String id, Notification.Type type,
546 | CallbackContext command) {
547 |
548 | JSONArray ids = new JSONArray().put(id);
549 | PluginResult result;
550 |
551 | List options =
552 | getNotificationMgr().getOptionsBy(type, toList(ids));
553 |
554 | if (options.isEmpty()) {
555 | // Status.NO_RESULT led to no callback invocation :(
556 | // Status.OK led to no NPE and crash
557 | result = new PluginResult(PluginResult.Status.NO_RESULT);
558 | } else {
559 | result = new PluginResult(PluginResult.Status.OK, options.get(0));
560 | }
561 |
562 | command.sendPluginResult(result);
563 | }
564 |
565 | /**
566 | * Set of options from local notifications.
567 | *
568 | * @param ids
569 | * Set of local notification IDs
570 | * @param type
571 | * The local notification life cycle type
572 | * @param command
573 | * The callback context used when calling back into JavaScript.
574 | */
575 | private void getOptions (JSONArray ids, Notification.Type type,
576 | CallbackContext command) {
577 |
578 | List options;
579 |
580 | if (ids.length() == 0) {
581 | options = getNotificationMgr().getOptionsByType(type);
582 | } else {
583 | options = getNotificationMgr().getOptionsBy(type, toList(ids));
584 | }
585 |
586 | command.success(new JSONArray(options));
587 | }
588 |
589 | /**
590 | * Call all pending callbacks after the deviceready event has been fired.
591 | */
592 | private static synchronized void deviceready () {
593 | isInBackground = false;
594 | deviceready = true;
595 |
596 | for (Map.Entry entry : eventQueue.entrySet()) {
597 | sendJavascript(entry.getKey(), entry.getValue());
598 | }
599 |
600 | eventQueue.clear();
601 | }
602 |
603 | /**
604 | * Fire given event on JS side. Does inform all event listeners.
605 | *
606 | * @param event
607 | * The event name
608 | */
609 | private void fireEvent (String event) {
610 | fireEvent(event, null);
611 | }
612 |
613 | /**
614 | * Fire given event on JS side. Does inform all event listeners.
615 | *
616 | * @param event
617 | * The event name
618 | * @param notification
619 | * Optional local notification to pass the id and properties.
620 | */
621 | static void fireEvent (String event, Notification notification) {
622 | String state = getApplicationState();
623 | String params = "\"" + state + "\"";
624 |
625 | if (notification != null) {
626 | params = notification.toString() + "," + params;
627 | }
628 |
629 | sendJavascript(event, params);
630 | }
631 |
632 | /**
633 | * Use this instead of deprecated sendJavascript
634 | *
635 | * @param event,params
636 | * JS code snippet as string
637 | */
638 | private static synchronized void sendJavascript(final String event, final String params) {
639 |
640 | if (!deviceready) {
641 | eventQueue.put(event, params);
642 | return;
643 | }
644 | self.getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("RCT-LOCAL-NOTIFICATION-"+event, params);
645 | }
646 |
647 | /**
648 | * Convert JSON array of integers to List.
649 | *
650 | * @param ary
651 | * Array of integers
652 | */
653 | private List toList (JSONArray ary) {
654 | ArrayList list = new ArrayList();
655 |
656 | for (int i = 0; i < ary.length(); i++) {
657 | list.add(ary.optInt(i));
658 | }
659 |
660 | return list;
661 | }
662 |
663 | /**
664 | * Current application state.
665 | *
666 | * @return
667 | * "background" or "foreground"
668 | */
669 | static String getApplicationState () {
670 | return isInBackground ? "background" : "foreground";
671 | }
672 |
673 | /**
674 | * Notification manager instance.
675 | */
676 | private Manager getNotificationMgr() {
677 | return Manager.getInstance(cordova.getActivity());
678 | }
679 | }
680 |
--------------------------------------------------------------------------------