Skip to content

Commit 7e15a40

Browse files
committed
Add ConnectionService for Android
1 parent ff7eccd commit 7e15a40

File tree

14 files changed

+5236
-322
lines changed

14 files changed

+5236
-322
lines changed

README.md

Lines changed: 133 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,104 @@
1-
# React Native CallKit - iOS >= 10.0 only
1+
# React Native CallKeep
22

3-
[![npm version](https://badge.fury.io/js/react-native-callkit.svg)](https://badge.fury.io/js/react-native-callkit)
4-
[![npm downloads](https://img.shields.io/npm/dm/react-native-callkit.svg?maxAge=2592000)](https://img.shields.io/npm/dm/react-native-callkit.svg?maxAge=2592000)
3+
[![npm version](https://badge.fury.io/js/react-native-callkeep.svg)](https://badge.fury.io/js/react-native-callkeep)
4+
[![npm downloads](https://img.shields.io/npm/dm/react-native-callkeep.svg?maxAge=2592000)](https://img.shields.io/npm/dm/react-native-callkeep.svg?maxAge=2592000)
55

6-
**React Native CallKit** utilises a brand new iOS 10 framework **CallKit** to make the life easier for VoIP developers using React Native.
6+
**React Native CallKit** utilises a brand new iOS 10 framework **CallKit** and Android ConnectionService to make the life easier for VoIP developers using React Native.
77

8-
For more information about **CallKit**, please see [Official CallKit Framework Document][1] or [Introduction to CallKit by Xamarin][2]
8+
For more information about **CallKit** on iOS, please see [Official CallKit Framework Document](https://developer.apple.com/reference/callkit?language=objc) or [Introduction to CallKit by Xamarin](https://developer.xamarin.com/guides/ios/platform_features/introduction-to-ios10/callkit/)
9+
For more information about **ConnectionService** on Android, please see [Android Documentation](https://developer.android.com/reference/android/telecom/ConnectionService) and [Build a calling app](https://developer.android.com/guide/topics/connectivity/telecom/selfManaged)
910

10-
**Note**: Since CallKit is quite new, this module will be updated frequently so be careful with the version you are using.
1111

12-
## Version
12+
# Installation
1313

14-
Use version >= **1.1.0** if you're using react native >= 0.40
14+
```sh
15+
npm install --save react-native-callkeep
16+
# or
17+
yarn add react-native-callkeep
18+
```
19+
20+
## Automatic linking
21+
22+
```sh
23+
react-native link react-native-callkeep
24+
```
25+
26+
### IOS (with CocoaPods)
1527

16-
## Installation (without CocoaPods)
28+
Include in a Podfile in your react-native ios directory:
1729

18-
### NPM module
30+
```
31+
pod 'react-native-callkeep', :path => '../node_modules/react-native-callkeep'
32+
```
1933

34+
Then:
2035
```bash
21-
npm install --save react-native-callkit
36+
cd ios
37+
pod install
2238
```
2339

24-
### Link Library
40+
## Manual linking
2541

26-
```bash
27-
rnpm link react-native-callkit
42+
### Android
43+
44+
1. In `android/app/build.gradle`
45+
Should have a line `compile project(':react-native-callkeep')` in `dependencies {}` section.
46+
47+
2. In `android/settings.gradle`
48+
Should have:
49+
50+
```java
51+
include ':react-native-callkeep'
52+
project(':react-native-callkeep').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-callkeep/android')
2853
```
2954

30-
## Installation (with CocoaPods)
55+
3. In `MainApplication.java`:
3156

32-
### NPM module
57+
```java
58+
import io.wazo.callkeep.RNCallKeepPackage;
3359

34-
```bash
35-
npm install --save react-native-callkit
60+
private static List<ReactPackage> getPackages() {
61+
return Arrays.<ReactPackage>asList(
62+
new MainReactPackage(),
63+
new RNCallKeepPackage() // Add this line
64+
);
65+
}
3666
```
3767

38-
### CocaPods
39-
```bash
40-
cd ios
41-
pod install
68+
4. Add permissionResult listener in `MainActivity.java`:
69+
70+
```java
71+
import io.wazo.callkeep.RNCallKeepModule;
72+
73+
public class MainActivity extends ReactActivity {
74+
// ...
75+
76+
// Permission results
77+
@Override
78+
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {
79+
switch (permsRequestCode) {
80+
case RNCallKeepModule.REQUEST_READ_PHONE_STATE:
81+
RNCallKeepModule.onRequestPermissionsResult(grantResults);
82+
break;
83+
}
84+
}
85+
}
4286
```
4387

44-
## Installation common steps
88+
### iOS
4589

46-
### Info.plist
90+
1. Drag `node_modules/react-native-callkeep/ios/RNCallKeep.xcodeproj` under `<your_xcode_project>/Libraries`.
91+
92+
2. Select <your_xcode_project> --> Build Phases --> Link Binary With Libraries.
93+
Drag `Libraries/RNCallKeep.xcodeproj/Products/libRNCallKeep.a` to Link Binary With Libraries.
94+
95+
3. Select <your_xcode_project> --> Build Settings
96+
In `Header Search Paths`, add `$(SRCROOT)/../node_modules/react-native-callkeep/ios/RNCallKeep`.
97+
98+
99+
## iOS installation common steps
100+
101+
### Info.plist (iOS)
47102

48103
Add `voip` under `UIBackgroundModes`
49104

@@ -62,54 +117,47 @@ In `Xcode` -> `Build Phases` -> `Link Binary With Libraries`, add `CallKit.frame
62117

63118
### AppDelegate.m
64119

65-
#### - Import Library
120+
#### Import Library
66121

67122
```obj-c
68-
#import "RNCallKit.h"
123+
#import "RNCallKeep.h"
69124
```
70125

71-
#### - Change the way you initialise React Root View (required if <= 1.2.1)
72-
73-
Initialise **RNCallKit** first, since we need our custom `observer` of `NSNotificationCenter` to be started as soon as the app is initialising
74-
75-
```diff
76-
77-
// This is how you normally initialise React Root View, delete it
78-
-RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
79-
- moduleName:@"MyApp"
80-
- initialProperties:nil
81-
- launchOptions:launchOptions];
82-
83-
// Initialise RNCallKit
84-
+RNCallKit *rncallkit = [[RNCallKit alloc] init];
85-
86-
// Initialise React Bridge with RNCallKit
87-
+RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:jsCodeLocation
88-
+ moduleProvider:^{ return @[rncallkit]; }
89-
+ launchOptions:launchOptions];
90-
91-
// Initialise React Root View with React Bridge you've just created
92-
+RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
93-
+ moduleName:@"MyApp"
94-
+ initialProperties:nil];
95-
```
96-
97-
#### - Handling User Activity
126+
#### Handling User Activity
98127

99128
This delegate will be called when the user tries to start a call from native Phone App
100129

101130
```obj-c
102-
103131
- (BOOL)application:(UIApplication *)application
104132
continueUserActivity:(NSUserActivity *)userActivity
105133
restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
106134
{
107-
return [RNCallKit application:application
135+
return [RNCallKeep application:application
108136
continueUserActivity:userActivity
109137
restorationHandler:restorationHandler];
110138
}
139+
```
111140

141+
## Android common step installation
112142

143+
1. In `android/app/src/main/AndroidManifest.xml` add these permissions:
144+
145+
146+
```xml
147+
<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"/>
148+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
149+
150+
<application>
151+
// ...
152+
<service android:name="io.wazo.callkeep.VoiceConnectionService"
153+
android:label="Wazo"
154+
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
155+
<intent-filter>
156+
<action android:name="android.telecom.ConnectionService" />
157+
</intent-filter>
158+
</service>
159+
// ....
160+
</application>
113161
```
114162

115163
## API
@@ -124,7 +172,7 @@ continueUserActivity:(NSUserActivity *)userActivity
124172
- **ringtoneSound**: string (optional)
125173
- If provided, it will be played when incoming calls received; the system will use the default ringtone if this is not provided
126174

127-
Initialise RNCallKit with options
175+
Initialise RNCallKeep with options
128176

129177
### displayIncomingCall
130178

@@ -190,7 +238,7 @@ User start call action from **Recents** in built-in **Phone** app
190238

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

193-
After all works are done, remember to call `RNCallKit.startCall(uuid, calleeNumber)`
241+
After all works are done, remember to call `RNCallKeep.startCall(uuid, calleeNumber)`
194242

195243
### - answerCall
196244

@@ -222,13 +270,13 @@ Do your normal `Hang Up` actions here
222270

223271
### - didActivateAudioSession
224272

225-
The `AudioSession` has been activated by **RNCallKit**, you might want to do following things when receiving this event:
273+
The `AudioSession` has been activated by **RNCallKeep**, you might want to do following things when receiving this event:
226274

227275
- Start playing ringback if it is an outgoing call
228276

229277
### - didDisplayIncomingCall
230278

231-
Callback for `RNCallKit.displayIncomingCall`
279+
Callback for `RNCallKeep.displayIncomingCall`
232280

233281
**error**: string (optional)
234282

@@ -242,35 +290,35 @@ A call was muted by the system or the user:
242290

243291
```javascript
244292
import React from 'react';
245-
import RNCallKit from 'react-native-callkit';
293+
import RNCallKeep from 'react-native-callkeep';
246294

247295
import uuid from 'uuid';
248296

249-
class RNCallKitExample extends React.Component {
297+
class RNCallKeepExample extends React.Component {
250298
constructor(props) {
251299

252-
// Initialise RNCallKit
300+
// Initialise RNCallKeep
253301
let options = {
254-
appName: 'RNCallKitExample',
302+
appName: 'RNCallKeepExample',
255303
imageName: 'my_image_name_in_bundle',
256304
ringtoneSound: 'my_ringtone_sound_filename_in_bundle',
257305
};
258306
try {
259-
RNCallKit.setup(options);
307+
RNCallKeep.setup(options);
260308
} catch (err) {
261309
console.log('error:', err.message);
262310
}
263311

264-
// Add RNCallKit Events
265-
RNCallKit.addEventListener('didReceiveStartCallAction', this.onRNCallKitDidReceiveStartCallAction);
266-
RNCallKit.addEventListener('answerCall', this.onRNCallKitPerformAnswerCallAction);
267-
RNCallKit.addEventListener('endCall', this.onRNCallKitPerformEndCallAction);
268-
RNCallKit.addEventListener('didActivateAudioSession', this.onRNCallKitDidActivateAudioSession);
269-
RNCallKit.addEventListener('didDisplayIncomingCall', this.onRNCallKitDidDisplayIncomingCall);
270-
RNCallKit.addEventListener('didPerformSetMutedCallAction', this.onRNCallKitDidPerformSetMutedCallAction);
312+
// Add RNCallKeep Events
313+
RNCallKeep.addEventListener('didReceiveStartCallAction', this.onRNCallKeepDidReceiveStartCallAction);
314+
RNCallKeep.addEventListener('answerCall', this.onRNCallKeepPerformAnswerCallAction);
315+
RNCallKeep.addEventListener('endCall', this.onRNCallKeepPerformEndCallAction);
316+
RNCallKeep.addEventListener('didActivateAudioSession', this.onRNCallKeepDidActivateAudioSession);
317+
RNCallKeep.addEventListener('didDisplayIncomingCall', this.onRNCallKeepDidDisplayIncomingCall);
318+
RNCallKeep.addEventListener('didPerformSetMutedCallAction', this.onRNCallKeepDidPerformSetMutedCallAction);
271319
}
272320

273-
onRNCallKitDidReceiveStartCallAction(data) {
321+
onRNCallKeepDidReceiveStartCallAction(data) {
274322
/*
275323
* Your normal start call action
276324
*
@@ -279,10 +327,10 @@ class RNCallKitExample extends React.Component {
279327
*/
280328

281329
let _uuid = uuid.v4();
282-
RNCallKit.startCall(_uuid, data.handle);
330+
RNCallKeep.startCall(_uuid, data.handle);
283331
}
284332

285-
onRNCallKitPerformAnswerCallAction(data) {
333+
onRNCallKeepPerformAnswerCallAction(data) {
286334
/* You will get this event when the user answer the incoming call
287335
*
288336
* Try to do your normal Answering actions here
@@ -291,7 +339,7 @@ class RNCallKitExample extends React.Component {
291339
*/
292340
}
293341

294-
onRNCallKitPerformEndCallAction(data) {
342+
onRNCallKeepPerformEndCallAction(data) {
295343
/* You will get this event when the user finish the incoming/outgoing call
296344
*
297345
* Try to do your normal Hang Up actions here
@@ -300,21 +348,21 @@ class RNCallKitExample extends React.Component {
300348
*/
301349
}
302350

303-
onRNCallKitDidActivateAudioSession(data) {
304-
/* You will get this event when the the AudioSession has been activated by **RNCallKit**,
351+
onRNCallKeepDidActivateAudioSession(data) {
352+
/* You will get this event when the the AudioSession has been activated by **RNCallKeep**,
305353
* you might want to do following things when receiving this event:
306354
*
307355
* - Start playing ringback if it is an outgoing call
308356
*/
309357
}
310358

311-
onRNCallKitDidDisplayIncomingCall(error) {
312-
/* You will get this event after RNCallKit finishes showing incoming call UI
359+
onRNCallKeepDidDisplayIncomingCall(error) {
360+
/* You will get this event after RNCallKeep finishes showing incoming call UI
313361
* You can check if there was an error while displaying
314362
*/
315363
}
316364

317-
onRNCallKitDidPerformSetMutedCallAction(muted) {
365+
onRNCallKeepDidPerformSetMutedCallAction(muted) {
318366
/* You will get this event after the system or the user mutes a call
319367
* You can use it to toggle the mic on your custom call UI
320368
*/
@@ -323,23 +371,23 @@ class RNCallKitExample extends React.Component {
323371
// This is a fake function where you can receive incoming call notifications
324372
onIncomingCall() {
325373
// Store the generated uuid somewhere
326-
// You will need this when calling RNCallKit.endCall()
374+
// You will need this when calling RNCallKeep.endCall()
327375
let _uuid = uuid.v4();
328-
RNCallKit.displayIncomingCall(_uuid, "886900000000")
376+
RNCallKeep.displayIncomingCall(_uuid, "886900000000")
329377
}
330378

331379
// This is a fake function where you make outgoing calls
332380
onOutgoingCall() {
333381
// Store the generated uuid somewhere
334-
// You will need this when calling RNCallKit.endCall()
382+
// You will need this when calling RNCallKeep.endCall()
335383
let _uuid = uuid.v4();
336-
RNCallKit.startCall(_uuid, "886900000000")
384+
RNCallKeep.startCall(_uuid, "886900000000")
337385
}
338386

339387
// This is a fake function where you hang up calls
340388
onHangUpCall() {
341389
// get the _uuid you stored earlier
342-
RNCallKit.endCall(_uuid)
390+
RNCallKeep.endCall(_uuid)
343391
}
344392

345393
render() {
@@ -355,8 +403,3 @@ Any pull request, issue report and suggestion are highly welcome!
355403
## License
356404

357405
[ISC License][3] (functionality equivalent to **MIT License**)
358-
359-
[1]: https://developer.apple.com/reference/callkit?language=objc
360-
[2]: https://developer.xamarin.com/guides/ios/platform_features/introduction-to-ios10/callkit/
361-
[3]: https://opensource.org/licenses/ISC
362-
[4]: https://github.com/zxcpoiu/react-native-incall-manager

RNCallKit.podspec renamed to RNCallKeep.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ require 'json'
33
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
44

55
Pod::Spec.new do |s|
6-
s.name = "RNCallKit"
6+
s.name = "RNCallKeep"
77
s.version = package['version']
88
s.summary = package['description']
99
s.homepage = package['homepage']
@@ -12,7 +12,7 @@ Pod::Spec.new do |s|
1212
s.source = { :git => package['repository']['url'], :tag => "v#{s.version}" }
1313
s.requires_arc = true
1414
s.platform = :ios, "8.0"
15-
s.source_files = "ios/RNCallKit/*.{h,m}"
15+
s.source_files = "ios/RNCallKeep/*.{h,m}"
1616
s.dependency 'React/Core'
1717
end
1818

0 commit comments

Comments
 (0)