Skip to content

Refactor / Simplify Codes, support didLoadWithEvents #69

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

Merged
merged 6 commits into from
Dec 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2016, Ian Yu-Hsun Lin
Copyright (c) 2016-2020, The react-native-voip-push-notification Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
Expand Down
185 changes: 101 additions & 84 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@

React Native VoIP Push Notification - Currently iOS >= 8.0 only

## Motivation

Since iOS 8.0 there is an execellent feature called **VoIP Push Notification** ([PushKit][1]), while in React Native only the traditional push notification is supported which limits the possibilities of building a VoIP app with React Native (like me!).

To understand the benefits of **Voip Push Notification**, please see [VoIP Best Practices][2].

**Note 1**: Not sure if Android support this sort of stuff since I'm neither an iOS nor Android expert, from my limited understanding that GCM's [sending high priority push notification][5] might be the case. Correct me if I'm wrong!

**Note 2** This module is inspired by [PushNotificationIOS][6] and [React Native Push Notification][7]

## RN Version

* 1.1.0+ ( RN 40+ )
Expand Down Expand Up @@ -103,7 +93,19 @@ Make sure you enabled the folowing in `Xcode` -> `Signing & Capabilities`:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];



// ===== (THIS IS OPTIONAL) =====
// --- register VoipPushNotification here ASAP rather than in JS. Doing this from the JS side may be too slow for some use cases
// --- see: https://github.com/react-native-webrtc/react-native-voip-push-notification/issues/59#issuecomment-691685841
[RNVoipPushNotificationManager voipRegistration];
// ===== (THIS IS OPTIONAL) =====



RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"AppName" initialProperties:nil];
}

...
Expand All @@ -121,13 +123,7 @@ Make sure you enabled the folowing in `Xcode` -> `Signing & Capabilities`:
// --- The system calls this method when a previously provided push token is no longer valid for use. No action is necessary on your part to reregister the push type. Instead, use this method to notify your server not to send push notifications using the matching push token.
}


