Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react-native): add all push support to Expo and non ringing push for vanilla #1097

Merged
merged 42 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
5effedd
feat(react-native): add ringing screen
santhoshvai Sep 11, 2023
0647b26
chore: wip
santhoshvai Sep 13, 2023
02b355d
Merge branch 'main' into expo-ringing
santhoshvai Sep 13, 2023
eb608cf
chore: after prebuild
santhoshvai Sep 13, 2023
6183d99
chore: wip
santhoshvai Sep 13, 2023
f27e7e6
chore: fixed metro issues
santhoshvai Sep 14, 2023
df4e31c
feat: add android support
santhoshvai Sep 15, 2023
2aedb39
update to expo 49
santhoshvai Sep 15, 2023
5a70392
Merge branch 'main' into expo-ringing
santhoshvai Sep 15, 2023
4c670d3
chore: deps
santhoshvai Sep 15, 2023
b22ad51
chore: align deps
santhoshvai Sep 15, 2023
d35c4af
Merge branch 'main' into expo-ringing
santhoshvai Sep 15, 2023
1026f20
feat: add callkeep and voip
santhoshvai Sep 15, 2023
00bd006
chore: wip
santhoshvai Sep 15, 2023
f3d4132
feat: add ios plugin support
santhoshvai Sep 18, 2023
9fc583f
feat: add more more test
santhoshvai Sep 18, 2023
d655261
chore: test typos
santhoshvai Sep 18, 2023
3e68cf6
chore: add the expo specific config
santhoshvai Sep 19, 2023
7b8e102
chore: clean prebuild
santhoshvai Sep 19, 2023
d6a6484
chore: prebuild again
santhoshvai Sep 19, 2023
7a40495
chore: wip
santhoshvai Sep 19, 2023
caf75cd
chore: add notify to docs
santhoshvai Sep 19, 2023
7250514
fix: remove expo router warnings
santhoshvai Sep 21, 2023
e305d88
chore: wip
santhoshvai Sep 21, 2023
5dae537
feat: add remote notifications support to config plugins
santhoshvai Sep 21, 2023
b837631
feat: expo ios and android background listeners
santhoshvai Sep 28, 2023
4deeacb
chore: init expo docs
santhoshvai Sep 29, 2023
2dfefb9
chore: wip
santhoshvai Sep 29, 2023
8f5976a
feat: ios vanilla non ringing push
santhoshvai Oct 2, 2023
ed8179e
chore: complete docs
santhoshvai Oct 2, 2023
1cb42ea
Merge branch 'main' into expo-ringing
santhoshvai Oct 2, 2023
1e4658f
seitch on and offf vale appropriately
santhoshvai Oct 2, 2023
d437c47
vale fixes
santhoshvai Oct 2, 2023
57f786f
vale fix for UI
santhoshvai Oct 2, 2023
57d27a8
feat: add logout
santhoshvai Oct 2, 2023
5072957
fix: ts error
santhoshvai Oct 2, 2023
b69dfeb
feat: support not using stream backend
santhoshvai Oct 4, 2023
2afecc3
Merge branch 'main' into expo-ringing
santhoshvai Oct 4, 2023
4fbbdaf
feat: support not using stream backend
santhoshvai Oct 4, 2023
4f69a80
feat: remove permissions
santhoshvai Oct 4, 2023
dbc91a7
remove members addition in dogfood meeting
santhoshvai Oct 6, 2023
9310866
Merge branch 'main' into expo-ringing
vishalnarkhede Oct 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .github/actions/rn-bootstrap/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ runs:
run: yarn build:react-native:deps
shell: bash

- name: Setup and link permissions
if: ${{ env.INSTALL_IOS_PERMISSIONS == 'true' }}
working-directory: sample-apps/react-native/dogfood
run: npx react-native setup-ios-permissions
shell: bash

- name: Cache pods
uses: actions/cache@v3
if: ${{ env.INSTALL_PODS == 'true' }}
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/react-native-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ jobs:
INSTALL_NODE: true
INSTALL_PODS: true
INSTALL_RN_DEPENDENCIES: true
INSTALL_IOS_PERMISSIONS: true

- name: Test RN SDK
run: yarn test:react-native:sdk
Expand Down Expand Up @@ -99,7 +98,6 @@ jobs:
INSTALL_MAESTRO: true
INSTALL_VIDEO_BUDDY: true
INSTALL_RN_DEPENDENCIES: true
INSTALL_IOS_PERMISSIONS: true

- name: Test
working-directory: sample-apps/react-native/dogfood
Expand Down
4 changes: 4 additions & 0 deletions .styles/Vocab/Base/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ APNs
SFUs
RTMPs
broadcasted
unmount
websockets
hardcoded
UIs
370 changes: 0 additions & 370 deletions .yarn/patches/react-native-incall-manager-npm-4.0.1-b8859eeb2a.patch

This file was deleted.

4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,5 @@
"typescript": "^4.9.5",
"vercel": "^32.1.0",
"vite": "^4.4.9"
},
"resolutions": {
"react-native-incall-manager@^4.0.0": "patch:react-native-incall-manager@npm%3A4.0.1#./.yarn/patches/react-native-incall-manager-npm-4.0.1-b8859eeb2a.patch",
"react-native-incall-manager@^4.0.1": "patch:react-native-incall-manager@npm%3A4.0.1#./.yarn/patches/react-native-incall-manager-npm-4.0.1-b8859eeb2a.patch"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Add the following in your `AppDelegate.m` or `AppDelegate.mm` file:
</TabItem>
</Tabs>

<!-- vale on -->
#### Declare permissions

Application needs permissions to access camera, microphone and network state.
Expand Down Expand Up @@ -401,8 +402,7 @@ Hit save and you should see on your emulator or device the following UI.
## Step 5 - Setup Video Client

Within this configuration, we will establish a `StreamVideoClient` instance and facilitate the user's connection to the Stream Video service.
In real application, client creation should be encapsulated within a `useEffect` hook and during unmount you should call `client.disconnectUser()`
to avoid creating multiple websockets.
In real application, client creation should be encapsulated within a `useEffect` hook and during unmount you should call `client.disconnectUser()` to avoid creating multiple websockets.

Client instance needs to be provided to `StreamVideo` component and it will provide the client instance to all the child components using React Context.
It needs to go at the top of the component tree.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ android {
}
```

<!-- vale on -->
In `android/gradle.properties` add the following:

```groovy
Expand Down Expand Up @@ -231,7 +232,7 @@ In this example
- and `token` is the user token generated by your server-side API. For development purpose, you can use the token generated by the [Token Generator](https://getstream.io/chat/docs/react/token_generator/).
You can read more information about client authentication on the [Client & Authentication](../../core/client-auth) guide.

A call of type audio_room can exist in either of two states: backstage and live.
A call of type `audio_room` can exist in either of two states: backstage and live.

- During the backstage mode, only the host and designated speakers have permission to join the call.
- In the live mode, anyone can join the call.
Expand Down Expand Up @@ -807,7 +808,7 @@ const styles = StyleSheet.create({
```

:::info
In practical applications, depending on business requirements you may want to dynamically sort the participants list based on certain criteria for example dominant speaker first or alfabetical etc.
In practical applications, depending on business requirements you may want to dynamically sort the participants list based on certain criteria for example dominant speaker first or alphabetical etc.
You can pass comparator function to `useParticipants` hook to sort the participants list.

```tsx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ In `android/gradle.properties` add the following:
android.enableDexingArtifactTransform.desugaring=false
```

<!-- vale on -->
#### Run the app

To ensure the best possible experience, we highly recommend running the app on a physical device.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,4 @@ The following options are supported when creating a call:
| `startsAt` | When the call will start. Used for calls scheduled in the future, livestreams, audio rooms etc | - |
| `team` | Restrict the access to this call to a specific team | - |
| `ring` | If you want the call to ring for each member | false |
| `notify` | If you want the call to notify each member by sending push notification | false |
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,4 @@ To receive push notifications from Stream Video Server, you'll need to:

1. Configure your push notification provider on the [Stream Dashboard](https://dashboard.getstream.io).
2. Add the native setup for both iOS and Android.
3. Setup the push config for the SDK.

:::note
Push notifications are not supported by the SDK for Expo yet. We are working on this and it will be supported soon.
:::
3. Setup the push config for the SDK.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: VoIP using Apple Push Notification service (APNs)
title: Apple Push Notification service (APNs)
---

import DashboardApnVoipConfig from '../../../../../shared/video/_dashboard-apn-voip-config.md';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
---
id: setup
title: Setup
title: React Native
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

This guide discusses how to add push notifications to your project. It will discuss both Android and iOS and go through all the necessary steps.
This guide discusses how to add push notifications for ringing calls to your project. It will discuss both Android and iOS and go through all the necessary steps.

The normal user experience in a ringing app, when a user receives a call, is to show a push notification. The user can then interact with the notification to accept or reject the call. In this guide, you will learn how to set up your React Native app to get push notifications from Stream for the incoming calls that your user will receive.
The normal user experience in a ringing app, when a user receives a call, is to show a push notification. The user can then interact with the notification to accept or reject the call. In this guide, you will learn how to set up your React Native app to get push notifications from Stream for the incoming calls that your user will receive.

| Android preview | iOS preview |
|---|---|
| ![Android preview of the Firebase push notification](../../assets/06-advanced/04-push-notifications/android-preview.png) | ![iOS preview of VoIP notification using Apple Push Notification service (APNs)](../../assets/06-advanced/04-push-notifications/ios-preview.png)
| ![Android preview of the Firebase push notification](../../../assets/06-advanced/04-push-notifications/android-preview.png) | ![iOS preview of VoIP notification using Apple Push Notification service (APNs)](../../../assets/06-advanced/04-push-notifications/ios-preview.png)

## Add push provider credentials to Stream

Please follow the below guides for adding appropriate push providers to Stream:

- Android - [Firebase Cloud Messaging](../push-providers/firebase/)
- iOS - [VoIP using Apple Push Notification Service (APNs)](../push-providers/apn-voip/)
- Android - [Firebase Cloud Messaging](../../push-providers/firebase/)
- iOS - [Apple Push Notification Service (APNs)](../../push-providers/apn-voip/)

## Install Dependencies

The first step is to install all necessary packages with your package manager of choice. Specifically, you will need to install the Firebase-related packages (for this use case that is [React Native Firebase App module](https://www.npmjs.com/package/@react-native-firebase/app) and [React Native Firebase Messaging module](https://www.npmjs.com/package/@react-native-firebase/messaging)) to receive notifications on Android. Also, you need to install [React Native VoIP Push Notification](https://github.com/react-native-webrtc/react-native-voip-push-notification) package for interacting with VoIP push notifications on iOS. And finally, you need to install [React Native CallKeep](https://github.com/react-native-webrtc/react-native-callkeep) package to report incoming calls to iOS [CallKit](https://developer.apple.com/documentation/callkit).

```bash title=Terminal
yarn add \
@react-native-firebase/app \
@react-native-firebase/messaging \
react-native-callkeep \
react-native-voip-push-notification
yarn add @react-native-firebase/app
yarn add @react-native-firebase/messaging
yarn add react-native-callkeep
yarn add react-native-voip-push-notification
npx pod-install
```

Expand All @@ -42,34 +38,86 @@ So what did we install precisely?

## Android-specific setup

The only setup required for Android is to configure the Firebase library. Follow [this guide at react-native-firebase documentation](https://rnfirebase.io/#2-android-setup) to generate credentials for your Android app and configure Firebase.
1. To create a Firebase project, go to the [Firebase console](https://console.firebase.google.com/) and click on **Add project**.

## iOS-specific setup
2. In the console, click the setting icon next to **Project overview** and open **Project settings**. Then, under **Your apps**, click the Android icon to open **Add Firebase to your Android app** and follow the steps. **Make sure that the Android package name you enter is the same as the value of** `android.package` **from your app.json.**

3. After registering the app, download the **google-services.json** file and place it inside of your project at the following location: `/android/app/google-services.json.`

4. To allow Firebase on Android to use the credentials, the `google-services` plugin must be enabled on the project. This requires modification to two files in the Android directory. Add the highlighted lines in the relevant files:

### Configure Firebase
```groovy title="/android/build.gradle"
buildscript {
dependencies {
// ... other dependencies
// highlight-next-line
classpath 'com.google.gms:google-services:4.3.15'
}
}
```

Follow [this guide at react-native-firebase documentation](https://rnfirebase.io/#3-ios-setup) to generate credentials for your iOS app and configure Firebase.
```groovy title="/android/build.gradle"
apply plugin: 'com.android.application'
// highlight-next-line
apply plugin: 'com.google.gms.google-services'
```

:::note

We don't use Firebase cloud messaging for iOS in the SDK. But the `react-native-firebase` library will throw an error if iOS credentials are not added.
The **google-services.json** file contains unique and non-secret identifiers of your Firebase project. For more information, see [Understand Firebase Projects](https://firebase.google.com/docs/projects/learn-more#config-files-objects).

:::

### Request for notification permissions

At an appropriate place in your app, request for notification permissions from the user. Below is a small example of how to request permissions using [`react-native-permissions`](https://github.com/zoontek/react-native-permissions) library:
<!-- vale off -->

```js
import { requestNotifications } from 'react-native-permissions';

await requestNotifications(['alert', 'sound']);
```
<!-- vale on -->
## iOS-specific setup

### Disable Firebase installation

We don't use Firebase cloud messaging for iOS in the SDK. Unless Firebase is used for other purposes in your app, you can safely remove it from being installed by iOS and avoid the auto-linking. To do that create a file named `react-native.config.js` in the root of your project and add the following contents:

```js title="react-native.config.js"
module.exports = {
dependencies: {
'@react-native-firebase/app': {
platforms: {
ios: null,
},
},
'@react-native-firebase/messaging': {
platforms: {
ios: null,
},
},
},
};
```

Once this is done, `pod install` must be run again to remove the installed pods.

### Link required libraries for react native callkeep library

1. In Xcode: Click on `Build Phases` tab, then open `Link Binary With Libraries`.
2. Add `CallKit.framework`
3. Add `Intents.framework` (and mark it Optional).

![Example of how to use link libraries required for callkeep library](../../assets/06-advanced/04-push-notifications/ios-callkit-libraries-link.png)
![Example of how to use link libraries required for callkeep library](../../../assets/06-advanced/04-push-notifications/ios-callkit-libraries-link.png)

### Add header search path for react native callkeep library

1. In Xcode: Click on `Build Settings` tab, then search for `Header Search Paths`.
2. Add `$(SRCROOT)/../node_modules/react-native-callkeep/ios/RNCallKeep`.

![Example of how to add header search paths that are required for callkeep library](../../assets/06-advanced/04-push-notifications/ios-search-paths.png)
![Example of how to add header search paths that are required for callkeep library](../../../assets/06-advanced/04-push-notifications/ios-search-paths.png)

### Add background modes

Expand All @@ -78,7 +126,6 @@ In Xcode: Open `Info.plist` file and add the following in `UIBackgroundModes`. B
```xml
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
<string>voip</string>
</array>
```
Expand All @@ -95,7 +142,7 @@ Update `AppDelegate.m` or `AppDelegate.mm` in Xcode with the following parts for

At the top of the file, right after '#import "AppDelegate.h"', add the following headers to import and invoke the methods for the required libraries.

```c
```objectivec
// highlight-start
#import <Firebase.h>
#import "RNCallKeep.h"
Expand All @@ -108,17 +155,17 @@ At the top of the file, right after '#import "AppDelegate.h"', add the following

We need to configure the Firebase library, set up the callkeep library and register VoIP at the app launch. To do this, add the following methods to your existing `didFinishLaunchingWithOptions` method,

```c

```objectivec
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// highlight-next-line
[FIRApp configure];

// add your app name here
// highlight-start
NSString *localizedAppName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"];
NSString *appName = [[[NSBundle mainBundle] infoDictionary]objectForKey :@"CFBundleDisplayName"];
[RNCallKeep setup:@{
@"appName": @"My awesome app",
@"appName": localizedAppName != nil ? localizedAppName : appName,
@"supportsVideo": @YES,
// pass @YES here if you want the call to be shown in calls history in the built-in dialer app
@"includesCallsInRecents": @NO,
Expand All @@ -136,7 +183,7 @@ We need to configure the Firebase library, set up the callkeep library and regis

Add the following method to process the VoIP token from iOS and send it to the `react-native-voip-push-notification` library.

```c
```objectivec
// handle updated push credentials
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type {
[RNVoipPushNotificationManager didUpdatePushCredentials:credentials forType:(NSString *)type];
Expand All @@ -145,7 +192,7 @@ Add the following method to process the VoIP token from iOS and send it to the `

The final method to add is the one that gets invoked when there is a VoIP push notification from Stream. When there is a push notification and if the app is in the background, we want to display an incoming call notification. Add the following method to achieve this,

```c
```objectivec
// handle incoming pushes
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
// send event to JS
Expand Down Expand Up @@ -302,6 +349,16 @@ setPushConfig();
AppRegistry.registerComponent('app', () => App);
```

## Disabling push - usually on logout

In some cases you would want to disable push from happening. For example, if user logs out of your app. Or if the user switches. You can disable push like below:

```js
import { StreamVideoRN } from '@stream-io/video-react-native-sdk';

StreamVideoRN.onPushLogout();
```

## Troubleshooting

- During development, you may be facing a situation where push notification is shown but its events like accepting or rejecting a call don't work. This is because, during hot module reloading the global event listeners may get de-registered. To properly test during development, make sure that you fully restart the app or test in release mode without the metro packager.
Expand Down
Loading
Loading