Skip to content

Commit

Permalink
Merge pull request #41 from linhvovan29546/dev/example-callkeep
Browse files Browse the repository at this point in the history
Dev/example callkeep
  • Loading branch information
linhvovan29546 authored Mar 25, 2023
2 parents 0e78cc6 + 4557cda commit 377ceef
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ protected void onCreate(Bundle savedInstanceState) {
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
Bundle bundle = getIntent().getExtras();

if (bundle.containsKey("mainComponent")) {
if (bundle.containsKey("mainComponent") && bundle.getString("mainComponent")!=null) {
setContentView(R.layout.custom_ingcoming_call_rn);
Fragment reactNativeFragment = new ReactFragment.Builder()
.setComponentName(bundle.getString("mainComponent"))
Expand Down
21 changes: 19 additions & 2 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

<!--callkeep-->
<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
Expand Down Expand Up @@ -50,7 +55,19 @@
android:enabled="true"
android:stopWithTask="false"
android:exported="true" />

<!--callkeep-->
<service android:name="io.wazo.callkeep.VoiceConnectionService"
android:label="Wazo"
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
android:foregroundServiceType="camera|microphone"
android:exported="true"
>

<intent-filter>
<action android:name="android.telecom.ConnectionService" />
</intent-filter>
</service>
<service android:name="io.wazo.callkeep.RNCallKeepBackgroundMessagingService" android:exported="true"/>
</application>

</manifest>
10 changes: 6 additions & 4 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.11",
"@react-navigation/native": "^5.8.0",
"@react-navigation/stack": "^5.10.0",
"react": "17.0.2",
"react-native": "0.65.1",
"react-native-background-timer": "^2.4.1",
"react-native-callkeep": "^4.3.8",
"react-native-gesture-handler": "^1.10.3",
"react-native-permissions": "^3.8.0",
"react-native-reanimated": "^1.13.1",
"react-native-safe-area-context": "^4.4.1",
"react-native-screens": "^3.18.2",
"uuid-random": "^1.3.2",
"@react-navigation/native": "^5.8.0",
"@react-navigation/stack": "^5.10.0"
"uuid-random": "^1.3.2"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/runtime": "^7.12.5",
"babel-plugin-module-resolver": "^4.0.0",
"metro-react-native-babel-preset": "^0.66.0"
}
}
}
51 changes: 6 additions & 45 deletions example/src/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,17 @@ import { StyleSheet, View, Text, TouchableOpacity } from 'react-native';
import ramdomUuid from 'uuid-random';
import BackgroundTimer from 'react-native-background-timer';
import { useNavigation } from '@react-navigation/native';