// --- 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)
// --- Handle incoming pushes
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {


Expand Down Expand Up @@ -160,34 +156,61 @@ Make sure you enabled the folowing in `Xcode` -> `Signing & Capabilities`:
## Linking:

On RN60+, auto linking with pod file should work.
Or you can try below:

## Linking Manually:
<details>
<summary>Linking Manually</summary>

### Add PushKit Framework:
### Add PushKit Framework:

- In your Xcode project, select `Build Phases` --> `Link Binary With Libraries`
- Add `PushKit.framework`

### Add RNVoipPushNotification:

#### Option 1: Use [rnpm][3]

```bash
rnpm link react-native-voip-push-notification
```

**Note**: If you're using rnpm link make sure the `Header Search Paths` is `recursive`. (In step 3 of manually linking)

#### Option 2: Manually

1. Drag `node_modules/react-native-voip-push-notification/ios/RNVoipPushNotification.xcodeproj` under `<your_xcode_project>/Libraries`
2. Select `<your_xcode_project>` --> `Build Phases` --> `Link Binary With Libraries`
- Drag `Libraries/RNVoipPushNotification.xcodeproj/Products/libRNVoipPushNotification.a` to `Link Binary With Libraries`
3. Select `<your_xcode_project>` --> `Build Settings`
- In `Header Search Paths`, add `$(SRCROOT)/../node_modules/react-native-voip-push-notification/ios/RNVoipPushNotification` with `recursive`
</details>

- In your Xcode project, select `Build Phases` --> `Link Binary With Libraries`
- Add `PushKit.framework`
## API and Usage:

### Add RNVoipPushNotification:
#### Native API:

#### Option 1: Use [rnpm][3]
Voip Push is time sensitive, these native API mainly used in AppDelegate.m, especially before JS bridge is up.
This usually

```bash
rnpm link react-native-voip-push-notification
```
* `(void)voipRegistration` ---
register delegate for PushKit if you like to register in AppDelegate.m ASAP instead JS side ( too late for some use cases )
* `(void)didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type` ---
call this api to fire 'register' event to JS
* `(void)didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type` ---
call this api to fire 'notification' event to JS
* `(void)addCompletionHandler:(NSString *)uuid completionHandler:(RNVoipPushNotificationCompletion)completionHandler` ---
add completionHandler to RNVoipPush module
* `(void)removeCompletionHandler:(NSString *)uuid` ---
remove completionHandler to RNVoipPush module

**Note**: If you're using rnpm link make sure the `Header Search Paths` is `recursive`. (In step 3 of manually linking)
#### JS API:

#### Option 2: Manually
* `registerVoipToken()` --- JS method to register PushKit delegate
* `onVoipNotificationCompleted(notification.uuid)` --- JS mehtod to tell PushKit we have handled received voip push

1. Drag `node_modules/react-native-voip-push-notification/ios/RNVoipPushNotification.xcodeproj` under `<your_xcode_project>/Libraries`
2. Select `<your_xcode_project>` --> `Build Phases` --> `Link Binary With Libraries`
- Drag `Libraries/RNVoipPushNotification.xcodeproj/Products/libRNVoipPushNotification.a` to `Link Binary With Libraries`
3. Select `<your_xcode_project>` --> `Build Settings`
- In `Header Search Paths`, add `$(SRCROOT)/../node_modules/react-native-voip-push-notification/ios/RNVoipPushNotification` with `recursive`
#### Events:

## Usage:
* `'register'` --- fired when PushKit give us the latest token
* `'notification'` --- fired when received voip push notification
* `'didLoadWithEvents'` --- fired when there are not-fired events been cached before js bridge is up

```javascript

Expand All @@ -201,51 +224,48 @@ class MyComponent extends React.Component {

...

componentDidMount() { // or anywhere which is most comfortable and appropriate for you
VoipPushNotification.requestPermissions(); // --- optional, you can use another library to request permissions
VoipPushNotification.registerVoipToken(); // --- required

VoipPushNotification.addEventListener('register', (token) => {
// --- send token to your apn provider server
});

VoipPushNotification.addEventListener('localNotification', (notification) => {
// --- when user click local push
});

VoipPushNotification.addEventListener('notification', (notification) => {
// --- when receive remote voip push, register your VoIP client, show local notification ... etc
//this.doRegisterOrSomething();
// --- or anywhere which is most comfortable and appropriate for you, usually ASAP
componentDidMount() {
VoipPushNotification.registerVoipToken(); // --- register token

VoipPushNotification.addEventListener('didLoadWithEvents', (events) => {
// --- this will fire when there are events occured before js bridge initialized
// --- use this event to execute your event handler manually by event type

if (!events || !Array.isArray(events) || events.length < 1) {
return;
}
for (let voipPushEvent of events) {
let { name, data } = voipPushEvent;
if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) {
this.onVoipPushNotificationRegistered(data);
} else if (name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent) {
this.onVoipPushNotificationiReceived(data);
}
}
});

// --- This is a boolean constant exported by this module
// --- you can use this constant to distinguish the app is launched by VoIP push notification or not
if (VoipPushNotification.wakeupByPush) {
// this.doSomething()

// --- remember to set this static variable back to false
// --- since the constant are exported only at initialization time, and it will keep the same in the whole app
VoipPushNotification.wakeupByPush = false;
}


// --- optionally, if you `addCompletionHandler` from the native side, once you have done the js jobs to initiate a call, call `completion()`
VoipPushNotification.onVoipNotificationCompleted(notification.getData().uuid);


/**
* Local Notification Payload
*
* - `alertBody` : The message displayed in the notification alert.
* - `alertAction` : The "action" displayed beneath an actionable notification. Defaults to "view";
* - `soundName` : The sound played when the notification is fired (optional).
* - `category` : The category of this notification, required for actionable notifications (optional).
* - `userInfo` : An optional object containing additional notification data.
*/
VoipPushNotification.presentLocalNotification({
alertBody: "hello! " + notification.getMessage()
});
});
}
// --- onVoipPushNotificationRegistered
VoipPushNotification.addEventListener('register', (token) => {
// --- send token to your apn provider server
});

// --- onVoipPushNotificationiReceived
VoipPushNotification.addEventListener('notification', (notification) => {
// --- when receive remote voip push, register your VoIP client, show local notification ... etc
this.doSomething();

// --- optionally, if you `addCompletionHandler` from the native side, once you have done the js jobs to initiate a call, call `completion()`
VoipPushNotification.onVoipNotificationCompleted(notification.uuid);
});
}

// --- unsubscribe event listeners
componentWillUnmount() {
VoipPushNotification.removeEventListener('didLoadWithEvents');
VoipPushNotification.removeEventListener('register');
VoipPushNotification.removeEventListener('notification');
}
...
}

Expand All @@ -263,6 +283,3 @@ class MyComponent extends React.Component {
[2]: https://developer.apple.com/library/ios/documentation/Performance/Conceptual/EnergyGuide-iOS/OptimizeVoIP.html
[3]: https://github.com/rnpm/rnpm
[4]: https://opensource.org/licenses/ISC
[5]: https://developers.google.com/cloud-messaging/concept-options#setting-the-priority-of-a-message
[6]: https://facebook.github.io/react-native/docs/pushnotificationios.html
[7]: https://github.com/zo0r/react-native-push-notification
Loading