Commit 468f7bcb authored by Libin Lu's avatar Libin Lu

local notification running

parent 62521382
apply plugin: "com.android.application" apply plugin: "com.android.application"
apply plugin: "com.google.gms.google-services"
import com.android.build.OutputFile import com.android.build.OutputFile
...@@ -84,13 +83,13 @@ def enableSeparateBuildPerCPUArchitecture = false ...@@ -84,13 +83,13 @@ def enableSeparateBuildPerCPUArchitecture = false
def enableProguardInReleaseBuilds = false def enableProguardInReleaseBuilds = false
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "23.0.1" buildToolsVersion "27.0.3"
defaultConfig { defaultConfig {
applicationId "com.google.firebase.quickstart.fcm" applicationId "com.google.firebase.quickstart.fcm"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 22 targetSdkVersion 26
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
ndk { ndk {
...@@ -131,12 +130,14 @@ dependencies { ...@@ -131,12 +130,14 @@ dependencies {
transitive = false transitive = false
} }
compile(project(':react-native-maps')) { compile(project(':react-native-maps')) {
exclude group: 'com.google.android.gms', module: 'play-services-base' transitive = false
// This resolution make compiler ignoring play-service-base's version requirement in react-native-maps
// so that it only read from react-native-fcm
// you can also lock the version in this gradle file and ignore all module declaration
// or you can use ResolutionStragety
} }
implementation "com.google.android.gms:play-services-base:12.0.1"
implementation "com.google.firebase:firebase-core:12.0.1"
implementation "com.google.firebase:firebase-messaging:12.0.1"
implementation "com.google.android.gms:play-services-maps:12.0.1"
implementation 'me.leolin:ShortcutBadger:1.1.21@aar'
compile fileTree(dir: "libs", include: ["*.jar"]) compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.facebook.react:react-native:+" // From node_modules compile "com.facebook.react:react-native:+" // From node_modules
} }
...@@ -147,3 +148,5 @@ task copyDownloadableDepsToLibs(type: Copy) { ...@@ -147,3 +148,5 @@ task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile from configurations.compile
into 'libs' into 'libs'
} }
apply plugin: 'com.google.gms.google-services'
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.firebase.quickstart.fcm" package="com.google.firebase.quickstart.fcm">
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
...@@ -9,10 +7,6 @@ ...@@ -9,10 +7,6 @@
<uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application <application
android:name=".MainApplication" android:name=".MainApplication"
android:allowBackup="true" android:allowBackup="true"
...@@ -20,28 +14,28 @@ ...@@ -20,28 +14,28 @@
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<receiver android:name="com.evollu.react.fcm.FIRLocalMessagingPublisher"/> <service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService">
<receiver android:enabled="true" android:exported="true" android:name="com.evollu.react.fcm.FIRSystemBootEventReceiver">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name="com.evollu.react.fcm.MessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter> </intent-filter>
</service> </service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService">
<service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
<intent-filter> <intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter> </intent-filter>
</service> </service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
<receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver"/>
<receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
...@@ -53,13 +47,17 @@ ...@@ -53,13 +47,17 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="fcm.ACTION.HELLO" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity> </activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" /> <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_notif" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="test-channel"/>
</application> </application>
</manifest> </manifest>
...@@ -5,6 +5,9 @@ import android.util.Log; ...@@ -5,6 +5,9 @@ import android.util.Log;
import com.facebook.react.ReactApplication; import com.facebook.react.ReactApplication;
import io.invertase.firebase.RNFirebasePackage; import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;
import com.airbnb.android.react.maps.MapsPackage; import com.airbnb.android.react.maps.MapsPackage;
import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactNativeHost;
...@@ -27,7 +30,9 @@ public class MainApplication extends Application implements ReactApplication { ...@@ -27,7 +30,9 @@ public class MainApplication extends Application implements ReactApplication {
return Arrays.<ReactPackage>asList( return Arrays.<ReactPackage>asList(
new MainReactPackage(), new MainReactPackage(),
new RNFirebasePackage(), new RNFirebasePackage(),
new MapsPackage() new MapsPackage(),
new RNFirebaseNotificationsPackage(),
new RNFirebaseMessagingPackage()
); );
} }
}; };
......
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.android.tools.build:gradle:3.1.1'
classpath 'com.google.gms:google-services:3.0.0' classpath 'com.google.gms:google-services:3.1.2'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
...@@ -21,5 +22,6 @@ allprojects { ...@@ -21,5 +22,6 @@ allprojects {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android" url "$rootDir/../node_modules/react-native/android"
} }
google()
} }
} }
#Fri Jan 06 16:34:59 EST 2017 #Sun Apr 15 21:46:36 EDT 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
...@@ -19,11 +19,9 @@ import { StackNavigator } from 'react-navigation'; ...@@ -19,11 +19,9 @@ import { StackNavigator } from 'react-navigation';
import firebase from 'react-native-firebase'; import firebase from 'react-native-firebase';
import {registerKilledListener, registerAppListener} from "./Listeners"; import {registerAppListener} from "./Listeners";
import firebaseClient from "./FirebaseClient"; import firebaseClient from "./FirebaseClient";
registerKilledListener();
class MainPage extends Component { class MainPage extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -35,6 +33,13 @@ class MainPage extends Component { ...@@ -35,6 +33,13 @@ class MainPage extends Component {
} }
async componentDidMount(){ async componentDidMount(){
// Build a channel
const channel = new firebase.notifications.Android.Channel('test-channel', 'Test Channel', firebase.notifications.Android.Importance.Max)
.setDescription('My apps test channel');
// Create the channel
firebase.notifications().android.createChannel(channel);
registerAppListener(this.props.navigation); registerAppListener(this.props.navigation);
firebase.notifications().getInitialNotification() firebase.notifications().getInitialNotification()
.then((notificationOpen: NotificationOpen) => { .then((notificationOpen: NotificationOpen) => {
...@@ -55,7 +60,7 @@ class MainPage extends Component { ...@@ -55,7 +60,7 @@ class MainPage extends Component {
if (!await firebase.messaging().hasPermission()) { if (!await firebase.messaging().hasPermission()) {
try { try {
await firebase.messaging().requestPermission(); await firebase.messaging().requestPermission();
} catch { } catch(e) {
alert("Failed to grant permission") alert("Failed to grant permission")
} }
} }
...@@ -70,70 +75,54 @@ class MainPage extends Component { ...@@ -70,70 +75,54 @@ class MainPage extends Component {
firebase.messaging().unsubscribeFromTopic('sometopic'); firebase.messaging().unsubscribeFromTopic('sometopic');
} }
componentWillMount(){ componentWillUnmount(){
this.onTokenRefreshListener(); this.onTokenRefreshListener();
this.notificationOpenedListener(); this.notificationOpenedListener();
this.messageListener(); this.messageListener();
} }
showLocalNotification() { showLocalNotification() {
if(Platform.OS === 'ios'){ let notification = new firebase.notifications.Notification();
const notification = new firebase.notifications.Notification() notification = notification.setNotificationId(new Date().valueOf().toString())
.setNotificationId(new Date().valueOf().toString())
.setTitle( "Test Notification with action") .setTitle( "Test Notification with action")
.setBody("Force touch to reply") .setBody("Force touch to reply")
.setSound("bell.mp3") .setSound("bell.mp3")
.setCategory()
.setBadge(10)
.setData({ .setData({
key1: 'value1', key1: 'value1',
key2: 'value2', key2: 'value2'
});
}
FCM.presentLocalNotification({
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)
}); });
notification.ios.badge = 10
notification.android.setAutoCancel(true);
notification.android.setBigPicture("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png", "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg", "content title", "summary text")
notification.android.setColor("red")
notification.android.setColorized(true)
notification.android.setOngoing(true)
notification.android.setPriority(firebase.notifications.Android.Priority.High)
notification.android.setSmallIcon("ic_launcher")
notification.android.setVibrate([300])
notification.android.addAction(new firebase.notifications.Android.Action("view", "ic_launcher", "VIEW"))
notification.android.addAction(new firebase.notifications.Android.Action("dismiss", "ic_launcher", "DISMISS"))
notification.android.setChannelId("test-channel")
firebase.notifications().displayNotification(notification)
} }
scheduleLocalNotification() { scheduleLocalNotification() {
FCM.scheduleLocalNotification({ let notification = new firebase.notifications.Notification();
id: 'testnotif', notification = notification.setNotificationId(new Date().valueOf().toString())
fire_date: new Date().getTime()+5000, .setTitle( "Test Notification with action")
vibrate: 500, .setBody("Force touch to reply")
title: 'Hello', .setSound("bell.mp3")
body: 'Test Scheduled Notification', .setData({
sub_text: 'sub text', key1: 'value1',
priority: "high", key2: 'value2'
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',
wake_screen: true,
extra1: {a: 1},
extra2: 1
}); });
notification.android.setChannelId("test-channel")
notification.android.setPriority(firebase.notifications.Android.Priority.High)
notification.android.setSmallIcon("ic_launcher")
firebase.notifications().scheduleNotification(notification, { fireDate: new Date().getTime() + 5000 })
} }
sendRemoteNotification(token) { sendRemoteNotification(token) {
...@@ -146,10 +135,7 @@ class MainPage extends Component { ...@@ -146,10 +135,7 @@ class MainPage extends Component {
"custom_notification": { "custom_notification": {
"title": "Simple FCM Client", "title": "Simple FCM Client",
"body": "Click me to go to detail", "body": "Click me to go to detail",
"sound": "default", data: {targetScreen: 'detail'}
"priority": "high",
"show_in_foreground": true,
targetScreen: 'detail'
} }
}, },
"priority": 10 "priority": 10
...@@ -172,37 +158,6 @@ class MainPage extends Component { ...@@ -172,37 +158,6 @@ class MainPage extends Component {
firebaseClient.send(JSON.stringify(body), "notification"); firebaseClient.send(JSON.stringify(body), "notification");
} }
sendRemoteData(token) {
let body = {
"to": token,
"data":{
"title": "Simple FCM Client",
"body": "This is a notification with only DATA.",
"sound": "default"
},
"priority": "normal"
}
firebaseClient.send(JSON.stringify(body), "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() { render() {
let { token, tokenCopyFeedback } = this.state; let { token, tokenCopyFeedback } = this.state;
...@@ -225,18 +180,10 @@ class MainPage extends Component { ...@@ -225,18 +180,10 @@ class MainPage extends Component {
<Text style={styles.buttonText}>Send Remote Notification</Text> <Text style={styles.buttonText}>Send Remote Notification</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity onPress={() => this.sendRemoteData(token)} style={styles.button}>
<Text style={styles.buttonText}>Send Remote Data</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.showLocalNotification()} style={styles.button}> <TouchableOpacity onPress={() => this.showLocalNotification()} style={styles.button}>
<Text style={styles.buttonText}>Show Local Notification</Text> <Text style={styles.buttonText}>Show Local Notification</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity onPress={() => this.showLocalNotificationWithAction(token)} style={styles.button}>
<Text style={styles.buttonText}>Show Local Notification with Action</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.scheduleLocalNotification()} style={styles.button}> <TouchableOpacity onPress={() => this.scheduleLocalNotification()} style={styles.button}>
<Text style={styles.buttonText}>Schedule Notification in 5s</Text> <Text style={styles.buttonText}>Schedule Notification in 5s</Text>
</TouchableOpacity> </TouchableOpacity>
...@@ -245,7 +192,7 @@ class MainPage extends Component { ...@@ -245,7 +192,7 @@ class MainPage extends Component {
Init notif: Init notif:
</Text> </Text>
<Text> <Text>
{JSON.stringify(this.state.initNotif)} {JSON.stringify(this.state.initNotif && this.state.initNotif.data)}
</Text> </Text>
<Text style={styles.instructions}> <Text style={styles.instructions}>
......
...@@ -16,16 +16,19 @@ export function registerKilledListener(message: RemoteMessage){ ...@@ -16,16 +16,19 @@ export function registerKilledListener(message: RemoteMessage){
// these callback will be triggered only when app is foreground or background // these callback will be triggered only when app is foreground or background
export function registerAppListener(navigation){ export function registerAppListener(navigation){
this.notificationListener = firebase.notifications().onNotification(notification => {
firebase.notifications().displayNotification(notification);
})
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => { this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
const notif: Notification = notificationOpen.notification; const notif: Notification = notificationOpen.notification;
if(notif.targetScreen === 'detail'){ if(notif.data.targetScreen === 'detail'){
setTimeout(()=>{ setTimeout(()=>{
navigation.navigate('Detail') navigation.navigate('Detail')
}, 500) }, 500)
} }
setTimeout(()=>{ setTimeout(()=>{
alert(`User tapped notification\n${JSON.stringify(notif)}`) alert(`User tapped notification\n${notif.notificationId}`)
}, 500) }, 500)
}); });
...@@ -34,7 +37,16 @@ export function registerAppListener(navigation){ ...@@ -34,7 +37,16 @@ export function registerAppListener(navigation){
}); });
this.messageListener = firebase.messaging().onMessage((message: RemoteMessage) => { this.messageListener = firebase.messaging().onMessage((message: RemoteMessage) => {
// Process your message as required if(message.data && message.data.custom_notification){
let notification = new firebase.notifications.Notification();
notification = notification.setNotificationId(new Date().valueOf().toString())
.setTitle(message.title)
.setBody(message.body)
.setData(message.data)
.setSound("bell.mp3")
notification.android.setChannelId("test-channel")
firebase.notifications().displayNotification(notification);
}
}); });
} }
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
*/ */
import React, { Component } from 'react'; import React, { Component } from 'react';
import {registerKilledListener} from './app/Listeners';
import { import {
AppRegistry, AppRegistry,
StyleSheet, StyleSheet,
...@@ -21,3 +23,5 @@ export default class SimpleFcmClient extends Component { ...@@ -21,3 +23,5 @@ export default class SimpleFcmClient extends Component {
} }
AppRegistry.registerComponent('SimpleFcmClient', () => SimpleFcmClient); AppRegistry.registerComponent('SimpleFcmClient', () => SimpleFcmClient);
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => registerKilledListener);
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
import React, { Component } from 'react'; import React, { Component } from 'react';
import {registerKilledListener} from './app/Listeners';
import { import {
AppRegistry, AppRegistry,
...@@ -23,5 +22,3 @@ export default class SimpleFcmClient extends Component { ...@@ -23,5 +22,3 @@ export default class SimpleFcmClient extends Component {
} }
AppRegistry.registerComponent('SimpleFcmClient', () => SimpleFcmClient); AppRegistry.registerComponent('SimpleFcmClient', () => SimpleFcmClient);
\ No newline at end of file
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => registerKilledListener);
\ No newline at end of file
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#import <React/RCTBundleURLProvider.h> #import <React/RCTBundleURLProvider.h>
#import "RCTRootView.h" #import "RCTRootView.h"
#import <Firebase.h>
#import "RNFirebaseNotifications.h" #import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h" #import "RNFirebaseMessaging.h"
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ {
[FIRApp configure];
NSURL *jsCodeLocation; NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment