Thư viện Android Telecom Jetpack mới giúp bạn dễ dàng cho nền tảng biết được cho biết cuộc gọi của bạn đang diễn ra. Bạn có thể tìm thấy mã nguồn và ứng dụng mẫu trên GitHub.
Phần phụ thuộc và quyền
Trước tiên, hãy mở tệp build.gradle của mô-đun ứng dụng rồi thêm phần phụ thuộc cho phần phụ thuộc Mô-đun viễn thông androidx:
dependencies {
implementation ("androidx.core:core-telecom:1.0.0-alpha02")
}
Trong tệp kê khai ứng dụng, hãy khai báo rằng ứng dụng của bạn dùng MANAGE_OWN_CALLS
`
quyền:
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
Đăng ký ứng dụng
Để cho Android biết về ứng dụng của mình, bạn phải đăng ký ứng dụng cũng như các chức năng của ứng dụng. Thông tin này cho Android biết ứng dụng của bạn hỗ trợ những tính năng nào, chẳng hạn như gọi video, gọi phát trực tuyến và giữ cuộc gọi. Thông tin này rất quan trọng để Android có thể định cấu hình hoạt động với các tính năng của ứng dụng.
private val callsManager = CallsManager(context)
var capabilities: @CallsManager.Companion.Capability Int =
CallsManager.CAPABILITY_BASELINE or
CallsManager.CAPABILITY_SUPPORTS_CALL_STREAMING or
CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING
callsManager.registerAppWithTelecom(capabilities)
Tích hợp nền tảng
Hai tình huống gọi phổ biến nhất của mọi ứng dụng gọi là gọi đến và các cuộc gọi đi. Để đăng ký chính xác hướng cuộc gọi và thông báo thông báo cho người dùng một cách thích hợp, hãy sử dụng các API dưới đây.
Đăng ký cuộc gọi
Ví dụ sau minh hoạ cách đăng ký cuộc gọi đến:
companion object {
const val APP_SCHEME = "MyCustomScheme"
const val ALL_CALL_CAPABILITIES = (CallAttributes.SUPPORTS_SET_INACTIVE
or CallAttributes.SUPPORTS_STREAM or CallAttributes.SUPPORTS_TRANSFER)
const val INCOMING_NAME = "Luke"
val INCOMING_URI: Uri = Uri.fromParts(APP_SCHEME, "", "")
// Define all possible properties for CallAttributes
val INCOMING_CALL_ATTRIBUTES =
CallAttributes(
INCOMING_NAME,
INCOMING_URI,
DIRECTION_INCOMING,
CALL_TYPE_VIDEO_CALL,
ALL_CALL_CAPABILITIES)
}
Đối tượng callAttributes
có thể có các thuộc tính sau:
displayName
: Tên của người gọi, cuộc họp hoặc phiên.address
: Địa chỉ của cuộc gọi. Lưu ý: quyền này có thể được mở rộng cho một cuộc họp .direction
: Hướng của cuộc gọi, chẳng hạn như cuộc gọi đến hoặc cuộc gọi đi.callType
: Thông tin liên quan đến dữ liệu được truyền, chẳng hạn như video và âm thanh.callCapabilities
: Một đối tượng chỉ định khả năng của lệnh gọi.
Đối tượng callCapabilities
có thể có các thuộc tính sau:
streaming
: Cho biết liệu cuộc gọi có hỗ trợ truyền trực tuyến âm thanh sang thiết bị khác hay không Thiết bị chạy Android.transfer
: Cho biết có thể chuyển cuộc gọi hay không.hold
: Cho biết có thể thực hiện cuộc gọi ở chế độ giữ máy hay không.
Thêm cuộc gọi
Phương thức addCall()
trả về một ngoại lệ nếu thiết bị không hỗ trợ
viễn thông hoặc nếu đã xảy ra lỗi khi thiết lập cuộc gọi.
try {
callsManager.addCall(
INCOMING_CALL_ATTRIBUTES,
onIsCallAnswered, // Watch needs to know if it can answer the call
onIsCallDisconnected,
onIsCallActive,
onIsCallInactive
) {
callControlScope = this
}
}
Trả lời cuộc gọi
Sau khi thực hiện cuộc gọi đến, bạn phải trả lời hoặc từ chối cuộc gọi đó. Chiến dịch này bài kiểm tra minh hoạ cách trả lời một cuộc gọi:
when (answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
}
}
Nếu cuộc gọi khác đang diễn ra, answer()
sẽ trả lời
CallControlResult.Error
, cho biết lý do không thể trả lời cuộc gọi. Trong
thì trong trường hợp này, người dùng cần chuyển cuộc gọi còn lại sang trạng thái chờ.
Từ chối cuộc gọi
Để từ chối một cuộc gọi, hãy ngắt kết nối cuộc gọi bằng DisconnectCause.Rejected
.
fun onRejectCall(){
coroutineScope.launch {
callControlScope?.let {
it.disconnect(DisconnectCause(DisconnectCause.REJECTED))
}
}
}
Cuộc gọi đi
Khi thực hiện cuộc gọi đi, sau khi bên từ xa trả lời, bạn phải đặt lời kêu gọi active (đang hoạt động) để thông báo cho nền tảng rằng cuộc gọi đang diễn ra:
when (setActive()) {
is CallControlResult.Success -> {
onIsCallActive()
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
Giữ cuộc gọi
Nếu ứng dụng gọi điện của bạn hỗ trợ giữ cuộc gọi, hãy dùng setInActive
để yêu cầu
nền tảng nơi cuộc gọi của bạn không hoạt động và micrô và máy ảnh được thoải mái sử dụng
được dùng bởi các ứng dụng khác:
when (setInActive()) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
Ngắt kết nối
Để ngắt kết nối cuộc gọi, thông báo cho bộ phận Viễn thông ngắt kết nối bằng cách cung cấp nguyên nhân hợp lệ:
coroutineScope.launch {
callControlScope?.disconnect(DisconnectCause(DisconnectCause.LOCAL))
}
Định tuyến âm thanh
Trong cuộc gọi, đôi khi người dùng chuyển đổi giữa các thiết bị, chẳng hạn như loa,
tai nghe hoặc thiết bị Bluetooth. Sử dụng availableEndpoints
và
currentCallEndpoint
API để nhận danh sách tất cả thiết bị có sẵn để truy cập
người dùng và thiết bị nào đang hoạt động.
Ví dụ này kết hợp cả hai quy trình để tạo một đối tượng giao diện người dùng nhằm hiển thị cho người dùng danh sách thiết bị và thiết bị nào đang hoạt động:
availableEndpoint = combine(callControlScope.availableEndpoints,
callControlScope.currentCallEndpoint) {
availableDevices: List<CallEndpoint>, activeDevice : CallEndpoint ->
availableDevices.map {
EndPointUI(
isActive = activeDevice.endpointName == it.endpointName, it
)
}
}
Để thay đổi một thiết bị đang hoạt động, hãy dùng requestEndpointChange
với
CallEndpoint
mà bạn muốn đổi sang.
coroutineScope.launch {
callControlScope?.requestEndpointChange(callEndpoint)
}
Hỗ trợ trên nền trước
Thư viện Viễn thông có hỗ trợ trên nền trước. Thư viện này sử dụng
ConnectionService
cho các thiết bị chạy Android 13 trở xuống. Đối với Android 14 trở lên
cao hơn, bạn có thể dùng micrô và camera foregroundtypes một cách chính xác
hỗ trợ các dịch vụ trên nền trước. Tìm hiểu thêm về các dịch vụ trên nền trước.
Để đáp ứng các yêu cầu về nền trước, ứng dụng phải đăng thông báo giúp người dùng biết rằng ứng dụng đang chạy ở nền trước.
Để đảm bảo ứng dụng của bạn được ưu tiên thực thi trên nền trước, hãy tạo một sau khi bạn đăng ký cuộc gọi với nền tảng. Ưu tiên khi ở nền trước sẽ bị xoá khi ứng dụng của bạn chấm dứt cuộc gọi hoặc khi thông báo của bạn không còn xuất hiện hợp lệ.
is TelecomCall.Registered -> {
val notification = createNotification(call)
notificationManager.notify(TELECOM_NOTIFICATION_ID, notification)
}
Hỗ trợ nền tảng
Đồng hồ có ứng dụng nhận điểm cuối chung. Ứng dụng này cung cấp người dùng thông qua giao diện cơ bản, chẳng hạn như trả lời, từ chối và ngắt kết nối cuộc gọi. Ứng dụng hỗ trợ những thao tác này bằng cách triển khai các hàm lambda để cho nền tảng biết rằng bạn đã thực hiện hành động trên thiết bị.
Mỗi hàm lambda sẽ hết thời gian chờ sau 5 giây với một giao dịch không thành công nếu ứng dụng của bạn không phản hồi.
callsManager.addCall(
attributes,
onIsCallAnswered, // Watch/Auto need to know if they can answer the call
onIsCallDisconnected,
onIsCallActive,
onIsCallInactive
) {
//Call Scope
}
/**
* Can the call be successfully answered??
* TIP: Check the connection/call state to see if you can answer a call
* Example you may need to wait for another call to hold.
**/
val onIsCallAnswered: suspend(type: Int) -> Unit = {}
/**
* Can the call perform a disconnect
*/
val onIsCallDisconnected: suspend (cause: DisconnectCause) -> Unit = {}
/**
* Check is see if you can make the call active.
* Other calls and state might stop us from activating the call
*/
val onIsCallActive: suspend () -> Unit = {
updateCurrentCall {
}
}
/**
* Check to see if you can make the call inactivate
*/
val onIsCallInactive: suspend () -> Unit = {}