Skip to content

Commit 4ae5507

Browse files
author
Brandon Huang
committed
2 parents 54e01f2 + 184b0c8 commit 4ae5507

File tree

21 files changed

+624
-171
lines changed

21 files changed

+624
-171
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Bug report
2+
3+
- [ ] I've checked the [example](https://github.com/react-native-webrtc/react-native-callkeep/tree/master/example) to reproduce the issue.
4+
5+
- Reproduced on:
6+
- [ ] Android
7+
- [ ] iOS
8+
9+
## Description
10+
11+
12+
## Steps to Reproduce
13+
14+
15+
## Versions
16+
- Callkeep:
17+
- React Native:
18+
- iOS:
19+
- Android:
20+
- Phone model:
21+
22+
23+
## Logs
24+
25+
```
26+
Paste here
27+
```

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
example/
2+
node_modules/

AUTHORS

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
CallKeep is a fork of react-native-callkit by ianlin.
2-
Since it only target iOS devices, we created CallKeep to target both Android and iOS.
2+
Since react-native-callkit only targets iOS devices, we created react-native-callkeep to target both Android and iOS.
33

44
Ian Yu-Hsun Lin <[email protected]>
55
Wazo Communication inc. <[email protected]>
6+
Dan Jenkins <[email protected]>
7+
Kyle Kurz <[email protected]>
8+
9+
Chevon Christie
10+
Linus Unnebäck <[email protected]>
11+
Geraint White <[email protected]>
12+
Samuel Bégin

MIGRATION_v2_v3.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Migration from CallKeep v2 to v3
2+
3+
Thanks to the Sangoma team, CallKeep now allows multi calls through native UI.
4+
Here's how to upgrade your codebase for this new version.
5+
6+
## Common
7+
8+
### setup
9+
10+
Since the v3, you have to call `setup` each time your application is launched.
11+
12+
### didPerformDTMFAction
13+
14+
`didPerformDTMFAction` now take `digits` instead of `dtmf` as key of its argument.
15+
16+
### didPerformSetMutedCallAction
17+
18+
`didPerformSetMutedCallAction` now returns an object as argument with `{ muted, callUUID }`.
19+
20+
### startCall
21+
22+
`startCall` takes 3 arguments now : `uuid`, `handle`, `contactIdentifier`.
23+
24+
### Call uuids
25+
26+
`setCurrentCallActive`, `endCall`, now takes a `callUuid` argument.
27+
28+
Events are also with an `callUUID` in the argument object.
29+
30+
### ⚠️ Lower case your uuids
31+
32+
There is no more check on the uuid case, everything is returned to your application in lower case.
33+
So you have to send lower cased uuid to allow matching your calls.
34+
35+
### News methods
36+
37+
There is now new method like [updateDisplay]()
38+
39+
## Android
40+
41+
### Update `MainActivity.java`
42+
43+
- Add new imports
44+
45+
```diff
46+
+ import android.support.annotation.NonNull;
47+
+ import android.support.annotation.Nullable;
48+
```
49+
50+
- Update `onRequestPermissionsResult` method:
51+
52+
```java
53+
// Permission results
54+
@Override
55+
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
56+
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
57+
switch (requestCode) {
58+
case RNCallKeepModule.REQUEST_READ_PHONE_STATE:
59+
RNCallKeepModule.onRequestPermissionsResult(requestCode, permissions, grantResults);
60+
break;
61+
}
62+
}
63+
```

README.md

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ RNCallKeep.setup(options);
9090
### setAvailable
9191
_This feature is available only on Android._
9292

93-
Tell _ConnectionService_ that the device is ready to make outgoing calls.
93+
Tell _ConnectionService_ that the device is ready to make outgoing calls via the native Phone app.
9494
If not the user will be stuck in the build UI screen without any actions.
95-
Eg: Call it with `false` when disconnected from the sip client, when your token expires ...
95+
Eg: Call it with `false` when disconnected from the sip client, when your token expires, when your user log out ...
96+
Eg: When your used log out (or the connection to your server is broken, etc..), you have to call `setAvailable(false)` so CallKeep will refuse the call and your user will not be stuck in the native UI.
9697

