Build ứng dụng Voice Call trên nền tảng Android
Build ứng dụng Voice call/Video call
Danh sách bài học
Build ứng dụng Voice Call trên nền tảng Android
Xây dựng Ứng dụng Voice Call trên Android
Ở bài trước, chúng ta đã cùng thực hiện BUILD MỘT ỨNG DỤNG VIDEO CALL TRÊN NỀN TẢNG IOS.
Và một nền tảng mobile cũng rất phổ biến khác đó chính là Android. Ở bài học này, Kteam sẽ hướng dẫn các bạn cách xây dựng ứng dụng voice call trên nền tảng Android
Chúng ta cùng bắt đầu ngay nhé!
Nội dung
Trong bài này, Kteam sẽ hướng dẫn bạn các nội dung chính như sau:
- Thêm Stringee SDK vào project
- Kết nối Stringee server
- Xử lý luồng tạo cuộc gọi đi
- Xử lý luồng nhận cuộc gọi đến
- Thêm các tính năng phụ: mute,đổi loa
- Test lại luồng tạo , nhận cuộc gọi
Thư viện sử dụng
- Đăng kí account và tạo project mới
- Tham khảo Samples: Android - OneToOneCallSample (bài 3 và bài 4)
- Code sample Android code sample
- Xem document: Getting started with Stringee Call API using Android SDK
Hướng dẫn code
Chuẩn bị
- Tạo một project Android với minSdkVersion >= 16.
- Tạo class MainActivity làm màn hình chính để thực hiện việc kết nối đến Stringee Server.
- Tạo class CallActivity để hiển thị màn hình của cuộc gọi.
Cài đặt Stringee SDK
Stringee Android SDK được phân phối dưới dạng AAR và có thể được thêm vào dự án của bạn bằng cách tham chiếu AAR từ xa với Maven.
- 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.stringee.sdk.android:stringee-android-sdk:2.0'
implementation 'com.android.volley:volley:1.2.1'
}
Permissions
Stringee Android SDK 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" />
// Nếu sử dụng class StringeeAudioManager của Stringee quản lý phát âm thanh thì cần thêm các permission này
<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
- 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
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
Để tiết kiệm thời gian, chúng ta sẽ hard code access_token ở trong ứng dụng:
- Ở class MainActivity, khởi tạo một biến để chứa access_token.
public class MainActivity extends AppCompatActivity {
private String token = "access_token";
- Lấy access_token và hard code dữ liệu :
Để làm điều đó, Stringee đã 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ệc được cuộc gọi.
- Thêm đối tượng StringeeClient vào class MainActivity.
public static StringeeClient client;
- Khởi tạo đối tượng StringeeClient và lắng nghe sự kiện từ StringeeConnectionListener để giao tiếp với Stringee Server:
client = new StringeeClient(this);
// Lắng nghe sự kiện của StringeeClient
client.setConnectionListener(new StringeeConnectionListener() {
@Override
public void onConnectionConnected(final StringeeClient stringeeClient, boolean isReconnecting) {
}
@Override
public void onConnectionDisconnected(StringeeClient stringeeClient, boolean isReconnecting) {
}
@Override
public void onIncomingCall(StringeeCall stringeeCall) {
}
@Override
public void onIncomingCall2(StringeeCall2 stringeeCall2) {
}
@Override
public void onConnectionError(StringeeClient stringeeClient, final StringeeError stringeeError) {
}
@Override
public void onRequestNewToken(StringeeClient stringeeClient) {
}
@Override
public void onCustomMessage(String s, JSONObject jsonObject) {
}
@Override
public void onTopicMessage(String s, JSONObject jsonObject) {
}
});
- Khi client kết nối thành công đến Stringee Server, hàm onConnectionConnected(StringeeClient stringeeClient, boolean isReconnecting) được gọi đến.
- Khi client mất kết nối với Stringee Server, hàm onConnectionDisconnected(StringeeClient stringeeClient, boolean isReconnecting) được gọi đến.
- Khi client kết nối thất bạn đến Stringee Server, hàm onConnectionError(StringeeClient stringeeClient, StringeeError stringeeError) được gọi đến.
- Khi access_token hết hạn, hàm onRequestNewToken(StringeeClient stringeeClient) được gọi đến. Bạn sẽ cần tạo lại access_token mới và kết nối lại.
- Khi client nhận được cuộc gọi đến, ở đây chúng ta dùng đối tương StringeeCall để thực hiện cuộc gọi video nên hàm onIncomingCall(StringeeCall stringeeCall) được gọi đến.
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:
- Thêm đối tượng stringeeCall vào class CallActivity:
private StringeeCall stringeeCall;
// Class StringeeAudioManager dùng để quản lý âm thanh
private StringeeAudioManager audioManager;
Tạo cuộc gọi đi
Để tạo cuộc gọi đi bạn cần thực hiệc các bước sau:
- Khởi tạo stringeeCall:
stringeeCall = new StringeeCall(client, from, to);
stringeeCall.setVideoCall(false); // false: Audio Call, true: Video Call
Trong đó:
- client: Đối tượng StringeeClient đã được khởi tạo và dùng để connect đến Stringee Server trước đó. Cần đảm bảo đã kết nối đến Stringee Server thành công và vẫn đang giữ kết nối .
- from: id của người gọi.
- to: id của người nhận.
- Mặc định là cuộc gọi thoại nên nếu bạn muốn khởi tạo cuộc gọi video bạn cần gọi hàm** setVideoCall(true)** trước khi gọi hàm makeCall() và sau khi khởi tạo StringeeCall.
- Thực hiện cuộc gọi:
// Khởi tạo cuộc gọi
stringeeCall.makeCall();
- Lắng nghe sự kiện của cuộc gọi:
// Lắng nghe sự kiện của cuộc gọi
stringeeCall.setCallListener(new StringeeCall.StringeeCallListener() {
@Override
public void onSignalingStateChange(StringeeCall stringeeCall, StringeeCall.SignalingState signalingState, String reason, int sipCode, String sipReason) {
}
@Override
public void onError(StringeeCall stringeeCall, int code, String description) {
}
@Override
public void onHandledOnAnotherDevice(StringeeCall stringeeCall, StringeeCall.SignalingState signalingState, String description) {
}
@Override
public void onMediaStateChange(StringeeCall stringeeCall, StringeeCall.MediaState mediaState) {
}
@Override
public void onLocalStream(StringeeCall stringeeCall) {
}
@Override
public void onRemoteStream(StringeeCall stringeeCall) {
}
@Override
public void onVideoTrackAdded(StringeeVideoTrack stringeeVideoTrack) {
}
@Override
public void onVideoTrackRemoved(StringeeVideoTrack stringeeVideoTrack) {
}
@Override
public void onCallInfo(StringeeCall stringeeCall, JSONObject callInfo) {
}
@Override
public void onTrackMediaStateChange(String from, MediaType mediaType, boolean enable) {
}
});
// Khởi tạo audioManager để quản lý việc phát âm thanh
audioManager = StringeeAudioManager.create(this);
audioManager.start(new StringeeAudioManager.AudioManagerEvents() {
@Override
public void onAudioDeviceChanged(StringeeAudioManager.AudioDevice selectedAudioDevice, Set<StringeeAudioManager.AudioDevice> availableAudioDevices) {
// Mọi thay đổi thiết bị âm thanh sẽ nhận được ở đây
}
});
audioManager.setSpeakerphoneOn(false); // false: loa trong, true: loa ngoài
- Khi tạo/trả lời cuộc gọi thất bại, hàm onError(StringeeCall stringeeCall, int code, String description) được gọi đến.
- 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, hàm onSignalingStateChange(StringeeCall call, StringeeCall.SignalingState signalingState, String reason, int sipCode, String sipReason) được gọi đến.
- Khi media stream của cuộc gọi đã kết nối hoặc mất kết nối, hàm onMediaStateChange(StringeeCall stringeeCall, StringeeCall.MediaState mediaState) được gọi đến.
- Khi cuộc gọi được xử lý trên thiết bị khác, hàm onHandledOnAnotherDevice(StringeeCall stringeeCall, StringeeCall.SignalingState signalingState, String description) được gọi đến.
- Một cuộc gọi thực sự được thành công khi trạng thái của media là MediaState.CONNECTED.
Trả lời cuộc gọi
Để có thể trả lời được cuộc gọi đến, bạn làm theo những bước sau:
- Xử lý nhận cuộc gọi ở hàm onIncomingCall2(StringeeCall stringeeCall) thuộc StringeeConnectionListener:
Lưu trữ stringeeCall vào đối tượng HashMap() với khóa là callId. Sau đó gửi callId của cuộc gọi sang class CallActivity.
@Override
public void onIncomingCall2(StringeeCall stringeeCall) {
callsMap.put(stringeeCall.getCallId(), stringeeCall);
Intent intent = new Intent(MainActivity.this, CallActivity.class);
intent.putExtra("call_id", stringeeCall.getCallId());
startActivity(intent);
}
- Gán StringeeCall từ callsMap:
String callId = getIntent().getStringExtra("call_id");
stringeeCall = callsMap.get(callId);
- Lắng nghe sự kiện của cuộc gọi:
Như việc khởi tạo cuộc gọi, ta cần lắng nghe các sự kiện của cuộc gọi - Gửi tín hiệu RINGING:
// Gửi tín hiệu RINGING
stringeeCall.ringing(new StatusListener() {
@Override
public void onSuccess() {
}
});
- Trả lời và bắt đầu cuộc gọi:
stringeeCall.answer();
- Từ chối cuộc gọi
stringeeCall.reject();
// Nếu sử dụng StringeeAudioManager, cần gọi hàm này để đưa trạng thái của audio về như lúc trước khi vào cuộc gọi
audioManager.stop();
Một số tính năng dùng trong cuộc gọi
- Ngừng cuộc gọi
Ngừng cuộc gọi và giải phong tài nguyên của cuộc gọi:
stringeeCall.hangup();
// Nếu sử dụng StringeeAudioManager, cần gọi hàm này để đưa trạng thái của audio về như lúc trước khi vào cuộc gọi
audioManager.stop();
- Tắt tiếng
Tắt tiếng của mình:
bool mute = true // true: tắt, false: mở
stringeeCall.mute(true);
- Chuyển đổi loa
Chuyển đổi giữa loa trong và loa ngoài bằng StringeeAudioManager:
bool isSpeaker = true // true: loa ngoài, false: loa trong
audioManager.setSpeakerphoneOn(isSpeaker);
Kết
Trong bài này, chúng ta đã cùng thực hiện xây dựng một Ứng dụng Voice Call trên nền tảng Android. Hi vọng bài học đã phần nào giúp các bạn tìm được phương án tối ưu và tiết kiệm thời gian nhất để build ứng dụng giao tiếp cho công việc/học tập của mình.
Ở bài sau, chúng ta sẽ tiếp tục với bài học XÂY DỰNG ỨNG DỤNG VIDEO CALL TRÊN NỀN TẢNG ANDROID.
Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của bạn để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.
Tải xuống
Tài liệu
Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Build ứng dụng Voice Call trên nền tảng Android dưới dạng file PDF trong link bên dưới.
Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com
Đừng quên like và share để ủng hộ Kteam và tác giả nhé!
Thảo luận
Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.
Nội dung bài viết
Tác giả/Dịch giả
Khóa học
Build ứng dụng Voice call/Video call
Trong khóa học BUILD ỨNG DỤNG VOICE CALL/VIDEO CALL này, Kteam sẽ hướng dẫn các bạn cách làm tối ưu hơn để tiết kiệm thời gian phát triển bằng việc sử dụng SDKs của đơn vị thứ ba.
Xin chào, xin cho tôi hỏi mình lập trình di động chạy nên tảng nào vậy bạn