แอปพลิเคชันโทรศัพท์เริ่มต้นช่วยให้เฟรมเวิร์กโทรคมนาคมของ Android แจ้งแอปพลิเคชันสถานะการโทรของคุณ โดยใช้ตัวจัดการบทบาทและบริการในสายเพื่อสร้างการแทนที่สำหรับแอปโทรศัพท์เริ่มต้นในอุปกรณ์ Android และใช้ InCallService API การติดตั้งใช้งานของคุณต้องเป็นไปตามข้อกำหนดต่อไปนี้
แอปต้องไม่มีความสามารถในการโทร และต้องประกอบด้วยอินเทอร์เฟซผู้ใช้สำหรับการโทรเพียงอย่างเดียว และต้องจัดการกับการเรียกใช้ทั้งหมดที่เฟรมเวิร์กโทรคมนาคมรับทราบ และไม่มีข้อสันนิษฐานเกี่ยวกับลักษณะของการโทร เช่น ต้องไม่ถือว่าการโทรเป็นการโทรแบบใช้ซิม และไม่ได้จำกัดการโทรที่อิงจาก ConnectionService ใดๆ เช่น การบังคับใช้ข้อจำกัดเกี่ยวกับโทรศัพท์สำหรับวิดีโอคอล
แอปการโทรช่วยให้ผู้ใช้รับสายหรือโทรด้วยเสียงหรือวิดีโอคอลใน อุปกรณ์ แอปการโทรใช้อินเทอร์เฟซผู้ใช้ของตนเองในการโทรแทนการใช้ อินเทอร์เฟซแอปโทรศัพท์เริ่มต้นดังที่แสดงในภาพหน้าจอต่อไปนี้
เฟรมเวิร์ก Android มีแพ็กเกจ android.telecom
ซึ่ง
มีชั้นเรียนที่ช่วยคุณสร้างแอปโทรตามโทรคมนาคม
การสร้างแอปของคุณตามเฟรมเวิร์กโทรคมนาคมมอบ
ประโยชน์ดังต่อไปนี้
- แอปของคุณทำงานร่วมกับระบบย่อยระบบโทรคมนาคมแบบเนทีฟได้อย่างถูกต้องใน อุปกรณ์
- แอปของคุณทํางานร่วมกับแอปการโทรอื่นๆ ที่ปฏิบัติตามข้อกําหนดด้วยเช่นกันได้อย่างถูกต้อง กรอบการทำงาน
- เฟรมเวิร์กนี้จะช่วยให้แอปจัดการการกำหนดเส้นทางเสียงและวิดีโอได้
- เฟรมเวิร์กนี้ช่วยให้แอปทราบว่าการโทรมุ่งเน้นหรือไม่
การประกาศและสิทธิ์ในไฟล์ Manifest
ในไฟล์ Manifest ของแอป ให้ประกาศว่าแอปของคุณใช้
MANAGE_OWN_CALLS
สิทธิ์ตามที่แสดงในตัวอย่างต่อไปนี้
<manifest … >
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
</manifest>
ดูข้อมูลเพิ่มเติมเกี่ยวกับการประกาศสิทธิ์ของแอปได้ที่ สิทธิ์
คุณต้องประกาศบริการที่ระบุคลาสที่นำพารามิเตอร์
ConnectionService
ชั้นเรียนในแอปของคุณ โทรคมนาคม
ระบบย่อยกำหนดให้บริการต้องประกาศสิทธิ์ BIND_TELECOM_CONNECTION_SERVICE
เชื่อมโยงกับโดเมนได้ ตัวอย่างต่อไปนี้แสดงวิธีประกาศบริการใน
ไฟล์ Manifest ของแอป
<service android:name="com.example.MyConnectionService"
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.ConnectionService" />
</intent-filter>
</service>
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการประกาศคอมโพเนนต์ของแอป รวมถึงบริการ โปรดดู คอมโพเนนต์ของแอป
ใช้บริการการเชื่อมต่อ
แอปการโทรต้องติดตั้งใช้งานคลาส ConnectionService
ที่เชื่อมโยงกับระบบย่อยโทรคมนาคม
การใช้งาน ConnectionService
ของคุณควรลบล้าง
วิธีการต่อไปนี้
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
ระบบย่อยโทรคมนาคมเรียกวิธีนี้เพื่อตอบสนองต่อ แอปของคุณกำลังโทรหา
placeCall(Uri, Bundle)
เพื่อสร้างสายโทรออกใหม่ แอปของคุณแสดงผลอินสแตนซ์ใหม่ของการใช้งานคลาสConnection
(ดูข้อมูลเพิ่มเติมได้ที่ ใช้การเชื่อมต่อ) เพื่อแสดง สายโทรออก คุณปรับแต่งการเชื่อมต่อขาออกเพิ่มเติมได้โดยทําดังนี้ การดำเนินการต่อไปนี้- แอปของคุณควรเรียกเมธอด
setConnectionProperties(int)
ด้วยค่าคงที่PROPERTY_SELF_MANAGED
เป็นอาร์กิวเมนต์ เพื่อระบุว่าการเชื่อมต่อมาจากแอปการโทร - หากแอปรองรับการพักสาย ให้เรียกใช้เมธอด
setConnectionCapabilities(int)
และตั้งค่า อาร์กิวเมนต์ค่าบิตมาสก์ของค่าคงที่CAPABILITY_HOLD
และCAPABILITY_SUPPORT_HOLD
- หากต้องการตั้งชื่อผู้โทร ให้ใช้วิธีการ
setCallerDisplayName(String, int)
ผ่านPRESENTATION_ALLOWED
เป็นค่าคงที่เป็นพารามิเตอร์int
เพื่อระบุว่าชื่อผู้โทรควร ได้อีกด้วย - หากต้องการตรวจสอบว่าสายที่โทรออกมีสถานะวิดีโอที่เหมาะสม โปรดโทรหา
setVideoState(int)
ของออบเจ็กต์Connection
และส่งค่าที่แสดงผลโดย เมธอดgetVideoState()
ของConnectionRequest
ออบเจ็กต์
- แอปของคุณควรเรียกเมธอด
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
ระบบย่อยโทรคมนาคมจะเรียกวิธีนี้เมื่อแอปของคุณเรียกใช้เมธอด
placeCall(Uri, Bundle)
แต่การโทรออกไม่สามารถ ได้ เพื่อให้สอดคล้องกับสถานการณ์นี้ แอปของคุณควรแจ้งให้ผู้ใช้ทราบ (สำหรับ เช่น การใช้กล่องการแจ้งเตือนหรือข้อความโทสต์) ว่าไม่สามารถโทรออก วางแล้ว แอปของคุณอาจโทรออกไม่ได้หากมีการเชื่อมต่ออยู่ หมายเลขฉุกเฉิน หรือหากมีสายที่สนทนาอยู่ในแอปอื่นที่ไม่สามารถ พักสายก่อนโทรออกonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
ระบบย่อยโทรคมนาคมเรียกเมธอดนี้เมื่อแอปของคุณเรียกใช้เมธอด
addNewIncomingCall(PhoneAccountHandle, Bundle)
เพื่อแจ้งระบบเมื่อมีสายเรียกเข้าใหม่ในแอป แอปของคุณแสดงผล อินสแตนซ์ใหม่ของการติดตั้งใช้งานConnection
(สำหรับ ดูข้อมูลเพิ่มเติมที่ใช้การเชื่อมต่อ) เพื่อแสดงสายเรียกเข้าใหม่ คุณสามารถปรับแต่งการกำหนดค่า โดยดำเนินการดังต่อไปนี้- แอปของคุณควรเรียกเมธอด
setConnectionProperties(int)
ด้วยค่าคงที่PROPERTY_SELF_MANAGED
เป็นอาร์กิวเมนต์ เพื่อระบุว่าการเชื่อมต่อมาจากแอปการโทร - หากแอปรองรับการพักสาย ให้เรียกใช้เมธอด
setConnectionCapabilities(int)
และตั้งค่า อาร์กิวเมนต์ค่าบิตมาสก์ของค่าคงที่CAPABILITY_HOLD
และCAPABILITY_SUPPORT_HOLD
- หากต้องการตั้งชื่อผู้โทร ให้ใช้วิธีการ
setCallerDisplayName(String, int)
ผ่านPRESENTATION_ALLOWED
เป็นค่าคงที่เป็นพารามิเตอร์int
เพื่อระบุว่าชื่อผู้โทรควร ได้อีกด้วย - หากต้องการระบุหมายเลขโทรศัพท์หรือที่อยู่ของสายเรียกเข้า ให้ใช้
เมธอด
setAddress(Uri, int)
ของออบเจ็กต์Connection
- หากต้องการตรวจสอบว่าสายที่โทรออกมีสถานะวิดีโอที่เหมาะสม โปรดโทรหา
setVideoState(int)
ของออบเจ็กต์Connection
และส่งค่าที่แสดงผลโดย เมธอดgetVideoState()
ของConnectionRequest
ออบเจ็กต์
- แอปของคุณควรเรียกเมธอด
onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
ระบบย่อยโทรคมนาคมเรียกใช้เมธอดนี้เมื่อแอปของคุณเรียกใช้เมธอด
addNewIncomingCall(PhoneAccountHandle, Bundle)
เพื่อแจ้ง Telecom มีสายเรียกเข้าใหม่ แต่ไม่อนุญาตให้ใช้สายเรียกเข้า (สำหรับ โปรดดูข้อมูลที่หัวข้อข้อจำกัดในการโทร) แอปของคุณควร ปฏิเสธสายเรียกเข้าโดยไม่ส่งเสียง โดยคุณจะโพสต์การแจ้งเตือนเพื่อแจ้งข้อมูลได้ ผู้ใช้สายที่ไม่ได้รับ
ใช้การเชื่อมต่อ
แอปของคุณควรสร้างคลาสย่อยของ Connection
เพื่อ
แสดงถึงการโทรในแอปของคุณ คุณควรลบล้างเมธอดต่อไปนี้ใน
การใช้งานของคุณ:
onShowIncomingCallUi()
ระบบย่อยโทรคมนาคมจะเรียกวิธีนี้เมื่อคุณเพิ่มสายเรียกเข้าใหม่ และ แอปของคุณควรแสดง UI ของสายเรียกเข้า
onCallAudioStateChanged(CallAudioState)
ระบบย่อยโทรคมนาคมเรียกวิธีการนี้เพื่อแจ้งแอปของคุณว่าเสียงที่ มีการเปลี่ยนแปลงเส้นทางหรือโหมด ซึ่งเรียกว่าเพื่อตอบสนองต่อแอปของคุณที่เปลี่ยน โหมดเสียงโดยใช้
setAudioRoute(int)
อาจมีการเรียกวิธีการนี้ในกรณีที่ระบบเปลี่ยนเส้นทางเสียง (เช่น เมื่อชุดหูฟังบลูทูธยกเลิกการเชื่อมต่อ)onHold()
ระบบย่อยโทรคมนาคมเรียกใช้เมธอดนี้เมื่อต้องการพักสาย ในการตอบสนองต่อคำขอนี้ แอปของคุณควรพักสายแล้วเรียกใช้
setOnHold()
วิธีในการแจ้งให้ระบบทราบ ที่มีการระงับสายอยู่ ระบบย่อยโทรคมนาคมอาจเรียกใช้เมธอดนี้เมื่อ บริการระหว่างการโทร เช่น Android Auto ที่แสดงให้เห็นว่าการโทรต้องการ ส่งต่อคำขอของผู้ใช้ให้พักสาย ระบบย่อยโทรคมนาคมยังเรียก วิธีนี้ในกรณีที่ผู้ใช้เปิดใช้การโทรในแอปอื่น สำหรับข้อมูลเพิ่มเติม ข้อมูลเกี่ยวกับบริการในสาย โปรดดูInCallService
onUnhold()
ระบบย่อยโทรคมนาคมจะเรียกใช้เมธอดนี้เมื่อ อุปกรณ์ต้องการต่อสายที่พักสายอยู่ เมื่อแอปของคุณกลับมาทำงานอีกครั้งแล้ว ระบบควรเรียกใช้
setActive()
เพื่อแจ้งให้ระบบทราบว่าไม่มีการพักสายแล้ว โทรคมนาคม ระบบย่อยอาจเรียกใช้วิธีการนี้เมื่อบริการในสาย เช่น Android Auto ที่แสดงว่าสายของคุณต้องการส่งต่อคำขอเพื่อโทรต่อ สำหรับ ดูข้อมูลเพิ่มเติมเกี่ยวกับบริการในสายได้ที่InCallService
onAnswer()
ระบบย่อยโทรคมนาคมเรียกเมธอดนี้เพื่อแจ้ง แอปของคุณที่ควรรับสายเรียกเข้า เมื่อแอปตอบคำถามแล้ว ระบบควรเรียกใช้
setActive()
เพื่อแจ้งระบบว่ามีการรับสายแล้ว โทรคมนาคม ระบบย่อยอาจเรียกวิธีการนี้เมื่อแอปของคุณเพิ่มสายเรียกเข้าใหม่และ มีสายที่สนทนาอยู่ในแอปอื่นอยู่แล้ว จึงไม่สามารถพักสายได้ ระบบย่อยโทรคมนาคมจะแสดง UI ของสายเรียกเข้าในนามของแอปของคุณใน อินสแตนซ์เหล่านี้ เฟรมเวิร์กมีวิธีการที่ทำงานมากเกินไปซึ่ง สนับสนุนเพื่อระบุสถานะวิดีโอที่จะรับสาย สำหรับข้อมูลเพิ่มเติม โปรดดูข้อมูลเพิ่มเติมที่onAnswer(int)
onReject()
ระบบย่อยโทรคมนาคมเรียกเมธอดนี้เมื่อต้องการปฏิเสธสายเรียกเข้า การโทร เมื่อแอปปฏิเสธการเรียก แอปควรเรียก
setDisconnected(DisconnectCause)
และระบุREJECTED
เป็นพารามิเตอร์ แอปของคุณควร จากนั้นเรียกใช้เมธอดdestroy()
เพื่อแจ้ง ระบบที่แอปประมวลผลการโทร การโทรของระบบย่อยโทรคมนาคม วิธีนี้เมื่อผู้ใช้ปฏิเสธสายเรียกเข้าจากแอปของคุณonDisconnect()
ระบบย่อยโทรคมนาคมเรียกวิธีนี้เมื่อต้องการยกเลิกการเชื่อมต่อสาย เมื่อการโทรสิ้นสุดลง แอปควรเรียกเมธอด
setDisconnected(DisconnectCause)
และระบุLOCAL
เป็นพารามิเตอร์เพื่อระบุว่า คำขอของผู้ใช้ทำให้การโทรถูกตัดการเชื่อมต่อ จากนั้นแอปของคุณควรเรียกเมธอดdestroy()
วิธีในการแจ้งให้โทรคมนาคม ระบบย่อยที่แอปได้ประมวลผลการเรียก ระบบอาจเรียกใช้เมธอดนี้ เมื่อผู้ใช้ตัดการเชื่อมต่อการโทรผ่านบริการอื่นในสาย เช่น Android Auto นอกจากนี้ ระบบจะเรียกวิธีการนี้เมื่อการเรียกของคุณต้อง ยกเลิกการเชื่อมต่อ เพื่อให้สามารถโทรออกได้ เช่น หากผู้ใช้ต้องการ เพื่อโทรฉุกเฉิน ดูข้อมูลเพิ่มเติมเกี่ยวกับบริการระหว่างการโทรได้ที่InCallService
รับมือกับสถานการณ์การโทรที่พบบ่อย
การใช้ ConnectionService
API ในการโทร
ต้องมีการโต้ตอบกับชั้นเรียนอื่นๆ ใน android.telecom
ใหม่ ส่วนต่อไปนี้จะอธิบายสถานการณ์การโทรที่พบบ่อย และวิธี
ต้องใช้ API ในการจัดการ
รับสายเรียกเข้า
ขั้นตอนในการจัดการสายเรียกเข้าจะเปลี่ยนไปหรือไม่ว่ามีสายโทรเข้าในแอปอื่นๆ หรือไม่ หรือไม่ เหตุผลที่กระบวนการทำงานแตกต่างกันคือ กรอบการทำงานของโทรคมนาคม ต้องสร้างข้อจำกัดบางอย่างเมื่อมีการเรียกใช้ในแอปอื่นๆ ดูแลให้แอปการโทรทั้งหมดในอุปกรณ์มีสภาพแวดล้อมที่เสถียร สำหรับข้อมูลเพิ่มเติม โปรดดูข้อมูลที่หัวข้อข้อจำกัดในการโทร
ไม่มีสายที่ใช้งานอยู่ในแอปอื่นๆ
หากต้องการรับสายเรียกเข้าเมื่อไม่มีสายที่ใช้งานอยู่ในแอปอื่นๆ ให้ทําตาม ขั้นตอนเหล่านี้:
- แอปของคุณได้รับสายเรียกเข้าใหม่โดยใช้กลไกปกติ
- ใช้เมธอด
addNewIncomingCall(PhoneAccountHandle, Bundle)
เพื่อ แจ้งระบบย่อยโทรคมนาคมเกี่ยวกับสายเรียกเข้าใหม่ - ระบบย่อยโทรคมนาคมเชื่อมโยงกับการใช้งาน
ConnectionService
ของแอปและขออินสแตนซ์ใหม่ ของคลาสConnection
หมายถึงรายการเข้าใหม่ โดยใช้เมธอดonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
- ระบบย่อยโทรคมนาคมแจ้งให้แอปของคุณทราบว่าควรแสดงสายเรียกเข้า
อินเทอร์เฟซผู้ใช้โดยใช้เมธอด
onShowIncomingCallUi()
- แอปของคุณแสดง UI ที่เข้ามาใหม่โดยใช้การแจ้งเตือนที่มี
Intent แบบเต็มหน้าจอ ดูข้อมูลเพิ่มเติมได้ที่
onShowIncomingCallUi()
- เรียกใช้เมธอด
setActive()
หากผู้ใช้ รับสายเรียกเข้า หรือsetDisconnected(DisconnectCause)
ระบุREJECTED
เป็นพารามิเตอร์ตามด้วย ไปยังเมธอดdestroy()
หากผู้ใช้ ปฏิเสธสายเรียกเข้า
สายที่สนทนาอยู่ในแอปอื่นๆ ที่จะพักสายไม่ได้
เพื่อรับสายเรียกเข้าเมื่อมีสายที่สนทนาอยู่ในแอปอื่นๆ ซึ่งทำไม่ได้ ถูกระงับ โปรดทำตามขั้นตอนต่อไปนี้
- แอปของคุณได้รับสายเรียกเข้าใหม่โดยใช้กลไกปกติ
- ใช้เมธอด
addNewIncomingCall(PhoneAccountHandle, Bundle)
เพื่อ แจ้งระบบย่อยโทรคมนาคมเกี่ยวกับสายเรียกเข้าใหม่ - ระบบย่อยโทรคมนาคมเชื่อมโยงกับการใช้งาน
ConnectionService
ของแอปและขออินสแตนซ์ใหม่ ของออบเจ็กต์Connection
ที่แสดงถึง สายเรียกเข้าโดยใช้เมธอดonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
- ระบบย่อยโทรคมนาคมจะแสดง UI ของสายเรียกเข้าสำหรับสายเรียกเข้าของคุณ
- หากผู้ใช้รับสาย ระบบย่อยโทรคมนาคมจะเรียกใช้เมธอด
onAnswer()
คุณควรเรียกใช้เมธอดsetActive()
เพื่อระบุไปยังโทรคมนาคม ระบบย่อยที่เชื่อมต่อการโทรแล้ว - หากผู้ใช้ปฏิเสธสาย ระบบย่อยโทรคมนาคมจะเรียกใช้เมธอด
onReject()
คุณควรเรียกเมธอดsetDisconnected(DisconnectCause)
โดยระบุREJECTED
เป็นพารามิเตอร์ ตามด้วย ไปยังเมธอดdestroy()
โทรออก
ขั้นตอนการโทรออกจะต้องมีการจัดการกับความเป็นไปได้ที่ ไม่สามารถโทรออกได้เนื่องจากข้อจำกัดที่กำหนดโดยเฟรมเวิร์กโทรคมนาคม ดูข้อมูลเพิ่มเติมได้ที่ข้อจำกัดในการโทร
หากต้องการโทรออก ให้ทำตามขั้นตอนต่อไปนี้
- ผู้ใช้เริ่มโทรออกภายในแอปของคุณ
- ใช้เมธอด
placeCall(Uri, Bundle)
เพื่อแจ้ง ระบบย่อยเกี่ยวกับสายโทรออกใหม่ ข้อต่อไปนี้ ข้อควรพิจารณาสำหรับพารามิเตอร์เมธอด- พารามิเตอร์
Uri
แสดงที่อยู่ที่มี กำลังโทรหา สำหรับหมายเลขโทรศัพท์ปกติ ให้ใช้ URItel:
สคีม - พารามิเตอร์
Bundle
ช่วยให้คุณระบุข้อมูล เกี่ยวกับแอปการโทรโดยเพิ่มออบเจ็กต์PhoneAccountHandle
ของแอปในส่วนเพิ่มเติมEXTRA_PHONE_ACCOUNT_HANDLE
บัญชี แอปต้องระบุออบเจ็กต์PhoneAccountHandle
ให้กับสายโทรออกทุกสาย - พารามิเตอร์
Bundle
ยังให้คุณระบุได้ด้วยว่า สายที่โทรออกมีวิดีโอด้วยการระบุค่าSTATE_BIDIRECTIONAL
ในส่วนที่เกินมาEXTRA_START_CALL_WITH_VIDEO_STATE
พิจารณาว่าโดยค่าเริ่มต้น ระบบย่อยโทรคมนาคมจะกำหนดเส้นทางวิดีโอไปยัง ลำโพง
- พารามิเตอร์
- ระบบย่อยโทรคมนาคมเชื่อมโยงกับ
ConnectionService
ของแอป การใช้งานของคุณ - หากแอปของคุณโทรออกไม่ได้ การโทรของระบบย่อยโทรคมนาคม
เมธอด
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
เพื่อ แจ้งแอปของคุณว่าไม่สามารถโทรออกได้ในขณะนี้ แอปของคุณ ควรแจ้งให้ผู้ใช้ทราบว่าไม่สามารถโทรออกได้ - หากแอปของคุณโทรออกได้ ระบบย่อยของระบบโทรคมนาคม
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
แอปควรแสดงผลอินสแตนซ์ของคลาสConnection
เพื่อแสดงถึงสายโทรออกใหม่ สำหรับ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับพร็อพเพอร์ตี้ที่คุณควรตั้งค่าในการเชื่อมต่อ ดูใช้บริการเชื่อมต่อ - เมื่อเชื่อมต่อสายโทรออกแล้ว ให้โทรหาเมธอด
setActive()
เพื่อแจ้งระบบย่อยของโทรคมนาคม การโทรทำงานอยู่
วางสาย
หากต้องการวางสาย ให้ทำตามขั้นตอนต่อไปนี้
- เรียก
setDisconnected(DisconnectCause)
ที่ส่งLOCAL
เป็นพารามิเตอร์หากผู้ใช้ วางสาย หรือส่งREMOTE
เป็นพารามิเตอร์หากคู่สนทนาสิ้นสุดการโทร - เรียกใช้เมธอด
destroy()
ข้อจำกัดในการโทร
เพื่อให้ผู้ใช้ของคุณได้รับประสบการณ์การโทรที่เรียบง่ายและสอดคล้องกัน โทรคมนาคม
จะมีการบังคับใช้ข้อจำกัดบางประการสำหรับการจัดการการโทรในอุปกรณ์ สำหรับ
เช่น ผู้ใช้ได้ติดตั้งแอปการโทร 2 แอป
ConnectionService
API ที่จัดการด้วยตนเอง, FooTalk และ
BarTalk ในกรณีนี้ มีข้อจำกัดต่อไปนี้
สำหรับอุปกรณ์ที่ใช้ API ระดับ 27 หรือต่ำกว่า จะมีเพียงแอปเดียวที่สามารถรักษา การโทรที่ดำเนินอยู่ในช่วงเวลาใดเวลาหนึ่ง ข้อจำกัดนี้หมายความว่าในขณะที่ผู้ใช้มี การโทรที่ดำเนินอยู่โดยใช้แอป FooTalk แอป BarTalk ไม่สามารถเริ่มต้นหรือรับสายได้ การโทรใหม่
ในอุปกรณ์ที่ใช้ API ระดับ 28 ขึ้นไป หากทั้ง FooTalk และ BarTalk ประกาศ
CAPABILITY_SUPPORT_HOLD
และCAPABILITY_HOLD
ผู้ใช้จะสามารถโทรออกได้มากกว่า 1 สายโดย สลับไปมาระหว่างแอปเพื่อเริ่มต้นหรือรับสายอื่นหากผู้ใช้มีส่วนร่วมในการโทรที่มีการจัดการตามปกติ (เช่น การใช้ แอปโทรศัพท์หรือแอปโทรศัพท์ในตัว) ผู้ใช้จะต้องไม่อยู่ในสายที่มาจาก แอปการโทร ซึ่งหมายความว่าหากผู้ใช้อยู่ในสายปกติโดยใช้ ผู้ให้บริการเครือข่ายมือถือก็ไม่สามารถเข้าร่วม FooTalk หรือ BarTalk พร้อมกันได้ด้วยเช่นกัน
ระบบย่อยโทรคมนาคมจะตัดการเชื่อมต่อการโทรของแอปหากผู้ใช้กดหมายเลข โทรฉุกเฉิน
แอปของคุณจะไม่สามารถรับหรือโทรออกได้ในขณะที่ผู้ใช้อยู่ในสายฉุกเฉิน
หากมีสายที่สนทนาอยู่ในแอปการโทรอื่นเมื่อแอปรับสาย สายเรียกเข้า การรับสายเรียกเข้าจะวางสายที่สนทนาอยู่ แอปอื่น แอปของคุณไม่ควรแสดงอินเทอร์เฟซผู้ใช้สายเรียกเข้าตามปกติ เฟรมเวิร์กโทรคมนาคมจะแสดงอินเทอร์เฟซผู้ใช้เมื่อมีสายเรียกเข้า และแจ้งข้อมูล ผู้ใช้ที่รับสายใหม่จะวางสายที่สนทนาอยู่ ช่วงเวลานี้ หมายความว่าหากผู้ใช้อยู่ในสาย FooTalk และแอป BarTalk ได้รับ โครงสร้างโทรคมนาคมจะแจ้งให้ผู้ใช้ทราบว่ามี สายเรียกเข้าจาก BarTalk และการรับสาย BarTalk จะเป็นการวางสาย FooTalk โทร
การกลายเป็นแอปโทรศัพท์เริ่มต้น
แอปโทรศัพท์/แอปโทรศัพท์เริ่มต้นคือแอปซึ่งมีอินเทอร์เฟซผู้ใช้ขณะโทรขณะที่อุปกรณ์
อยู่ในสาย และยังเป็นวิธีเริ่มต้นการโทรและดูประวัติการโทรแก่ผู้ใช้อีกด้วย
บนอุปกรณ์ของตน อุปกรณ์มาพร้อมกับแอปโทรศัพท์/แอปโทรศัพท์เริ่มต้นของระบบ ผู้ใช้
อาจเลือกแอปเดียวที่จะรับช่วงต่อจากแอประบบ แอปที่ต้องการ
เติมเต็มบทบาทนี้จะใช้ RoleManager
เพื่อขอให้กรอก
บทบาทRoleManager.ROLE_DIALER
แอปโทรศัพท์เริ่มต้นจะมีอินเทอร์เฟซผู้ใช้ขณะที่อุปกรณ์กำลังอยู่ในสาย และอุปกรณ์
ไม่ได้อยู่ในโหมดใช้ในรถยนต์ (กล่าวคือ UiModeManager#getCurrentModeType()
ไม่ได้อยู่ในโหมดรถยนต์
Configuration.UI_MODE_TYPE_CAR
)
หากต้องการเติมเต็มบทบาท RoleManager.ROLE_DIALER
แอปต้องเป็นไปตาม
จำนวนข้อกำหนด
- ต้องจัดการ Intent
Intent#ACTION_DIAL
ซึ่งหมายความว่าแอปจะต้องจัดเตรียม UI ของแป้นหมายเลขสำหรับให้ผู้ใช้เริ่มโทรออก - ต้องใช้
InCallService
API อย่างสมบูรณ์และให้บริการทั้งสายเรียกเข้า UI รวมถึง UI ของการโทรที่ดำเนินอยู่
หมายเหตุ: หากแอปที่ป้อน RoleManager.ROLE_DIALER
แสดงผล
null
InCallService
ในระหว่างผูกมัด เฟรมเวิร์กโทรคมนาคมจะลดลงโดยอัตโนมัติ
กลับไปใช้แอปโทรศัพท์ที่โหลดไว้ล่วงหน้าในอุปกรณ์ ระบบจะแสดงการแจ้งเตือนไปยัง
เพื่อแจ้งให้ผู้ใช้ทราบว่าระบบยังคงโทรต่อโดยใช้แอปแป้นโทรศัพท์ที่โหลดไว้ให้ล่วงหน้า บัญชี
แอปไม่ควรแสดงผลการเชื่อมโยง null
การทำเช่นนี้หมายความว่า
ข้อกำหนดของ RoleManager.ROLE_DIALER
หมายเหตุ: หากแอปเติมข้อมูลครบ RoleManager.ROLE_DIALER
และทำการเปลี่ยนแปลงในเวลา
ซึ่งทำให้ไม่เป็นไปตามข้อกำหนดของบทบาทนี้อีกต่อไป
RoleManager
จะนำแอปของคุณออกจากบทบาทโดยอัตโนมัติและปิด
แอปของคุณ ตัวอย่างเช่น หากคุณใช้
PackageManager.setComponentEnabledSetting(ComponentName, int, int)
ถึง
ปิดใช้InCallService
ที่แอปประกาศในไฟล์ Manifest แบบเป็นโปรแกรม
จะไม่ปฏิบัติตามข้อกำหนดที่คาดไว้
RoleManager.ROLE_DIALER
แป้นโทรศัพท์ที่โหลดล่วงหน้าจะถูกใช้งานทุกครั้งที่ผู้ใช้โทรฉุกเฉิน แม้ว่า
ในแอปจะมีบทบาท RoleManager.ROLE_DIALER
เพื่อให้ได้มาซึ่ง
เมื่อโทรฉุกเฉิน แป้นโทรศัพท์เริ่มต้นควรใช้ "ทุกครั้ง"
TelecomManager.placeCall(Uri, Bundle)
เพื่อโทรออก (รวมถึง
โทรฉุกเฉิน) วิธีนี้ช่วยให้แพลตฟอร์มยืนยันได้ว่าคำขอมาจากแหล่งที่มาดังกล่าว
แป้นโทรศัพท์เริ่มต้น หากแอปโทรศัพท์ที่ไม่ได้โหลดไว้ล่วงหน้าใช้ Intent#ACTION_CALL
เพื่อวาง
การโทรฉุกเฉิน ระบบจะรับสายไปยังแอปแป้นโทรศัพท์ที่โหลดล่วงหน้าโดยใช้ Intent#ACTION_DIAL
เพื่อการยืนยัน ทำให้ผู้ใช้ได้รับประสบการณ์ที่ไม่ดี
ด้านล่างคือตัวอย่างการลงทะเบียนไฟล์ Manifest สำหรับ InCallService
ข้อมูลเมตา
TelecomManager#METADATA_IN_CALL_SERVICE_UI
ระบุว่า
การใช้งาน InCallService
มีวัตถุประสงค์เพื่อแทนที่ UI ในตัว
ข้อมูลเมตา TelecomManager#METADATA_IN_CALL_SERVICE_RINGING
บ่งบอกว่า
InCallService
จะเล่นเสียงเรียกเข้าเมื่อมีสายเข้า โปรดดู
ด้านล่างเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการแสดงสายเรียกเข้า
UI และการเล่นเสียงเรียกเข้าในแอป
<service android:name="your.package.YourInCallServiceImplementation"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
<meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
<meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
</service>
หมายเหตุ: คุณไม่ควรทำเครื่องหมาย InCallService
ด้วยแอตทริบิวต์
android:exported="false"
; การทำเช่นนั้นอาจส่งผลให้ไม่สามารถเชื่อมโยงกับการติดตั้งใช้งาน
ระหว่างการโทร
นอกจากการใช้ InCallService
API แล้ว คุณต้องประกาศกิจกรรมใน
ไฟล์ Manifest ของคุณซึ่งจัดการ Intent Intent#ACTION_DIAL
ตัวอย่างด้านล่างจะแสดง
วิธีการทำงาน
<activity android:name="your.package.YourDialerActivity"
android:label="@string/yourDialerActivityLabel">
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
</activity>
เมื่อผู้ใช้ติดตั้งและเรียกใช้แอปพลิเคชันเป็นครั้งแรก คุณควรใช้
RoleManager
เพื่อแจ้งให้ผู้ใช้ทราบว่าต้องการให้แอปของคุณดำเนินการหรือไม่
เป็นแอปโทรศัพท์เริ่มต้นแอปใหม่
โค้ดด้านล่างแสดงวิธีที่แอปของคุณสามารถขอเป็นแอปโทรศัพท์/แอปโทรศัพท์เริ่มต้นได้
private static final int REQUEST_ID = 1;
public void requestRole() {
RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER);
startActivityForResult(intent, REQUEST_ID);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ID) {
if (resultCode == android.app.Activity.RESULT_OK) {
// Your app is now the default dialer app
} else {
// Your app is not the default dialer app
}
}
}
สิทธิ์เข้าถึง InCallService สำหรับอุปกรณ์ที่สวมใส่ได้
-
ถ้าแอปของคุณเป็นแอปที่ใช้ร่วมกันกับบุคคลที่สาม และต้องการเข้าถึง InCallService API
ที่แอปสามารถทำได้มีดังนี้
- ประกาศสิทธิ์ MANAGE_ONGOING_CALLS ในไฟล์ Manifest
- เชื่อมโยงกับอุปกรณ์ที่สวมใส่ได้จริงผ่านทาง
CompanionDeviceManager
API เป็นแอปที่ใช้ร่วมกัน โปรดดูหัวข้อต่อไปนี้ https://developer.android.com/guide/topics/connectivity/Companion-device-pairing - ใช้ InCallService นี้โดยใช้สิทธิ์ BIND_INCALL_SERVICE
การแสดงการแจ้งเตือนสายเรียกเข้า
เมื่อแอปของคุณได้รับสายเรียกเข้าใหม่ผ่านInCallService#onCallAdded(Call)
ซึ่งทำหน้าที่แสดง UI ของสายเรียกเข้า ซึ่งควรดำเนินการโดยใช้
NotificationManager
API เพื่อโพสต์การแจ้งเตือนสายเรียกเข้าใหม่
ที่ที่แอปประกาศข้อมูลเมตา TelecomManager#METADATA_IN_CALL_SERVICE_RINGING
มีหน้าที่เล่นเสียงเรียกเข้าสำหรับสายเข้า แอปของคุณควรสร้าง
NotificationChannel
ซึ่งระบุเสียงเรียกเข้าที่ต้องการ เช่น
NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls",
NotificationManager.IMPORTANCE_MAX);
// other channel setup stuff goes here.
// We'll use the default system ringtone for our incoming call notification channel. You can
// use your own audio resource here.
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
channel.setSound(ringtoneUri, new AudioAttributes.Builder()
// Setting the AudioAttributes is important as it identifies the purpose of your
// notification sound.
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build());
NotificationManager mgr = getSystemService(NotificationManager.class);
mgr.createNotificationChannel(channel);
เมื่อแอปได้รับสายเรียกเข้าใหม่ แอปจะสร้าง Notification
สำหรับ
สายเรียกเข้าและเชื่อมโยงกับช่องทางการแจ้งเตือนสายเรียกเข้า คุณสามารถระบุ
PendingIntent
ในการแจ้งเตือนซึ่งจะเปิดโหมดเต็มหน้าจอของคุณ
UI ของสายเรียกเข้า เฟรมเวิร์กเครื่องมือจัดการการแจ้งเตือนจะแสดงการแจ้งเตือนของคุณเป็น
การแจ้งเตือนล่วงหน้าหากผู้ใช้กำลังใช้โทรศัพท์ เมื่อผู้ใช้ไม่ได้ใช้
ระบบจะใช้ UI ของสายเรียกเข้าแบบเต็มหน้าจอแทน
เช่น
// Create an intent which triggers your fullscreen incoming call user interface.
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(context, YourIncomingCallActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
// Build the notification as an ongoing high priority item; this ensures it will show as
// a heads up notification which slides down over top of the current content.
final Notification.Builder builder = new Notification.Builder(context);
builder.setOngoing(true);
builder.setPriority(Notification.PRIORITY_HIGH);
// Set notification content intent to take user to the fullscreen UI if user taps on the
// notification body.
builder.setContentIntent(pendingIntent);
// Set full screen intent to trigger display of the fullscreen UI when the notification
// manager deems it appropriate.
builder.setFullScreenIntent(pendingIntent, true);
// Setup notification content.
builder.setSmallIcon( yourIconResourceId );
builder.setContentTitle("Your notification title");
builder.setContentText("Your notification content.");
// Use builder.addAction(..) to add buttons to answer or reject the call.
NotificationManager notificationManager = mContext.getSystemService(
NotificationManager.class);
notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, builder.build());
```