When a Stringee call is made, Stringee Server pushes a message to the client who receives the call. If the client has already connected to Stringee Server, the incoming call can be received via onIncomingCall event and you can ignore the pushed message. Otherwise (the client disconnects from Stringee Server or the app is killed) the client only receives a message pushed from Stringee Server. Then the client must connect to Stringee Server to receive the incoming call.
This tutorial will walk you through the steps of integrating push notification into your app to receive Stringee push message.
Stringee supports Push Notification via Firebase Cloud Messaging (Android) and Voip Notification APNS(iOS). First you get registration token for Push Notification from Firebase or APNS. Then you call Stringee API to register this token to Stringee server. Follow these steps:
The Callkit framework supports iOS 10 and above. Callkit lets Display the system-calling UI for your app's VoIP services, and coordinate your calling services with other apps and the system. For more information, see Callkit
The Pushkit framework supports iOS 8.0 and above. Pushkit sends specific types of notifications such as VoIP invitations, watchOS complication updates, and file provider change notifications... It's very useful for VoIP apps. For more information, see Pushkit
With Callkit and Pushkit support, you can display an incoming call:
Go to Stringee dashboard, choose Push Notification -> Choose your project -> Choose your existing app or create a new app.
Enter App name and Package name:
To integrate push notification, you must upload an APNs Auth Key. When sending push notifications using an APNs Auth Key, we require the following information about your app:
To create an APNs auth key, follow the steps below.
Visit the Apple Developer Member Center
Click on “Certificates, Identifiers & Profiles”. Go to Keys from the Left Menu. Create a new Auth Key by clicking on the “+” button in the top right corner.
On the following page, add a Key Name, and select APNs
Hit the Register button.
On this page, you will be able to download your auth key file. Please do not rename this file, and upload it as it is to our dashboard, as shown later below.
Locate and copy your Team ID – click on your name/company name at the top right corner, then select “View Account”.
Copy Team ID. Then go to the iOS app on Stringee dashboard and upload the APNs Auth Key. Click "Upload" button ==> Choose your APNs Auth Key, enter Key ID, Team Id ==> Upload.
To use Pushkit in react native, there are 2 options:
In this tutorial, we use react-native-voip-push-notification to work with Pushkit framework. And reactreact-native-callkeep to work with Callkit framework. You can check out their documentation for usage.
npm install --save react-native-voip-push-notification
cd ios/ && pod install
npm install --save react-native-callkeep
cd ios/ && pod install
Enable Push Notifications in Capabilities
Enable Voice over IP in Capabilities -> Background Modes
...
#import <PushKit/PushKit.h>
#import "RNVoipPushNotificationManager.h"
#import "RNCallKeep.h"
...
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
/* Add PushKit delegate method */
// --- Handle updated push credentials
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type {
// Register VoIP push token (a property of PKPushCredentials) with server
[RNVoipPushNotificationManager didUpdatePushCredentials:credentials forType:(NSString *)type];
}
// --- Handle incoming pushes (for ios <= 10)
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type {
[RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type];
}
// --- Handle incoming pushes (for ios >= 11)
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
NSString *uuid = [[NSUUID UUID] UUIDString];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:uuid forKey:@"uuid"];
// --- You should make sure to report to callkit BEFORE execute `completion()`
if ([[CXCallObserver alloc] init].calls.count == 0) {
// --- Process the received push
[[NSNotificationCenter defaultCenter] postNotificationName:@"voipRemoteNotificationReceived" object:self userInfo:dict];
[RNCallKeep reportNewIncomingCall:uuid handle:@"Stringee" handleType:@"generic" hasVideo:true localizedCallerName:@"Connecting..." fromPushKit: YES payload:nil];
} else {
// Show fake call
[RNCallKeep reportNewIncomingCall:uuid handle:@"Stringee" handleType:@"generic" hasVideo:true localizedCallerName:@"FakeCall" fromPushKit: YES payload:nil];
[RNCallKeep endCallWithUUID:uuid reason:1];
}
completion();
}
...
@end
After got the device token, register it to Stringee server
...
import { StringeeClient, StringeeCall } from "stringee-react-native";
import RNCallKeep from 'react-native-callkeep';
import VoipPushNotification from "react-native-voip-push-notification";
...
const iOS = Platform.OS === "ios" ? true : false;
const options = {
ios: {
appName: 'Stringee',
}
};
...
class MyComponent extends React.Component {
...
constructor(props) {
super(props);
...
if (iOS) {
RNCallKeep.setup(options);
VoipPushNotification.requestPermissions(); // required
VoipPushNotification.addEventListener('register', (token) => {
this.refs.stringeeClient.registerPush(
token,
false, // isProduction: false: In development, true: In Production.
true, // (iOS) isVoip: true: Voip PushNotification. Stringee supports this push notification.
(status, code, message) => {
console.log(message);
}
);
});
VoipPushNotification.addEventListener('notification', (notification) => {
// Handle incoming pushes
});
}
...
}
// The client connects to Stringee server
_clientDidConnect = ({ userId }) => {
...
if (iOS) {
VoipPushNotification.registerVoipToken();
}
...
}
render() {
return (
...
<View style={styles.container}>
<StringeeClient ref="stringeeClient" eventHandlers={this.clientEventHandlers} />
<StringeeCall ref="stringeeCall" eventHandlers={this.callEventHandlers}
</View>
...
);
}
...
}
When incomming call you can get 2 event: IncomingCall event and VoipPushNotification event And you have to show a Callkit with a uuid and you should save the uuid for controlling your CallKit
class MyComponent extends Component {
...
state = {
currentCallKitId: "",
};
...
}
Simple, you just show a Callkit
_callIncomingCall = ({ callId, from, to, fromAlias, toAlias, callType, isVideoCall }) => {
console.log("IncomingCallId-" + callId + ' from-' + from + ' to-' + to + ' fromAlias-' + fromAlias + ' toAlias-' + toAlias + ' isVideoCall-' + isVideoCall + 'callType-' + callType);
this.refs.stringeeCall.initAnswer(callId, (status, code, message) => {
console.log(message);
});
var callKitUUID = uuid.v1();
this.setState({ currentCallKitId: callKitUUID });
RNCallKeep.displayIncomingCall(callKitUUID, "Stringee", fromAlias, "generic", true);
}
When receive VoipPushNotification event, native ios will show a Callkit (unless a Callkit already exists) and response a CallkitUUID And your mission is saving the CallkitUUID to a state
VoipPushNotification.addEventListener('notification', (notification) => {
// Handle incoming pushes
callKitUUID = notification.getData().uuid;
if (this.state.currentCallKitId == "") {
this.setState({ currentCallKitId: callKitUUID });
} else {
// if Callkit already exists then end Callkit wiht the callKitUUID
RNCallKeep.endCall(callKitUUID);
}
});
After that, when handle IncomingCall event you need update information for the Callkit
_callIncomingCall = ({ callId, from, to, fromAlias, toAlias, callType, isVideoCall }) => {
console.log("IncomingCallId-" + callId + ' from-' + from + ' to-' + to + ' fromAlias-' + fromAlias + ' toAlias-' + toAlias + ' isVideoCall-' + isVideoCall + 'callType-' + callType);
this.refs.stringeeCall.initAnswer(callId, (status, code, message) => {
console.log(message);
});
if (this.state.currentCallKitId != "") {
RNCallKeep.updateDisplay(this.state.currentCallKitId, fromAlias, "")
} else {
var callKitUUID = uuid.v1();
this.setState({ currentCallKitId: callKitUUID });
RNCallKeep.displayIncomingCall(callKitUUID, "Stringee", fromAlias, "generic", true);
}
}
We're using Firebase Cloud Messaging (FCM) for push notification. So you must create a Firebase project in the Firebase console for Cloud Messaging projects. To create a FireBase project, go to https://console.firebase.google.com/
After creating a new FireBase project, add Firebase to your Android app
After adding app, download the google-services.json file.
Go to Firebase project console, choose Project Settings ==> Cloud Messaging, you'll get the Server key.
Go to Stringee Dashboard, choose Push Notificaton -> Choose your project -> Choose your app if existing or create new app -> Enter the Server key, project package name.
We suggest using React Native Firebase to get notification from Firebase.
Install React Native Firebase
# Using npm
npm install --save @react-native-firebase/app
# Using Yarn
yarn add @react-native-firebase/app
Install Cloud Messaging
# Install the messaging module
npm install @react-native-firebase/messaging
Copy google-services.json (From step 2.1) file into the /android/app directory.
Add the google-services plugin as a dependency inside of your /android/build.gradle file:
buildscript {
// ...
dependencies {
// ...
classpath 'com.google.gms:google-services:4.2.0' // google-services plugin
}
}
allprojects {
// ...
repositories {
// ...
maven {
url "https://maven.google.com" // Google's Maven repository
}
}
}
Lastly, execute the plugin by adding the following to the very bottom of your /android/app/build.gradlefile:
apply plugin: 'com.google.gms.google-services'
import messaging from '@react-native-firebase/messaging';
...
const token = messaging().getToken;
Register the registration token to Stringee Server In order to receive push notification, you must register the token to Stringee Server by calling:
class MyComponent extends React.Component {
...
componentWillMount() { // or anywhere which is most comfortable and appropriate for you
this.refs.stringeeClient.registerPush(
token,
false, // only for iOS
false, // only for iOS
(status, code, message) => {
console.log(message);
}
);
}
render() {
return (
<View style={styles.container}>
<StringeeClient ref="stringeeClient" eventHandlers={this.clientEventHandlers} />
</View>
);
}
...
}
...
messaging().onTokenRefresh(token => {
this.refs.stringeeClient.registerPush(
token,
true,
true,
(result, code, desc) => {},
);
});
...
Make sure you call the registerPush method to register the new token to Stringee server.
To receive messages, using messaging() from React Native Firebase:
import messaging from '@react-native-firebase/messaging';
...
messaging().setBackgroundMessageHandler(remoteMessage);
To show notification, we suggest using Notifee:
# Using npm
npm install --save @notifee/react-native
# Using Yarn
yarn add @notifee/react-native
...
async function onMessageReceived(message) {
const data = JSON.parse(message.data.data);
const callStatus = data.callStatus;
const from = data.from.number;
const notificationId = '11111'; // YOUR_NOTIFICATION_ID
console.log('data: ' + callStatus);
const channelId = await notifee.createChannel({
id: 'YOUR_CHANNEL_ID',
name: 'ChannelName',
vibration: true,
});
switch (callStatus) {
case 'started':
await notifee.displayNotification({
id: notificationId,
title: 'Incoming Call',
body: 'Call from ' + from,
android: {
channelId,
pressAction: {
id: 'default',
mainComponent: appName,
},
},
});
break;
case 'ended':
break;
}
}
messaging().setBackgroundMessageHandler(onMessageReceived);
...
@Override
protected String getMainComponentName() {
return NotifeeApiModule.getMainComponent("StringeeCallkit_ReactNative");
}
You should register push notification when you connect Stringee server first time:
this.refs.stringeeClient.registerPush(
token,
false, // isProduction: false: In development, true: In production.
true, // (iOS) isVoip: true: Voip PushNotification. Stringee supports this push notification.
(status, code, message) => {
console.log(message);
}
);
When you no longer want to receive push notification from Stringee server, you must call:
this.refs.stringeeClient.unregisterPush(
token,
(status, code, message) => {
console.log(message);
}
);
Now you complete the tutorial for push notification. You can view the completed sample on: iOS sample or Android sample.