Khung Android Telecom (còn gọi là "Viễn thông") quản lý âm thanh và
các cuộc gọi video trên thiết bị chạy Android. Bao gồm cả các cuộc gọi trên SIM, chẳng hạn như
các cuộc gọi
sử dụng khung điện thoại và các lệnh gọi VoIP triển khai
ConnectionService
.
Các thành phần chính mà Telecom quản lý là ConnectionService
và
InCallService
.
Quá trình triển khai ConnectionService
sử dụng các công nghệ như VoIP để kết nối
các cuộc gọi đến các bên khác. Cách triển khai ConnectionService
phổ biến nhất trên
số điện thoại là ConnectionService
. Ứng dụng này kết nối các cuộc gọi của nhà mạng.
Phương thức triển khai InCallService
cung cấp giao diện người dùng cho các cuộc gọi được quản lý bằng
Viễn thông và cho phép người dùng kiểm soát cũng như tương tác với các cuộc gọi này. Nhiều nhất
cách triển khai phổ biến của InCallService
là ứng dụng điện thoại đi kèm với
một thiết bị.
Viễn thông đóng vai trò là một tổng đài. Phương thức này định tuyến các cuộc gọi ConnectionService
các phương thức triển khai cung cấp cho giao diện người dùng gọi mà InCallService
mà các nhà triển khai cung cấp.
Bạn có thể muốn triển khai Telecom API (API Viễn thông) vì những lý do sau:
- Để tạo bản sao thay thế cho ứng dụng điện thoại của hệ thống.
- Để tích hợp một giải pháp gọi điện vào trải nghiệm gọi điện trên Android.
Tạo ứng dụng điện thoại thay thế
Cách 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 API InCallService
. Việc triển khai của bạn phải đáp ứng các yêu cầu sau:
các yêu cầu:
- Máy chủ không được có tính năng gọi và chỉ được bao gồm một 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 nhận biết được và không thực hiện
giả định về bản chất của lệnh gọi. Ví dụ: mô-đun này không được giả định
là các cuộc gọi điện thoại dựa trên SIM, cũng như không triển khai các hạn chế gọi điện
đều dựa trên một
ConnectionService
bất kỳ, chẳng hạn như việc thực thi chế độ cài đặt điện thoại cho cuộc gọi video.
Để biết thêm thông tin, hãy xem InCallService
.
Tích hợp giải pháp gọi điện
Để tích hợp giải pháp gọi điện vào Android, bạn có các tuỳ chọn sau:
Triển khai API ConnectionService tự quản lý: Lựa chọn này phù hợp với những nhà phát triển có các ứng dụng gọi độc lập không muốn để hiển thị cuộc gọi của họ trong ứng dụng điện thoại mặc định, cũng như không hiển thị các cuộc gọi khác trong giao diện người dùng.
Khi dùng
ConnectionService
tự quản lý, bạn sẽ giúp ứng dụng của mình không chỉ tương tác với tính năng gọi điện thoại gốc trên thiết bị, mà còn với các ứng dụng gọi độc lập khác triển khai API này. Chế độ tự quản lý APIConnectionService
cũng quản lý chế độ tập trung và định tuyến âm thanh. Để biết thông tin chi tiết, hãy xem Tạo ứng dụng gọi điện.Triển khai API ConnectionService được quản lý: Lựa chọn này hỗ trợ phát triển một giải pháp gọi điện dựa vào ứng dụng điện thoại hiện có trên thiết bị để cung cấp giao diện người dùng cho các cuộc gọi. Ví dụ: việc triển khai tính năng gọi điện SIP và gọi VoIP của bên thứ ba luôn miễn phí. Để biết thêm thông tin, hãy xem
getDefaultDialerPackage()
.Riêng
ConnectionService
chỉ cung cấp phương tiện để kết nối các cuộc gọi. Nó không có giao diện người dùng được liên kết.Triển khai cả InCallService và API ConnectionService: Đây là lựa chọn lý tưởng nếu bạn muốn tạo Giải pháp gọi dựa trên
ConnectionService
, hoàn thiện với người dùng riêng giao diện người dùng và cũng hiển thị tất cả các lệnh gọi khác trên Android trong cùng một giao diện người dùng. Khi sử dụng phương pháp này, bạn không được triển khaiInCallService
đưa ra bất kỳ giả định nào về nguồn của lệnh gọi mà nó hiển thị. Ngoài ra, Việc triển khaiConnectionService
phải tiếp tục hoạt động mà không có ứng dụng điện thoại mặc định của bạn thànhInCallService
tuỳ chỉnh.
Hiện màn hình cuộc gọi
Thiết bị chạy Android 10 (API cấp 29) trở lên cho phép ứng dụng của bạn xác định
cuộc gọi từ các số không có trong sổ địa chỉ của người dùng có khả năng là làm phiền
cuộc gọi. Người dùng có thể chọn từ chối tự động các cuộc gọi làm phiền. Để cung cấp nhiều hơn
thông tin minh bạch cho người dùng khi họ bỏ lỡ cuộc gọi, thông tin về các cuộc gọi bị chặn
các cuộc gọi được ghi lại trong nhật ký cuộc gọi. Việc sử dụng API Android 10 sẽ loại bỏ
để có được
READ_CALL_LOG
quyền từ người dùng để cung cấp tính năng sàng lọc cuộc gọi và tên nhận dạng người gọi
của Google.
Bạn sử dụng
CallScreeningService
để sàng lọc cuộc gọi. Gọi
onScreenCall()
cho mọi cuộc gọi đến hoặc cuộc gọi đi mới khi số này không nằm trong
danh bạ của người dùng. Bạn có thể xem
Đối tượng Call.Details
cho thông tin
về cuộc gọi này. Cụ thể,
getCallerNumberVerificationStatus()
hàm này bao gồm thông tin từ nhà cung cấp mạng về số khác.
Nếu trạng thái xác minh không thành công, đây là một dấu hiệu tốt cho thấy cuộc gọi
từ một số điện thoại không hợp lệ hoặc từ một cuộc gọi có khả năng làm phiền.
Kotlin
class ScreeningService : CallScreeningService() { // This function is called when an ingoing or outgoing call // is from a number not in the user's contacts list override fun onScreenCall(callDetails: Call.Details) { // Can check the direction of the call val isIncoming = callDetails.callDirection == Call.Details.DIRECTION_INCOMING if (isIncoming) { // the handle (e.g. phone number) that the Call is currently connected to val handle: Uri = callDetails.handle // determine if you want to allow or reject the call when (callDetails.callerNumberVerificationStatus) { Connection.VERIFICATION_STATUS_FAILED -> { // Network verification failed, likely an invalid/spam call. } Connection.VERIFICATION_STATUS_PASSED -> { // Network verification passed, likely a valid call. } else -> { // Network could not perform verification. // This branch matches Connection.VERIFICATION_STATUS_NOT_VERIFIED. } } } } }
Java
class ScreeningService extends CallScreeningService { @Override public void onScreenCall(@NonNull Call.Details callDetails) { boolean isIncoming = callDetails.getCallDirection() == Call.Details.DIRECTION_INCOMING; if (isIncoming) { Uri handle = callDetails.getHandle(); switch (callDetails.getCallerNumberVerificationStatus()) { case Connection.VERIFICATION_STATUS_FAILED: // Network verification failed, likely an invalid/spam call. break; case Connection.VERIFICATION_STATUS_PASSED: // Network verification passed, likely a valid call. break; default: // Network could not perform verification. // This branch matches Connection.VERIFICATION_STATUS_NOT_VERIFIED } } } }
Đặt hàm onScreenCall()
để gọi
respondToCall()
để cho hệ thống biết cách phản hồi cuộc gọi mới. Hàm này nhận một
CallResponse
mà bạn có thể sử dụng để yêu cầu hệ thống chặn cuộc gọi, từ chối cuộc gọi như thể
người dùng đã thực hiện hoặc tắt tiếng. Bạn cũng có thể yêu cầu hệ thống bỏ qua việc thêm đoạn mã này
cuộc gọi đến nhật ký cuộc gọi của thiết bị.
Kotlin
// Tell the system how to respond to the incoming call // and if it should notify the user of the call. val response = CallResponse.Builder() // Sets whether the incoming call should be blocked. .setDisallowCall(false) // Sets whether the incoming call should be rejected as if the user did so manually. .setRejectCall(false) // Sets whether ringing should be silenced for the incoming call. .setSilenceCall(false) // Sets whether the incoming call should not be displayed in the call log. .setSkipCallLog(false) // Sets whether a missed call notification should not be shown for the incoming call. .setSkipNotification(false) .build() // Call this function to provide your screening response. respondToCall(callDetails, response)
Java
// Tell the system how to respond to the incoming call // and if it should notify the user of the call. CallResponse.Builder response = new CallResponse.Builder(); // Sets whether the incoming call should be blocked. response.setDisallowCall(false); // Sets whether the incoming call should be rejected as if the user did so manually. response.setRejectCall(false); // Sets whether ringing should be silenced for the incoming call. response.setSilenceCall(false); // Sets whether the incoming call should not be displayed in the call log. response.setSkipCallLog(false); // Sets whether a missed call notification should not be shown for the incoming call. response.setSkipNotification(false); // Call this function to provide your screening response. respondToCall(callDetails, response.build());
Bạn phải đăng ký phương thức triển khai CallScreeningService
trong tệp kê khai
có bộ lọc ý định và quyền thích hợp để hệ thống có thể kích hoạt
một cách chính xác.
<service
android:name=".ScreeningService"
android:permission="android.permission.BIND_SCREENING_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallScreeningService" />
</intent-filter>
</service>
Chuyển hướng cuộc gọi
Các thiết bị chạy Android 10 trở lên quản lý ý định cuộc gọi theo cách khác với
thiết bị chạy Android 9 trở xuống. Trên Android 10 trở lên,
ACTION_NEW_OUTGOING_CALL
Thông báo truyền tin không được dùng nữa và được thay thế bằng
CallRedirectionService
API. CallRedirectionService
cung cấp các giao diện để bạn sử dụng
sửa đổi các cuộc gọi đi do nền tảng Android thực hiện. Ví dụ: bên thứ ba
có thể huỷ cuộc gọi và định tuyến lại qua VoIP.
Kotlin
class RedirectionService : CallRedirectionService() { override fun onPlaceCall( handle: Uri, initialPhoneAccount: PhoneAccountHandle, allowInteractiveResponse: Boolean ) { // Determine if the call should proceed, be redirected, or cancelled. val callShouldProceed = true val callShouldRedirect = false when { callShouldProceed -> { placeCallUnmodified() } callShouldRedirect -> { // Update the URI to point to a different phone number or modify the // PhoneAccountHandle and redirect. redirectCall(handle, initialPhoneAccount, true) } else -> { cancelCall() } } } }
Java
class RedirectionService extends CallRedirectionService { @Override public void onPlaceCall( @NonNull Uri handle, @NonNull PhoneAccountHandle initialPhoneAccount, boolean allowInteractiveResponse ) { // Determine if the call should proceed, be redirected, or cancelled. // Your app should implement this logic to determine the redirection. boolean callShouldProceed = true; boolean callShouldRedirect = false; if (callShouldProceed) { placeCallUnmodified(); } else if (callShouldRedirect) { // Update the URI to point to a different phone number or modify the // PhoneAccountHandle and redirect. redirectCall(handle, initialPhoneAccount, true); } else { cancelCall(); } } }
Bạn phải đăng ký dịch vụ này trong tệp kê khai để hệ thống có thể khởi động dịch vụ đó chính xác.
<service
android:name=".RedirectionService"
android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallRedirectionService"/>
</intent-filter>
</service>
Để sử dụng dịch vụ chuyển hướng, ứng dụng của bạn phải yêu cầu vai trò chuyển hướng cuộc gọi
khỏi RoleManager
. Quy trình này sẽ yêu cầu
của người dùng nếu họ muốn cho phép ứng dụng của bạn xử lý lệnh chuyển hướng cuộc gọi. Nếu ứng dụng của bạn
người dùng chưa được cấp vai trò này, thì dịch vụ chuyển hướng của bạn sẽ không được sử dụng.
Khi người dùng chạy ứng dụng, bạn nên kiểm tra xem ứng dụng của mình có vai trò này hay không.
bạn có thể yêu cầu mã đó nếu cần. Bạn khởi chạy một ý định do RoleManager
tạo,
do đó, hãy đảm bảo bạn ghi đè
onActivityResult()
để xử lý lựa chọn của người dùng.
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Tell the system that you want your app to handle call redirects. This // is done by using the RoleManager to register your app to handle redirects. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { val roleManager = getSystemService(Context.ROLE_SERVICE) as RoleManager // Check if the app needs to register call redirection role. val shouldRequestRole = roleManager.isRoleAvailable(RoleManager.ROLE_CALL_REDIRECTION) && !roleManager.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION) if (shouldRequestRole) { val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION) startActivityForResult(intent, REDIRECT_ROLE_REQUEST_CODE) } } } companion object { private const val REDIRECT_ROLE_REQUEST_CODE = 1 } }
Java
class MainActivity extends AppCompatActivity { private static final int REDIRECT_ROLE_REQUEST_CODE = 0; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Tell the system that you want your app to handle call redirects. This // is done by using the RoleManager to register your app to handle redirects. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { RoleManager roleManager = (RoleManager) getSystemService(Context.ROLE_SERVICE); // Check if the app needs to register call redirection role. boolean shouldRequestRole = roleManager.isRoleAvailable(RoleManager.ROLE_CALL_REDIRECTION) && !roleManager.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION); if (shouldRequestRole) { Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION); startActivityForResult(intent, REDIRECT_ROLE_REQUEST_CODE); } } } }