Ứng dụng điện thoại mặc định cho phép khung Android Telecom thông báo cho ứng dụng về trạng thái gọi bằng cách dùng trình quản lý vai trò và dịch vụ trong cuộc gọi để tạo ứng dụng thay thế cho ứng dụng điện thoại mặc định trên thiết bị Android, triển khai InCallService API. Việc triển khai của bạn phải đáp ứng các yêu cầu sau:
Lớp này không được có tính năng gọi và chỉ được bao gồm giao diện người dùng để gọi. Nó phải xử lý tất cả các cuộc gọi mà khung Viễn thông biết được và không đưa ra giả định về bản chất của cuộc gọi. Ví dụ: ứng dụng này không được giả định các cuộc gọi là cuộc gọi điện thoại dựa trên SIM, cũng như không được triển khai các hạn chế gọi dựa trên bất kỳ một ConnectionService nào, chẳng hạn như việc thực thi các hạn chế về điện thoại đối với cuộc gọi video.
Ứng dụng gọi điện cho phép người dùng nhận hoặc thực hiện cuộc gọi thoại/video trên thiết bị. Các ứng dụng gọi điện dùng giao diện người dùng riêng để gọi điện, thay vì dùng giao diện người dùng giao diện mặc định của ứng dụng Điện thoại, như trong ảnh chụp màn hình sau đây.
Khung Android bao gồm gói android.telecom
,
chứa các lớp giúp bạn tạo một ứng dụng gọi điện theo
khung. Việc xây dựng ứng dụng của bạn theo khung viễn thông sẽ mang lại
các lợi ích sau:
- Ứng dụng của bạn tương tác chính xác với hệ thống con viễn thông gốc trong thiết bị.
- Ứng dụng của bạn tương tác chính xác với các ứng dụng gọi khác cũng tuân thủ khung này.
- Khung này giúp ứng dụng của bạn quản lý việc định tuyến âm thanh và video.
- Khung này giúp ứng dụng của bạn xác định xem các lệnh gọi của khung này có tâm điểm hay không.
Quyền và nội dung khai báo trong tệp kê khai
Trong tệp kê khai ứng dụng, hãy khai báo rằng ứng dụng sử dụng
MANAGE_OWN_CALLS
như được minh hoạ trong ví dụ sau đây:
<manifest … >
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
</manifest>
Để biết thêm thông tin về việc khai báo quyền cho ứng dụng, hãy xem Quyền.
Bạn phải khai báo một dịch vụ chỉ định lớp sẽ triển khai
ConnectionService
trong ứng dụng của bạn. Viễn thông
hệ thống con yêu cầu dịch vụ khai báo quyền BIND_TELECOM_CONNECTION_SERVICE
có thể liên kết với nó. Ví dụ sau đây trình bày cách khai báo dịch vụ trong
tệp kê khai ứng dụng của bạn:
<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>
Để biết thêm thông tin về việc khai báo thành phần ứng dụng (bao gồm cả dịch vụ), hãy xem Thành phần ứng dụng.
Triển khai dịch vụ kết nối
Ứng dụng gọi của bạn phải cung cấp phương thức triển khai lớp ConnectionService
mà hệ thống con viễn thông có thể liên kết.
Quá trình triển khai ConnectionService
của bạn sẽ ghi đè
các phương thức sau:
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
Hệ thống con viễn thông gọi phương thức này để phản hồi ứng dụng của bạn gọi
placeCall(Uri, Bundle)
để tạo một cuộc gọi đi mới. Ứng dụng của bạn trả về một thực thể mới của quá trình triển khai lớpConnection
(để biết thêm thông tin, hãy xem Triển khai mối kết nối) để biểu thị cuộc gọi đi. Bạn có thể tuỳ chỉnh thêm kết nối đi bằng cách thực hiện các hành động sau:- Ứng dụng của bạn phải gọi phương thức
setConnectionProperties(int)
có hằng sốPROPERTY_SELF_MANAGED
làm đối số để cho biết rằng kết nối bắt nguồn từ một ứng dụng gọi điện. - Nếu ứng dụng của bạn hỗ trợ tạm ngưng cuộc gọi, hãy gọi phương thức
setConnectionCapabilities(int)
và đặt giá trị đối số cho giá trị mặt nạ bit của hằng sốCAPABILITY_HOLD
vàCAPABILITY_SUPPORT_HOLD
. - Để đặt tên cho phương thức gọi, hãy sử dụng phương thức
setCallerDisplayName(String, int)
đang truyềnPRESENTATION_ALLOWED
là hằng số dưới dạng tham sốint
để cho biết tên của phương thức gọi hiển thị. - Để đảm bảo cuộc gọi đi có trạng thái video phù hợp, hãy thực hiện lệnh gọi
Phương thức
setVideoState(int)
của đối tượngConnection
và gửi giá trị được phương thức trả về Phương thứcgetVideoState()
của Đối tượngConnectionRequest
.
- Ứng dụng của bạn phải gọi phương thức
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
Hệ thống con viễn thông gọi phương thức này khi ứng dụng của bạn gọi phương thức
placeCall(Uri, Bundle)
và cuộc gọi đi thì không thể được đặt. Để ứng phó với tình huống này, ứng dụng của bạn phải thông báo cho người dùng (để ví dụ: sử dụng hộp cảnh báo hoặc thông báo ngắn) cho biết không thể thực hiện cuộc gọi đi . Ứng dụng của bạn có thể không thực hiện được cuộc gọi nếu có cuộc gọi khẩn cấp hoặc nếu có một cuộc gọi đang diễn ra trong một ứng dụng khác mà không thể hãy giữ máy trước khi thực hiện cuộc gọi.onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
Hệ thống con viễn thông gọi phương thức này khi ứng dụng của bạn gọi phương thức
addNewIncomingCall(PhoneAccountHandle, Bundle)
để thông báo cho hệ thống về cuộc gọi đến mới trong ứng dụng của bạn. Ứng dụng của bạn trả về một thực thể mới của việc triển khaiConnection
(cho để biết thêm thông tin, hãy xem bài viết Triển khai mối liên kết) để đại diện cho cuộc gọi đến mới. Bạn có thể tuỳ chỉnh thêm kết nối bằng cách thực hiện các thao tác sau:- Ứng dụng của bạn phải gọi phương thức
setConnectionProperties(int)
có hằng sốPROPERTY_SELF_MANAGED
làm đối số để cho biết rằng kết nối bắt nguồn từ một ứng dụng gọi điện. - Nếu ứng dụng của bạn hỗ trợ tạm ngưng cuộc gọi, hãy gọi phương thức
setConnectionCapabilities(int)
và đặt giá trị đối số cho giá trị mặt nạ bit của hằng sốCAPABILITY_HOLD
vàCAPABILITY_SUPPORT_HOLD
. - Để đặt tên cho phương thức gọi, hãy sử dụng phương thức
setCallerDisplayName(String, int)
đang truyềnPRESENTATION_ALLOWED
là hằng số dưới dạng tham sốint
để cho biết tên của phương thức gọi hiển thị. - Để chỉ định số điện thoại hoặc địa chỉ của cuộc gọi đến, hãy sử dụng
Phương thức
setAddress(Uri, int)
của đối tượngConnection
. - Để đảm bảo cuộc gọi đi có trạng thái video phù hợp, hãy thực hiện lệnh gọi
Phương thức
setVideoState(int)
của đối tượngConnection
và gửi giá trị được phương thức trả về Phương thứcgetVideoState()
của Đối tượngConnectionRequest
.
- Ứng dụng của bạn phải gọi phương thức
onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
Hệ thống con viễn thông gọi phương thức này khi ứng dụng của bạn gọi phương thức
addNewIncomingCall(PhoneAccountHandle, Bundle)
để thông báo cho Telecom về một cuộc gọi đến mới, nhưng không được phép cho cuộc gọi đến (để hãy xem các giới hạn gọi điện). Ứng dụng của bạn sẽ từ chối cuộc gọi đến, tùy ý đăng thông báo để thông báo người dùng của cuộc gọi nhỡ.
Triển khai mối kết nối
Ứng dụng phải tạo một lớp con của Connection
để
đại diện cho các cuộc gọi trong ứng dụng của bạn. Bạn nên ghi đè các phương thức sau trong
cách triển khai của bạn:
onShowIncomingCallUi()
Hệ thống con viễn thông gọi phương thức này khi bạn thêm cuộc gọi đến mới và ứng dụng của bạn phải cho thấy giao diện người dùng có cuộc gọi đến.
onCallAudioStateChanged(CallAudioState)
Hệ thống con viễn thông gọi phương thức này để thông báo cho ứng dụng của bạn rằng âm thanh hiện tại tuyến đường hoặc chế độ đã thay đổi. Lệnh này được gọi để phản hồi việc ứng dụng của bạn thay đổi chế độ phát âm thanh bằng
setAudioRoute(int)
. Phương thức này cũng có thể được gọi nếu hệ thống thay đổi đường truyền âm thanh (ví dụ: khi tai nghe Bluetooth ngắt kết nối).onHold()
Hệ thống con viễn thông gọi phương thức này khi muốn tạm dừng một cuộc gọi. Để phản hồi yêu cầu này, ứng dụng của bạn sẽ giữ cuộc gọi rồi gọi Phương thức
setOnHold()
để thông báo cho hệ thống cho biết cuộc gọi đang được giữ. Hệ thống con viễn thông có thể gọi phương thức này khi một dịch vụ đang gọi điện (chẳng hạn như Android Auto) cho biết cuộc gọi của bạn muốn chuyển tiếp yêu cầu của người dùng về việc giữ cuộc gọi. Hệ thống con viễn thông này cũng gọi phương thức này nếu người dùng kích hoạt một cuộc gọi trong một ứng dụng khác. Để biết thêm thông tin về các dịch vụ trong cuộc gọi, xemInCallService
.onUnhold()
Hệ thống con viễn thông gọi phương thức này khi nó muốn tiếp tục một cuộc gọi đã bị giữ máy. Sau khi ứng dụng của bạn tiếp tục lệnh gọi, nó sẽ gọi
setActive()
để thông báo cho hệ thống rằng cuộc gọi không còn bị giữ máy. Viễn thông hệ thống con có thể gọi phương thức này khi một dịch vụ đang gọi điện, chẳng hạn như Android Auto, đang cho thấy cuộc gọi của bạn muốn chuyển tiếp một yêu cầu để tiếp tục cuộc gọi đó. Cho để biết thêm thông tin về các dịch vụ trong cuộc gọi, hãy xemInCallService
.onAnswer()
Hệ thống con viễn thông gọi phương thức này để thông báo ứng dụng của bạn để trả lời cuộc gọi đến. Khi ứng dụng của bạn đã trả lời lệnh gọi, nó sẽ gọi
setActive()
để thông báo cho hệ thống rằng cuộc gọi đã được trả lời. Viễn thông hệ thống con có thể gọi phương thức này khi ứng dụng của bạn thêm cuộc gọi đến mới và hiện có một cuộc gọi đang diễn ra trong một ứng dụng khác không thể chuyển sang chế độ chờ. Hệ thống con viễn thông hiển thị giao diện người dùng của cuộc gọi đến thay mặt cho ứng dụng của bạn trong các trường hợp này. Khung này cung cấp một phương thức nạp chồng để cung cấp hỗ trợ để chỉ định trạng thái video sẽ trả lời cuộc gọi. Để biết thêm thông tin, hãy xemonAnswer(int)
.onReject()
Hệ thống con viễn thông gọi phương thức này khi muốn từ chối lời mời đến . Sau khi từ chối lệnh gọi, ứng dụng của bạn phải gọi
setDisconnected(DisconnectCause)
và chỉ địnhREJECTED
làm tham số. Ứng dụng của bạn sẽ sau đó gọi phương thứcdestroy()
để thông báo hệ thống mà ứng dụng đã xử lý cuộc gọi. Hệ thống con viễn thông gọi phương thức này khi người dùng từ chối cuộc gọi đến từ ứng dụng của bạn.onDisconnect()
Hệ thống con viễn thông gọi phương thức này khi muốn ngắt kết nối một cuộc gọi. Sau khi lệnh gọi kết thúc, ứng dụng nên gọi phương thức
setDisconnected(DisconnectCause)
và chỉ địnhLOCAL
làm tham số để cho biết rằng một phương thức yêu cầu của người dùng khiến cuộc gọi bị ngắt kết nối. Sau đó, ứng dụng của bạn sẽ gọi hàm Phương thứcdestroy()
để thông báo cho hệ thống viễn thông hệ thống con mà ứng dụng đã xử lý lệnh gọi. Hệ thống có thể gọi phương thức này khi người dùng đã ngắt kết nối cuộc gọi thông qua một dịch vụ trong cuộc gọi khác, chẳng hạn như Android Auto. Hệ thống cũng gọi phương thức này khi lệnh gọi của bạn phải ngắt kết nối để cho phép thực hiện cuộc gọi khác, ví dụ: nếu người dùng muốn để thực hiện cuộc gọi khẩn cấp. Để biết thêm thông tin về dịch vụ trong cuộc gọi, hãy xemInCallService
.
Xử lý các tình huống gọi điện phổ biến
Sử dụng API ConnectionService
trong lệnh gọi
luồng bao gồm việc tương tác với các lớp khác trong android.telecom
. Các phần sau đây mô tả các trường hợp gọi điện phổ biến và cách
ứng dụng sẽ sử dụng API để xử lý chúng.
Trả lời cuộc gọi đến
Quy trình xử lý cuộc gọi đến sẽ thay đổi dù có cuộc gọi trong các ứng dụng khác hay không hay không. Nguyên nhân của sự khác biệt về luồng là khung viễn thông phải thiết lập một số quy tắc ràng buộc khi có các lệnh gọi đang diễn ra trong các ứng dụng khác để đảm bảo môi trường ổn định cho mọi ứng dụng gọi trên thiết bị. Để biết thêm hãy xem Hạn chế về việc gọi.
Không có cuộc gọi nào đang diễn ra trong các ứng dụng khác
Để trả lời cuộc gọi đến khi không có cuộc gọi nào đang hoạt động trong các ứng dụng khác, hãy làm theo các bước sau:
- Ứng dụng của bạn nhận được một cuộc gọi đến mới theo cơ chế thông thường.
- Sử dụng phương thức
addNewIncomingCall(PhoneAccountHandle, Bundle)
để thông báo cho hệ thống viễn thông con về cuộc gọi đến mới. - Hệ thống con viễn thông liên kết với quá trình triển khai
ConnectionService
của ứng dụng và yêu cầu một thực thể mới của lớpConnection
đại diện cho lớp mới sắp đến bằng phương thứconCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
. - Hệ thống con viễn thông sẽ thông báo cho ứng dụng của bạn rằng cần hiện cuộc gọi đến
giao diện người dùng bằng phương thức
onShowIncomingCallUi()
. - Ứng dụng của bạn hiển thị giao diện người dùng đến bằng cách sử dụng thông báo kèm theo
ý định toàn màn hình. Để biết thêm thông tin, hãy xem
onShowIncomingCallUi()
. - Gọi phương thức
setActive()
nếu người dùng chấp nhận cuộc gọi đến, hoặcsetDisconnected(DisconnectCause)
chỉ địnhREJECTED
làm tham số, theo sau là gọi phương thứcdestroy()
nếu người dùng từ chối cuộc gọi đến.
Cuộc gọi đang diễn ra trong các ứng dụng khác không thể chuyển sang chế độ chờ
Để trả lời cuộc gọi đến khi có cuộc gọi đang diễn ra trong các ứng dụng khác không thể trả lời bị tạm dừng, hãy làm theo các bước sau:
- Ứng dụng của bạn nhận được một cuộc gọi đến mới theo cơ chế thông thường.
- Sử dụng phương thức
addNewIncomingCall(PhoneAccountHandle, Bundle)
để thông báo cho hệ thống viễn thông con về cuộc gọi đến mới. - Hệ thống con viễn thông liên kết với quá trình triển khai
ConnectionService
của ứng dụng và yêu cầu một thực thể mới của đối tượngConnection
đại diện cho cuộc gọi đến bằng phương thứconCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
. - Hệ thống con viễn thông hiển thị giao diện người dùng cho cuộc gọi đến cho cuộc gọi đến.
- Nếu người dùng chấp nhận cuộc gọi, hệ thống con viễn thông sẽ gọi phương thức
onAnswer()
. Bạn nên gọi phương thứcsetActive()
để cho biết dịch vụ viễn thông đó hệ thống con mà cuộc gọi hiện đã được kết nối. - Nếu người dùng từ chối cuộc gọi, hệ thống con viễn thông sẽ gọi phương thức
onReject()
. Bạn nên gọi phương thứcsetDisconnected(DisconnectCause)
, chỉ địnhREJECTED
làm tham số, theo sau là một gọi phương thứcdestroy()
.
Thực hiện cuộc gọi đi
Quy trình thực hiện cuộc gọi đi liên quan đến việc xử lý khả năng không thể thực hiện cuộc gọi vì các hạn chế do khung viễn thông áp đặt. Để biết thêm thông tin, hãy xem Các quy tắc ràng buộc đối với việc gọi.
Để thực hiện cuộc gọi đi, hãy làm theo các bước sau:
- Người dùng bắt đầu một cuộc gọi đi trong ứng dụng của bạn.
- Sử dụng phương thức
placeCall(Uri, Bundle)
để thông báo hệ thống viễn thông con về cuộc gọi đi mới. Thực hiện các bước sau các cân nhắc cho tham số phương thức:- Tham số
Uri
đại diện cho địa chỉ mà cuộc gọi đang được thực hiện. Đối với các số điện thoại thông thường, hãy dùng URItel:
hệ thống. - Tham số
Bundle
cho phép bạn cung cấp thông tin về ứng dụng gọi bằng cách thêm đối tượngPhoneAccountHandle
của ứng dụng vào phần bổ sungEXTRA_PHONE_ACCOUNT_HANDLE
. Thông tin ứng dụng phải cung cấp đối tượngPhoneAccountHandle
cho mọi cuộc gọi đi. - Tham số
Bundle
cũng cho phép bạn chỉ định xem cuộc gọi đi bao gồm video bằng cách chỉ định giá trịSTATE_BIDIRECTIONAL
trongEXTRA_START_CALL_WITH_VIDEO_STATE
bổ sung. Hãy xem xét rằng theo mặc định, hệ thống con viễn thông định tuyến các cuộc gọi video đến loa ngoài.
- Tham số
- Hệ thống con viễn thông liên kết với
ConnectionService
của ứng dụng trong quá trình triển khai. - Nếu ứng dụng của bạn không thể thực hiện cuộc gọi đi, hệ thống con viễn thông sẽ gọi
phương thức
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
để thông báo cho ứng dụng rằng không thể thực hiện cuộc gọi vào thời điểm hiện tại. Ứng dụng của bạn phải thông báo cho người dùng rằng không thể thực hiện cuộc gọi. - Nếu ứng dụng của bạn có thể thực hiện cuộc gọi đi, hệ thống con viễn thông sẽ gọi
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
. Ứng dụng của bạn sẽ trả về một thực thể của lớpConnection
để biểu thị lệnh gọi đi mới. Cho thêm thông tin về thuộc tính mà bạn nên đặt trong kết nối, hãy xem phần Triển khai dịch vụ kết nối. - Khi cuộc gọi đi đã được kết nối, hãy gọi phương thức
setActive()
để thông báo cho hệ thống viễn thông phụ cho biết cuộc gọi đang hoạt động.
Kết thúc cuộc gọi
Để kết thúc cuộc gọi, hãy làm theo các bước sau:
- Gọi
setDisconnected(DisconnectCause)
gửiLOCAL
dưới dạng tham số nếu người dùng đã kết thúc cuộc gọi hoặc gửiREMOTE
dưới dạng tham số nếu bên kia đã kết thúc cuộc gọi. - Gọi phương thức
destroy()
.
Các quy tắc ràng buộc đối với lệnh gọi
Để đảm bảo trải nghiệm gọi điện nhất quán và đơn giản cho người dùng, dịch vụ viễn thông
khung thực thi một số quy tắc ràng buộc để quản lý lệnh gọi trên thiết bị. Cho
ví dụ: hãy xem xét việc người dùng đã cài đặt hai ứng dụng gọi có triển khai
API ConnectionService
tự quản lý, FooTalk và
BarTalk. Trong trường hợp này, các điều kiện ràng buộc sau sẽ được áp dụng:
Trên các thiết bị chạy trên API cấp 27 trở xuống, chỉ một ứng dụng có thể duy trì cuộc gọi đang diễn ra tại bất kỳ thời điểm cụ thể nào. Hạn chế này có nghĩa là mặc dù người dùng có cuộc gọi đang diễn ra bằng ứng dụng FooTalk, ứng dụng BarTalk không thể bắt đầu hoặc nhận một cuộc gọi mới.
Trên các thiết bị chạy ở API cấp 28 trở lên, nếu cả FooTalk và BarTalk khai báo
CAPABILITY_SUPPORT_HOLD
vàCAPABILITY_HOLD
quyền truy cập, thì người dùng có thể duy trì nhiều cuộc gọi đang diễn ra bằng cách chuyển đổi giữa các ứng dụng để bắt đầu hoặc trả lời một cuộc gọi khác.Nếu người dùng tham gia vào các cuộc gọi được quản lý thông thường (ví dụ: sử dụng ứng dụng Trình quay số hoặc Điện thoại tích hợp sẵn), người dùng không thể tham gia các cuộc gọi bắt nguồn từ gọi điện. Điều này có nghĩa là nếu người dùng tham gia một cuộc gọi thông thường bằng nhà mạng di động, họ cũng không thể đồng thời tham gia cuộc gọi FooTalk hoặc BarTalk.
Hệ thống con viễn thông sẽ ngắt kết nối các cuộc gọi của ứng dụng nếu người dùng quay số cuộc gọi khẩn cấp.
Ứng dụng của bạn không thể nhận hoặc thực hiện cuộc gọi trong khi người dùng đang thực hiện cuộc gọi khẩn cấp.
Nếu có một cuộc gọi đang diễn ra trong một ứng dụng gọi khác khi ứng dụng đó nhận được một cuộc gọi đến, trả lời cuộc gọi đến sẽ kết thúc mọi cuộc gọi đang diễn ra trong ứng dụng khác. Ứng dụng của bạn không được hiển thị giao diện người dùng cho cuộc gọi đến thông thường. Khung viễn thông hiển thị giao diện người dùng của cuộc gọi đến và thông báo người dùng trả lời cuộc gọi mới sẽ kết thúc(các) cuộc gọi đang diễn ra của họ. Chiến dịch này có nghĩa là nếu người dùng đang thực hiện cuộc gọi FooTalk và ứng dụng BarTalk nhận được cuộc gọi đến, khung viễn thông sẽ thông báo cho người dùng rằng họ có cuộc gọi đến của BarTalk và việc trả lời cuộc gọi này sẽ chấm dứt Cuộc gọi qua FooTalk.
Trở thành Ứng dụng điện thoại mặc định
Ứng dụng gọi điện/trình quay số mặc định là ứng dụng cung cấp giao diện người dùng trong cuộc gọi khi thiết bị đang
trong một cuộc gọi. API này cũng cung cấp cho người dùng một cách thức để bắt đầu cuộc gọi và xem nhật ký cuộc gọi
trên thiết bị của họ. Thiết bị đi kèm với ứng dụng điện thoại/trình quay số mặc định do hệ thống cung cấp. Người dùng
có thể chọn một ứng dụng duy nhất để đảm nhận vai trò này từ ứng dụng hệ thống. Một ứng dụng mong muốn
thực hiện vai trò này sử dụng RoleManager
để yêu cầu chúng điền vào
Vai trò RoleManager.ROLE_DIALER
.
Ứng dụng điện thoại mặc định cung cấp giao diện người dùng khi thiết bị đang gọi điện và thiết bị
không ở chế độ ô tô (tức là UiModeManager#getCurrentModeType()
không ở chế độ trên ô tô)
Configuration.UI_MODE_TYPE_CAR
).
Để thực hiện vai trò RoleManager.ROLE_DIALER
, ứng dụng phải đáp ứng
số lượng yêu cầu:
- Phải xử lý ý định
Intent#ACTION_DIAL
. Tức là ứng dụng phải cung cấp giao diện người dùng bàn phím số để người dùng bắt đầu cuộc gọi đi. - Ứng dụng này phải triển khai đầy đủ API
InCallService
và cung cấp cả cuộc gọi đến Giao diện người dùng, cũng như một giao diện người dùng cho cuộc gọi đang diễn ra.
Lưu ý: Nếu ứng dụng điền RoleManager.ROLE_DIALER
sẽ trả về một giá trị
null
InCallService
trong khi ràng buộc, khung Viễn thông sẽ tự động giảm
quay lại sử dụng ứng dụng gọi điện được tải trước trên thiết bị. Hệ thống sẽ hiển thị thông báo để
cho người dùng biết rằng cuộc gọi của họ vẫn được tiếp tục bằng ứng dụng gọi điện được tải trước. Thông tin
ứng dụng không bao giờ được trả về một liên kết null
; làm như vậy có nghĩa là trang web không thực hiện
của RoleManager.ROLE_DIALER
.
Lưu ý: Nếu ứng dụng của bạn điền vào RoleManager.ROLE_DIALER
và thực hiện thay đổi lúc
thời gian chạy không còn đáp ứng được các yêu cầu của vai trò này,
RoleManager
sẽ tự động xoá ứng dụng của bạn khỏi vai trò này và đóng
ứng dụng của bạn. Ví dụ: nếu bạn sử dụng
PackageManager.setComponentEnabledSetting(ComponentName, int, int)
đến
tắt InCallService
mà ứng dụng của bạn khai báo trong tệp kê khai bằng phương thức lập trình, ứng dụng của bạn
sẽ không còn đáp ứng các yêu cầu như mong đợi
RoleManager.ROLE_DIALER
.
Trình quay số được tải trước sẽ LUÔN được sử dụng khi người dùng thực hiện cuộc gọi khẩn cấp, ngay cả khi
ứng dụng thực hiện vai trò RoleManager.ROLE_DIALER
. Để đảm bảo có được
khi thực hiện cuộc gọi khẩn cấp, trình quay số mặc định LUÔN sẽ sử dụng
TelecomManager.placeCall(Uri, Bundle)
để thực hiện cuộc gọi (bao gồm
cuộc gọi khẩn cấp). Điều này đảm bảo rằng nền tảng có thể xác minh rằng yêu cầu đến từ
trình quay số mặc định. Nếu ứng dụng gọi điện không được tải trước sử dụng Intent#ACTION_CALL
để đặt
cuộc gọi khẩn cấp, cuộc gọi đó sẽ được chuyển lên ứng dụng gọi điện được tải trước bằng Intent#ACTION_DIAL
để xác nhận; thì đây là trải nghiệm người dùng chưa tối ưu.
Dưới đây là ví dụ về cách đăng ký tệp kê khai cho InCallService
. Siêu dữ liệu
TelecomManager#METADATA_IN_CALL_SERVICE_UI
cho biết rằng URL cụ thể này
Việc triển khai InCallService
nhằm thay thế giao diện người dùng tích hợp sẵn trong cuộc gọi.
Siêu dữ liệu TelecomManager#METADATA_IN_CALL_SERVICE_RINGING
cho biết rằng
InCallService
sẽ phát nhạc chuông khi có cuộc gọi đến. Xem
bên dưới để biết thêm thông tin về cách hiển thị cuộc gọi đến
giao diện người dùng và phát nhạc chuông trong ứng dụng của bạn.
<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>
Lưu ý: Bạn KHÔNG nên đánh dấu InCallService
bằng thuộc tính này
android:exported="false"
; làm như vậy có thể dẫn đến việc
không liên kết được với phương thức triển khai của bạn
trong khi gọi điện.
Ngoài việc triển khai API InCallService
, bạn cũng phải khai báo hoạt động trong
tệp kê khai xử lý ý định Intent#ACTION_DIAL
. Ví dụ dưới đây minh hoạ
cách thực hiện việc này:
<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>
Khi người dùng cài đặt ứng dụng của bạn và chạy ứng dụng đó lần đầu tiên, bạn nên sử dụng
RoleManager
để nhắc người dùng xem họ có muốn ứng dụng của bạn
làm ứng dụng điện thoại mặc định mới.
Mã dưới đây cho biết cách ứng dụng của bạn có thể yêu cầu trở thành ứng dụng gọi điện/quay số mặc định:
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
}
}
}
Truy cập vào InCallService dành cho thiết bị đeo
-
Nếu ứng dụng của bạn là ứng dụng đồng hành bên thứ ba và muốn truy cập API InCallService, thì
ứng dụng có thể thực hiện là:
- Khai báo quyền MANAGE_ONGOING_CALL trong tệp kê khai
- Liên kết với một thiết bị đeo thực qua
CompanionDeviceManager
API làm ứng dụng đồng hành. Hãy xem: https://developer.android.com/guide/topics/connector/đồng hành-device-pairing - Triển khai InCallService với quyền BIND_INCALL_SERVICE
Hiện Thông báo cuộc gọi đến
Khi ứng dụng của bạn nhận được một cuộc gọi đến mới quaInCallService#onCallAdded(Call)
,
chịu trách nhiệm hiển thị giao diện người dùng có cuộc gọi đến cho cuộc gọi đến. Trình quản lý thẻ của Google cần thực hiện việc này bằng cách sử dụng
Các API NotificationManager
để đăng thông báo cuộc gọi đến mới.
Khi ứng dụng của bạn khai báo siêu dữ liệu TelecomManager#METADATA_IN_CALL_SERVICE_RINGING
,
chịu trách nhiệm phát nhạc chuông cho cuộc gọi đến. Ứng dụng của bạn sẽ tạo ra một
NotificationChannel
chỉ định nhạc chuông mong muốn. Ví dụ:
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);
Khi nhận được một cuộc gọi đến mới, ứng dụng của bạn sẽ tạo một Notification
cho
cuộc gọi đến và liên kết cuộc gọi đó với kênh thông báo cuộc gọi đến. Bạn có thể chỉ định một
PendingIntent
trên thông báo sẽ mở chế độ toàn màn hình
giao diện người dùng cuộc gọi đến. Khung trình quản lý thông báo sẽ hiển thị thông báo của bạn dưới dạng
nếu người dùng đang sử dụng điện thoại. Khi người dùng không sử dụng
điện thoại, thì giao diện người dùng cuộc gọi đến toàn màn hình sẽ được sử dụng.
Ví dụ:
// 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());
```