diff --git a/.gitignore b/.gitignore
index 7233a1c..39359e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,7 @@ build/
local.properties
*.iml
*.hprof
+google-services.json
# Own
#
diff --git a/NOTIFICATIONS.md b/NOTIFICATIONS.md
new file mode 100644
index 0000000..90507e0
--- /dev/null
+++ b/NOTIFICATIONS.md
@@ -0,0 +1,5 @@
+## 🎛 Notifications
+
+Detailed guide will be published soon...
+
+Meanwhile, you can check this [tutorial](https://dev.to/jakubkoci/react-native-push-notifications-313i) which helped me to set up and test notifications.
\ No newline at end of file
diff --git a/README.md b/README.md
index e4a8629..ef55e36 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ yarn ios
yarn android
```
-👁🗨 If you are planning to use Expo modules, such as preconfigured `expo-updates` and others, or add new ones, what I strongly recommend, then proceed to [Expo Configuration](/EXPO_CONFIGURATION.md) and follow the steps carefully.
+👁🗨 If you are planning to use Expo modules, such as preconfigured `expo-updates` and others, or add new ones, what I strongly recommend, then proceed to [Expo Configuration](/EXPO_CONFIGURATION.md) and follow the steps.
🟢 If you would like to rename the app, you can use [react-native-rename-next](https://github.com/mayconmesquita/react-native-rename-next). Don't forget to run `yarn ios:pods` after the process is finished. Also keep in mind that bundle identifier must be valid for both platforms or change it manually.
@@ -52,28 +52,31 @@ yarn android
- [Reanimated 2](https://github.com/software-mansion/react-native-reanimated) - React Native's Animated library reimplemented
- [MobX](https://github.com/mobxjs/mobx) - simple, scalable state management, with [mobx-persist](https://github.com/pinqy520/mobx-persist) for persisting your stores
### Extra helpful libraries
-- [React Native Navigation Hooks](https://github.com/underscopeio/react-native-navigation-hooks) - a set of React hooks for React Native Navigation
+- [React Native Notifications](https://github.com/wix/react-native-notifications) - a library that takes care of handling notifications
+- [React Native Navigation Hooks](https://github.com/underscopeio/react-native-navigation-hooks) - a set of hooks for React Native Navigation
- [React Native Vector Icons](https://github.com/oblador/react-native-vector-icons) - customizable icons for React Native. Even though Expo SDK includes `expo-icons` which you can still use, but the reason of adding `react-native-vector-icons` is to get icons as sources before launching tab based app
- [React Native Gesture Handler](https://github.com/kmagiera/react-native-gesture-handler) - native touches and gesture system for React Native
- [React Native Defice Info](https://github.com/react-native-community/react-native-device-info) - device information for React Native iOS and Android
- [Hermes Engine](https://reactnative.dev/docs/hermes) - a JavaScript engine optimized for running React Native apps on Android.
- [Typescript](https://www.typescriptlang.org/) - strict syntactical superset of JavaScript
-### Small useful libraries/hooks from me
+### Small useful services/hooks from me
- `useStyles()` - a hook that takes care of dark mode in your app. Supports toggling modes while you are in app. No dependencies (needs only `react-native`, so could be reusable).
- `appUpdates` - a service that shows and simplifies integration with `expo-updates`. In order to use it, you will need to change `Expo.plist` and `AndroidManifest.xml` with your actual information. More information about [expo-updates](https://docs.expo.io/versions/latest/sdk/updates/).
- `translate` - a service that shows and simplifies integration with `expo-localization` and `i18n-js`. You can see an example of `en`, `ru` and `de` localizations in `ExpoScreen`.
+- `notifications` - a service that takes care of setting up notifications which utilizes [React Native Notifications](https://github.com/wix/react-native-notifications). For more information, please, take a look at this [guide](/NOTIFICATIONS.md).
## Enhancements
There are still some things I would like to add to the starter:
- 🔳 Dark Mode support.
- 🔳 Localization via [expo-localization](https://docs.expo.io/versions/latest/sdk/localization) and [i18n-js](https://github.com/fnando/i18n-js).
-- ⬜️ Notifications (remote).
+- 🔳 Notifications (remote) using [React Native Notifications](https://github.com/wix/react-native-notifications).
Feel free to open an issue for suggestions.
## Known issues (warnings)
- Expo splash screen. There is some weird behavior using `expo-splash-screen` with `react-native-navigation`. That is why this module has been excluded: [ios](https://github.com/kanzitelli/expo-rnn-starter/blob/master/ios/Podfile#L8) & [android](https://github.com/kanzitelli/expo-rnn-starter/blob/master/android/app/build.gradle#L196).
- Dark Mode in Android. React Native Navigation doesn't toggle navigation and tab bars' background color to dark when dark mode is toggled on. However it does so on iOS. As a workaround, we can subscribe to toggle events and then using `Navigation.mergeOptions` & `Navigation.setDefaultOptions` to change stylings for navigations and tab bars. Anyways, it needs some time to dive into it and come up with better solution. Current progress could be found [here](https://github.com/kanzitelli/expo-rnn-starter/tree/android-dark-mode).
+- Notifications received in background for iOS and Android. There is an issue with getting a callback triggered for notifications received while the app in background. For more information, please, check this [issue](https://github.com/wix/react-native-notifications/issues/670).
Feel free to open an issue for any other warning or problems.
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 2943c92..18a2a9a 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -216,6 +216,9 @@ dependencies {
} else {
implementation jscFlavor
}
+
+ implementation project(':react-native-notifications')
+ implementation 'com.google.firebase:firebase-core:16.0.0'
}
// Run this once to be able to run the application with BUCK
@@ -226,4 +229,5 @@ task copyDownloadableDepsToLibs(type: Copy) {
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
-apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
\ No newline at end of file
+apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
+apply plugin: 'com.google.gms.google-services'
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 43e5ad7..186f86a 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -26,6 +26,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable-hdpi/notification_icon.png b/android/app/src/main/res/drawable-hdpi/notification_icon.png
new file mode 100644
index 0000000..715a891
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/notification_icon.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/notification_icon.png b/android/app/src/main/res/drawable-mdpi/notification_icon.png
new file mode 100644
index 0000000..73850fc
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/notification_icon.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/notification_icon.png b/android/app/src/main/res/drawable-xhdpi/notification_icon.png
new file mode 100644
index 0000000..cf12ca4
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/notification_icon.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/notification_icon.png b/android/app/src/main/res/drawable-xxhdpi/notification_icon.png
new file mode 100644
index 0000000..ef0e23c
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/notification_icon.png differ
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..d33d01b
--- /dev/null
+++ b/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+
+
+ #4D7198
+
\ No newline at end of file
diff --git a/android/build.gradle b/android/build.gradle
index acf9299..132bbe5 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -17,6 +17,7 @@ buildscript {
classpath('com.android.tools.build:gradle:4.0.0')
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
+ classpath 'com.google.gms:google-services:4.3.4'
}
}
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 2360dd1..63e3f83 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -225,6 +225,8 @@ PODS:
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsinspector (0.63.4)
+ - react-native-notifications (3.4.1):
+ - React-Core
- React-RCTActionSheet (0.63.4):
- React-Core/RCTActionSheetHeaders (= 0.63.4)
- React-RCTAnimation (0.63.4):
@@ -383,6 +385,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
+ - react-native-notifications (from `../node_modules/react-native-notifications`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
- React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
@@ -479,6 +482,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
+ react-native-notifications:
+ :path: "../node_modules/react-native-notifications"
React-RCTActionSheet:
:path: "../node_modules/react-native/Libraries/ActionSheetIOS"
React-RCTAnimation:
@@ -572,6 +577,7 @@ SPEC CHECKSUMS:
React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31
React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
+ react-native-notifications: 77c7c863273e79caaa2523f239e714b033995262
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0
diff --git a/ios/rnn_starter.xcodeproj/project.pbxproj b/ios/rnn_starter.xcodeproj/project.pbxproj
index 0b9c638..d7c586f 100644
--- a/ios/rnn_starter.xcodeproj/project.pbxproj
+++ b/ios/rnn_starter.xcodeproj/project.pbxproj
@@ -745,7 +745,7 @@
"-ObjC",
"-lc++",
);
- PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+ PRODUCT_BUNDLE_IDENTIFIER = "io.batyr.expo-rnn-starter";
PRODUCT_NAME = rnn_starter;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -771,7 +771,7 @@
"-ObjC",
"-lc++",
);
- PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+ PRODUCT_BUNDLE_IDENTIFIER = "io.batyr.expo-rnn-starter";
PRODUCT_NAME = rnn_starter;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
diff --git a/ios/rnn_starter/AppDelegate.m b/ios/rnn_starter/AppDelegate.m
index 59eafaa..5f4a609 100644
--- a/ios/rnn_starter/AppDelegate.m
+++ b/ios/rnn_starter/AppDelegate.m
@@ -8,6 +8,8 @@
#import
#import
+#import "RNNotifications.h"
+
#ifdef FB_SONARKIT_ENABLED
#import
#import
@@ -42,6 +44,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
InitializeFlipper(application);
#endif
+ [RNNotifications startMonitorNotifications];
+
self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]];
self.launchOptions = launchOptions;
@@ -89,4 +93,14 @@ - (void)appController:(EXUpdatesAppController *)appController didStartWithSucces
appController.bridge = [self initializeReactNativeApp];
}
+-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
+{
+ [RNNotifications didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
+}
+
+- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
+{
+ [RNNotifications didFailToRegisterForRemoteNotificationsWithError:error];
+}
+
@end
diff --git a/package.json b/package.json
index f5a3b29..9c31f2d 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"react-native-gesture-handler": "^1.9.0",
"react-native-navigation": "^7.6.0",
"react-native-navigation-hooks": "^6.2.0",
+ "react-native-notifications": "^3.4.1",
"react-native-reanimated": "2.0.0-rc.0",
"react-native-unimodules": "^0.12.0",
"react-native-vector-icons": "^7.1.0"
diff --git a/src/services/index.tsx b/src/services/index.tsx
index c75a68a..108bce4 100644
--- a/src/services/index.tsx
+++ b/src/services/index.tsx
@@ -3,11 +3,13 @@ import React from 'react';
import NavigationService from './navigation';
import AppUpdatesService from './appUpdates';
import TranslateService from './translate';
+import NotificationsService from './notifications';
export const services = {
navigation: NavigationService,
appUpdates: AppUpdatesService,
t: TranslateService,
+ notifications: NotificationsService,
};
const servicesContext = React.createContext(services);
diff --git a/src/services/notifications.ts b/src/services/notifications.ts
new file mode 100644
index 0000000..e05fa1d
--- /dev/null
+++ b/src/services/notifications.ts
@@ -0,0 +1,55 @@
+import { NotificationBackgroundFetchResult, Notifications as RNNotifications } from 'react-native-notifications';
+
+class NotificationsService implements IService {
+ init = async () => {
+ // this.registerReactNativeNotifications();
+ }
+
+ private registerReactNativeNotifications() {
+ this.registerDevice()
+ this.registerNotificationEvents()
+ }
+
+ private registerDevice() {
+ RNNotifications.events().registerRemoteNotificationsRegistered(event => {
+ // TODO: Send the token to my server so it could send back push notifications...
+ console.log('[RNNotification] Device Token Received', event.deviceToken)
+ })
+ RNNotifications.events().registerRemoteNotificationsRegistrationFailed(event => {
+ console.error(event)
+ })
+
+ RNNotifications.registerRemoteNotifications()
+ }
+
+ private registerNotificationEvents() {
+ RNNotifications.events().registerNotificationReceivedForeground((notification, completion) => {
+ console.log('[RNNotification] Notification Received - Foreground', notification)
+
+ // Calling completion on iOS with `alert: true` will present the native iOS inApp notification.
+ completion({ alert: false, sound: false, badge: false })
+ })
+
+ RNNotifications.events().registerNotificationOpened((notification, completion) => {
+ console.log('[RNNotification] Notification opened by device user', notification)
+ console.log(`[RNNotification] Notification opened with an action identifier: ${notification.identifier}`)
+ completion()
+ })
+
+ // doesn't work for some reason
+ RNNotifications.events().registerNotificationReceivedBackground((notification, completion) => {
+ console.log('[RNNotification] Notification Received - Background', notification)
+
+ // Calling completion on iOS with `alert: true` will present the native iOS inApp notification.
+ completion(NotificationBackgroundFetchResult.NEW_DATA);
+ })
+
+ RNNotifications.getInitialNotification()
+ .then(notification => {
+ console.log('[RNNotification] Initial notification was:', notification || 'N/A')
+ })
+ .catch(err => console.error('[RNNotification] getInitialNotifiation() failed', err))
+ }
+}
+
+export default new NotificationsService();
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 0c7f348..5efca5f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7966,6 +7966,11 @@ react-native-navigation@^7.6.0:
react-lifecycles-compat "2.0.0"
tslib "1.9.3"
+react-native-notifications@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/react-native-notifications/-/react-native-notifications-3.4.1.tgz#3046bae51863e1073d71820598f0b85a3b389535"
+ integrity sha512-jJHo5z5XR0smZIVj4yjoqDWZ3HX26TL8FMsUIBiIy1Hh9b0q/HAl1xN651sTW/HM49+Mr2F+ShSf6nXBnGB4fQ==
+
react-native-reanimated@2.0.0-rc.0:
version "2.0.0-rc.0"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.0.0-rc.0.tgz#7a1b0bfd48e3de9dfa985a524463b6a216531358"