Skip to content

Commit 8ef2532

Browse files
committed
Add simple example of CallKeep integration
1 parent 724104d commit 8ef2532

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+7966
-0
lines changed

example/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
node_modules/**/*
2+
.expo/*
3+
npm-debug.*
4+
*.jks
5+
*.p8
6+
*.p12
7+
*.key
8+
*.mobileprovision
9+
*.orig.*
10+
web-build/
11+
web-report/
12+
13+
ios/Pods/

example/.watchmanconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

example/App.js

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { Platform, StyleSheet, Text, View, TouchableOpacity, ScrollView } from 'react-native';
3+
import uuid from 'uuid';
4+
import RNCallKeep from 'react-native-callkeep';
5+
import BackgroundTimer from 'react-native-background-timer';
6+
import DeviceInfo from 'react-native-device-info';
7+
8+
BackgroundTimer.start();
9+
10+
const hitSlop = { top: 10, left: 10, right: 10, bottom: 10};
11+
const styles = StyleSheet.create({
12+
container: {
13+
flex: 1,
14+
marginTop: 20,
15+
backgroundColor: '#fff',
16+
alignItems: 'center',
17+
justifyContent: 'center',
18+
},
19+
button: {
20+
marginTop: 20,
21+
marginBottom: 20,
22+
},
23+
logContainer: {
24+
flex: 3,
25+
width: '100%',
26+
backgroundColor: '#D9D9D9',
27+
},
28+
log: {
29+
fontSize: 10,
30+
}
31+
});
32+
33+
RNCallKeep.setup({
34+
ios: {
35+
appName: 'CallKeepDemo',
36+
},
37+
android: {
38+
alertTitle: 'Permissions required',
39+
alertDescription: 'This application needs to access your phone accounts',
40+
cancelButton: 'Cancel',
41+
okButton: 'ok',
42+
},
43+
});
44+
45+
const getNewUuid = () => uuid.v4().toLowerCase();
46+
47+
const format = uuid => uuid.split('-')[0];
48+
49+
const getRandomNumber = () => String(Math.floor(Math.random() * 100000));
50+
51+
export default function App() {
52+
const [logText, setLog] = useState('');
53+
const [calls, setCalls] = useState({}); // callKeep uuid: number
54+
55+
const log = (text) => {
56+
console.info(text);
57+
setLog(logText + "\n" + text);
58+
};
59+
60+
const addCall = (callUUID, number) => setCalls({ ...calls, [callUUID]: number });
61+
const removeCall = (callUUID) => {
62+
const { [callUUID]: _, ...updated } = calls;
63+
setCalls(updated);
64+
};
65+
66+
const displayIncomingCall = (number) => {
67+
const callUUID = getNewUuid();
68+
addCall(callUUID, number);
69+
70+
log(`[displayIncomingCall] ${format(callUUID)}, number: ${number}`);
71+
72+
RNCallKeep.displayIncomingCall(callUUID, number, number, 'number', false);
73+
};
74+
75+
const displayIncomingCallNow = () => {
76+
displayIncomingCall(getRandomNumber());
77+
};
78+
79+
const displayIncomingCallDelayed = () => {
80+
BackgroundTimer.setTimeout(() => {
81+
displayIncomingCall(getRandomNumber());
82+
}, 3000);
83+
};
84+
85+
const answerCall = ({ callUUID }) => {
86+
const number = calls[callUUID];
87+
log(`[answerCall] ${format(callUUID)}, number: ${number}`);
88+
89+
RNCallKeep.startCall(callUUID, number, number);
90+
RNCallKeep.setCurrentCallActive(callUUID);
91+
};
92+
93+
const didPerformDTMFAction = ({ callUUID, digits }) => {
94+
const number = calls[callUUID];
95+
log(`[didPerformDTMFAction] ${format(callUUID)}, number: ${number} (${digits})`);
96+
};
97+
98+
const didReceiveStartCallAction = ({ handle }) => {
99+
if (!handle) {
100+
// @TODO: sometime we receive `didReceiveStartCallAction` with handle` undefined`
101+
return;
102+
}
103+
const callUUID = getNewUuid();
104+
addCall(callUUID, handle);
105+
106+
log(`[didReceiveStartCallAction] ${callUUID}, number: ${handle}`);
107+
108+
RNCallKeep.startCall(callUUID, handle, handle);
109+
RNCallKeep.setCurrentCallActive(callUUID);
110+
};
111+
112+
const didPerformSetMutedCallAction = ({ muted, callUUID }) => {
113+
const number = calls[callUUID];
114+
log(`[didPerformSetMutedCallAction] ${format(callUUID)}, number: ${number} (${muted})`);
115+
};
116+
117+
const didToggleHoldCallAction = ({ hold, callUUID }) => {
118+
const number = calls[callUUID];
119+
log(`[didToggleHoldCallAction] ${format(callUUID)}, number: ${number} (${hold})`);
120+
};
121+
122+
const endCall = ({ callUUID }) => {
123+
const handle = calls[callUUID];
124+
log(`[endCall] ${format(callUUID)}, number: ${handle}`);
125+
console.log('handle', handle);
126+
127+
removeCall(callUUID);
128+
};
129+
130+
const hangup = (callUUID) => {
131+
RNCallKeep.endCall(callUUID);
132+
removeCall(callUUID);
133+
};
134+
135+
useEffect(() => {
136+
RNCallKeep.addEventListener('answerCall', answerCall);
137+
RNCallKeep.addEventListener('didPerformDTMFAction', didPerformDTMFAction);
138+
RNCallKeep.addEventListener('didReceiveStartCallAction', didReceiveStartCallAction);
139+
RNCallKeep.addEventListener('didPerformSetMutedCallAction', didPerformSetMutedCallAction);
140+
RNCallKeep.addEventListener('didToggleHoldCallAction', didToggleHoldCallAction);
141+
RNCallKeep.addEventListener('endCall', endCall);
142+
143+
return () => {
144+
RNCallKeep.removeEventListener('answerCall', answerCall);
145+
RNCallKeep.removeEventListener('didPerformDTMFAction', didPerformDTMFAction);
146+
RNCallKeep.removeEventListener('didReceiveStartCallAction', didReceiveStartCallAction);
147+
RNCallKeep.removeEventListener('didPerformSetMutedCallAction', didPerformSetMutedCallAction);
148+
RNCallKeep.removeEventListener('didToggleHoldCallAction', didToggleHoldCallAction);
149+
RNCallKeep.removeEventListener('endCall', endCall);
150+
}
151+
});
152+
153+
if (Platform.OS === 'ios' && DeviceInfo.isEmulator()) {
154+
return <Text style={styles.container}>CallKeep doesn't work on iOS emulator</Text>;
155+
}
156+
157+
return (
158+
<View style={styles.container}>
159+
<TouchableOpacity onPress={displayIncomingCallNow} style={styles.button} hitSlop={hitSlop}>
160+
<Text>Display incoming call now</Text>
161+
</TouchableOpacity>
162+
163+
<TouchableOpacity onPress={displayIncomingCallDelayed} style={styles.button} hitSlop={hitSlop}>
164+
<Text>Display incoming call now in 3s</Text>
165+
</TouchableOpacity>
166+
167+
{Object.keys(calls).map(callUUID => (
168+
<TouchableOpacity key={callUUID} onPress={() => hangup(callUUID)} style={styles.button} hitSlop={hitSlop}>
169+
<Text>Hangup {calls[callUUID]}</Text>
170+
</TouchableOpacity>
171+
))}
172+
173+
<ScrollView style={styles.logContainer}>
174+
<Text style={styles.log}>
175+
{logText}
176+
</Text>
177+
</ScrollView>
178+
</View>
179+
);
180+
}

example/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# CallKeep example
2+
3+
4+
5+
## How to install it
6+
7+
```
8+
# Install dependancies
9+
yarn install
10+
11+
cd ios
12+
pod install
13+
```
14+
15+
## How to use it
16+
17+
```
18+
# Start metro bundler
19+
yarn start
20+
21+
# Start the application (in another term)
22+
yarn android # or yarn ios
23+
```
24+
25+
26+
## How this example was setted up
27+
28+
```sh
29+
expo init CallKeepDemo
30+
expo eject
31+
yarn add react-native-callkeep
32+
./node_modules/.bin/react-native link react-native-callkeep
33+
```

example/android/app/BUCK

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# To learn about Buck see [Docs](https://buckbuild.com/).
2+
# To run your application with Buck:
3+
# - install Buck
4+
# - `npm start` - to start the packager
5+
# - `cd android`
6+
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7+
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8+
# - `buck install -r android/app` - compile, install and run application
9+
#
10+
11+
lib_deps = []
12+
13+
for jarfile in glob(['libs/*.jar']):
14+
name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
15+
lib_deps.append(':' + name)
16+
prebuilt_jar(
17+
name = name,
18+
binary_jar = jarfile,
19+
)
20+
21+
for aarfile in glob(['libs/*.aar']):
22+
name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
23+
lib_deps.append(':' + name)
24+
android_prebuilt_aar(
25+
name = name,
26+
aar = aarfile,
27+
)
28+
29+
android_library(
30+
name = "all-libs",
31+
exported_deps = lib_deps,
32+
)
33+
34+
android_library(
35+
name = "app-code",
36+
srcs = glob([
37+
"src/main/java/**/*.java",
38+
]),
39+
deps = [
40+
":all-libs",
41+
":build_config",
42+
":res",
43+
],
44+
)
45+
46+
android_build_config(
47+
name = "build_config",
48+
package = "com.callkeepdemo",
49+
)
50+
51+
android_resource(
52+
name = "res",
53+
package = "com.callkeepdemo",
54+
res = "src/main/res",
55+
)
56+
57+
android_binary(
58+
name = "app",
59+
keystore = "//android/keystores:debug",
60+
manifest = "src/main/AndroidManifest.xml",
61+
package_type = "debug",
62+
deps = [
63+
":app-code",
64+
],
65+
)

0 commit comments

Comments
 (0)