9798
```js
9899
RNCallKeep.setAvailable(true);
@@ -180,21 +181,17 @@ RNCallKeep.startCall(uuid, handle, contactIdentifier);
180181

181182

182183
### updateDisplay
183-
_This feature is available only on Android._
184-
185-
Sets the Android caller name and number
186-
Use this to update the Android display after an outgoing call has started
184+
Use this to update the display after an outgoing call has started.
187185

188186
```js
189-
RNCallKeep.updateDisplay(uuid, localizedCallerName, handle)
187+
RNCallKeep.updateDisplay(uuid, displayName, handle)
190188
```
191189
- `uuid`: string
192190
- The `uuid` used for `startCall` or `displayIncomingCall`
191+
- `displayName`: string (optional)
192+
- Name of the caller to be displayed on the native UI
193193
- `handle`: string
194194
- Phone number of the caller
195-
- `localizedCallerName`: string (optional)
196-
- Name of the caller to be displayed on the native UI
197-
198195

199196
### endCall
200197

@@ -324,6 +321,20 @@ _This feature is available only on Android._
324321
await RNCallKeep.hasPhoneAccount();
325322
```
326323

324+
### hasOutgoingCall (async)
325+
326+
_This feature is available only on Android, useful when waking up the application for an outgoing call._
327+
328+
When waking up the Android application in background mode (eg: when the application is killed and the user make a call from the native Phone application).
329+
The user can hang up the call before your application has been started in background mode, and you can lost the `RNCallKeepPerformEndCallAction` event.
330+
331+
To be sure that the outgoing call is still here, you can call `hasOutgoingCall` when you app waken up.
332+
333+
334+
```js
335+
const hasOutgoingCall = await RNCallKeep.hasOutgoingCall();
336+
```
337+
327338
### hasDefaultPhoneAccount
328339

