ไลบรารี Android Telecom Jetpack ใหม่ช่วยให้บอกแพลตฟอร์มได้อย่างง่ายดายว่า ระบุว่ามีการโทรของคุณแล้ว คุณค้นหาซอร์สโค้ดและแอปตัวอย่างได้ใน GitHub
การขึ้นต่อกันและสิทธิ์
ก่อนอื่น ให้เปิดไฟล์ build.gradle ของโมดูลแอป แล้วเพิ่มทรัพยากร Dependency สำหรับ โมดูล androidx Telecom:
dependencies {
implementation ("androidx.core:core-telecom:1.0.0-alpha02")
}
ในไฟล์ Manifest ของแอป ให้ประกาศว่าแอปของคุณใช้ MANAGE_OWN_CALLS
`
สิทธิ์:
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
ลงทะเบียนแอปพลิเคชัน
คุณต้องลงทะเบียนแอปและความสามารถของแอปเพื่อให้ Android ทราบเกี่ยวกับแอปของคุณ ข้อมูลนี้จะบอก Android ว่าแอปของคุณรองรับฟีเจอร์ใดบ้าง เช่น วิดีโอคอล การโทร การสตรีม และการพักสาย ข้อมูลนี้สําคัญเพื่อให้ Android กําหนดค่าได้ ทำงานกับฟีเจอร์ของแอปได้
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)
การผสานรวมแพลตฟอร์ม
สถานการณ์การโทรที่พบบ่อยที่สุด 2 แบบสำหรับแอปพลิเคชันการโทรคือสายเรียกเข้า และสายโทรออก เพื่อบันทึกทิศทางการโทรอย่างถูกต้องและ แจ้งเตือนผู้ใช้อย่างเหมาะสมโดยใช้ API ด้านล่าง
ลงทะเบียนการโทร
ตัวอย่างนี้แสดงวิธีลงทะเบียนสายเรียกเข้า
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)
}
ออบเจ็กต์ callAttributes
อาจมีพร็อพเพอร์ตี้ต่อไปนี้
displayName
: ชื่อของผู้โทร การประชุม หรือเซสชันaddress
: ที่อยู่ของการโทร โปรดทราบว่าสามารถขยายระยะเวลานี้ไปยังการประชุมได้ ลิงก์direction
: ทิศทางการโทร เช่น สายเรียกเข้าหรือสายโทรออกcallType
: รายละเอียดเกี่ยวกับข้อมูลที่ส่ง เช่น วิดีโอ และเสียงcallCapabilities
: ออบเจ็กต์ที่ระบุความสามารถในการเรียกใช้
ออบเจ็กต์ callCapabilities
อาจมีพร็อพเพอร์ตี้ต่อไปนี้
streaming
: ระบุว่าการโทรรองรับการสตรีมเสียงไปยังอุปกรณ์อื่นหรือไม่ อุปกรณ์ที่ใช้ระบบ Androidtransfer
: ระบุว่าโอนสายได้หรือไม่hold
: ระบุว่าจะพักสายได้หรือไม่
เพิ่มสาย
เมธอด addCall()
จะแสดงข้อยกเว้นหากอุปกรณ์ไม่รองรับ
โทรคมนาคม หรือหากเกิดข้อผิดพลาดขณะตั้งค่าการโทร
try {
callsManager.addCall(
INCOMING_CALL_ATTRIBUTES,
onIsCallAnswered, // Watch needs to know if it can answer the call
onIsCallDisconnected,
onIsCallActive,
onIsCallInactive
) {
callControlScope = this
}
}
รับสาย
หลังจากโทรออกแล้ว คุณต้องรับสายหรือปฏิเสธสาย ช่วงเวลานี้ การสอบสาธิตวิธีการรับสาย:
when (answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
}
}
หากมีการโทรอื่นอีก answer()
จะโทรกลับ
CallControlResult.Error
ซึ่งแจ้งสาเหตุที่ไม่สามารถรับสายได้ ใน
ในกรณีนี้ ผู้ใช้ต้องพักสายอีกสายหนึ่ง
ปฏิเสธสาย
หากไม่ต้องการรับสาย ให้ยกเลิกการเชื่อมต่อกับ DisconnectCause.Rejected
fun onRejectCall(){
coroutineScope.launch {
callControlScope?.let {
it.disconnect(DisconnectCause(DisconnectCause.REJECTED))
}
}
}
สายโทรออก
เมื่อโทรออก เมื่อผู้รับสายจากทางไกลรับสาย คุณต้องตั้งค่า โทรไปยังใช้งานอยู่ เพื่อให้แพลตฟอร์มทราบว่าการโทรอยู่ระหว่างดำเนินการ:
when (setActive()) {
is CallControlResult.Success -> {
onIsCallActive()
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
พักสาย
หากแอปโทรรองรับการพักสาย ให้ใช้ setInActive
เพื่อบอก
แพลตฟอร์มที่ไม่ได้ใช้งานการโทรของคุณ และการใช้ไมโครโฟนและกล้อง
ใช้โดยแอปอื่นๆ:
when (setInActive()) {
is CallControlResult.Success -> {
}
is CallControlResult.Error -> {
updateCurrentCall {
copy(errorCode = result.errorCode)
}
}
}
ยกเลิกการเชื่อมต่อ
หากต้องการยกเลิกการเชื่อมต่อ ให้แจ้งสแต็ก Telecom ให้ยกเลิกการเชื่อมต่อโดยการระบุ สาเหตุที่เป็นไปได้:
coroutineScope.launch {
callControlScope?.disconnect(DisconnectCause(DisconnectCause.LOCAL))
}
เสียงกำหนดเส้นทาง
ระหว่างการโทร บางครั้งผู้ใช้สลับไปมาระหว่างอุปกรณ์ต่างๆ เช่น ลําโพง
หูฟังโทรศัพท์ หรืออุปกรณ์บลูทูธ ใช้ availableEndpoints
และ
currentCallEndpoint
API เพื่อรับรายการอุปกรณ์ทั้งหมดที่ใช้ได้สำหรับ
ผู้ใช้ และอุปกรณ์ที่ใช้งานอยู่
ตัวอย่างนี้ได้รวมทั้ง 2 ขั้นตอนเข้าด้วยกันเพื่อสร้างออบเจ็กต์ UI ที่จะแสดงให้ผู้ใช้เห็น รายชื่ออุปกรณ์และอุปกรณ์ที่ใช้งานอยู่
availableEndpoint = combine(callControlScope.availableEndpoints,
callControlScope.currentCallEndpoint) {
availableDevices: List<CallEndpoint>, activeDevice : CallEndpoint ->
availableDevices.map {
EndPointUI(
isActive = activeDevice.endpointName == it.endpointName, it
)
}
}
หากต้องการเปลี่ยนอุปกรณ์ที่ใช้งานอยู่ ให้ใช้ requestEndpointChange
ด้วย
CallEndpoint
ที่คุณต้องการเปลี่ยนไปใช้
coroutineScope.launch {
callControlScope?.requestEndpointChange(callEndpoint)
}
การสนับสนุนในเบื้องหน้า
ไลบรารีโทรคมนาคมมาพร้อมการสนับสนุนในเบื้องหน้า ไลบรารีนี้ใช้
ConnectionService
สำหรับอุปกรณ์ที่ใช้ Android 13 และต่ำกว่า สำหรับ Android 14 และ
สูงจะใช้ไมโครโฟนและกล้องประเภทพื้นหน้าเพื่อ
รองรับบริการที่ทำงานอยู่เบื้องหน้า ดูข้อมูลเพิ่มเติมเกี่ยวกับบริการที่ทำงานอยู่เบื้องหน้า
แอปพลิเคชันต้องโพสต์การแจ้งเตือนเป็นส่วนหนึ่งของข้อกำหนดเบื้องหน้า เพื่อให้ผู้ใช้ทราบว่าแอปพลิเคชันกำลังทำงานในเบื้องหน้า
หากต้องการให้แอปมีลำดับความสำคัญของการดำเนินการในเบื้องหน้า ให้สร้าง เมื่อคุณลงทะเบียนการโทรกับแพลตฟอร์มแล้ว ลำดับความสำคัญในเบื้องหน้า ถูกนำออกเมื่อแอปของคุณสิ้นสุดการโทร หรือการแจ้งเตือนไม่แสดงอีกต่อไป ใช้ได้
is TelecomCall.Registered -> {
val notification = createNotification(call)
notificationManager.notify(TELECOM_NOTIFICATION_ID, notification)
}
การรองรับ Surface
นาฬิกามีแอปพลิเคชันตัวรับสัญญาณปลายทางทั่วไป แอปพลิเคชันนี้จะให้ ผู้ใช้ที่มีอินเทอร์เฟซพื้นฐาน เช่น การรับสาย การปฏิเสธ และการตัดการเชื่อมต่อ แอปพลิเคชันรองรับการดำเนินการเหล่านี้ด้วยการใช้ฟังก์ชัน lambda ซึ่งแจ้งแพลตฟอร์มที่คุณได้ดำเนินการบนอุปกรณ์แล้ว
ฟังก์ชัน lambda แต่ละรายการจะหมดเวลาหลังผ่านไป 5 วินาทีหากทำธุรกรรมไม่สำเร็จ แอปพลิเคชันไม่ตอบสนอง
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 = {}