Android cung cấp một bản triển khai Bluetooth đầy đủvới hỗ trợ nhiều cấu hình Bluetooth phổ biến trong ô tô. Ngoài ra, còn có nhiều điểm cải tiến giúp nâng cao hiệu suất và trải nghiệm với các thiết bị và dịch vụ khác.
Quản lý kết nối Bluetooth
Trong Android, CarBluetoothService duy trì các thiết bị Bluetooth và danh sách ưu tiên của người dùng hiện tại cho từng kết nối cấu hình với IVI. Các thiết bị được kết nối với cấu hình theo thứ tự ưu tiên đã xác định. Thời điểm bật, tắt và kết nối thiết bị với một cấu hình được điều khiển bởi chính sách kết nối mặc định. Bạn có thể ghi đè chính sách này bằng cách sử dụng lớp phủ tài nguyên nếu muốn.
Định cấu hình tính năng quản lý kết nối ô tô
Tắt chính sách mặc định cho điện thoại
Ngăn xếp Bluetooth của Android duy trì một chính sách kết nối cho điện thoại được bật theo mặc định. Bạn phải tắt chính sách này trên thiết bị để chính sách này không xung đột với chính sách ô tô dự kiến trong
CarBluetoothService. Mặc dù lớp phủ sản phẩm Ô tô sẽ xử lý việc này cho bạn,
bạn có thể tắt chính sách cho điện thoại trong
lớp phủ tài nguyên bằng cách đặt enable_phone_policy thành false trong
MAXIMUM_CONNECTED_DEVICES trong
/packages/apps/Bluetooth/res/values/config.xml.
Sử dụng chính sách ô tô mặc định
CarBluetoothService duy trì các quyền mặc định của cấu hình. Danh sách các thiết bị đã biết
và mức độ ưu tiên kết nối lại cấu hình của các thiết bị đó nằm trong
service/src/com/android/car/BluetoothProfileDeviceManager.java.
Ngoài ra, bạn có thể tìm thấy chính sách quản lý kết nối Bluetooth trong
service/src/com/android/car/BluetoothDeviceConnectionPolicy.java. Theo mặc định,
chính sách này xác định các trường hợp mà Bluetooth sẽ kết nối và ngắt kết nối với các thiết bị đã liên kết. Chính sách này cũng quản lý các trường hợp cụ thể của ô tô khi bộ chuyển đổi cần được bật và
tắt.
Tạo chính sách quản lý kết nối ô tô tuỳ chỉnh của riêng bạn
Nếu chính sách ô tô mặc định không đáp ứng đủ nhu cầu của bạn, thì bạn cũng có thể tắt chính sách này để sử dụng chính sách tuỳ chỉnh của riêng mình. Chính sách tuỳ chỉnh của bạn phải chịu trách nhiệm xác định thời điểm bật và tắt bộ chuyển đổi Bluetooth, cũng như thời điểm kết nối thiết bị. Bạn có thể sử dụng nhiều sự kiện để bật/tắt bộ chuyển đổi Bluetooth và bắt đầu kết nối thiết bị, bao gồm cả các sự kiện do thay đổi trong các thuộc tính cụ thể của ô tô.
Tắt chính sách ô tô mặc định
Trước tiên, để sử dụng chính sách tuỳ chỉnh, bạn phải tắt chính sách ô tô mặc định bằng cách
đặt useDefaultBluetoothConnectionPolicy thành false trong một
lớp phủ tài nguyên.
Tài nguyên này ban đầu được xác định là một phần của
MAXIMUM_CONNECTED_DEVICES trong
packages/services/Car/service/res/values/config.xml.
Bật và tắt bộ chuyển đổi Bluetooth
Một trong những chức năng cốt lõi của chính sách là bật và tắt bộ chuyển đổi Bluetooth vào
thời điểm thích hợp. Bạn có thể sử dụng các API khung BluetoothAdapter.enable() và
BluetoothAdapter.disable() để bật và tắt bộ chuyển đổi.
Các lệnh gọi này phải tuân theo trạng thái được duy trì mà người dùng đã chọn thông qua phần Cài đặt hoặc
bất kỳ phương tiện nào khác. Bạn có thể thực hiện việc này theo một trong những cách sau:
/** * Turn on the Bluetooth adapter. */ private void enableBluetooth() { BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { return; } bluetoothAdapter.enable(); } /** * Turn off the Bluetooth adapter. */ private void disableBluetooth() { BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { return; } // Will shut down _without_ persisting the off state as the desired state // of the Bluetooth adapter for next start up. This does nothing if the adapter // is already off, keeping the existing saved desired state for next reboot. bluetoothAdapter.disable(false); }
Xác định thời điểm bật và tắt bộ chuyển đổi Bluetooth
Với chính sách tuỳ chỉnh, bạn có thể tự do xác định những sự kiện cho biết thời điểm tốt nhất để
bật và tắt bộ chuyển đổi. Một trong những cách để thực hiện việc này là sử dụng các trạng thái nguồn
MAXIMUM_CONNECTED_DEVICES trong
CarPowerManager:
private final CarPowerStateListenerWithCompletion mCarPowerStateListener =
new CarPowerStateListenerWithCompletion() {
@Override
public void onStateChanged(int state, CompletableFuture<Void> future) {
if (state == CarPowerManager.CarPowerStateListener.ON) {
if (isBluetoothPersistedOn()) {
enableBluetooth();
}
return;
}
// "Shutdown Prepare" is when the user perceives the car as off
// This is a good time to turn off Bluetooth
if (state == CarPowerManager.CarPowerStateListener.SHUTDOWN_PREPARE) {
disableBluetooth();
// Let CarPowerManagerService know we're ready to shut down
if (future != null) {
future.complete(null);
}
return;
}
}
};Xác định thời điểm kết nối thiết bị
Tương tự, khi bạn xác định các sự kiện sẽ kích hoạt quá trình bắt đầu kết nối thiết bị,
CarBluetoothManager sẽ cung cấp lệnh gọi API connectDevices() đó
tiến hành kết nối thiết bị dựa trên danh sách ưu tiên được xác định cho từng cấu hình Bluetooth.
Một ví dụ về thời điểm bạn có thể muốn thực hiện việc này là bất cứ khi nào bộ chuyển đổi Bluetooth bật:
private class BluetoothBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); if (state == BluetoothAdapter.STATE_ON) { // mContext should be your app's context Car car = Car.createCar(mContext); CarBluetoothManager carBluetoothManager = (CarBluetoothManager) car.getCarManager(Car.BLUETOOTH_SERVICE); carBluetoothManager.connectDevices(); } } } }
Xác minh tính năng quản lý kết nối ô tô
Cách dễ nhất để xác minh hành vi của chính sách kết nối là bật Bluetooth trên IVI và xác thực rằng chính sách này tự động kết nối với các thiết bị chính xác theo đúng thứ tự. Bạn có thể bật/tắt bộ chuyển đổi Bluetooth thông qua giao diện người dùng cài đặt hoặc bằng các lệnh adb sau:
adb shell su u$(adb shell am get-current-user)_system svc bluetooth disable
adb shell su u$(adb shell am get-current-user)_system svc bluetooth enable
Ngoài ra, bạn có thể sử dụng kết quả của lệnh sau để xem thông tin gỡ lỗi liên quan đến kết nối Bluetooth:
adb shell dumpsys car_service
Cuối cùng, nếu bạn đã xây dựng chính sách ô tô của riêng mình, thì việc xác minh mọi hành vi kết nối tuỳ chỉnh đều yêu cầu bạn phải kiểm soát các sự kiện mà bạn đã chọn để kích hoạt kết nối thiết bị.
Cấu hình Bluetooth ô tô
Trong Android, IVI có thể hỗ trợ nhiều thiết bị được kết nối đồng thời qua Bluetooth. Các dịch vụ điện thoại Bluetooth nhiều thiết bị cho phép người dùng kết nối các thiết bị riêng biệt đồng thời, chẳng hạn như điện thoại cá nhân và điện thoại công việc, đồng thời thực hiện cuộc gọi rảnh tay từ một trong hai thiết bị.
Mỗi cấu hình Bluetooth riêng lẻ sẽ thực thi các giới hạn kết nối, thường là trong quá trình triển khai dịch vụ cấu hình. Theo mặc định, CarBluetoothService không đưa ra thêm nhận định nào về số lượng tối đa thiết bị được phép kết nối.
Cấu hình rảnh tay
Cấu hình rảnh tay Bluetooth (HFP) cho phép xe thực hiện và nhận cuộc gọi điện thoại thông qua một thiết bị từ xa được kết nối. Mỗi kết nối thiết bị sẽ đăng ký một tài khoản điện thoại riêng với TelecomManager. Tài khoản này sẽ quảng cáo mọi tài khoản điện thoại có sẵn cho các ứng dụng IVI.
IVI có thể kết nối với nhiều thiết bị thông qua HFP. MAX_STATE_MACHINES_POSSIBLE
MAXIMUM_CONNECTED_DEVICES trong
HeadsetClientService xác định số lượng tối đa kết nối HFP
đồng thời.
Khi người dùng thực hiện hoặc nhận cuộc gọi điện thoại từ một thiết bị, tài khoản điện thoại tương ứng
sẽ tạo một đối tượng HfpClientConnection. Ứng dụng Trình quay số
tương tác với đối tượng HfpClientConnection để quản lý các tính năng cuộc gọi, chẳng hạn như chấp nhận cuộc gọi hoặc gác máy.
Xin lưu ý rằng ứng dụng Trình quay số mặc định không hỗ trợ nhiều thiết bị HFP được kết nối đồng thời. Để triển khai HFP nhiều thiết bị, bạn cần tuỳ chỉnh
để cho phép người dùng chọn tài khoản thiết bị cần sử dụng khi thực hiện cuộc gọi. Sau đó, ứng dụng sẽ gọi telecomManager.placeCall bằng tài khoản chính xác. Bạn cũng cần
xác minh rằng các chức năng khác trên nhiều thiết bị hoạt động như dự kiến.
Xác minh HFP nhiều thiết bị
Cách kiểm tra để đảm bảo rằng tính năng kết nối nhiều thiết bị hoạt động đúng cách qua Bluetooth:
- Sử dụng Bluetooth, kết nối một thiết bị với IVI và truyền phát âm thanh từ thiết bị đó.
- Kết nối 2 điện thoại với IVI qua Bluetooth.
- Chọn một điện thoại. Thực hiện cuộc gọi đi trực tiếp từ điện thoại,
và thực hiện cuộc gọi đi bằng IVI.
- Trong cả hai lần, hãy xác minh rằng âm thanh được truyền phát sẽ tạm dừng và âm thanh điện thoại phát qua loa được kết nối với IVI.
- Sử dụng cùng một điện thoại, nhận cuộc gọi đến trực tiếp trên điện thoại và
nhận cuộc gọi đến bằng IVI.
- Trong cả hai lần, hãy xác minh rằng âm thanh được truyền phát sẽ tạm dừng và âm thanh điện thoại sẽ phát qua loa được kết nối với IVI.
- Lặp lại bước 3 và 4 với điện thoại được kết nối khác.
Gọi khẩn cấp
Khả năng thực hiện cuộc gọi khẩn cấp là một khía cạnh quan trọng của các chức năng điện thoại và Bluetooth trong ô tô. Có một số cách để bắt đầu cuộc gọi khẩn cấp từ IVI, bao gồm:
- Giải pháp eCall độc lập
- Giải pháp eCall được tích hợp vào IVI
- Dựa vào điện thoại Bluetooth được kết nối khi không có hệ thống tích hợp
Kết nối cuộc gọi khẩn cấp
Mặc dù thiết bị eCall rất quan trọng đối với sự an toàn, nhưng thiết bị này hiện không được tích hợp vào Android. Bạn có thể sử dụng ConnectionService để hiển thị các tính năng gọi khẩn cấp thông qua Android. Tính năng này cũng mang lại lợi ích là giới thiệu các lựa chọn hỗ trợ tiếp cận cho cuộc gọi khẩn cấp. Để tìm hiểu thêm, hãy xem bài viết Xây dựng ứng dụng gọi điện.
Dưới đây là ví dụ về cách thiết lập ConnectionService khẩn cấp :
public class YourEmergencyConnectionService extends ConnectionService { @Override public Connection onCreateOutgoingConnection( PhoneAccountHandle connectionManagerAccount, ConnectionRequest request) { // Your equipment specific procedure to make ecall // ... } private void onYourEcallEquipmentReady() { PhoneAccountHandle handle = new PhoneAccountHandle(new ComponentName(context, YourEmergencyConnectionService), YourEmergencyConnectionId); PhoneAccount account = new PhoneAccount.Builder(handle, eCallOnlyAccount) .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL)) .setCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS | PhoneAccount.CAPABILITY_MULTI_USER) .build(): mTelecomManager.registerPhoneAccount(account); mTelecomManager.enablePhoneAccount(account.getAccountHandle(), true); } }
Bật Bluetooth cho cuộc gọi khẩn cấp
Trước Android 10, việc gọi khẩn cấp liên quan đến việc quay số trực tiếp từ điện thoại và gọi
thiết bị đặc biệt nếu có (ví dụ: tự động kích hoạt khi phát hiện thấy nguy hiểm hoặc hành động của
người dùng). Trong Android 10 trở lên, Trình quay số trong ô tô có thể trực tiếp gọi một
số khẩn cấp, miễn là MAXIMUM_CONNECTED_DEVICES này trong
apps/Bluetooth/res/values/config.xml:
<!-- For supporting emergency call through the hfp client connection service -->
<bool name=”hfp_client_connection_service_support_emergency_call”>true</bool>
Bằng cách triển khai tính năng gọi khẩn cấp theo cách này, các ứng dụng khác, chẳng hạn như ứng dụng nhận dạng giọng nói, cũng có thể gọi một số khẩn cấp.
Cấu hình truy cập danh bạ
Cấu hình truy cập danh bạ Bluetooth (PBAP) tải danh bạ và nhật ký cuộc gọi xuống từ một thiết bị từ xa được kết nối. PBAP duy trì một danh sách tổng hợp, có thể tìm kiếm gồm các địa chỉ liên hệ được cập nhật bởi máy trạng thái ứng dụng PBAP. Mỗi thiết bị thông minh được kết nối tương tác với một máy trạng thái ứng dụng PBAP riêng biệt, dẫn đến việc các địa chỉ liên hệ được liên kết với thiết bị thích hợp khi thực hiện cuộc gọi.
PBAP là một chiều và do đó yêu cầu IVI khởi tạo kết nối với mọi
MAXIMUM_CONNECTED_DEVICES trong
PbapClientService xác định số lượng tối đa kết nối thiết bị PBAP đồng thời được phép với IVI. Ứng dụng PBAP lưu trữ các địa chỉ liên hệ cho từng
thiết bị thông minh được kết nối trong
Trình cung cấp danh bạ. Sau đó, một ứng dụng có thể truy cập vào trình cung cấp này để lấy danh
bạ cho từng thiết bị.
Ngoài ra, cả IVI và thiết bị di động đều phải cho phép kết nối cấu hình thì mới có thể kết nối. Khi ứng dụng PBAP ngắt kết nối, cơ sở dữ liệu nội bộ sẽ xoá tất cả địa chỉ liên hệ và nhật ký cuộc gọi được liên kết với thiết bị thông minh đã kết nối trước đó.
Cấu hình truy cập tin nhắn
Cấu hình truy cập tin nhắn Bluetooth (MAP) cho phép xe gửi và nhận tin nhắn SMS thông qua một thiết bị từ xa được kết nối. Hiện tại, tin nhắn không được lưu trữ cục bộ trên IVI. Thay vào đó, bất cứ khi nào thiết bị từ xa được kết nối nhận được tin nhắn, IVI nhận và phân tích tin nhắn, đồng thời truyền nội dung của tin nhắn đó trong một thực thể Ý định. Sau đó, một ứng dụng có thể nhận được thực thể này.
Để kết nối với thiết bị di động nhằm mục đích gửi và nhận
tin nhắn, IVI phải bắt đầu kết nối MAP.
MAXIMUM_CONNECTED_DEVICES trong
MapClientService xác định số lượng tối đa kết nối thiết bị MAP đồng thời được phép với IVI. Mỗi kết nối phải được IVI và
thiết bị di động cho phép thì mới có thể chuyển tin nhắn.
Cấu hình phân phối âm thanh nâng cao
Cấu hình phân phối âm thanh nâng cao Bluetooth (A2DP) cho phép xe nhận luồng âm thanh từ một thiết bị từ xa được kết nối.
Không giống như các cấu hình khác, số lượng tối đa thiết bị A2DP được kết nối sẽ được thực thi trong ngăn xếp gốc
chứ không phải trong Java. Giá trị này hiện được mã hoá cứng thành 1 bằng
biến kDefaultMaxConnectedAudioDevices trong
packages/modules/Bluetooth/system/btif/src/btif_av.cc.
Cấu hình điều khiển từ xa âm thanh/video
Cấu hình điều khiển từ xa âm thanh/video Bluetooth (AVRCP) cho phép xe điều khiển và duyệt trình phát nội dung đa phương tiện trên một thiết bị từ xa được kết nối. Vì IVI đóng vai trò là bộ điều khiển AVRCP, nên mọi chế độ điều khiển được kích hoạt ảnh hưởng đến việc phát âm thanh đều dựa vào kết nối A2DP với thiết bị đích.
Để một trình phát nội dung đa phương tiện cụ thể trên điện thoại Android có thể được IVI duyệt qua AVRCP,
ứng dụng nội dung đa phương tiện trên điện thoại phải cung cấp
MediaBrowserService và cho phép com.android.bluetooth truy cập vào
dịch vụ đó.
Bài viết Xây dựng dịch vụ trình duyệt nội dung đa phương tiện giải thích chi tiết cách thực hiện việc này.