import { CallKeepService } from '../services/CallKeepService';
import RNCallKeep from 'react-native-callkeep';
CallKeepService.instance().setupCallKeep()
export default function Home() {
const navigation = useNavigation();
React.useEffect(() => {
RNNotificationCall.addEventListener('answer', (data: answerPayload) => {
const { callUUID, payload } = data;
console.log('press answer', data);
RNNotificationCall.backToApp();
});
RNNotificationCall.addEventListener('endCall', (data: declinePayload) => {
const { callUUID, endAction, payload } = data;
console.log('press endCall', data);
});

return () => {
RNNotificationCall.removeEventListener('answer');
RNNotificationCall.removeEventListener('endCall');
};
}, []);
const getCurrentCallId = () => {
return ramdomUuid().toLowerCase();
};
CallKeepService.navigation = navigation
const display = () => {
// Start a timer that runs once after X milliseconds
const timeoutId = BackgroundTimer.setTimeout(() => {
// this will be executed once after 10 seconds
// even when app is the the background
const uid = getCurrentCallId();
console.log('uid', uid);
RNNotificationCall.displayNotification(uid, null, 30000, {
channelId: 'com.abc.incomingcall',
channelName: 'Incoming video call',
notificationIcon: 'ic_launcher', //mipmap
notificationTitle: 'Linh Vo',
notificationBody: 'Incoming video call',
answerText: 'Answer',
declineText: 'Decline',
notificationColor: 'colorAccent', //path color in android
notificationSound: undefined, //raw
mainComponent: 'MyReactNativeApp',
payload: {
kiokas: 'ádada',
ssskis: 'awq',
},
});
// Cancel the timeout if necessary
BackgroundTimer.clearTimeout(timeoutId);
}, 0);

//rest of code will be performing for iOS on background too
const uuid = ramdomUuid()
CallKeepService.instance().displayCall(uuid)
};
const onHide = () => {
RNNotificationCall.hideNotification();
Expand Down
166 changes: 166 additions & 0 deletions example/src/services/CallKeepService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { PermissionsAndroid, Platform } from 'react-native';
import RNNotificationCall, {
answerPayload,
declinePayload,
} from '../../../src/index';
import RNCallKeep from 'react-native-callkeep';
import { request, check, PERMISSIONS, RESULTS } from 'react-native-permissions';

const appName = 'Incoming-Test';
const isAndroid = Platform.OS === 'android';
const answerOption = {
channelId: 'com.abc.incomingcall',
channelName: 'Incoming video call',
notificationIcon: 'ic_launcher', //mipmap
notificationTitle: 'Linh Vo',
answerText: 'Answer',
declineText: 'Decline',
notificationColor: 'colorAccent', //path color in android
notificationSound: undefined, //raw
};
// this service only focus for Android

export class CallKeepService {
private static _instance?: CallKeepService;
static navigation: any;
constructor() {
//setup callkeep
// this.setupCallKeep();
}
static instance(): CallKeepService {
if (!CallKeepService._instance) {
CallKeepService._instance = new CallKeepService();
}
return CallKeepService._instance;
}

async setupCallKeep() {
await new Promise((resolve) => {
console.log('setup call keep done in promise');
this.setupCallKeepFunc().then(resolve);
});
}

async setupCallKeepFunc() {
const granted = await request(PERMISSIONS.ANDROID.READ_PHONE_NUMBERS);
if (granted !== RESULTS.GRANTED) return;
//only setup when granted permission
await this.setup();
//setup done
if (isAndroid) {
RNCallKeep.setAvailable(true);
}
this.registerEvent();
}
async setup() {
try {
await RNCallKeep.setup({
ios: {
appName: appName,
maximumCallGroups: '1',
maximumCallsPerCallGroup: '1',
includesCallsInRecents: false,
imageName: 'callkitIcon', //image name from ios
},
android: {
alertTitle: 'Permissions required',
alertDescription:
'This application needs to access your phone accounts',
cancelButton: 'Cancel',
okButton: 'ok',
selfManaged: true,
additionalPermissions: [],
foregroundService: {
channelId: 'com.test.app.callkeep',
channelName: 'Incoming Call',
notificationTitle: 'Incoming Call',
notificationIcon: 'ic_launcher_round',
},
},
});
return {
result: 'setupDone',
};
} catch (error) {
console.log('error setup callkeep', error);
return error;
}
}
registerEvent() {
isAndroid &&
RNCallKeep.addEventListener(
'createIncomingConnectionFailed',
this.onFailCallAction
);
RNCallKeep.addEventListener('answerCall', this.onCallKeepAnswerCallAction);
RNCallKeep.addEventListener('endCall', this.onCallKeepEndCallAction);
if (isAndroid) {
//event only on android
RNCallKeep.addEventListener(
'showIncomingCallUi',
({ handle, callUUID, name }) => {
RNNotificationCall.displayNotification(callUUID, null, 30000, {
...answerOption,
channelId: 'com.abc.incomingcall',
channelName: 'Incoming video call',
notificationTitle: 'Linh Vo',
notificationBody: 'Incoming video call',
payload: {
kiokas: 'ádada',
ssskis: 'awq',
},
});
}
);
// Listen to headless action events
RNNotificationCall.addEventListener('endCall', (data: declinePayload) => {
const { callUUID } = data;
// End call action here
console.log('endCall', callUUID);
RNCallKeep.endCall(callUUID);
});
RNNotificationCall.addEventListener('answer', (data: answerPayload) => {
const { callUUID } = data;
//open app from quit state
RNNotificationCall.backToApp();
//call api answer
console.log('answer', callUUID);
RNCallKeep.answerIncomingCall(callUUID);
});
// You can listener firebase message event here
}
}
onFailCallAction() {
RNCallKeep.endAllCalls();
}

//handle event
onCallKeepAnswerCallAction(answerData: any) {
const { callUUID } = answerData;
// called when the user answer the incoming call
//navigate to another screen
//some project need to rehandle with redux state or other state manager refer https://github.com/linhvovan29546/react-native-full-screen-notification-incoming-call/issues/17#issuecomment-1318225574
CallKeepService.navigation.navigate('Detail');
}
onCallKeepEndCallAction(answerData: any) {
const { callUUID } = answerData;
//end call action of callkit
//action destroy screen
//You need to call RNCallKeep.endCall(callUUID) to end call
}

async displayCall(uuid: string) {
const granted = await check(PERMISSIONS.ANDROID.READ_PHONE_NUMBERS);
//only display call when permission granted
if (granted !== RESULTS.GRANTED) return;
console.log('display call', uuid);
RNCallKeep.displayIncomingCall(
uuid,
'Linh Vo',
'Linh Vo',
'number',
true,
undefined
);
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-full-screen-notification-incoming-call",
"version": "0.1.10",
"version": "0.1.11",
"description": "Android full screen notification incoming call for React Native",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down Expand Up @@ -143,5 +143,6 @@
}
]
]
}
},
"dependencies": {}
}

0 comments on commit 377ceef

Please sign in to comment.