Thực hiện lệnh

Trang này mô tả cách thực hiện lệnh thông qua tương tác bằng giọng nói.

Thực hiện lệnh đa phương tiện

Lệnh liên quan đến nội dung đa phương tiện có thể được chia thành ba nhóm riêng biệt:

  • Nguồn nội dung nghe nhì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 phát qua VIA).
  • Nguồn nội dung nghe nhìn cục bộ (chẳng hạn như đài trên ô tô).

Xử lý các lệnh nguồn phương tiện bên ngoài

Nguồn nội dung nghe nhìn bên ngoài được định nghĩa là ứng dụng Android có hỗ trợ MediaSessionCompatMediaBrowseCompat API (tham khảo bài viết Tạo ứng dụng đa phương tiện cho Ô tô để xem nội dung giải thích chi tiết về việc sử dụng các API này).

Lưu ý quan trọng: Để một ứng dụng trợ lý có thể kết nối với MediaBrowseService trong số tất cả ứng dụng đa phương tiện đã cài đặt trong hệ thống, thì ứng dụng phải:

  1. Được cài đặt dưới dạng chữ ký hệ thống (xem nguyên tắc Phát triển ứng dụng đa phương tiện trong AAOS và mã PackageValidator mẫu).
  2. Duy trì đặc quyền của hệ thống android.permission.MEDIA_CONTENT_CONTROL quyền (xem Cấp quyền quyền dành riêng cho hệ thống).

Ngoài MediaBrowserCompatMediaControllerCompat, AAOS cung cấp:

  • CarMediaService cung cấp thông tin tập trung về nguồn truyền thông hiện được chọn. Đây là cũng được dùng để tiếp tục nguồn nội dung nghe nhìn đã phát trước đó sau khi ô tô khởi động lại.
  • car-media-common cung cấp các phương thức 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 nguyên tắc dành riêng cho việc triển khai tương tác bằng giọng nói chung các lệnh.

Lấy danh sách các nguồn nội dung nghe nhìn đã cài đặt

Có thể phát hiện các nguồn nội dung nghe nhìn bằng cách sử dụng PackageManager, và lọc ra các dịch vụ phù hợ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 nội dung đa phương tiện đặc biệt, phải được loại trừ. Dưới đâ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;
}

Lưu ý rằng nguồn nội dung nghe nhìn có thể được cài đặt hoặc gỡ cài đặt bất cứ lúc nào. Trong để duy trì danh sách chính xác, bạn nên triển khai BroadcastReceiver cho các thao tác theo ý định ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED, ACTION_PACKAGE_REPLACED, và ACTION_PACKAGE_REMOVED.

Kết nối với nguồn nội dung nghe nhìn đang phát

CarMediaService cung cấp các phương thức để lấy nguồn nội dung nghe nhìn hiện được chọn và khi nội dung nghe nhìn này các thay đổi về nguồn. Những thay đổi này có thể xảy ra vì người dùng đã tương tác với Giao diện người dùng một cách trực tiếp hoặc do sử dụng các nút phần cứng trong ô tô. Mặt khác, thư viện car-media-common cung cấp các cách thuận tiện để kết nối với một nội dung nghe nhìn nhất định nguồn. Dưới đây là một đoạn mã đơn giản về cách kết nối với ứng dụng web hiện đang chọn ứng dụng đa phương tiệ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
    }

    …
}

Điều khiển chế độ phát của nguồn nội dung nghe nhìn đang phát

Bằng một MediaBrowserCompat đã kết nối rất dễ dàng để gửi giao thông vận tải điều khiển ứng dụng đích. Sau đây là một ví dụ:

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 nội dung nghe nhìn cục bộ (đài, đầu đĩa CD, Bluetooth, USB)

Các nguồn phương tiện cục bộ hiển thị chức năng của chúng cho hệ thống bằng cách sử dụng cùng một Các API MediaSession và MediaBrowse được nêu chi tiết ở trên. Để phù hợp với các đặc điểm 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 đa phương tiện của họ.

Xử lý nút chọn

Có thể xác định Radio MediaBrowseService bằng ACTION_PLAY_BROADCASTRADIO bộ lọc ý định. Trẻ phải tuân theo các chế độ điều khiển chế độ phát và duyệt qua nội dung nghe nhìn cấu trúc được mô tả trong Triển khai đài. AAOS cung cấp car-broadcastradio-support thư viện chứa các hằng số và phương thức để giúp OEM tạo MediaBrowseService các triển khai cho các dịch vụ vô tuyến của riêng mình tuân theo giao thức đã xác định, đồng thời hỗ trợ các ứng dụng sử dụng cây duyệt qua (ví dụ: VIA).

Xử lý đầu vào phụ, âm thanh CD và phương tiện USB

Không có phương thức triển khai mặc định nào cho các nguồn nội dung nghe nhìn này trong AOSP. Phương pháp đề xuất là:

  • Yêu cầu OEM triển khai các dịch vụ nội dung đa phương tiện cho từng nhà cung cấp. Để biết thông tin chi tiết, hãy xem bài viết Tạo ứng dụng đa phương tiện cho ô tô.
  • Các hoạt động triển khai MediaBrowseService này sẽ được xác định và phản hồi trong ý định các thao tác được xác định trong phần Ý định phát chung.
  • Các dịch vụ này sẽ hiển thị cây duyệt qua theo những nguyên tắc được mô tả tại Các loại nguồn khác.

