Hướng dẫn xây dựng ứng dụng gọi video 1-1 trên nền tảng React Native với Stringee Call API
Tổng quan về Stringee Call API
Chuẩn bị
Trước khi bạn có thể dùng Stringee Call API để tạo và nhận cuộc gọi video, bạn cần :
-
Tạo tài khoản Stringee miễn phí tại đây.
-
Tạo project trên Stringee Dashboard.
- Cấu hình answer_url
-
Để hiểu rõ hơn về answer_url, bạn xem tại đây .Bạn có thể tham khảo cách tạo answer_url tại đây
-
Để có thể thực hiệc cuộc gọi ban cần cấu hình answer_url vào project của bạn như sau:
Nếu bạn chưa có sẵn answer_url, bạn có thể sử dụng Project's answer_url sau để đẩy nhanh quá trình:
https://developer.stringee.com/scco_helper/simple_project_answer_url?record=false&appToPhone=auto&recordFormat=mp3
(Source code: https://github.com/stringeecom/server-samples/blob/master/answer_url/php/project_answer_url.php)
Khi xây dựng ứng dụng, bạn nên có answer_url của riêng mình.
Tích hợp stringee-react-native
Chuẩn bị
-
Tạo một project React Native.
-
Tạo một CallScreen để hiển thị màn hình của cuộc gọi.
Cài đặt stringee-react-native
- Ở terminal, chuyển đường dẫn tới React Native Project
- Chạy lệh
$ npm install stringee-react-native --save
Cài đặt với từng môi trường
Android
- Mở file build.gradle và thêm các dòng sau:
buildscript {
repositories {
...
mavenCentral()
}
}
...
allprojects {
repositories {
...
mavenCentral()
}
}
- Mở file app/build.gradle và thêm các dòng sau:
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
...
implementation 'com.android.volley:volley:1.2.1'
}
- Permissions
Với Android Stringee yêu cầu một số permissions, mở file AndroidManifest.xml và thêm các dòng sau:
/// permission cho việc kết nối internet
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
// permission cho cuộc gọi
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> // permission này mới thêm trên android sdk version 31
Ghi chú:
-
Bạn bắt buộc phải cấp đủ quyền trước khi thực hiện cuộc gọi, trước khi thực hiện cuộc gọi bàn bắt buộc yêu cầu các quyền sau: RECORD_AUDIO, CAMERA
-
Với việc sử dụng class StringeeAudioManager bạn cần cấp thêm quyền BLUETOOTH_CONNECT đối với android sdk version 31 trở lên
- ProGuard
- Tạo file proguard-rules.pro trong thư mục app và thêm:
-dontwarn org.webrtc.**
-keep class org.webrtc.** { *; }
-dontwarn org.apache.http.**
-keep class com.stringee.** { *; }
- Thêm các dòng sau trong app/buidl.gradle:
android {
...
buildTypes {
...
release {
...
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
iOS
- Vào thư mục iOS và chạy lệnh
pod install
- Thêm quyền truy cập camera và microphone vào file Info.split
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) uses Camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) uses Microphone</string>
Kết nối Stringee server
Để kết nối đến Stringee Server, bạn cần có access_token. Trong quá trình xây dựng ứng dụng, access_token nên được tạo ra từ server của bạn, bạn có thể tìm hiểu thêm về authentication ở đây: Client authentication, và code mẫu tạo access_token: https://github.com/stringeecom/server-samples/tree/master/access_token.
Để tiết kiệm thời gian, chúng tôi sẽ hard code access_token ở trong ứng dụng:
- Khởi tạo một biến để chứa access_token.
const token = "access_token";
- Lấy access_token và hard code dữ liệu :
Để làm điều đó, chúng tôi đã cung cấp sẵn tool để sinh ra access_token, bạn truy cập vào Dashboard -> Tools -> Generate Access token và sinh access_token của bạn.
Tiếp theo, chúng ta sẽ kết nối đến Stringee Server. Bạn cần phải kết nối được đến Stringee Server trước thì mới có thể thực hiện được cuộc gọi.
- Khởi tạo StringeeClient.
import { StringeeClient } from 'stringee-react-native'
...
const Home = () => {
const client = useRef();
useEffect(() => {
client.current.connect(userToken)
}, [])
const setupStringeeClient = () => {
<StringeeClient
ref={client}
/>
}
}
- Lắng nghe sự kiện từ StringeeClient để giao tiếp với Stringee Server trong eventHandlers của bạn:
const setupStringeeClient = () => {
const clientDidConnect = (data) => {
console.log(data)
setUserId(data.userId);
}
const clientDidDisConnect = (data) => {
console.log("clientDidDisConnect", data);
}
const clientDidFailWithError = (data) => {
console.log("clientDidFailWithError", data);
}
const clientRequestAccessToken = (data) => {
console.log("clientRequestAccessToken", data);
}
const callIncomingCall2 = (data) => {
console.log("onIncomingCall2", data);
}
const eventHandlers = {
onConnect: clientDidConnect,
onDisConnect: clientDidDisConnect,
onFailWithError: clientDidFailWithError,
onRequestAccessToken: clientRequestAccessToken,
onIncomingCall2: callIncomingCall2,
}
return (
<StringeeClient
ref={client}
eventHandlers={eventHandlers}
/>
)
}
Xử lý logic cuộc gọi
Sau khi kết nối đến Stringee Server, bạn cần thực hiện các bước sau:
- Khởi tạo đối tượng StringeeCall2 vào màn hình cuộc gọi và tiền xử lý cuộc gọi:
import { StringeeCall2, StringeeVideoView } from 'stringee-react-native'
const Call = ({ route }) => {
const call = useRef();
const setupStringeeCall2 = () => {
return (
<StringeeCall2
ref={call}
clientId={route.params.clientId}
/>
)
}
}
- Lắng nghe sự kiện của cuộc gọi trong eventHandlers:
const setupStringeeCall2 = () => {
const callDidChangeSignalingState = (data) => {
console.log('callDidChangeSignalingState', data);
switch (data.code) {
case 0:
break;
case 1:
break;
case 2:
setCallState(CallState.CALLING)
break;
case 3:
navigation.goBack()
break;
case 4:
navigation.goBack()
break;
}
}
const callDidChangeMediaState = (data) => {
console.log('callDidChangeMediaState', data);
}
const callDidReceiveLocalStream = (data) => {
console.log('callDidReceiveLocalStream', data);
setLocalStream(true)
}
const callDidReceiveRemoteStream = (data) => {
console.log('callDidReceiveRemoteStream', data);
setRemoteStream(true)
}
const didReceiveDtmfDigit = (data) => {
console.log('didReceiveDtmfDigit', data);
}
const didReceiveCallInfo = (data) => {
console.log('didReceiveCallInfo', data);
}
const didHandleOnAnotherDevice = (data) => {
console.log('didHandleOnAnotherDevice', data);
}
const didAudioDeviceChange = (data) => {
console.log('didAudioDeviceChange', data)
}
const callEvents = {
onChangeSignalingState: callDidChangeSignalingState,
onChangeMediaState: callDidChangeMediaState,
onReceiveLocalStream: callDidReceiveLocalStream,
onReceiveRemoteStream: callDidReceiveRemoteStream,
onReceiveDtmfDigit: didReceiveDtmfDigit,
onReceiveCallInfo: didReceiveCallInfo,
onHandleOnAnotherDevice: didHandleOnAnotherDevice,
onAudioDeviceChange: didAudioDeviceChange
}
-
Khi tạo/trả lời cuộc gọi thành công, cuộc gọi sẽ đi qua rất nhiều trạng thái như là: calling, ringing, answered, ended, busy. Mỗi lần trạng thái của cuộc gọi thay đổi, bạn sẽ nhận được event onChangeSignalingState.
-
Khi media stream của cuộc gọi đã kết nối hoặc mất kết nối, bạn sẽ nhận được event onChangeMediaState.
-
Khi cuộc gọi được xử lý trên thiết bị khác, bạn sẽ nhận được event onHandleOnAnotherDevice.
Tạo cuộc gọi đi
- Tạo một call object và đưa tới màn hình cuộc gọi.
const makeCall = () => {
navigation.navigate('Call', {
clientId: client.current.getId(),
callObj: {
from: userId,
to: toUserID,
isVideoCall: true,
videoResolution: 'NORMAL'
}
});
}
- Bắt đầu cuộc gọi ở màn hình call
useEffect(() => {
if (route.params.callObj) {
call.current.makeCall(JSON.stringify(route.params.callObj), (status, code, message, callId) =>{
console.log('makeCall', status, code, message);
setCallId(callId)
})
}
})
Trả lời cuộc gọi
- Bạn sẽ nhận được event onIncomingCall2 từ eventHandlers của StringeeClient đưa object nhận được tới màn hình call
const callIncomingCall2 = (data) => {
console.log("onIncomingCall2", data);
navigation.navigate('Call', { incomingCall: data, clientId: client.current.getId() })
}
- Ở màn hình call thực hiện khởi tạo cuộc gọi
useEffect(() => {
if (route.params.incomingCall) {
call.current.initAnswer(route.params.incomingCall.callId, (status, code, message) => {
console.log('initAnswer', status, code, message);
setCallId(route.params.incomingCall.callId);
})
}
})
- Tiếp nhận hoặc từ chối cuộc gọi
// trả lời cuộc gọi
call.current.answer(callId, (status, code, message) => {
if (status) {
setCallState(CallState.CALLING)
} else {
console.log('answer', status, code, message);
navigation.goBack();
}
})
// từ chối cuộc gọi
call.current.reject(callId, (status, code, message) => {
navigation.goBack()
console.log('reject', status, code, message);
})
Hiển thị video
stringee-react-native cung cấp component StringeeVideoView để hiển thị video
{remoteStream && <StringeeVideoView
style={styles.remoteView}
callId={callId}
local={false}
/>}
{localStream && <StringeeVideoView
callId={callId}
local={true}
style={styles.localView}
/>}
Ngừng cuộc gọi
Ngừng cuộc gọi và giải phóng tài nguyên của cuộc gọi:
call.current.hangup(callId, (status, code, message) => {
console.log('hangup', status, code, message);
navigation.goBack()
})
Chạy app
Bây giờ ứng dụng của bạn có thể chạy được trên thiết bị. Bạn có thể tham khảo sample phiên bản đầy đủ ở đây: https://github.com/stringeecom/react-native-samples
Xem thêm: Hướng dẫn xây dựng ứng dụng gọi video 1-1 trên nền tảng Android với Stringee Call API Xem thêm: Hướng dẫn viết ứng dụng gọi video 1-1 trên nền tảng iOS với Stringee Call API
All Rights Reserved