329340
Checks if the user has set a default [phone account](https://developer.android.com/reference/android/telecom/PhoneAccount).
@@ -352,6 +363,8 @@ or by the app calling `RNCallKeep.startCall`.
352363

353364
Try to start your app call action from here (e.g. get credentials of the user by `data.handle` and/or send INVITE to your SIP server)
354365

366+
Note: on iOS `callUUID` is not defined as the call is not yet managed by CallKit. You have to generate your own and call `startCall`.
367+
355368
```js
356369
RNCallKeep.addEventListener('didReceiveStartCallAction', ({ handle, callUUID, name }) => {
357370

@@ -407,7 +420,7 @@ RNCallKeep.addEventListener('didActivateAudioSession', () => {
407420
Callback for `RNCallKeep.displayIncomingCall`
408421

409422
```js
410-
RNCallKeep.addEventListener('didDisplayIncomingCall', ({ error }) => {
423+
RNCallKeep.addEventListener('didDisplayIncomingCall', ({ error, uuid, handle, localizedCallerName, fromPushKit }) => {
411424
// you might want to do following things when receiving this event:
412425
// - Start playing ringback if it is an outgoing call
413426
});
@@ -458,6 +471,17 @@ RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits, callUUID }) => {
458471
- The digits that emit the dtmf tone
459472
- `callUUID` (string)
460473
- The UUID of the call.
474+
475+
### - checkReachability
476+
477+
On Android when the application is in background, after a certain delay the OS will close every connection with informing about it.
478+
So we have to check if the application is reachable before making a call from the native phone application.
479+
480+
```js
481+
RNCallKeep.addEventListener('checkReachability', () => {
482+
RNCallKeep.setReachable();
483+
});
484+
```
461485

462486
## Example
463487

@@ -564,7 +588,7 @@ class RNCallKeepExample extends React.Component {
564588
onDTMFAction = (data) => {
565589
let { digits, callUUID } = data;
566590
// Called when the system or user performs a DTMF action
567-
}
591+
};
568592

569593
audioSessionActivated = (data) => {
570594
// you might want to do following things when receiving this event:
@@ -584,6 +608,36 @@ class RNCallKeepExample extends React.Component {
584608
}
585609
```
586610

611+
## Receiving a call when the application is not reachable.
612+
613+
In some case your application can be unreachable :
614+
- when the user kill the application
615+
- when it's in background since a long time (eg: after ~5mn the os will kill all connections).
616+
617+
To be able to wake up your application to display the incoming call, you can use [https://github.com/ianlin/react-native-voip-push-notification](react-native-voip-push-notification) on iOS or BackgroundMessaging from [react-native-firebase](https://rnfirebase.io/docs/v5.x.x/messaging/receiving-messages#4)-(Optional)(Android-only)-Listen-for-FCM-messages-in-the-background).
618+
619+
You have to send a push to your application, like with Firebase for Android and with a library supporting PushKit pushes for iOS.
620+
621+
### PushKit
622+
623+
Since iOS 13, you'll have to report the incoming calls that wakes up your application with a VoIP push. Add this in your `AppDelegate.m` if you're using VoIP pushes to wake up your application :
624+
625+
```objective-c
626+
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
627+
// Process the received push
628+
[RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type];
629+
630+
// Retrieve information like handle and callerName here
631+
// NSString *uuid = /* fetch for payload or ... */ [[[NSUUID UUID] UUIDString] lowercaseString];
632+
// NSString *callerName = @"caller name here";
633+
// NSString *handle = @"caller number here";
634+
635+
[RNCallKeep reportNewIncomingCall:uuid handle:handle handleType:@"generic" hasVideo:false localizedCallerName:callerName fromPushKit: YES];
636+
637+
completion();
638+
}
639+
```
640+
587641
## Debug
588642

589643
### Android

actions.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,17 @@ const RNCallKeepDidPerformSetMutedCallAction = 'RNCallKeepDidPerformSetMutedCall
1313
const RNCallKeepDidToggleHoldAction = 'RNCallKeepDidToggleHoldAction';
1414
const RNCallKeepDidPerformDTMFAction = 'RNCallKeepDidPerformDTMFAction';
1515
const RNCallKeepProviderReset = 'RNCallKeepProviderReset';
16+
const RNCallKeepCheckReachability = 'RNCallKeepCheckReachability';
1617
const isIOS = Platform.OS === 'ios';
1718

18-
const didReceiveStartCallAction = handler =>
19-
eventEmitter.addListener(RNCallKeepDidReceiveStartCallAction, (data) => handler(data));
19+
const didReceiveStartCallAction = handler => {
20+
if (isIOS) {
21+
// Tell CallKeep that we are ready to receive `RNCallKeepDidReceiveStartCallAction` event and prevent delay
22+
RNCallKeepModule._startCallActionEventListenerAdded();
23+
}
24+
25+
return eventEmitter.addListener(RNCallKeepDidReceiveStartCallAction, (data) => handler(data));
26+
};
2027

2128
const answerCall = handler =>
2229
eventEmitter.addListener(RNCallKeepPerformAnswerCallAction, (data) => handler(data));
@@ -45,6 +52,9 @@ const didPerformDTMFAction = handler =>
4552
const didResetProvider = handler =>
4653
eventEmitter.addListener(RNCallKeepProviderReset, handler);
4754

55+
const checkReachability = handler =>
56+
eventEmitter.addListener(RNCallKeepCheckReachability, handler);
57+
4858
export const listeners = {
4959
didReceiveStartCallAction,
5060
answerCall,
@@ -56,5 +66,5 @@ export const listeners = {
5666
didToggleHoldCallAction,
5767
didPerformDTMFAction,
5868
didResetProvider,
69+
checkReachability,
5970
};
60-
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2016-2019 The CallKeep Authors (see the AUTHORS file)
3+
* SPDX-License-Identifier: ISC, MIT
4+
*
5+
* Permission to use, copy, modify, and distribute this software for any
6+
* purpose with or without fee is hereby granted, provided that the above
7+
* copyright notice and this permission notice appear in all copies.
8+
*
9+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16+
*/
17+
18+
package io.wazo.callkeep;
19+
20+
import android.content.Intent;
21+
import android.os.Bundle;
22+
import android.util.Log;
23+
24+
import com.facebook.react.HeadlessJsTaskService;
25+
import com.facebook.react.bridge.WritableMap;
26+
import com.facebook.react.bridge.Arguments;
27+
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
28+
29+
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALLER_NAME;
30+
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_NUMBER;
31+
import static io.wazo.callkeep.RNCallKeepModule.EXTRA_CALL_UUID;
32+
33+
import javax.annotation.Nullable;
34+
35+
public class RNCallKeepBackgroundMessagingService extends HeadlessJsTaskService {
36+
@Override
37+
protected @Nullable
38+
HeadlessJsTaskConfig getTaskConfig(Intent intent) {
39+
Bundle extras = intent.getExtras();
40+
41+
return new HeadlessJsTaskConfig(
42+
"RNCallKeepBackgroundMessage",
43+
Arguments.fromBundle(extras),
44+
60000,
45+
false
46+
);
47+
}
48+
}

0 commit comments

Comments
 (0)