Xử lý Bluetooth

Nội dung đa phương tiện Bluetooth được hiển thị thông qua cấu hình Bluetooth AVRCP. Trong để hỗ trợ truy cập vào chức năng này, AAOS bao gồm một Phương thức triển khai MediaBrowserService và MediaSession tóm tắt thông tin liên lạc (xem gói/ứng dụng/Bluetooth).

Cấu trúc cây trình duyệt nội dung đa phương tiện tương ứng được xác định tại BrowseTree . Các lệnh điều khiển chế độ phát có thể được gửi tương tự như bất kỳ ứng dụng nào khác, bằng cách sử dụng phương thức triển khai MediaSession.

Xử lý các lệnh truyền trực tuyến nội dung nghe nhìn

Để triển khai tính năng truyền trực tuyến nội dung nghe nhìn phía máy chủ, VIA phải trở thành chính nó một nguồn truyền thông, triển khai API MediaBrowse và MediaSession. Tham khảo Tạo ứ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ể (cùng những thứ khác):

  • Tham gia liền mạch vào quá trình lựa chọn nguồn nội dung nghe nhìn
  • Tự động tiếp tục sau khi ô tô khởi động lại
  • Sử dụng giao diện người dùng Media Center để điều khiển chế độ phát và duyệt web
  • Nhận các sự kiện nút phương tiện phần cứng tiêu chuẩn

Không có cách thức chuẩn hoá để tương tác với mọi ứng dụng chỉ đường. Để tích hợp với Google Maps, vui lòng xem Google Maps dành cho ý định trên Android Automotive. Để tích hợp với các sản phẩm khác ứng dụng, liên hệ trực tiếp với nhà phát triển ứng dụng. Trước khi chạy ý định đối với 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 phần Ý đị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 đích không có sẵn.

Thực hiện lệnh trên xe

Bạn có thể truy cập vào các thuộc tính xe để đọc và ghi thông qua CarPropertyManager. Giải thích các loại thuộc tính xe, cách triển khai và các thông tin chi tiết khác trong Tài sản cấu hình. Để có thông tin mô tả chính xác về các cơ sở lưu trú được hỗ trợ của Android, tốt nhất bạn nên tham khảo trực tiếp hardware/interfaces/automotive/vehicle/2.0/types.hal. CarProperty (Tài sản về xe) enum được xác định ở đó chứa cả thuộc tính chuẩn và thuộc tính cụ thể của nhà cung cấp, dữ liệu loại, thay đổi chế độ, đơn vị và định nghĩa quyền đọc/ghi.

Để truy cập vào các hằng số tương tự này trong Java, bạn có thể sử dụng vehiclePropertyIds và các lớp đi kèm. Các thuộc tính khác nhau có các quyền Android khác nhau kiểm soát truy cập. Các quyền này được khai báo trong CarService tệp kê khai và mối liên kết giữa các thuộc tính và quyền được mô tả trong CarPropertyIds Javadoc và thực thi trong PropertyHalServiceIds.

Đọc thông tin về tài sản xe

Sau đây là ví dụ minh hoạ 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 hoạ cách bật và tắt điều hoà không khí 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 lệnh giao tiếp

Xử lý các lệnh nhắn tin

VIA phải xử lý thư đến sau lệnh "nhấn để đọc" quy trình được mô tả trong Trợ lý thoại Nhấn để đọc, có thể xử lý việc gửi tin trả lời lại cho người gửi tin nhắn đến (không bắt buộc). Ngoài ra, VIA có thể sử dụng SmsManager (một phần của android.telephony gói thuê bao) để soạn và gửi tin nhắn SMS trực tiếp từ xe ô tô hoặc qua Bluetooth.

Xử lý lệnh gọi

Tương tự như vậy, VIA có thể sử dụng TelephonyManager để 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 ngăn xếp điện thoại hoặc với Trình quay số trên ô tô . Trong mọi trường hợp, ứng dụng Trình quay số trên ô tô 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 đến 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 xem danh sách các ý định phổ biến trên Android. Nhiều các lệnh của người dùng có thể được phân giải ở phía máy chủ (ví dụ: đọc email và sự kiện trên lịch) của người dùng, đồng thời không yêu cầu bất kỳ tương tác nào với hệ thống khác với chính tương tác bằng giọng nói.

Thao tác sống động (hiển thị nội dung hình ảnh)

Khi tăng cường hành động hoặc sự 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 tình trạng phân tâm của người lái xe, hãy đảm bảo nội dung đơn giản, ngắn gọn và dễ thao tác. Thông tin chi tiết liên quan đến các nguyên tắc về giao diện người dùng/trải nghiệm người dùng về hành động sống động, hãy xem Các Trợ lý có sẵn: Hướng dẫn về trải nghiệm người dùng.

Để cho phép tuỳ chỉnh và tính nhất quán với phần còn lại của thiết kế đầu phát trung tâm (HU), VIA sẽ sử dụng Xe hơi Thư viện giao diện người dùng cho hầu hết các thành phần trên giao diện người dùng. Để biết thông tin chi tiết, hãy xem Tuỳ chỉnh.