Trang này mô tả cách thực hiện các lệnh bằng tương tác bằng giọng nói.
Thực hiện các lệnh truyền thông
Lệnh liên quan đến phương tiện có thể được chia thành ba nhóm khác nhau:
- Các nguồn phương tiện bên ngoài (chẳng hạn như Spotify được cài đặt trong AAOS).
- Các nguồn phương tiện phụ trợ (chẳng hạn như nhạc được truyền qua VIA).
- Các nguồn phương tiện truyền thông địa phương (chẳng hạn như đài phát thanh xe hơi).
Xử lý các lệnh nguồn phương tiện bên ngoài
Các nguồn phương tiện bên ngoài được định nghĩa là các ứng dụng Android hỗ trợ API MediaSessionCompat
và MediaBrowseCompat
(tham khảo Xây dựng ứng dụng phương tiện cho ô tô để biết giải thích chi tiết về cách sử dụng các API này).
Quan trọng: Để một ứng dụng trợ lý kết nối với MediaBrowseService
của tất cả các ứng dụng đa phương tiện đã cài đặt trong hệ thống, ứng dụng đó phải:
- Được cài đặt dưới dạng có chữ ký hệ thống (xem hướng dẫn Phát triển ứng dụng phương tiện cho AAOS và mã
PackageValidator
mẫu). - Giữ quyền đặc quyền của hệ thống
android.permission.MEDIA_CONTENT_CONTROL
(xem Cấp quyền đặc quyền của hệ thống ).
Ngoài MediaBrowserCompat
và MediaControllerCompat
, AAOS còn cung cấp những tính năng sau:
-
CarMediaService
cung cấp thông tin tập trung về nguồn phương tiện hiện được chọn. Điều này cũng được sử dụng để tiếp tục nguồn phương tiện đang phát trước đó sau khi tắt máy-khởi động lại ô tô. -
car-media-common
cung cấp các phương pháp thuận tiện để liệt kê, kết nối và tương tác với các ứng dụng đa phương tiện.
Dưới đây là các hướng dẫn cụ thể để thực hiện các lệnh tương tác bằng giọng nói phổ biến.
Nhận danh sách các nguồn phương tiện được cài đặt
Có thể phát hiện các nguồn phương tiện bằng cách sử dụng PackageManager
và lọc các dịch vụ khớp với MediaBrowserService.SERVICE_INTERFACE
. Trong một số ô tô có thể có một số triển khai dịch vụ trình duyệt phương tiện đặc biệt cần được loại trừ. Đây là một ví dụ về logic này:
private Map<String, MediaSource> getAvailableMediaSources() { List<String> customMediaServices = Arrays.asList(mContext.getResources() .getStringArray(R.array.custom_media_packages)); List<ResolveInfo> mediaServices = mPackageManager.queryIntentServices( new Intent(MediaBrowserService.SERVICE_INTERFACE), PackageManager.GET_RESOLVED_FILTER); Map<String, MediaSource> result = new HashMap<>(); for (ResolveInfo info : mediaServices) { String packageName = info.serviceInfo.packageName; if (customMediaServices.contains(packageName)) { // Custom media sources should be ignored, as they might have a // specialized handling (e.g., radio). continue; } String className = info.serviceInfo.name; ComponentName componentName = new ComponentName(packageName, className); MediaSource source = MediaSource.create(mContext, componentName); result.put(source.getDisplayName().toString().toLowerCase(), source); } return result; }
Xin lưu ý rằng các nguồn phương tiện có thể được cài đặt hoặc gỡ cài đặt bất kỳ lúc nào. Để duy trì danh sách chính xác, bạn nên triển khai một phiên bản BroadcastReceiver
cho các hành động có ý định ACTION_PACKAGE_ADDED
, ACTION_PACKAGE_CHANGED
, ACTION_PACKAGE_REPLACED
và ACTION_PACKAGE_REMOVED
.
Kết nối với nguồn phương tiện hiện đang phát
CarMediaService
cung cấp các phương thức để lấy nguồn phương tiện hiện được chọn và khi nguồn phương tiện này thay đổi. Những thay đổi này có thể xảy ra do người dùng tương tác trực tiếp với giao diện người dùng hoặc do sử dụng các nút phần cứng trên ô tô. Mặt khác, thư viện car-media-common cung cấp những cách thuận tiện để kết nối với một nguồn phương tiện nhất định. Dưới đây là đoạn mã đơn giản về cách kết nối với ứng dụng phương tiện hiện được chọn:
public class MediaActuator implements MediaBrowserConnector.onConnectedBrowserChanged { private final Car mCar; private CarMediaManager mCarMediaManager; private MediaBrowserConnector mBrowserConnector; … public void initialize(Context context) { mCar = Car.createCar(context); mBrowserConnector = new MediaBrowserConnector(context, this); mCarMediaManager = (CarMediaManager) mCar.getCarManager(Car.CAR_MEDIA_SERVICE); mBrowserConnector.connectTo(mCarMediaManager.getMediaSource()); … } @Override public void onConnectedBrowserChanged( @Nullable MediaBrowserCompat browser) { // TODO: Handle connected/disconnected browser } … }
Kiểm soát phát lại nguồn phương tiện hiện đang phát
Với MediaBrowserCompat
được kết nối, thật dễ dàng gửi các lệnh điều khiển truyền tải đến ứng dụng đích. Đây là một ví dụ đơn giản:
public class MediaActuator … { … private MediaControllerCompat mMediaController; @Override public void onConnectedBrowserChanged( @Nullable MediaBrowserCompat browser) { if (browser != null && browser.isConnected()) { mMediaController = new MediaControllerCompat(mContext, browser.getSessionToken()); } else { mMediaController = null; } } private boolean playSongOnCurrentSource(String song) { if (mMediaController == null) { // No source selected. return false; } MediaControllerCompat.TransportControls controls = mMediaController.getTransportControls(); PlaybackStateCompat state = controller.getPlaybackState(); if (state == null || ((state.getActions() & PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH) == 0)) { // Source can't play from search return false; } controls.playFromSearch(query, null); return true; } … }
Xử lý các lệnh nguồn phương tiện cục bộ (radio, đầu CD, Bluetooth, USB)
Các nguồn truyền thông địa phương hiển thị chức năng của họ cho hệ thống bằng cách sử dụng cùng các API MediaSession và MediaBrowse được nêu chi tiết ở trên. Để phù hợp với đặc điểm riêng của từng loại phần cứng, các dịch vụ MediaBrowse này sử dụng các quy ước cụ thể để sắp xếp thông tin và lệnh phương tiện của chúng.
Xử lý đài phát thanh
Radio MediaBrowseService có thể được xác định bằng bộ lọc ý định ACTION_PLAY_BROADCASTRADIO
. Họ phải tuân theo các điều khiển phát lại và cấu trúc duyệt phương tiện được mô tả trong Thực hiện radio . AAOS cung cấp thư viện car-broadcastradio-support
chứa các hằng số và phương thức để giúp OEM tạo triển khai MediaBrowseService cho các dịch vụ vô tuyến của riêng họ tuân theo giao thức đã xác định và cung cấp hỗ trợ cho các ứng dụng sử dụng cây duyệt của họ (ví dụ: VIA).
Xử lý đầu vào phụ, âm thanh CD và phương tiện USB
Không có triển khai mặc định nào cho các nguồn phương tiện này như một phần của AOSP. Cách tiếp cận được đề xuất là:
- Yêu cầu các OEM triển khai các dịch vụ truyền thông cho từng người trong số họ. Để biết chi tiết, hãy xem Xây dựng ứng dụng đa phương tiện cho ô tô .
- Việc triển khai MediaBrowseService này sẽ được xác định và phản hồi trong các hành động có ý định được xác định tại Ý định phát chung .
- Các dịch vụ này sẽ hiển thị cây duyệt theo các nguyên tắc được mô tả tại Các loại nguồn khác .
Xử lý Bluetooth
Nội dung phương tiện Bluetooth được hiển thị thông qua cấu hình Bluetooth AVRCP. Để tạo điều kiện truy cập vào chức năng này, AAOS bao gồm triển khai MediaBrowserService và MediaSession để tóm tắt các chi tiết liên lạc (xem gói/ứng dụng/Bluetooth ).
Cấu trúc cây trình duyệt phương tiện tương ứng được xác định tại lớp BrowserTree . Các lệnh điều khiển phát lại có thể được phân phối tương tự như bất kỳ ứng dụng nào khác bằng cách sử dụng triển khai MediaSession của ứng dụng đó.
Xử lý các lệnh truyền phát phương tiện
Để triển khai truyền phát phương tiện phía máy chủ, VIA phải trở thành nguồn phương tiện, triển khai API MediaBrowse và MediaSession. Tham khảo Xây dựng ứng dụng đa phương tiện cho ô tô . Bằng cách triển khai các API này, ứng dụng điều khiển bằng giọng nói sẽ có thể (trong số những thứ khác):
- Tham gia liền mạch vào việc lựa chọn nguồn phương tiện
- Được tự động tiếp tục sau khi khởi động lại xe
- Cung cấp khả năng kiểm soát phát lại và duyệt web bằng giao diện người dùng Media Center
- Nhận các sự kiện nút phương tiện phần cứng tiêu chuẩn
Thực hiện các lệnh điều hướng
Không có cách tương tác chuẩn hóa với tất cả các ứng dụng điều hướng. Để tích hợp với Google Maps, hãy xem Google Maps dành cho Android Automotive Intents . Để tích hợp với các ứng dụng khác, hãy liên hệ trực tiếp với nhà phát triển ứng dụng. Trước khi triển khai ý định cho bất kỳ ứng dụng nào (bao gồm cả Google Maps), hãy xác minh rằng ý định đó có thể được giải quyết (xem Yêu cầu ý định ). Điều này tạo cơ hội thông báo cho người dùng trong trường hợp ứng dụng mục tiêu không có sẵn.
Thực hiện các lệnh của xe
Quyền truy cập vào các thuộc tính của xe để đọc và ghi được cung cấp thông qua CarPropertyManager . Các loại thuộc tính phương tiện, cách triển khai và các chi tiết khác được giải thích trong Cấu hình thuộc tính . Để có mô tả chính xác về các thuộc tính được Android hỗ trợ, tốt nhất bạn nên tham khảo trực tiếp hardware/interfaces/automotive/vehicle/2.0/types.hal
. Enum VehicleProperty được xác định ở đó chứa cả thuộc tính, kiểu dữ liệu, chế độ thay đổi, đơn vị và định nghĩa truy cập đọc/ghi cụ thể của nhà cung cấp và tiêu chuẩn.
Để truy cập các hằng số tương tự này từ Java, bạn có thể sử dụng VehiclePropertyIds và các lớp đồng hành của nó. Các thuộc tính khác nhau có các quyền Android khác nhau kiểm soát quyền truy cập của chúng. Các quyền này được khai báo trong tệp kê khai CarService và ánh xạ giữa các thuộc tính và quyền được mô tả trong VehiclePropertyIds Javadoc và được thực thi trong PropertyHalServiceIds .
Đọc thuộc tính xe
Sau đây là ví dụ minh họa cách đọc tốc độ của xe:
public class CarActuator ... { private final Car mCar; private final CarPropertyManager mCarPropertyManager; private final TextToSpeech mTTS; /** Global VHAL area id */ public static final int GLOBAL_AREA_ID = 0; public CarActuator(Context context, TextToSpeech tts) { mCar = Car.createCar(context); mCarPropertyManager = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE); mTTS = tts; ... } @Nullable private void getSpeedInMetersPerSecond() { if (!mCarPropertyManager.isPropertyAvailable(VehiclePropertyIds.PERF_VEHICLE_SPEED, GLOBAL_AREA_ID)) { mTTS.speak("I'm sorry, but I can't read the speed of this vehicle"); return; } // Data type and unit can be found in // automotive/vehicle/2.0/types.hal float speedInMps = mCarPropertyManager.getFloatProperty( VehiclePropertyIds.PERF_VEHICLE_SPEED, GLOBAL_AREA_ID); int speedInMph = (int)(speedInMetersPerSecond * 2.23694f); mTTS.speak(String.format("Sure. Your current speed is %d miles " + "per hour", speedInUserUnit); } ... }
Đặt thuộc tính xe
Sau đây là ví dụ minh họa cách bật và tắt điều hòa phía trước.
public class CarActuator … { … private void changeFrontAC(boolean turnOn) { List<CarPropertyConfig> configs = mCarPropertyManager .getPropertyList(new ArraySet<>(Arrays.asList( VehiclePropertyIds.HVAC_AC_ON))); if (configs == null || configs.size() != 1) { mTTS.speak("I'm sorry, but I can't control the AC of your vehicle"); return; } // Find the front area Ids for the AC property. int[] areaIds = configs.get(0).getAreaIds(); List<Integer> areasToChange = new ArrayList<>(); for (int areaId : areaIds) { if ((areaId & (VehicleAreaSeat.SEAT_ROW_1_CENTER | VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_1_RIGHT)) == 0) { continue; } boolean isACInAreaAlreadyOn = mCarPropertyManager .getBooleanProperty(VehiclePropertyIds.HVAC_AC_ON, areaId); if ((!isACInAreaAlreadyOn && turnOn) || (isACInAreaAlreadyOn && !turnOn)) { areasToChange.add(areaId); } } if (areasToChange.isEmpty()) { mTTS.speak(String.format("The AC is already %s", turnOn ? "on" : "off")); return; } for (int areaId : areasToChange) { mCarPropertyManager.setBooleanProperty( VehiclePropertyIds.HVAC_AC_ON, areaId, turnOn); } mTTS.speak(String.format("Okay, I'm turning your front AC %s", turnOn ? "on" : "off")); } … }
Thực hiện các lệnh giao tiếp
Xử lý các lệnh nhắn tin
VIA phải xử lý các tin nhắn đến theo luồng "chạm để đọc" được mô tả trong Trợ lý giọng nói Chạm để đọc , luồng này có thể tùy ý xử lý việc gửi trả lời lại cho người gửi tin nhắn đến. Ngoài ra, VIA có thể sử dụng SmsManager
(một phần của gói android.telephony
) để soạn và gửi tin nhắn SMS trực tiếp từ ô tô hoặc qua Bluetooth.
Xử lý lệnh gọi
Theo cách tương tự, VIA có thể sử dụng TelephonyManager
để thực hiện cuộc gọi điện thoại và gọi đến số thư thoại của người dùng. Trong những trường hợp này, VIA sẽ tương tác trực tiếp với hệ thống điện thoại hoặc với ứng dụng Trình quay số ô tô. Trong mọi trường hợp, ứng dụng Car Dialer phải là ứng dụng hiển thị giao diện người dùng liên quan đến cuộc gọi thoại cho người dùng.
Thực hiện các lệnh khác
Để biết danh sách các điểm tích hợp có thể có khác giữa VIA và hệ thống, hãy kiểm tra danh sách các ý định phổ biến của Android . Nhiều lệnh của người dùng có thể được giải quyết phía máy chủ (ví dụ: đọc email và sự kiện lịch của người dùng) và không yêu cầu bất kỳ tương tác nào với hệ thống ngoài chính tương tác bằng giọng nói.
Hành động nhập vai (hiển thị nội dung trực quan)
Khi nâng cao hành động hoặc hiểu biết của người dùng, VIA có thể cung cấp nội dung hình ảnh bổ sung trên màn hình ô tô. Để giảm thiểu sự mất tập trung của người lái xe, hãy giữ nội dung đó đơn giản, ngắn gọn và có thể hành động được. Để biết chi tiết về nguyên tắc UI/UX về các hành động sống động, hãy xem Trợ lý được tải trước: Hướng dẫn UX .
Để cho phép tùy chỉnh và nhất quán với phần còn lại của thiết kế bộ phận chính (HU), VIA nên sử dụng các thành phần Thư viện giao diện người dùng ô tô cho hầu hết các thành phần giao diện người dùng. Để biết chi tiết, hãy xem Tùy chỉnh .