diff --git a/Examples/simple-fcm-client/android/app/build.gradle b/Examples/simple-fcm-client/android/app/build.gradle
index f1ca431b9de224901e27d46a047123de1b174599..8bc520d7db3692870c109b03a5525deedb6b0fed 100644
--- a/Examples/simple-fcm-client/android/app/build.gradle
+++ b/Examples/simple-fcm-client/android/app/build.gradle
@@ -131,6 +131,9 @@ android {
}
dependencies {
+ compile(project(':react-native-maps')) {
+ exclude group: 'com.google.android.gms', module: 'play-services-base'
+ }
compile project(':react-native-fcm')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:26.1.0"
diff --git a/Examples/simple-fcm-client/android/app/src/main/AndroidManifest.xml b/Examples/simple-fcm-client/android/app/src/main/AndroidManifest.xml
index a0aba2877e579add45e89a746d888fbc3fe2d924..869cb8fefd4c80722074ea7936798c78034b9cd6 100644
--- a/Examples/simple-fcm-client/android/app/src/main/AndroidManifest.xml
+++ b/Examples/simple-fcm-client/android/app/src/main/AndroidManifest.xml
@@ -7,6 +7,7 @@
+
getPackages() {
return Arrays.asList(
new MainReactPackage(),
+ new MapsPackage(),
new FIRMessagingPackage()
);
}
diff --git a/Examples/simple-fcm-client/android/settings.gradle b/Examples/simple-fcm-client/android/settings.gradle
index d75953b2ce301dc0e1eeee99427c6f34c1a60141..a8ad2f34040e848c6547cf6c982601d43f31c66d 100644
--- a/Examples/simple-fcm-client/android/settings.gradle
+++ b/Examples/simple-fcm-client/android/settings.gradle
@@ -1,4 +1,6 @@
rootProject.name = 'SimpleFcmClient'
+include ':react-native-maps'
+project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android')
include ':app'
include ':react-native-fcm'
diff --git a/Examples/simple-fcm-client/app/App.js b/Examples/simple-fcm-client/app/App.js
index 9f9f38243ba49e52988cb568847be180d8f5df64..55d60a7dc6dc36afcbc092d68d58c351ff3f4f82 100644
--- a/Examples/simple-fcm-client/app/App.js
+++ b/Examples/simple-fcm-client/app/App.js
@@ -11,17 +11,20 @@ import {
TouchableOpacity,
View,
Clipboard,
- Platform
+ Platform,
+ ScrollView
} from 'react-native';
-import FCM from "react-native-fcm";
+import { StackNavigator } from 'react-navigation';
+
+import FCM, {NotificationActionType} from "react-native-fcm";
import {registerKilledListener, registerAppListener} from "./Listeners";
import firebaseClient from "./FirebaseClient";
registerKilledListener();
-export default class App extends Component {
+class MainPage extends Component {
constructor(props) {
super(props);
@@ -38,11 +41,16 @@ export default class App extends Component {
description: 'used for example',
priority: 'high'
})
- registerAppListener();
+ registerAppListener(this.props.navigation);
FCM.getInitialNotification().then(notif => {
this.setState({
initNotif: notif
})
+ if(notif && notif.targetScreen === 'detail'){
+ setTimeout(()=>{
+ this.props.navigation.navigate('Detail')
+ }, 500)
+ }
});
try{
@@ -65,16 +73,30 @@ export default class App extends Component {
showLocalNotification() {
FCM.presentLocalNotification({
- vibrate: 500,
- title: 'Hello',
channel: 'default',
- body: 'Test Notification',
- big_text: 'i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large',
- priority: "high",
- sound: "bell.mp3",
- large_icon: "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg",
- show_in_foreground: true,
- number: 10
+ id: new Date().valueOf().toString(), // (optional for instant notification)
+ title: "Test Notification with action", // as FCM payload
+ body: "Force touch to reply", // as FCM payload (required)
+ sound: "bell.mp3", // "default" or filename
+ priority: "high", // as FCM payload
+ click_action: "com.myapp.MyCategory", // as FCM payload - this is used as category identifier on iOS.
+ badge: 10, // as FCM payload IOS only, set 0 to clear badges
+ number: 10, // Android only
+ ticker: "My Notification Ticker", // Android only
+ auto_cancel: true, // Android only (default true)
+ large_icon: "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg", // Android only
+ icon: "ic_launcher", // as FCM payload, you can relace this with custom icon you put in mipmap
+ big_text: "Show when notification is expanded", // Android only
+ sub_text: "This is a subText", // Android only
+ color: "red", // Android only
+ vibrate: 300, // Android only default: 300, no vibration if you pass 0
+ wake_screen: true, // Android only, wake up screen when notification arrives
+ group: "group", // Android only
+ picture: "https://google.png", // Android only bigPicture style
+ ongoing: true, // Android only
+ my_custom_data:'my_custom_field_value', // extra data you want to throw
+ lights: true, // Android only, LED blinking (default false)
+ show_in_foreground: true // notification when app is in foreground (local & remote)
});
}
@@ -89,7 +111,10 @@ export default class App extends Component {
priority: "high",
large_icon: "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg",
show_in_foreground: true,
- picture: 'https://firebase.google.com/_static/af7ae4b3fc/images/firebase/lockup.png'
+ picture: 'https://firebase.google.com/_static/af7ae4b3fc/images/firebase/lockup.png',
+ wake_screen: true,
+ extra1: {a: 1},
+ extra2: 1
});
}
@@ -102,10 +127,11 @@ export default class App extends Component {
"data":{
"custom_notification": {
"title": "Simple FCM Client",
- "body": "This is a notification with only NOTIFICATION.",
+ "body": "Click me to go to detail",
"sound": "default",
"priority": "high",
- "show_in_foreground": true
+ "show_in_foreground": true,
+ targetScreen: 'detail'
}
},
"priority": 10
@@ -115,9 +141,12 @@ export default class App extends Component {
"to": token,
"notification":{
"title": "Simple FCM Client",
- "body": "This is a notification with only NOTIFICATION.",
+ "body": "Click me to go to detail",
"sound": "default"
- },
+ },
+ data: {
+ targetScreen: 'detail'
+ },
"priority": 10
}
}
@@ -139,21 +168,21 @@ export default class App extends Component {
firebaseClient.send(JSON.stringify(body), "data");
}
- sendRemoteNotificationWithData(token) {
- let body = {
- "to": token,
- "notification":{
- "title": "Simple FCM Client",
- "body": "This is a notification with NOTIFICATION and DATA (NOTIF).",
- "sound": "default"
- },
- "data":{
- "hello": "there"
- },
- "priority": "high"
- }
-
- firebaseClient.send(JSON.stringify(body), "notification-data");
+ showLocalNotificationWithAction() {
+ FCM.presentLocalNotification({
+ title: 'Test Notification with action',
+ body: 'Force touch to reply',
+ priority: "high",
+ show_in_foreground: true,
+ click_action: "com.myidentifi.fcm.text", // for ios
+ android_actions: JSON.stringify([{
+ id: "view",
+ title: 'view'
+ },{
+ id: "dismiss",
+ title: 'dismiss'
+ }]) // for android, take syntax similar to ios's. only buttons are supported
+ });
}
render() {
@@ -161,19 +190,11 @@ export default class App extends Component {
return (
+
Welcome to Simple Fcm Client!
-
- Init notif: {JSON.stringify(this.state.initNotif)}
-
-
-
- this.setClipboardContent(this.state.token)} style={styles.instructions}>
- Token: {this.state.token}
-
-
{this.state.tokenCopyFeedback}
@@ -190,17 +211,32 @@ export default class App extends Component {
Send Remote Data
- this.sendRemoteNotificationWithData(token)} style={styles.button}>
- Send Remote Notification With Data
+ this.showLocalNotification()} style={styles.button}>
+ Show Local Notification
- this.showLocalNotification()} style={styles.button}>
- Send Local Notification
+ this.showLocalNotificationWithAction(token)} style={styles.button}>
+ Show Local Notification with Action
this.scheduleLocalNotification()} style={styles.button}>
Schedule Notification in 5s
+
+
+ Init notif:
+
+
+ {JSON.stringify(this.state.initNotif)}
+
+
+
+ Token:
+
+ this.setClipboardContent(this.state.token)}>
+ {this.state.token}
+
+
);
}
@@ -216,6 +252,25 @@ export default class App extends Component {
}
}
+class DetailPage extends Component {
+ render(){
+ return
+ Detail page
+
+ }
+}
+
+export default StackNavigator({
+ Main: {
+ screen: MainPage,
+ },
+ Detail: {
+ screen: DetailPage
+ }
+}, {
+ initialRouteName: 'Main',
+});
+
const styles = StyleSheet.create({
container: {
flex: 1,
@@ -241,8 +296,8 @@ const styles = StyleSheet.create({
button: {
backgroundColor: "teal",
paddingHorizontal: 20,
- paddingVertical: 10,
- marginVertical: 15,
+ paddingVertical: 15,
+ marginVertical: 10,
borderRadius: 10
},
buttonText: {
diff --git a/Examples/simple-fcm-client/app/Listeners.js b/Examples/simple-fcm-client/app/Listeners.js
index 0144e1f55ee357d441663b83e0c47f69ecf3300c..942e9f269ffb9a441d90ccf2e6a9cf60adb8c62c 100644
--- a/Examples/simple-fcm-client/app/Listeners.js
+++ b/Examples/simple-fcm-client/app/Listeners.js
@@ -1,6 +1,6 @@
-import { Platform, AsyncStorage } from 'react-native';
+import { Platform, AsyncStorage, AppState } from 'react-native';
-import FCM, {FCMEvent, RemoteNotificationResult, WillPresentNotificationResult, NotificationType} from "react-native-fcm";
+import FCM, {FCMEvent, RemoteNotificationResult, WillPresentNotificationResult, NotificationType, NotificationActionType, NotificationActionOption, NotificationCategoryOption} from "react-native-fcm";
AsyncStorage.getItem('lastNotification').then(data=>{
if(data){
@@ -10,22 +10,60 @@ AsyncStorage.getItem('lastNotification').then(data=>{
}
})
+AsyncStorage.getItem('lastMessage').then(data=>{
+ if(data){
+ // if notification arrives when app is killed, it should still be logged here
+ console.log('last message', JSON.parse(data));
+ AsyncStorage.removeItem('lastMessage');
+ }
+})
+
export function registerKilledListener(){
// these callback will be triggered even when app is killed
FCM.on(FCMEvent.Notification, notif => {
AsyncStorage.setItem('lastNotification', JSON.stringify(notif));
+ if(notif.opened_from_tray){
+ setTimeout(()=>{
+ if(notif._actionIdentifier === 'reply'){
+ if(AppState.currentState !== 'background'){
+ console.log('User replied '+ JSON.stringify(notif._userText))
+ alert('User replied '+ JSON.stringify(notif._userText));
+ } else {
+ AsyncStorage.setItem('lastMessage', JSON.stringify(notif._userText));
+ }
+ }
+ if(notif._actionIdentifier === 'view'){
+ alert("User clicked View in App");
+ }
+ if(notif._actionIdentifier === 'dismiss'){
+ alert("User clicked Dismiss");
+ }
+ }, 1000)
+ }
});
}
// these callback will be triggered only when app is foreground or background
-export function registerAppListener(){
+export function registerAppListener(navigation){
FCM.on(FCMEvent.Notification, notif => {
console.log("Notification", notif);
- if(notif.local_notification){
+
+ if(Platform.OS ==='ios' && notif._notificationType === NotificationType.WillPresent && !notif.local_notification){
+ // this notification is only to decide if you want to show the notification when user if in forground.
+ // usually you can ignore it. just decide to show or not.
+ notif.finish(WillPresentNotificationResult.All)
return;
}
+
if(notif.opened_from_tray){
- return;
+ if(notif.targetScreen === 'detail'){
+ setTimeout(()=>{
+ navigation.navigate('Detail')
+ }, 500)
+ }
+ setTimeout(()=>{
+ alert(`User tapped notification\n${JSON.stringify(notif)}`)
+ }, 500)
}
if(Platform.OS ==='ios'){
@@ -42,6 +80,8 @@ export function registerAppListener(){
break;
case NotificationType.WillPresent:
notif.finish(WillPresentNotificationResult.All) //other types available: WillPresentNotificationResult.None
+ // this type of notificaiton will be called only when you are in foreground.
+ // if it is a remote notification, don't do any app logic here. Another notification callback will be triggered with type NotificationType.Remote
break;
}
}
@@ -49,7 +89,6 @@ export function registerAppListener(){
FCM.on(FCMEvent.RefreshToken, token => {
console.log("TOKEN (refreshUnsubscribe)", token);
- this.props.onChangeToken(token);
});
FCM.enableDirectChannel();
@@ -60,3 +99,35 @@ export function registerAppListener(){
FCM.isDirectChannelEstablished().then(d => console.log(d));
}, 1000);
}
+
+FCM.setNotificationCategories([
+ {
+ id: 'com.myidentifi.fcm.text',
+ actions: [
+ {
+ type: NotificationActionType.TextInput,
+ id: 'reply',
+ title: 'Quick Reply',
+ textInputButtonTitle: 'Send',
+ textInputPlaceholder: 'Say something',
+ intentIdentifiers: [],
+ options: NotificationActionOption.AuthenticationRequired
+ },
+ {
+ type: NotificationActionType.Default,
+ id: 'view',
+ title: 'View in App',
+ intentIdentifiers: [],
+ options: NotificationActionOption.Foreground
+ },
+ {
+ type: NotificationActionType.Default,
+ id: 'dismiss',
+ title: 'Dismiss',
+ intentIdentifiers: [],
+ options: NotificationActionOption.Destructive
+ }
+ ],
+ options: [NotificationCategoryOption.CustomDismissAction, NotificationCategoryOption.PreviewsShowTitle]
+ }
+])
diff --git a/Examples/simple-fcm-client/ios/Podfile.lock b/Examples/simple-fcm-client/ios/Podfile.lock
index 5e427a7309e3434a3284c5a644de958204b5ab22..32fd9c5bbc5429d570d632415930c3904a0bfd9f 100644
--- a/Examples/simple-fcm-client/ios/Podfile.lock
+++ b/Examples/simple-fcm-client/ios/Podfile.lock
@@ -1,19 +1,20 @@
PODS:
- - Firebase/Core (4.7.0):
- - FirebaseAnalytics (= 4.0.5)
- - FirebaseCore (= 4.0.12)
- - Firebase/Messaging (4.7.0):
+ - Firebase/Core (4.9.0):
+ - FirebaseAnalytics (= 4.0.9)
+ - FirebaseCore (= 4.0.15)
+ - Firebase/Messaging (4.9.0):
- Firebase/Core
- - FirebaseMessaging (= 2.0.7)
- - FirebaseAnalytics (4.0.5):
+ - FirebaseMessaging (= 2.1.0)
+ - FirebaseAnalytics (4.0.9):
- FirebaseCore (~> 4.0)
- FirebaseInstanceID (~> 2.0)
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- nanopb (~> 0.3)
- - FirebaseCore (4.0.12):
+ - FirebaseCore (4.0.15):
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- - FirebaseInstanceID (2.0.7)
- - FirebaseMessaging (2.0.7):
+ - FirebaseInstanceID (2.0.9):
+ - FirebaseCore (~> 4.0)
+ - FirebaseMessaging (2.1.0):
- FirebaseAnalytics (~> 4.0)
- FirebaseCore (~> 4.0)
- FirebaseInstanceID (~> 2.0)
@@ -35,15 +36,15 @@ DEPENDENCIES:
- Firebase/Messaging
SPEC CHECKSUMS:
- Firebase: dbfb98ccec2dcfcd21ab9cc1b4981a3f3c8c5e26
- FirebaseAnalytics: 5b02a63ead2c3f0259cfc7f15e053e440587ecf8
- FirebaseCore: 6cf108b63997bc08c04a1ffa55a3ac0d71a59ffc
- FirebaseInstanceID: 148c25c986c8699e67304b114e365713dce467f2
- FirebaseMessaging: 1a11d1c0a9ed9b3f75a0685bb0ae5932e1062f5f
+ Firebase: 632216af3ed7f31e3be34776947fdc7546cfb572
+ FirebaseAnalytics: 388b630c15713f5dbf364071f5f3d6077fb52f4e
+ FirebaseCore: 3bd047463058fa6b5d312c97502c52e45401cdfb
+ FirebaseInstanceID: d2058a35e9bebda1b6dd42486b84917bde552a9d
+ FirebaseMessaging: 2bafab2d0f3ab3dfd753101c2c32995c2051b5da
GoogleToolboxForMac: 2501e2ad72a52eb3dfe7bd9aee7dad11b858bd20
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03
PODFILE CHECKSUM: 31f07bb14b00eef65c77cff51721f530ad6eb826
-COCOAPODS: 1.2.1
+COCOAPODS: 1.4.0
diff --git a/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/project.pbxproj b/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/project.pbxproj
index 98b9dab434a31be0bbc44d4492e6767b2e5f2bfd..27945b50738bc766cfe7b72833d4e6c7d69223fb 100644
--- a/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/project.pbxproj
+++ b/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/project.pbxproj
@@ -23,11 +23,13 @@
140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
3A6D62911E2044AB00D0D2C7 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6D62901E2044AB00D0D2C7 /* libz.tbd */; };
+ 3A7531B520323B2400888478 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A7531B220323B0700888478 /* libRCTAnimation.a */; };
3AC87E631F6C190900194883 /* bell.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3AC87E621F6C190900194883 /* bell.mp3 */; };
4339BFE81DAEE9D100F53B62 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4339BFE71DAEE9D100F53B62 /* GoogleService-Info.plist */; };
5FE70723D2AE04BF2D98342D /* libPods-SimpleFcmClientTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E8C044191FA88F1BCCF08BD /* libPods-SimpleFcmClientTests.a */; };
6976C617E52062E3EE272128 /* libPods-SimpleFcmClient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A959965489E40CE19F2B06B4 /* libPods-SimpleFcmClient.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
+ B5EEA6C40DAD43C696D4A7EE /* libAirMaps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 441E689027CF4924A5FEA8F6 /* libAirMaps.a */; };
FAE94A218EB64E38BF8D8E9B /* libRNFIRMessaging.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 692E216422234A4CB6A7A838 /* libRNFIRMessaging.a */; };
/* End PBXBuildFile section */
@@ -186,6 +188,27 @@
remoteGlobalIDString = 3D3CD9181DE5FBD800167DC4;
remoteInfo = "jschelpers-tvOS";
};
+ 3A7531B120323B0700888478 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 3A7531AC20323B0700888478 /* RCTAnimation.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 134814201AA4EA6300B7C361;
+ remoteInfo = RCTAnimation;
+ };
+ 3A7531B320323B0700888478 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 3A7531AC20323B0700888478 /* RCTAnimation.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
+ remoteInfo = "RCTAnimation-tvOS";
+ };
+ 3AA3D5D4204DD40F00C3E8E6 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 955F937AAFAB473EA79C80F7 /* AirMaps.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 11FA5C511C4A1296003AC2EE;
+ remoteInfo = AirMaps;
+ };
3AAE7F501F55B50200E914A8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
@@ -260,16 +283,19 @@
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; };
3A6D628E1E20449400D0D2C7 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
3A6D62901E2044AB00D0D2C7 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
+ 3A7531AC20323B0700888478 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; };
3AC87E621F6C190900194883 /* bell.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = bell.mp3; sourceTree = ""; };
4339BFE31DAEBB4800F53B62 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; };
4339BFE61DAED4D900F53B62 /* SimpleFcmClient.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = SimpleFcmClient.entitlements; path = SimpleFcmClient/SimpleFcmClient.entitlements; sourceTree = ""; };
4339BFE71DAEE9D100F53B62 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 441E689027CF4924A5FEA8F6 /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libAirMaps.a; sourceTree = ""; };
55A6E80F734FA3F596B96C04 /* Pods-SimpleFcmClientTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleFcmClientTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleFcmClientTests/Pods-SimpleFcmClientTests.debug.xcconfig"; sourceTree = ""; };
64204739CA77D9B1EB1F0788 /* Pods-SimpleFcmClientTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleFcmClientTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleFcmClientTests/Pods-SimpleFcmClientTests.release.xcconfig"; sourceTree = ""; };
692E216422234A4CB6A7A838 /* libRNFIRMessaging.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFIRMessaging.a; sourceTree = ""; };
73B4AFC1AC5C6373F8074CBC /* Pods-SimpleFcmClient.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleFcmClient.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleFcmClient/Pods-SimpleFcmClient.debug.xcconfig"; sourceTree = ""; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; };
+ 955F937AAFAB473EA79C80F7 /* AirMaps.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = AirMaps.xcodeproj; path = "../node_modules/react-native-maps/lib/ios/AirMaps.xcodeproj"; sourceTree = ""; };
A959965489E40CE19F2B06B4 /* libPods-SimpleFcmClient.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SimpleFcmClient.a"; sourceTree = BUILT_PRODUCTS_DIR; };
C7DEB70C413E484CBFA6AC45 /* RNFIRMessaging.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFIRMessaging.xcodeproj; path = "../node_modules/react-native-fcm/ios/RNFIRMessaging.xcodeproj"; sourceTree = ""; };
CF6939675D5A4A68FBE567C0 /* Pods-SimpleFcmClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleFcmClient.release.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleFcmClient/Pods-SimpleFcmClient.release.xcconfig"; sourceTree = ""; };
@@ -289,6 +315,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 3A7531B520323B2400888478 /* libRCTAnimation.a in Frameworks */,
3A6D62911E2044AB00D0D2C7 /* libz.tbd in Frameworks */,
146834051AC3E58100842450 /* libReact.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
@@ -302,6 +329,7 @@
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
FAE94A218EB64E38BF8D8E9B /* libRNFIRMessaging.a in Frameworks */,
6976C617E52062E3EE272128 /* libPods-SimpleFcmClient.a in Frameworks */,
+ B5EEA6C40DAD43C696D4A7EE /* libAirMaps.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -422,10 +450,28 @@
name = Products;
sourceTree = "";
};
+ 3A7531AD20323B0700888478 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 3A7531B220323B0700888478 /* libRCTAnimation.a */,
+ 3A7531B420323B0700888478 /* libRCTAnimation.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 3AA3D5D1204DD40F00C3E8E6 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 3AA3D5D5204DD40F00C3E8E6 /* libAirMaps.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
3AF0A6071F7BE4DC004B899F /* Recovered References */ = {
isa = PBXGroup;
children = (
692E216422234A4CB6A7A838 /* libRNFIRMessaging.a */,
+ 441E689027CF4924A5FEA8F6 /* libAirMaps.a */,
);
name = "Recovered References";
sourceTree = "";
@@ -472,6 +518,7 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
+ 3A7531AC20323B0700888478 /* RCTAnimation.xcodeproj */,
146833FF1AC3E56700842450 /* React.xcodeproj */,
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
@@ -483,6 +530,7 @@
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
C7DEB70C413E484CBFA6AC45 /* RNFIRMessaging.xcodeproj */,
+ 955F937AAFAB473EA79C80F7 /* AirMaps.xcodeproj */,
);
name = Libraries;
sourceTree = "";
@@ -571,7 +619,7 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0800;
+ LastUpgradeCheck = 800;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
00E356ED1AD99517003FC87E = {
@@ -605,10 +653,18 @@
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
+ {
+ ProductGroup = 3AA3D5D1204DD40F00C3E8E6 /* Products */;
+ ProjectRef = 955F937AAFAB473EA79C80F7 /* AirMaps.xcodeproj */;
+ },
{
ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
},
+ {
+ ProductGroup = 3A7531AD20323B0700888478 /* Products */;
+ ProjectRef = 3A7531AC20323B0700888478 /* RCTAnimation.xcodeproj */;
+ },
{
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
@@ -806,6 +862,27 @@
remoteRef = 3A6D627D1E20428000D0D2C7 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
+ 3A7531B220323B0700888478 /* libRCTAnimation.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTAnimation.a;
+ remoteRef = 3A7531B120323B0700888478 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 3A7531B420323B0700888478 /* libRCTAnimation.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTAnimation.a;
+ remoteRef = 3A7531B320323B0700888478 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 3AA3D5D5204DD40F00C3E8E6 /* libAirMaps.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libAirMaps.a;
+ remoteRef = 3AA3D5D4204DD40F00C3E8E6 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
3AAE7F511F55B50200E914A8 /* libthird-party.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -899,13 +976,16 @@
files = (
);
inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-SimpleFcmClientTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
5FF00A260C7092D33989ED96 /* [CP] Embed Pods Frameworks */ = {
@@ -974,13 +1054,16 @@
files = (
);
inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-SimpleFcmClient-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@@ -1042,6 +1125,7 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1062,6 +1146,7 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1089,6 +1174,7 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
+ "$(SRCROOT)/../node_modules/react-native-maps/lib/ios/**",
);
INFOPLIST_FILE = SimpleFcmClient/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -1123,6 +1209,7 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-fcm/ios",
+ "$(SRCROOT)/../node_modules/react-native-maps/lib/ios/**",
);
INFOPLIST_FILE = SimpleFcmClient/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
diff --git a/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/xcshareddata/xcschemes/SimpleFcmClient.xcscheme b/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/xcshareddata/xcschemes/SimpleFcmClient.xcscheme
index 5f74c52d9416acdb85d93ae5e524be40596b5467..8432ca92e95c98f9968615a30d7f8c2c76a65702 100644
--- a/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/xcshareddata/xcschemes/SimpleFcmClient.xcscheme
+++ b/Examples/simple-fcm-client/ios/SimpleFcmClient.xcodeproj/xcshareddata/xcschemes/SimpleFcmClient.xcscheme
@@ -54,6 +54,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
=4.0.0 <4.1.0-0"
yargs "^6.4.0"
+react-navigation@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-1.2.1.tgz#06cb2c97eb1b2e20bdb4ff7aee1acfa218a1561b"
+ dependencies:
+ clamp "^1.0.1"
+ hoist-non-react-statics "^2.2.0"
+ path-to-regexp "^1.7.0"
+ prop-types "^15.5.10"
+ react-native-drawer-layout-polyfill "^1.3.2"
+ react-native-safe-area-view "^0.7.0"
+ react-native-tab-view "^0.0.74"
+
react-proxy@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a"
@@ -3785,13 +3932,13 @@ read-pkg@^1.0.0:
util-deprecate "~1.0.1"
readable-stream@^2.0.1, readable-stream@^2.1.4:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
- process-nextick-args "~1.0.6"
+ process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
@@ -3882,18 +4029,18 @@ replace-ext@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924"
-request@^2.55.0, request@^2.79.0:
- version "2.79.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
+request@2.81.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
- caseless "~0.11.0"
+ caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
- har-validator "~2.0.6"
+ har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
@@ -3901,24 +4048,26 @@ request@^2.55.0, request@^2.79.0:
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
- qs "~6.3.0"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
- tunnel-agent "~0.4.1"
+ tunnel-agent "^0.6.0"
uuid "^3.0.0"
-request@^2.81.0:
- version "2.81.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
+request@^2.55.0, request@^2.79.0:
+ version "2.79.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
- caseless "~0.12.0"
+ caseless "~0.11.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
- har-validator "~4.2.1"
+ har-validator "~2.0.6"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
@@ -3926,12 +4075,10 @@ request@^2.81.0:
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
- performance-now "^0.2.0"
- qs "~6.4.0"
- safe-buffer "^5.0.1"
+ qs "~6.3.0"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
- tunnel-agent "^0.6.0"
+ tunnel-agent "~0.4.1"
uuid "^3.0.0"
require-directory@^2.1.1:
@@ -3950,6 +4097,12 @@ resolve@^1.1.6:
version "1.2.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.2.0.tgz#9589c3f2f6149d1417a40becc1663db6ec6bc26c"
+resolve@^1.2.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
+ dependencies:
+ path-parse "^1.0.5"
+
response-time@~2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a"
@@ -3971,8 +4124,8 @@ right-align@^0.1.1:
align-text "^0.1.1"
rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
glob "^7.0.5"
@@ -4015,8 +4168,8 @@ safe-buffer@~5.0.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
sane@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/sane/-/sane-2.0.0.tgz#99cb79f21f4a53a69d4d0cd957c2db04024b8eb2"
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/sane/-/sane-2.4.1.tgz#29f991208cf28636720efdc584293e7fd66663a5"
dependencies:
anymatch "^1.3.0"
exec-sh "^0.2.0"
@@ -4024,7 +4177,7 @@ sane@^2.0.0:
minimatch "^3.0.2"
minimist "^1.1.1"
walker "~1.0.5"
- watch "~0.10.0"
+ watch "~0.18.0"
optionalDependencies:
fsevents "^1.1.1"
@@ -4174,6 +4327,10 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
+source-map@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+
source-map@~0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
@@ -4304,19 +4461,19 @@ supports-color@^3.1.0, supports-color@^3.1.2:
dependencies:
has-flag "^1.0.0"
-supports-color@^4.0.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836"
+supports-color@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a"
dependencies:
- has-flag "^2.0.0"
+ has-flag "^3.0.0"
"symbol-tree@>= 3.1.0 < 4.0.0":
version "3.2.1"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.1.tgz#8549dd1d01fa9f893c18cc9ab0b106b4d9b168cb"
tar-pack@^3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984"
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f"
dependencies:
debug "^2.2.0"
fstream "^1.0.10"
@@ -4375,11 +4532,11 @@ time-stamp@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.0.1.tgz#9f4bd23559c9365966f3302dbba2b07c6b99b151"
-tmp@^0.0.31:
- version "0.0.31"
- resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7"
+tmp@^0.0.33:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
dependencies:
- os-tmpdir "~1.0.1"
+ os-tmpdir "~1.0.2"
tmpl@1.0.x:
version "1.0.4"
@@ -4543,6 +4700,13 @@ watch@~0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc"
+watch@~0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
+ dependencies:
+ exec-sh "^0.2.0"
+ minimist "^1.2.0"
+
webidl-conversions@^3.0.0, webidl-conversions@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
diff --git a/README.md b/README.md
index 84bad419a229f6b9f840056faa0d90817e02779f..29a8139b8b24fd6fd8ad2ab4b98ce26cff525af5 100644
--- a/README.md
+++ b/README.md
@@ -10,12 +10,14 @@
- An example working project is available at: https://github.com/evollu/react-native-fcm/tree/master/Examples/simple-fcm-client
-- DO NOT change Android targetSdkVersion >= 26. The notification won't show up because of notification channel requirement. [Help is needed](https://github.com/evollu/react-native-fcm/issues/698)
+- DO NOT change Android targetSdkVersion >= 26. The notification won't show up because of notification channel requirement.
+If you have to upgrade, you can use sdk-26 branch and post feedback on [here](https://github.com/evollu/react-native-fcm/pull/699)
## Installation
- Run `npm install react-native-fcm --save`
-- Run `react-native link react-native-fcm` (RN 0.29.1+, otherwise `rnpm link react-native-fcm`)
+- [Link libraries](https://facebook.github.io/react-native/docs/linking-libraries-ios.html)
+ Note: the auto link doesn't work with xcworkspace so CocoaPods user needs to do manual linking
## Configure Firebase Console
### FCM config file
@@ -43,6 +45,7 @@ https://github.com/evollu/react-native-fcm/blob/master/Examples/simple-fcm-clien
- Edit `android/app/build.gradle`. Add at the bottom of the file:
```diff
apply plugin: "com.android.application"
+ ...
+ apply plugin: 'com.google.gms.google-services'
```
@@ -53,6 +56,8 @@ https://github.com/evollu/react-native-fcm/blob/master/Examples/simple-fcm-clien
...
android:theme="@style/AppTheme">
++
+
+
+
+
@@ -73,6 +78,7 @@ https://github.com/evollu/react-native-fcm/blob/master/Examples/simple-fcm-clien
dependencies {
+ compile project(':react-native-fcm')
+ compile 'com.google.firebase:firebase-core:10.0.1' //this decides your firebase SDK version
++ compile 'com.google.firebase:firebase-messaging:10.0.1'
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
@@ -86,6 +92,19 @@ https://github.com/evollu/react-native-fcm/blob/master/Examples/simple-fcm-clien
include ':app'
```
+- Edit `MainActivity.java`. This fixes [a bug](https://stackoverflow.com/questions/14853327/intent-not-restored-correctly-after-activity-is-killed-if-clear-top-and-single-t/18307360#18307360)
+```diff
++ import android.content.Intent;
+...
+public class MainActivity extends ReactActivity {
++ @Override
++ public void onNewIntent(Intent intent) {
++ super.onNewIntent(intent);
++ setIntent(intent);
++ }
+}
+```
+
### Config for notification and `click_action` in Android
To allow android to respond to `click_action`, you need to define Activities and filter on specific intent. Since all javascript is running in MainActivity, you can have MainActivity to handle actions:
@@ -184,7 +203,7 @@ cd ios && pod init
Edit the newly created `Podfile`:
```diff
# Pods for YOURAPP
-+ pod 'FirebaseMessaging'
++ pod 'Firebase/Messaging'
```
Install the `Firebase/Messaging` pod:
@@ -192,13 +211,17 @@ Install the `Firebase/Messaging` pod:
pod install
```
NOTE: you don't need to enable `use_frameworks!`. if you have to have `use_frameworks!` make sure you don't have `inherit! :search_paths`
+NOTE: there is a working example in `master` branch
### Non Cocoapod approach
-1. Download the Firebase SDK framework from [Integrate without CocoaPods](https://firebase.google.com/docs/ios/setup#frameworks).
+1. Follow the instruction on [Integrate without CocoaPods](https://firebase.google.com/docs/ios/setup#frameworks).
- Import libraries, add Capabilities (background running and push notification), upload APNS and etc etc etc...
-2. Put frameworks under `ios/Pods` folder
-2. Follow the `README` to link frameworks (Analytics+Messaging)
+2. Put frameworks under `ios/Frameworks` folder, and drag those files into your xcode solution -> Frameworks
+3. Put `firebase.h` and `module.modulemap` under `ios/Frameworks` folder, no need to drag into solution
+4. Modify your project's `User Header Search Paths` and add `$(PROJECT_DIR)/Frameworks`
+
+NOTE: There is a working example in `no-pod` branch
### Shared steps
@@ -273,8 +296,7 @@ Edit AndroidManifest.xml
+
+
-
+
+
+
+
@@ -290,138 +312,8 @@ NOTE: `com.evollu.react.fcm.FIRLocalMessagingPublisher` is required for presenti
## Usage
+[Check example project](https://github.com/evollu/react-native-fcm/blob/master/Examples/simple-fcm-client/app/App.js#L68)
-```javascript
-import {Platform} from 'react-native';
-import FCM, {FCMEvent, RemoteNotificationResult, WillPresentNotificationResult, NotificationType} from 'react-native-fcm';
-
-// this shall be called regardless of app state: running, background or not running. Won't be called when app is killed by user in iOS
-FCM.on(FCMEvent.Notification, async (notif) => {
- // there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
- if(notif.local_notification){
- //this is a local notification
- }
- if(notif.opened_from_tray){
- //iOS: app is open/resumed because user clicked banner
- //Android: app is open/resumed because user clicked banner or tapped app icon
- }
- // await someAsyncCall();
-
- if(Platform.OS ==='ios'){
- //optional
- //iOS requires developers to call completionHandler to end notification process. If you do not call it your background remote notifications could be throttled, to read more about it see https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application.
- //This library handles it for you automatically with default behavior (for remote notification, finish with NoData; for WillPresent, finish depend on "show_in_foreground"). However if you want to return different result, follow the following code to override
- //notif._notificationType is available for iOS platfrom
- switch(notif._notificationType){
- case NotificationType.Remote:
- notif.finish(RemoteNotificationResult.NewData) //other types available: RemoteNotificationResult.NewData, RemoteNotificationResult.ResultFailed
- break;
- case NotificationType.NotificationResponse:
- notif.finish();
- break;
- case NotificationType.WillPresent:
- notif.finish(WillPresentNotificationResult.All) //other types available: WillPresentNotificationResult.None
- break;
- }
- }
-});
-FCM.on(FCMEvent.RefreshToken, (token) => {
- console.log(token)
- // fcm token may not be available on first load, catch it here
-});
-
-class App extends Component {
- componentDidMount() {
- // iOS: show permission prompt for the first call. later just check permission in user settings
- // Android: check permission in user settings
- FCM.requestPermissions().then(()=>console.log('granted')).catch(()=>console.log('notification permission rejected'));
-
- FCM.getFCMToken().then(token => {
- console.log(token)
- // store fcm token in your server
- });
-
- this.notificationListener = FCM.on(FCMEvent.Notification, async (notif) => {
- // optional, do some component related stuff
- });
-
- // initial notification contains the notification that launchs the app. If user launchs app by clicking banner, the banner notification info will be here rather than through FCM.on event
- // sometimes Android kills activity when app goes to background, and when resume it broadcasts notification before JS is run. You can use FCM.getInitialNotification() to capture those missed events.
- // initial notification will be triggered all the time even when open app by icon so send some action identifier when you send notification
- FCM.getInitialNotification().then(notif => {
- console.log(notif)
- });
- }
-
- componentWillUnmount() {
- // stop listening for events
- this.notificationListener.remove();
- }
-
- otherMethods(){
-
- FCM.subscribeToTopic('/topics/foo-bar');
- FCM.unsubscribeFromTopic('/topics/foo-bar');
- FCM.presentLocalNotification({
- id: "UNIQ_ID_STRING", // (optional for instant notification)
- title: "My Notification Title", // as FCM payload
- body: "My Notification Message", // as FCM payload (required)
- sound: "default", // as FCM payload
- priority: "high", // as FCM payload
- click_action: "ACTION", // as FCM payload
- badge: 10, // as FCM payload IOS only, set 0 to clear badges
- number: 10, // Android only
- ticker: "My Notification Ticker", // Android only
- auto_cancel: true, // Android only (default true)
- large_icon: "ic_launcher", // Android only
- icon: "ic_launcher", // as FCM payload, you can relace this with custom icon you put in mipmap
- big_text: "Show when notification is expanded", // Android only
- sub_text: "This is a subText", // Android only
- color: "red", // Android only
- vibrate: 300, // Android only default: 300, no vibration if you pass 0
- group: "group", // Android only
- picture: "https://google.png", // Android only bigPicture style
- ongoing: true, // Android only
- my_custom_data:'my_custom_field_value', // extra data you want to throw
- lights: true, // Android only, LED blinking (default false)
- show_in_foreground // notification when app is in foreground (local & remote)
- });
-
- FCM.scheduleLocalNotification({
- fire_date: new Date().getTime(), //RN's converter is used, accept epoch time and whatever that converter supports
- id: "UNIQ_ID_STRING", //REQUIRED! this is what you use to lookup and delete notification. In android notification with same ID will override each other
- body: "from future past",
- repeat_interval: "week" //day, hour
- })
-
- FCM.getScheduledLocalNotifications().then(notif=>console.log(notif));
-
- //these clears notification from notification center/tray
- FCM.removeAllDeliveredNotifications()
- FCM.removeDeliveredNotification("UNIQ_ID_STRING")
-
- //these removes future local notifications
- FCM.cancelAllLocalNotifications()
- FCM.cancelLocalNotification("UNIQ_ID_STRING")
-
- FCM.setBadgeNumber(1); // iOS only and there's no way to set it in Android, yet.
- FCM.getBadgeNumber().then(number=>console.log(number)); // iOS only and there's no way to get it in Android, yet.
- FCM.send('984XXXXXXXXX', {
- my_custom_data_1: 'my_custom_field_value_1',
- my_custom_data_2: 'my_custom_field_value_2'
- });
-
- FCM.deleteInstanceId()
- .then( () => {
- //Deleted instance id successfully
- //This will reset Instance ID and revokes all tokens.
- })
- .catch(error => {
- //Error while deleting instance id
- });
- }
-}
-```
### Build custom push notification for Android
Firebase android misses important feature of android notification like `group`, `priority` and etc. As a work around you can send data message (no `notification` payload at all) and this repo will build a local notification for you. If you pass `custom_notification` in the payload, the repo will treat the content as a local notification config and shows immediately.
@@ -538,6 +430,26 @@ FCM.send('984XXXXXXXXX', {
The `Data Object` is message data comprising as many key-value pairs of the message's payload as are needed (ensure that the value of each pair in the data object is a `string`). Your `Sender ID` is a unique numerical value generated when you created your Firebase project, it is available in the `Cloud Messaging` tab of the Firebase console `Settings` pane. The sender ID is used to identify each app server that can send messages to the client app.
+### Sending remote notifications with category on iOS
+If you want to send notification which will have actions as you defined in app it's important to correctly set it's `category` (`click_action`) property. It's also good to set `"content-available" : 1` so app will gets enough time to handle actions in background.
+
+So the fcm payload should look like this:
+```javascript
+{
+ "to": "some_device_token",
+ "content_available": true,
+ "notification": {
+ "title": "Alarm",
+ "subtitle": "First Alarm",
+ "body": "First Alarm",
+ "click_action": "com.myapp.MyCategory" // The id of notification category which you defined with FCM.setNotificationCategories
+ },
+ "data": {
+ "extra": "juice"
+ }
+ }
+ ```
+
## Q & A
#### Why do you build another local notification
@@ -547,18 +459,12 @@ Yes there are `react-native-push-notification` and `react-native-system-notifica
- The PushNotificationIOS by react native team is still missing features that recurring, so we are adding it here
#### My Android build is failing
-Try update your SDK and google play service. If you are having multiple plugins requiring different version of play-service sdk, use force to lock in version
+Try update your SDK and google play service.
+If you are having multiple plugins requiring different version of play-service sdk, skip conflicting group. The example project shows for how to colive with react-native-maps
```
-dependencies {
- ...
- compile ('com.android.support:appcompat-v7:25.0.1') {
- exclude group: 'com.google.android', module: 'support-v4'
- }
- compile ('com.google.android.gms:play-services-gcm:10.0.1') {
- force = true;
+ compile(project(':react-native-maps')) {
+ exclude group: 'com.google.android.gms', module: 'play-services-base'
}
- ...
-}
```
#### My App throws FCM function undefined error
@@ -640,3 +546,65 @@ Issues and pull requests are welcome. Let's make this thing better!
#### Credits
Local notification implementation is inspired by react-native-push-notification by zo0r
+
+## Sending remote notification
+
+How to send a push notification from your server? You should `POST` to this endpoint:
+
+ https://fcm.googleapis.com/fcm/send
+
+You need to set the headers of `Content-Type` to `application/json` and `Authorization` to `key=******` where you replace `******` with the "Legacy server key" from here the Firebase dashbaord. Get this information by first going to:
+
+1. https://console.firebase.google.com/
+2. Click on "Gear" icon and click "Project Settingss". Screenshot: https://screenshotscdn.firefoxusercontent.com/images/35b93de8-44e1-49af-89d7-140b74c267c7.png
+3. Click on "Cloud Message" tab and find "Legacy server key" here. Screenshot: https://screenshotscdn.firefoxusercontent.com/images/c52ec383-783d-47d3-a1e6-75249fb6f3fb.png
+
+The body should be json like this:
+
+```
+{
+ "to":"FCM_DEVICE_TOKEN_GOES_HERE",
+ "data": {
+ "custom_notification": {
+ "body": "test body",
+ "title": "test title",
+ "color":"#00ACD4",
+ "priority":"high",
+ "icon":"ic_launcher",
+ "group": "GROUP",
+ "sound": "default",
+ "id": "id",
+ "show_in_foreground": true
+ }
+ }
+}
+```
+
+Example:
+
+```
+fetch('https://fcm.googleapis.com/fcm/send', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ 'Authorization': 'key=EFefklefwef9efwefkejfwf'
+ },
+ body: JSON.stringify({
+ "to":"kajfsdf:efawefwe_fsdfdsf-asfawefwefwf_asdfsdfasd-asdfasdfsd9A_asdfsdf_asdf",
+ "data": {
+ "custom_notification": {
+ "body": "test body",
+ "title": "test title",
+ "color":"#00ACD4",
+ "priority":"high",
+ "icon":"ic_notif",
+ "group": "GROUP",
+ "sound": "default",
+ "id": "id",
+ "show_in_foreground": true
+ }
+ }
+ })
+})
+```
+
diff --git a/android/src/main/java/com/evollu/react/fcm/FIRLocalMessagingHelper.java b/android/src/main/java/com/evollu/react/fcm/FIRLocalMessagingHelper.java
index eca4004230c5523b11df61a72f219977069a3f74..a71173351f9065654d69f93c939af943176a7d02 100644
--- a/android/src/main/java/com/evollu/react/fcm/FIRLocalMessagingHelper.java
+++ b/android/src/main/java/com/evollu/react/fcm/FIRLocalMessagingHelper.java
@@ -58,7 +58,10 @@ public class FIRLocalMessagingHelper {
return;
}
- Long fireDate = Math.round(bundle.getDouble("fire_date"));
+ long fireDate = Math.round(bundle.getDouble("fire_date"));
+ if(fireDate == 0){
+ fireDate = Math.round(bundle.getLong("fire_date"));
+ }
if (fireDate == 0) {
Log.e(TAG, "failed to schedule notification because fire date is missing");
return;
diff --git a/android/src/main/java/com/evollu/react/fcm/FIRMessagingModule.java b/android/src/main/java/com/evollu/react/fcm/FIRMessagingModule.java
index adee2a88cf6d7c45b6a9d601004f6d76fe7c9d66..e68b759cd0e260b7713668dd6e6d9618318f444a 100644
--- a/android/src/main/java/com/evollu/react/fcm/FIRMessagingModule.java
+++ b/android/src/main/java/com/evollu/react/fcm/FIRMessagingModule.java
@@ -37,6 +37,7 @@ import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import com.google.firebase.FirebaseApp;
import static android.content.Context.NOTIFICATION_SERVICE;
@@ -133,6 +134,31 @@ public class FIRMessagingModule extends ReactContextBaseJavaModule implements Li
}
}
+ @ReactMethod
+ public void getEntityFCMToken(Promise promise) {
+ try {
+ String senderId = FirebaseApp.getInstance().getOptions().getGcmSenderId();
+ String token = FirebaseInstanceId.getInstance().getToken(senderId, "FCM");
+ Log.d(TAG, "Firebase token: " + token);
+ promise.resolve(token);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ promise.reject(null,e.getMessage());
+ }
+ }
+
+ @ReactMethod
+ public void deleteEntityFCMToken(Promise promise) {
+ try {
+ String senderId = FirebaseApp.getInstance().getOptions().getGcmSenderId();
+ FirebaseInstanceId.getInstance().deleteToken(senderId, "FCM");
+ promise.resolve(null);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ promise.reject(null,e.getMessage());
+ }
+ }
+
@ReactMethod
public void deleteInstanceId(Promise promise){
try {
@@ -354,4 +380,3 @@ public class FIRMessagingModule extends ReactContextBaseJavaModule implements Li
sendEvent("FCMNotificationReceived", parseIntent(intent));
}
}
-
diff --git a/android/src/main/java/com/evollu/react/fcm/InstanceIdService.java b/android/src/main/java/com/evollu/react/fcm/InstanceIdService.java
index 9ac9ef540dd7525158058ebdd1032cbaf6c65f7f..f01c160ceab4702d480c76a5290ab9f527b5224c 100644
--- a/android/src/main/java/com/evollu/react/fcm/InstanceIdService.java
+++ b/android/src/main/java/com/evollu/react/fcm/InstanceIdService.java
@@ -2,9 +2,14 @@ package com.evollu.react.fcm;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactInstanceManager;
+import com.facebook.react.bridge.ReactContext;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
@@ -25,11 +30,35 @@ public class InstanceIdService extends FirebaseInstanceIdService {
Log.d(TAG, "Refreshed token: " + refreshedToken);
// Broadcast refreshed token
-
Intent i = new Intent("com.evollu.react.fcm.FCMRefreshToken");
Bundle bundle = new Bundle();
bundle.putString("token", refreshedToken);
i.putExtras(bundle);
- LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
+
+ final Intent message = i;
+
+ Handler handler = new Handler(Looper.getMainLooper());
+ handler.post(new Runnable() {
+ public void run() {
+ // Construct and load our normal React JS code bundle
+ ReactInstanceManager mReactInstanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager();
+ ReactContext context = mReactInstanceManager.getCurrentReactContext();
+ // If it's constructed, send a notification
+ if (context != null) {
+ LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(message);
+ } else {
+ // Otherwise wait for construction, then send the notification
+ mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
+ public void onReactContextInitialized(ReactContext context) {
+ LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(message);
+ }
+ });
+ if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
+ // Construct it in the background
+ mReactInstanceManager.createReactContextInBackground();
+ }
+ }
+ }
+ });
}
}
diff --git a/android/src/main/java/com/evollu/react/fcm/ReactNativeJson.java b/android/src/main/java/com/evollu/react/fcm/ReactNativeJson.java
new file mode 100644
index 0000000000000000000000000000000000000000..e71f77adfc33c401c6735c545b5b6d861d6ff013
--- /dev/null
+++ b/android/src/main/java/com/evollu/react/fcm/ReactNativeJson.java
@@ -0,0 +1,122 @@
+package com.evollu.react.fcm;
+
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.bridge.ReadableMapKeySetIterator;
+import com.facebook.react.bridge.WritableArray;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.WritableNativeArray;
+import com.facebook.react.bridge.WritableNativeMap;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Iterator;
+
+public class ReactNativeJson {
+ public static WritableMap convertJsonToMap(JSONObject jsonObject) throws JSONException {
+ WritableMap map = new WritableNativeMap();
+
+ Iterator iterator = jsonObject.keys();
+ while (iterator.hasNext()) {
+ String key = iterator.next();
+ Object value = jsonObject.get(key);
+ if (value instanceof JSONObject) {
+ map.putMap(key, convertJsonToMap((JSONObject) value));
+ } else if (value instanceof JSONArray) {
+ map.putArray(key, convertJsonToArray((JSONArray) value));
+ } else if (value instanceof Boolean) {
+ map.putBoolean(key, (Boolean) value);
+ } else if (value instanceof Integer) {
+ map.putInt(key, (Integer) value);
+ } else if (value instanceof Double) {
+ map.putDouble(key, (Double) value);
+ } else if (value instanceof String) {
+ map.putString(key, (String) value);
+ } else {
+ map.putString(key, value.toString());
+ }
+ }
+ return map;
+ }
+
+ public static WritableArray convertJsonToArray(JSONArray jsonArray) throws JSONException {
+ WritableArray array = new WritableNativeArray();
+
+ for (int i = 0; i < jsonArray.length(); i++) {
+ Object value = jsonArray.get(i);
+ if (value instanceof JSONObject) {
+ array.pushMap(convertJsonToMap((JSONObject) value));
+ } else if (value instanceof JSONArray) {
+ array.pushArray(convertJsonToArray((JSONArray) value));
+ } else if (value instanceof Boolean) {
+ array.pushBoolean((Boolean) value);
+ } else if (value instanceof Integer) {
+ array.pushInt((Integer) value);
+ } else if (value instanceof Double) {
+ array.pushDouble((Double) value);
+ } else if (value instanceof String) {
+ array.pushString((String) value);
+ } else {
+ array.pushString(value.toString());
+ }
+ }
+ return array;
+ }
+
+ public static JSONObject convertMapToJson(ReadableMap readableMap) throws JSONException {
+ JSONObject object = new JSONObject();
+ ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
+ while (iterator.hasNextKey()) {
+ String key = iterator.nextKey();
+ switch (readableMap.getType(key)) {
+ case Null:
+ object.put(key, JSONObject.NULL);
+ break;
+ case Boolean:
+ object.put(key, readableMap.getBoolean(key));
+ break;
+ case Number:
+ object.put(key, readableMap.getDouble(key));
+ break;
+ case String:
+ object.put(key, readableMap.getString(key));
+ break;
+ case Map:
+ object.put(key, convertMapToJson(readableMap.getMap(key)));
+ break;
+ case Array:
+ object.put(key, convertArrayToJson(readableMap.getArray(key)));
+ break;
+ }
+ }
+ return object;
+ }
+
+ public static JSONArray convertArrayToJson(ReadableArray readableArray) throws JSONException {
+ JSONArray array = new JSONArray();
+ for (int i = 0; i < readableArray.size(); i++) {
+ switch (readableArray.getType(i)) {
+ case Null:
+ break;
+ case Boolean:
+ array.put(readableArray.getBoolean(i));
+ break;
+ case Number:
+ array.put(readableArray.getDouble(i));
+ break;
+ case String:
+ array.put(readableArray.getString(i));
+ break;
+ case Map:
+ array.put(convertMapToJson(readableArray.getMap(i)));
+ break;
+ case Array:
+ array.put(convertArrayToJson(readableArray.getArray(i)));
+ break;
+ }
+ }
+ return array;
+ }
+}
diff --git a/android/src/main/java/com/evollu/react/fcm/SendNotificationTask.java b/android/src/main/java/com/evollu/react/fcm/SendNotificationTask.java
index 37496238df5f5842241d0b34132a3c7508027fa7..b15326caaabe56d8a56bb48a0c6768bae66be873 100644
--- a/android/src/main/java/com/evollu/react/fcm/SendNotificationTask.java
+++ b/android/src/main/java/com/evollu/react/fcm/SendNotificationTask.java
@@ -15,11 +15,17 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.bridge.WritableArray;
+
+import org.json.JSONArray;
+
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@@ -35,7 +41,7 @@ public class SendNotificationTask extends AsyncTask {
private SharedPreferences sharedPreferences;
private Boolean mIsForeground;
- public SendNotificationTask(Context context, SharedPreferences sharedPreferences, Boolean mIsForeground, Bundle bundle){
+ SendNotificationTask(Context context, SharedPreferences sharedPreferences, Boolean mIsForeground, Bundle bundle){
this.mContext = context;
this.bundle = bundle;
this.sharedPreferences = sharedPreferences;
@@ -70,9 +76,12 @@ public class SendNotificationTask extends AsyncTask {
.setAutoCancel(bundle.getBoolean("auto_cancel", true))
.setNumber((int)bundle.getDouble("number"))
.setSubText(bundle.getString("sub_text"))
- .setGroup(bundle.getString("group"))
.setVibrate(new long[]{0, DEFAULT_VIBRATION})
.setExtras(bundle.getBundle("data"));
+
+ if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
+ notification.setGroup(bundle.getString("group"));
+ }
if (bundle.containsKey("ongoing") && bundle.getBoolean("ongoing")) {
notification.setOngoing(bundle.getBoolean("ongoing"));
@@ -207,11 +216,40 @@ public class SendNotificationTask extends AsyncTask {
PendingIntent.FLAG_UPDATE_CURRENT);
notification.setContentIntent(pendingIntent);
+
+ if (bundle.containsKey("android_actions")) {
+ WritableArray actions = ReactNativeJson.convertJsonToArray(new JSONArray(bundle.getString("android_actions")));
+ for (int a = 0; a < actions.size(); a++) {
+ ReadableMap action = actions.getMap(a);
+ String actionTitle = action.getString("title");
+ String actionId = action.getString("id");
+ Intent actionIntent = new Intent();
+ actionIntent.setClassName(mContext, intentClassName);
+ actionIntent.setAction("com.evollu.react.fcm." + actionId + "_ACTION");
+ actionIntent.putExtras(bundle);
+ actionIntent.putExtra("_actionIdentifier", actionId);
+ actionIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ PendingIntent pendingActionIntent = PendingIntent.getActivity(mContext, notificationID, actionIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ notification.addAction(0, actionTitle, pendingActionIntent);
+ }
+ }
Notification info = notification.build();
NotificationManagerCompat.from(mContext).notify(notificationID, info);
}
+
+ if(bundle.getBoolean("wake_screen", false)){
+ PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ if(pm != null && !pm.isScreenOn())
+ {
+ PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |PowerManager.ACQUIRE_CAUSES_WAKEUP |PowerManager.ON_AFTER_RELEASE,"FCMLock");
+ wl.acquire(5000);
+ }
+ }
+
//clear out one time scheduled notification once fired
if(!bundle.containsKey("repeat_interval") && bundle.containsKey("fire_date")) {
SharedPreferences.Editor editor = sharedPreferences.edit();
@@ -224,7 +262,7 @@ public class SendNotificationTask extends AsyncTask {
return null;
}
- public Bitmap getBitmapFromURL(String strURL) {
+ private Bitmap getBitmapFromURL(String strURL) {
try {
URL url = new URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@@ -238,11 +276,10 @@ public class SendNotificationTask extends AsyncTask {
}
}
- public String getMainActivityClassName() {
+ protected String getMainActivityClassName() {
String packageName = mContext.getPackageName();
Intent launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
- String className = launchIntent.getComponent().getClassName();
- return className;
+ return launchIntent != null ? launchIntent.getComponent().getClassName() : null;
}
}
diff --git a/index.d.ts b/index.d.ts
index fce43d2dc21b246039043c14b97c75bae5d3ad07..ac9fa5a5ebc028eed2b77ad0fb5d8c25465a6e99 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -25,6 +25,26 @@ declare module "react-native-fcm" {
const Local = "local_notification";
}
+ export enum NotificationCategoryOption {
+ CustomDismissAction = 'UNNotificationCategoryOptionCustomDismissAction',
+ AllowInCarPlay = 'UNNotificationCategoryOptionAllowInCarPlay',
+ PreviewsShowTitle = 'UNNotificationCategoryOptionHiddenPreviewsShowTitle',
+ PreviewsShowSubtitle = 'UNNotificationCategoryOptionHiddenPreviewsShowSubtitle',
+ None = 'UNNotificationCategoryOptionNone'
+ }
+
+ export enum NotificationActionOption {
+ AuthenticationRequired = 'UNNotificationActionOptionAuthenticationRequired',
+ Destructive = 'UNNotificationActionOptionDestructive',
+ Foreground = 'UNNotificationActionOptionForeground',
+ None = 'UNNotificationActionOptionNone'
+ }
+
+ export enum NotificationActionType {
+ Default = 'UNNotificationActionTypeDefault',
+ TextInput = 'UNNotificationActionTypeTextInput',
+ }
+
export interface Notification {
collapse_key: string;
opened_from_tray: boolean;
@@ -44,6 +64,8 @@ declare module "react-native-fcm" {
};
local_notification?: boolean;
_notificationType: string;
+ _actionIdentifier?: string;
+ _userText?: string;
finish(type?: string): void;
[key: string]: any;
}
@@ -83,6 +105,23 @@ declare module "react-native-fcm" {
remove(): void;
}
+ export interface NotificationAction {
+ type: NotificationActionType;
+ id: string;
+ title?: string;
+ textInputButtonTitle?: string;
+ textInputPlaceholder?: string;
+ options: NotificationActionOption | NotificationActionOption[];
+ }
+
+ export interface NotificationCategory {
+ id: string;
+ actions: NotificationAction[];
+ intentIdentifiers: string[];
+ hiddenPreviewsBodyPlaceholder?: string;
+ options?: NotificationCategoryOption | NotificationCategoryOption[];
+ }
+
export class FCM {
static requestPermissions(): Promise;
static getFCMToken(): Promise;
@@ -109,6 +148,8 @@ declare module "react-native-fcm" {
static enableDirectChannel(): void
static isDirectChannelEstablished(): Promise
static getAPNSToken(): Promise
+
+ static setNotificationCategories(categories: NotificationCategory[]): void;
}
export default FCM;
diff --git a/index.js b/index.js
index 0fd049eb03141df83e69e8b79911570f11df4815..c2781c400424d63e7f8a21da7c10e4343b549df1 100644
--- a/index.js
+++ b/index.js
@@ -26,6 +26,26 @@ export const NotificationType = {
Local: 'local_notification'
};
+export const NotificationCategoryOption = {
+ CustomDismissAction: 'UNNotificationCategoryOptionCustomDismissAction',
+ AllowInCarPlay: 'UNNotificationCategoryOptionAllowInCarPlay',
+ PreviewsShowTitle: 'UNNotificationCategoryOptionHiddenPreviewsShowTitle',
+ PreviewsShowSubtitle: 'UNNotificationCategoryOptionHiddenPreviewsShowSubtitle',
+ None: 'UNNotificationCategoryOptionNone'
+};
+
+export const NotificationActionOption = {
+ AuthenticationRequired: 'UNNotificationActionOptionAuthenticationRequired',
+ Destructive: 'UNNotificationActionOptionDestructive',
+ Foreground: 'UNNotificationActionOptionForeground',
+ None: 'UNNotificationActionOptionNone',
+};
+
+export const NotificationActionType = {
+ Default: 'UNNotificationActionTypeDefault',
+ TextInput: 'UNNotificationActionTypeTextInput',
+};
+
const RNFIRMessaging = NativeModules.RNFIRMessaging;
const FCM = {};
@@ -48,6 +68,14 @@ FCM.getFCMToken = () => {
return RNFIRMessaging.getFCMToken();
};
+FCM.getEntityFCMToken = () => {
+ return RNFIRMessaging.getEntityFCMToken();
+}
+
+FCM.deleteEntityFCMToken = () => {
+ return RNFIRMessaging.deleteEntityFCMToken();
+}
+
FCM.deleteInstanceId = () =>{
return RNFIRMessaging.deleteInstanceId();
};
@@ -157,7 +185,7 @@ FCM.on = (event, callback) => {
try {
await callback(data);
} catch (err) {
- console.error('Notification handler err', err);
+ console.error('Notification handler err:\n'+err.stack);
throw err;
}
if (!data._finishCalled) {
@@ -180,4 +208,12 @@ FCM.send = (senderId, payload) => {
RNFIRMessaging.send(senderId, payload);
};
+FCM.setNotificationCategories = (categories) => {
+ if (Platform.OS === 'ios') {
+ RNFIRMessaging.setNotificationCategories(categories);
+ }
+}
+
export default FCM;
+
+export {};
diff --git a/ios/RNFIRMessaging.h b/ios/RNFIRMessaging.h
index 9813c4ff9264462ffb36c0a04b024cde924b22ab..3bb8d94bfc899d708973d91896dfac98f4348372 100644
--- a/ios/RNFIRMessaging.h
+++ b/ios/RNFIRMessaging.h
@@ -1,9 +1,14 @@
#import
-@import FirebaseCore;
-@import FirebaseMessaging;
-@import FirebaseInstanceID;
+#if __has_include()
+#import
+#import
+#import
+#else
+@import Firebase;
+#endif
+
#import
@import UserNotifications;
diff --git a/ios/RNFIRMessaging.m b/ios/RNFIRMessaging.m
index 271dac8a5bbe7dc8729ef98b90f614968fe658e6..629589b442a9a5a7969d4f4a0db79e33be26807d 100644
--- a/ios/RNFIRMessaging.m
+++ b/ios/RNFIRMessaging.m
@@ -131,12 +131,105 @@ RCT_ENUM_CONVERTER(UNNotificationPresentationOptions, (@{
@end
+@implementation RCTConvert (UNNotificationAction)
+
+typedef NS_ENUM(NSUInteger, UNNotificationActionType) {
+ UNNotificationActionTypeDefault,
+ UNNotificationActionTypeTextInput
+};
+
++ (UNNotificationAction *) UNNotificationAction:(id)json {
+ NSDictionary *details = [self NSDictionary:json];
+
+ NSString *identifier = [RCTConvert NSString: details[@"id"]];
+ NSString *title = [RCTConvert NSString: details[@"title"]];
+ UNNotificationActionOptions options = [RCTConvert UNNotificationActionOptions: details[@"options"]];
+ UNNotificationActionType type = [RCTConvert UNNotificationActionType:details[@"type"]];
+
+ if (type == UNNotificationActionTypeTextInput) {
+ NSString *textInputButtonTitle = [RCTConvert NSString: details[@"textInputButtonTitle"]];
+ NSString *textInputPlaceholder = [RCTConvert NSString: details[@"textInputPlaceholder"]];
+
+ return [UNTextInputNotificationAction actionWithIdentifier:identifier title:title options:options textInputButtonTitle:textInputButtonTitle textInputPlaceholder:textInputPlaceholder];
+ }
+
+ return [UNNotificationAction actionWithIdentifier:identifier
+ title:title
+ options:options];
+
+}
+
+RCT_ENUM_CONVERTER(UNNotificationActionType, (@{
+ @"UNNotificationActionTypeDefault": @(UNNotificationActionTypeDefault),
+ @"UNNotificationActionTypeTextInput": @(UNNotificationActionTypeTextInput),
+ }), UNNotificationActionTypeDefault, integerValue)
+
+
+RCT_MULTI_ENUM_CONVERTER(UNNotificationActionOptions, (@{
+ @"UNNotificationActionOptionAuthenticationRequired": @(UNNotificationActionOptionAuthenticationRequired),
+ @"UNNotificationActionOptionDestructive": @(UNNotificationActionOptionDestructive),
+ @"UNNotificationActionOptionForeground": @(UNNotificationActionOptionForeground),
+ @"UNNotificationActionOptionNone": @(UNNotificationActionOptionNone),
+ }), UNNotificationActionOptionNone, integerValue)
+
+
+@end
+
+@implementation RCTConvert (UNNotificationCategory)
+
+
++ (UNNotificationCategory *) UNNotificationCategory:(id)json {
+ NSDictionary *details = [self NSDictionary:json];
+
+ NSString *identifier = [RCTConvert NSString: details[@"id"]];
+
+ NSMutableArray *actions = [[NSMutableArray alloc] init];
+ for (NSDictionary *actionDict in details[@"actions"]) {
+ [actions addObject:[RCTConvert UNNotificationAction:actionDict]];
+ }
+
+ NSArray *intentIdentifiers = [RCTConvert NSStringArray:details[@"intentIdentifiers"]];
+ NSString *hiddenPreviewsBodyPlaceholder = [RCTConvert NSString:details[@"hiddenPreviewsBodyPlaceholder"]];
+ UNNotificationCategoryOptions options = [RCTConvert UNNotificationCategoryOptions: details[@"options"]];
+
+ if (hiddenPreviewsBodyPlaceholder) {
+#if defined(__IPHONE_11_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0
+ return [UNNotificationCategory categoryWithIdentifier:identifier actions:actions intentIdentifiers:intentIdentifiers hiddenPreviewsBodyPlaceholder:hiddenPreviewsBodyPlaceholder options:options];
+#endif
+ }
+
+ return [UNNotificationCategory categoryWithIdentifier:identifier actions:actions intentIdentifiers:intentIdentifiers options:options];
+}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+
+RCT_MULTI_ENUM_CONVERTER(UNNotificationCategoryOptions, (@{
+ @"UNNotificationCategoryOptionNone": @(UNNotificationCategoryOptionNone),
+ @"UNNotificationCategoryOptionCustomDismissAction": @(UNNotificationCategoryOptionCustomDismissAction),
+ @"UNNotificationCategoryOptionAllowInCarPlay": @(UNNotificationCategoryOptionAllowInCarPlay),
+ @"UNNotificationCategoryOptionHiddenPreviewsShowTitle": @(UNNotificationCategoryOptionHiddenPreviewsShowTitle),
+ @"UNNotificationCategoryOptionHiddenPreviewsShowSubtitle": @(UNNotificationCategoryOptionHiddenPreviewsShowSubtitle),
+ }), UNNotificationCategoryOptionNone, integerValue)
+
+#pragma clang diagnostic pop
+
+
+@end
+
+@interface RCTEventEmitter ()
+- (void) addListener:(NSString *)eventName;
+@end
+
@interface RNFIRMessaging ()
@property (nonatomic, strong) NSMutableDictionary *notificationCallbacks;
@end
@implementation RNFIRMessaging
+static bool jsHandlerRegistered;
+static NSMutableArray* pendingNotifications;
+
RCT_EXPORT_MODULE();
- (NSArray *)supportedEvents {
@@ -144,21 +237,21 @@ RCT_EXPORT_MODULE();
}
+ (BOOL)requiresMainQueueSetup {
- return YES;
+ return YES;
}
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull RCTRemoteNotificationCallback)completionHandler {
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: userInfo];
[data setValue:@"remote_notification" forKey:@"_notificationType"];
[data setValue:@(RCTSharedApplication().applicationState == UIApplicationStateInactive) forKey:@"opened_from_tray"];
- [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
+ [self sendNotificationEventWhenAvailable:@{@"data": data, @"completionHandler": completionHandler}];
}
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification {
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: notification.userInfo];
[data setValue:@"local_notification" forKey:@"_notificationType"];
[data setValue:@(RCTSharedApplication().applicationState == UIApplicationStateInactive) forKey:@"opened_from_tray"];
- [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:@{@"data": data}];
+ [self sendNotificationEventWhenAvailable:@{@"data": data}];
}
+ (void)didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(nonnull RCTNotificationResponseCallback)completionHandler
@@ -169,14 +262,34 @@ RCT_EXPORT_MODULE();
if (response.actionIdentifier) {
[data setValue:response.actionIdentifier forKey:@"_actionIdentifier"];
}
- [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
+
+ if ([response isKindOfClass:UNTextInputNotificationResponse.class]) {
+ [data setValue:[(UNTextInputNotificationResponse *)response userText] forKey:@"_userText"];
+ }
+
+ NSDictionary *userInfo = @{@"data": data, @"completionHandler": completionHandler};
+ [self sendNotificationEventWhenAvailable:userInfo];
+
}
+ (void)willPresentNotification:(UNNotification *)notification withCompletionHandler:(nonnull RCTWillPresentNotificationCallback)completionHandler
{
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: notification.request.content.userInfo];
[data setValue:@"will_present_notification" forKey:@"_notificationType"];
- [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
+ [self sendNotificationEventWhenAvailable:@{@"data": data, @"completionHandler": completionHandler}];
+}
+
++ (void)sendNotificationEventWhenAvailable:(NSDictionary*)data
+{
+ if(!jsHandlerRegistered){
+ // JS hasn't registered callback yet. hold on that
+ if(!pendingNotifications){
+ pendingNotifications = [NSMutableArray array];
+ }
+ [pendingNotifications addObject:data];
+ } else {
+ [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:data];
+ }
}
- (void)dealloc
@@ -186,10 +299,11 @@ RCT_EXPORT_MODULE();
- (instancetype)init {
self = [super init];
+
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(handleNotificationReceived:)
- name:FCMNotificationReceived
- object:nil];
+ selector:@selector(handleNotificationReceived:)
+ name:FCMNotificationReceived
+ object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(sendDataMessageFailure:)
@@ -207,9 +321,38 @@ RCT_EXPORT_MODULE();
dispatch_async(dispatch_get_main_queue(), ^{
[[FIRMessaging messaging] setDelegate:self];
});
+
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ if(!jsHandlerRegistered){
+ [self sendPendingNotifications];
+ }
+ });
+
return self;
}
+-(void) addListener:(NSString *)eventName {
+ [super addListener:eventName];
+
+ if([eventName isEqualToString:FCMNotificationReceived]) {
+ [self sendPendingNotifications];
+ }
+}
+
+-(void) sendPendingNotifications {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ jsHandlerRegistered = true;
+
+ for (NSDictionary* data in pendingNotifications) {
+ [[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:data];
+ }
+
+ [pendingNotifications removeAllObjects];
+
+ });
+}
+
RCT_EXPORT_METHOD(enableDirectChannel)
{
[[FIRMessaging messaging] setShouldEstablishDirectChannel:@YES];
@@ -222,14 +365,25 @@ RCT_EXPORT_METHOD(isDirectChannelEstablished:(RCTPromiseResolveBlock)resolve rej
RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
- UILocalNotification *localUserInfo = self.bridge.launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
- if (localUserInfo) {
- resolve([[localUserInfo userInfo] copy]);
- } else {
- resolve([self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy]);
- }
+ NSDictionary* initialNotif;
+ NSDictionary *localUserInfo = [[self.bridge.launchOptions[UIApplicationLaunchOptionsLocalNotificationKey] userInfo] mutableCopy];
+
+ NSDictionary *remoteUserInfo = [self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] mutableCopy];
+ if(localUserInfo){
+ initialNotif = localUserInfo;
+ } else if (remoteUserInfo) {
+ initialNotif = remoteUserInfo;
+ }
+ if (initialNotif) {
+ [initialNotif setValue:@YES forKey:@"opened_from_tray"];
+ resolve(initialNotif);
+ } else {
+ resolve(nil);
+ }
}
+
+
RCT_EXPORT_METHOD(getAPNSToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
NSData * deviceToken = [FIRMessaging messaging].APNSToken;
@@ -246,6 +400,42 @@ RCT_EXPORT_METHOD(getFCMToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromi
resolve([FIRMessaging messaging].FCMToken);
}
+RCT_EXPORT_METHOD(getEntityFCMToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+ FIROptions *options = FIROptions.defaultOptions;
+ NSString *entity = options.GCMSenderID;
+ NSData * deviceToken = [FIRMessaging messaging].APNSToken;
+
+ if (deviceToken == nil) {
+ resolve(nil);
+ return;
+ }
+
+ [[FIRInstanceID instanceID]tokenWithAuthorizedEntity:entity scope:kFIRInstanceIDScopeFirebaseMessaging options:@{@"apns_token": deviceToken} handler:^(NSString * _Nullable token, NSError * _Nullable error) {
+
+ if (error != nil) {
+ reject([NSString stringWithFormat:@"%ld",error.code],error.localizedDescription,nil);
+ } else {
+ resolve(token);
+ }
+ }];
+}
+
+RCT_EXPORT_METHOD(deleteEntityFCMToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+ FIROptions *options = FIROptions.defaultOptions;;
+ NSString *entity = options.GCMSenderID;
+
+ [[FIRInstanceID instanceID]deleteTokenWithAuthorizedEntity:entity scope:kFIRInstanceIDScopeFirebaseMessaging handler:^(NSError * _Nullable error) {
+
+ if (error != nil) {
+ reject([NSString stringWithFormat:@"%ld",error.code],error.localizedDescription,nil);
+ } else {
+ resolve(nil);
+ }
+ }];
+}
+
RCT_EXPORT_METHOD(deleteInstanceId:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
[[FIRInstanceID instanceID]deleteIDWithHandler:^(NSError * _Nullable error) {
@@ -367,7 +557,9 @@ RCT_EXPORT_METHOD(removeAllDeliveredNotifications)
if([UNUserNotificationCenter currentNotificationCenter] != nil){
[[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];
} else {
- [RCTSharedApplication() setApplicationIconBadgeNumber: 0];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [RCTSharedApplication() setApplicationIconBadgeNumber: 0];
+ });
}
}
@@ -414,9 +606,25 @@ RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTPromiseResolveBlock)resolve
}
}
+RCT_EXPORT_METHOD(setNotificationCategories:(NSArray *)categories)
+{
+ if([UNUserNotificationCenter currentNotificationCenter] != nil) {
+ NSMutableSet *categoriesSet = [[NSMutableSet alloc] init];
+
+ for(NSDictionary *categoryDict in categories) {
+ UNNotificationCategory *category = [RCTConvert UNNotificationCategory:categoryDict];
+ [categoriesSet addObject:category];
+ }
+
+ [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categoriesSet];
+ }
+}
+
RCT_EXPORT_METHOD(setBadgeNumber: (NSInteger) number)
{
- [RCTSharedApplication() setApplicationIconBadgeNumber:number];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [RCTSharedApplication() setApplicationIconBadgeNumber:number];
+ });
}
RCT_EXPORT_METHOD(getBadgeNumber: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
@@ -486,9 +694,7 @@ RCT_EXPORT_METHOD(finishNotificationResponse: (NSString *)completionHandlerId){
self.notificationCallbacks[completionHandlerId] = completionHandler;
data[@"_completionHandlerId"] = completionHandlerId;
}
-
[self sendEventWithName:FCMNotificationReceived body:data];
-
}
- (void)sendDataMessageFailure:(NSNotification *)notification
diff --git a/ios/RNFIRMessaging.xcodeproj/project.pbxproj b/ios/RNFIRMessaging.xcodeproj/project.pbxproj
index f662aef6d3e04e7e8d0eb4cc1b1d7819a90c8d0c..855a0128228cac8dff27daf8ac2fe92ff7733ed2 100644
--- a/ios/RNFIRMessaging.xcodeproj/project.pbxproj
+++ b/ios/RNFIRMessaging.xcodeproj/project.pbxproj
@@ -230,6 +230,7 @@
"$(PROJECT_DIR)/../../../ios/Frameworks/**",
"$(SRCROOT)/../../../node_modules/react-native-firestack/ios/**",
"$(PROJECT_DIR)/../../../ios/Pods/Firebase/**",
+ "$(PROJECT_DIR)/../../../ios/Pods/Headers/Public/**",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
@@ -257,6 +258,7 @@
"$(PROJECT_DIR)/../../../ios/Frameworks/**",
"$(SRCROOT)/../../../node_modules/react-native-firestack/ios/**",
"$(PROJECT_DIR)/../../../ios/Pods/Firebase/**",
+ "$(PROJECT_DIR)/../../../ios/Pods/Headers/Public/**",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
diff --git a/package.json b/package.json
index a7eac5d9adffe9a837367d78bd58dad624c8c11f..138c264964773cbdbc11c1e8d1d7d9c2f8cad631 100644
--- a/package.json
+++ b/package.json
@@ -24,5 +24,5 @@
"type": "git",
"url": "git+https://github.com/evollu/react-native-fcm.git"
},
- "version": "11.0.1"
+ "version": "14.1.2"
}
diff --git a/react-native-fcm.podspec b/react-native-fcm.podspec
index 4cc7ab62d92e2a30e90fc1869b38591b290c83d1..0eb8862a9be8189b3a758794e13494fa7be848fb 100644
--- a/react-native-fcm.podspec
+++ b/react-native-fcm.podspec
@@ -12,6 +12,8 @@ Pod::Spec.new do |s|
s.source = { :git => 'https://github.com/evollu/react-native-fcm.git' }
s.platform = :ios, '8.0'
s.source_files = "ios/*.{h,m}"
+ s.public_header_files = ['ios/RNFIRMessaging.h']
+ s.static_framework = true
s.dependency "React"
s.dependency "Firebase/Messaging"