Phát triển ứng dụng

Để triển khai Ứng dụng Tương tác Giọng nói (VIA), bạn hãy hoàn thành các bước sau:

  1. Tạo bộ xương VIA.
  2. ( tùy chọn ) Triển khai quy trình thiết lập/đăng nhập.
  3. ( tùy chọn ) Triển khai màn hình Cài đặt.
  4. Khai báo các quyền cần thiết trong tệp kê khai.
  5. Triển khai giao diện người dùng bảng giọng nói.
  6. Triển khai nhận dạng giọng nói (phải bao gồm triển khai API Dịch vụ nhận dạng).
  7. Triển khai cách nói (tùy chọn, bạn có thể triển khai API TextToSpeech).
  8. Thực hiện thực hiện các lệnh. Xem nội dung này trong Thực hiện các lệnh .

Các phần sau đây mô tả cách hoàn thành từng bước được đề cập ở trên.

Tạo bộ xương VIA

Bản kê khai

Một ứng dụng được phát hiện là một ứng dụng có Tương tác giọng nói khi những thông tin sau được đưa vào tệp kê khai:

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myvoicecontrol">
    ...

  <application ... >
    <service android:name=".MyInteractionService"
        android:label="@string/app_name"
        android:permission="android.permission.BIND_VOICE_INTERACTION"
        android:process=":interactor">
      <meta-data
          android:name="android.voice_interaction"
          android:resource="@xml/interaction_service" />
      <intent-filter>
        <action android:name=
          "android.service.voice.VoiceInteractionService" />
      </intent-filter>
    </service>
  </application>
</manifest>

Trong ví dụ này:

  • VIA phải hiển thị một dịch vụ mở rộng VoiceInteractionService , với bộ lọc ý định cho hành động VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService") .
  • Dịch vụ này phải có quyền chữ ký hệ thống BIND_VOICE_INTERACTION .
  • Dịch vụ này phải bao gồm tệp siêu dữ liệu android.voice_interaction để chứa những nội dung sau:

    res/xml/interaction_service.xml

    <voice-interaction-service
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:sessionService=
          "com.example.MyInteractionSessionService"
        android:recognitionService=
          "com.example.MyRecognitionService"
        android:settingsActivity=
          "com.example.MySettingsActivity"
        android:supportsAssist="true"
        android:supportsLaunchVoiceAssistFromKeyguard="true"
        android:supportsLocalInteraction="true" />
    

Để biết chi tiết về từng trường, hãy xem R.styleable#VoiceInteractionService . Vì tất cả các VIA đều là dịch vụ nhận dạng giọng nói, bạn cũng phải đưa những thông tin sau vào bảng kê khai của mình:

AndroidManifest.xml

<manifest ...>
  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  <application ...>
    ...
    <service android:name=".RecognitionService" ...>
      <intent-filter>
        <action android:name="android.speech.RecognitionService" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
      <meta-data
        android:name="android.speech"
        android:resource="@xml/recognition_service" />
    </service>
  </application>
</manifest>

Dịch vụ nhận dạng giọng nói cũng yêu cầu phần siêu dữ liệu sau:

res/xml/recognition_service.xml

<recognition-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:settingsActivity="com.example.MyRecognizerSettingsActivity" />

VoiceInteractionService, VoiceInteractionSessionService và VoiceInteractionSession

Sơ đồ sau đây mô tả vòng đời của từng thực thể này:

Vòng đời

Hình 1. Vòng đời

Như đã nêu trước đó, VoiceInteractionService là điểm vào VIA. Trách nhiệm chính của dịch vụ này là:

  • Khởi tạo bất kỳ quy trình nào cần được tiếp tục chạy miễn là VIA này còn hoạt động. Ví dụ: phát hiện từ nóng.
  • Báo cáo các tác vụ thoại được hỗ trợ (xem Nhấn để đọc Trợ lý giọng nói ).
  • Khởi chạy các phiên tương tác bằng giọng nói từ màn hình khóa (keyguard).

Ở dạng đơn giản nhất, việc triển khai VoiceInteractionService sẽ như sau:

public class MyVoiceInteractionService extends VoiceInteractionService {
    private static final List<String> SUPPORTED_VOICE_ACTIONS =
        Arrays.asList(
            CarVoiceInteractionSession.VOICE_ACTION_READ_NOTIFICATION,
            CarVoiceInteractionSession.VOICE_ACTION_REPLY_NOTIFICATION,
            CarVoiceInteractionSession.VOICE_ACTION_HANDLE_EXCEPTION
    );

    @Override
    public void onReady() {
        super.onReady();
        // TODO: Setup hotword detector
    }

    @NonNull
    @Override
    public Set<String> onGetSupportedVoiceActions(
            @NonNull Set<String> voiceActions) {
        Set<String> result = new HashSet<>(voiceActions);
        result.retainAll(SUPPORTED_VOICE_ACTIONS);
        return result;
    }
    ...
}

Cần phải triển khai VoiceInteractionService#onGetSupportedVoiceActions() để xử lý Tap-to-Read của Trợ lý giọng nói . Hệ thống sử dụng VoiceInteractionSessionService để tạo và tương tác với VoiceInteractionSession . Nó chỉ có một trách nhiệm là bắt đầu các phiên mới khi được yêu cầu.

public class MyVoiceInteractionSessionService extends VoiceInteractionSessionService {
    @Override
    public VoiceInteractionSession onNewSession(Bundle args) {
        return new MyVoiceInteractionSession(this);
    }
}

Cuối cùng, VoiceInteractionSession là nơi hầu hết công việc sẽ được thực hiện. Một phiên bản phiên duy nhất có thể được sử dụng lại để hoàn thành nhiều tương tác của người dùng. Trong AAOS, tồn tại một trình trợ giúp CarVoiceInteractionSession , giúp triển khai một số chức năng độc đáo của ô tô.

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {

    public InteractionSession(Context context) {
        super(context);
    }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        closeSystemDialogs();
        // TODO: Unhide UI and update UI state
        // TODO: Start processing audio input
    }
    ...
}

VoiceInteractionSession có một tập hợp lớn các phương thức gọi lại được giải thích trong các phần sau. xem tài liệu về VoiceInteractionSession để biết danh sách đầy đủ.

Triển khai quy trình thiết lập/đăng nhập

Quá trình thiết lập và đăng nhập có thể xảy ra:

  • Trong quá trình cài đặt thiết bị (Trình hướng dẫn cài đặt).
  • Trong quá trình chuyển đổi dịch vụ tương tác bằng giọng nói (Cài đặt).
  • Khi khởi chạy lần đầu khi ứng dụng được chọn.

Để biết chi tiết về trải nghiệm người dùng được đề xuất và hướng dẫn trực quan, hãy xem Trợ lý được tải sẵn: Hướng dẫn UX .

Thiết lập trong quá trình trao đổi dịch vụ thoại

Người dùng luôn có thể chọn một VIA chưa được cấu hình đúng cách. Điều này có thể xảy ra vì:

  • Người dùng đã bỏ qua hoàn toàn Trình hướng dẫn cài đặt hoặc người dùng đã bỏ qua bước cấu hình tương tác bằng giọng nói.
  • Người dùng đã chọn VIA khác với VIA được định cấu hình trong quá trình cài đặt thiết bị.

Trong mọi trường hợp, VoiceInteractionService có một số cách để khuyến khích người dùng hoàn tất quá trình thiết lập:

  • Nhắc nhở thông báo.
  • Trả lời bằng giọng nói tự động khi người dùng cố gắng sử dụng nó.

Lưu ý : Chúng tôi không khuyến khích trình bày quy trình thiết lập VIA mà không có yêu cầu rõ ràng của người dùng. Điều này có nghĩa là VIA nên tránh tự động hiển thị nội dung trên HU trong khi khởi động thiết bị hoặc do người dùng chuyển đổi hoặc mở khóa.

Lời nhắc thông báo

Lời nhắc thông báo là một cách không xâm phạm để cho biết nhu cầu thiết lập và cung cấp cho người dùng khả năng điều hướng vào quy trình thiết lập trợ lý.

Lời nhắc thông báo

Hình 2. Lời nhắc thông báo

Đây là cách luồng này sẽ hoạt động:

Luồng nhắc nhở thông báo

Hình 3. Luồng nhắc nhở thông báo

Trả lời bằng giọng nói

Đây là quy trình đơn giản nhất để triển khai, bắt đầu một cách phát âm trong lệnh gọi lại VoiceInteractionSession#onShow() , giải thích cho người dùng những gì cần phải làm, sau đó hỏi họ (nếu thiết lập được cho phép với trạng thái Hạn chế UX) xem họ có muốn bắt đầu không luồng thiết lập. Nếu không thể thiết lập vào thời điểm đó, hãy giải thích tình huống này.

Thiết lập ngay lần sử dụng đầu tiên

Người dùng luôn có thể kích hoạt VIA chưa được cấu hình đúng cách. Trong trường hợp này:

  1. Thông báo bằng lời nói cho người dùng về tình huống này (ví dụ: "Để hoạt động bình thường, tôi cần bạn hoàn thành một vài bước …").
  2. Nếu công cụ hạn chế UX cho phép (xem UX_RESTRICTIONS_NO_SETUP ), hãy hỏi người dùng xem họ có muốn bắt đầu quá trình thiết lập hay không, sau đó mở màn hình Cài đặt cho VIA.
  3. Ngược lại (ví dụ: nếu người dùng đang lái xe), hãy để lại thông báo để người dùng nhấp vào tùy chọn khi thấy an toàn.

Xây dựng màn hình thiết lập tương tác bằng giọng nói

Màn hình thiết lập và đăng nhập nên được phát triển như những hoạt động thường xuyên. Xem hướng dẫn trực quan và UX để phát triển giao diện người dùng trong Trợ lý được tải trước: Hướng dẫn UX .

Hướng dẫn chung:

  • VIA sẽ cho phép người dùng tạm dừng và tiếp tục thiết lập bất kỳ lúc nào.
  • Không được phép thiết lập nếu hạn chế UX_RESTRICTIONS_NO_SETUP có hiệu lực. Để biết chi tiết, hãy xem Hướng dẫn phân tâm khi lái xe .
  • Màn hình setup phải phù hợp với hệ thống thiết kế của từng loại xe. Bố cục màn hình chung, biểu tượng, màu sắc và các khía cạnh khác phải nhất quán với phần còn lại của giao diện người dùng. Xem Tùy chỉnh để biết chi tiết.

Triển khai màn hình cài đặt

Tích hợp cài đặt

Hình 4. Tích hợp cài đặt

Màn hình cài đặt là hoạt động thông thường của Android. Nếu được triển khai, điểm vào của chúng phải được khai báo trong res/xml/interaction_service.xml như một phần của tệp kê khai VIA (xem Bản kê khai ). Phần Cài đặt là nơi tốt để tiếp tục thiết lập và đăng nhập (nếu người dùng chưa hoàn thành) hoặc cung cấp tùy chọn đăng xuất hoặc chuyển đổi người dùng nếu cần. Tương tự như các màn hình Thiết lập được mô tả ở trên, các màn hình này sẽ:

  • Cung cấp tùy chọn để thoát trở lại màn hình trước đó trong ngăn xếp màn hình (ví dụ: vào Cài đặt ô tô).
  • Không được phép trong khi lái xe. Để biết chi tiết, hãy xem Hướng dẫn phân tâm khi lái xe .
  • Phù hợp với từng hệ thống thiết kế xe. Để biết chi tiết, hãy xem Tùy chỉnh .

Khai báo các quyền cần thiết trong tệp kê khai

Các quyền mà VIA yêu cầu có thể được chia thành ba loại:

  • Quyền chữ ký hệ thống. Đây là những quyền chỉ được cấp cho các APK được hệ thống ký và cài đặt sẵn. Người dùng không thể cấp các quyền này, chỉ OEM mới có thể cấp những quyền đó khi xây dựng hình ảnh hệ thống của họ. Để biết thêm thông tin về cách lấy quyền chữ ký, hãy xem Cấp quyền đặc quyền của hệ thống .
  • Quyền nguy hiểm. Đây là những quyền mà người dùng phải cấp bằng hộp thoại PermissionsController. OEM có thể cấp trước một số quyền này cho VoiceInteractionService mặc định. Tuy nhiên, do mặc định này có thể thay đổi tùy theo thiết bị nên các ứng dụng sẽ có thể yêu cầu các quyền này khi cần.
  • Các quyền khác. Đây là tất cả các quyền khác không yêu cầu sự can thiệp của người dùng. Các quyền này được hệ thống tự động cấp.

Với những điều trên, phần sau chỉ tập trung vào việc yêu cầu các quyền nguy hiểm. Chỉ nên yêu cầu quyền khi người dùng đang ở màn hình đăng nhập hoặc cài đặt.

Nếu ứng dụng không có các quyền cần thiết để hoạt động thì quy trình được đề xuất là sử dụng giọng nói để giải thích tình huống cho người dùng và thông báo để cung cấp khả năng chi trả mà người dùng có thể sử dụng để điều hướng quay lại màn hình cài đặt VIA . Để biết chi tiết, xem 1. Lời nhắc thông báo .

Yêu cầu quyền như một phần của màn hình cài đặt

Các quyền nguy hiểm được yêu cầu bằng phương thức ActivityCompat#requestPermission() thông thường (hoặc tương đương). Để biết chi tiết về cách yêu cầu quyền, hãy xem Yêu cầu quyền của ứng dụng .

Yêu cầu quyền

Hình 5. Yêu cầu quyền

Quyền của người nghe thông báo

Để triển khai luồng TTR, VIA phải được chỉ định làm người nghe thông báo. Đây thực chất không phải là một quyền mà thay vào đó là một cấu hình cho phép hệ thống gửi thông báo đến những người nghe đã đăng ký. Để tìm hiểu xem VIA có được cấp quyền truy cập vào thông tin này hay không, các ứng dụng có thể:

Nếu quyền truy cập này không được cấp trước, VIA sẽ hướng người dùng đến phần Truy cập thông báo của Cài đặt ô tô, sử dụng kết hợp các phát ngôn và thông báo. Mã sau có thể được sử dụng để mở phần thích hợp của ứng dụng cài đặt:

private void requestNotificationListenerAccess() {
    Intent intent = new Intent(Settings
        .ACTION_NOTIFICATION_LISTENER_SETTINGS);
    intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
    startActivity(intent);
}

Triển khai giao diện người dùng bảng giọng nói

Khi VoiceInteractionSession nhận được lệnh gọi lại onShow() , nó có thể hiển thị giao diện người dùng bảng giọng nói. Để biết hướng dẫn trực quan và UX về cách triển khai bảng giọng nói, hãy xem Trợ lý được tải sẵn: Hướng dẫn UX .

Hiển thị bảng giọng nói

Hình 6. Hiển thị bảng âm thanh

Có hai tùy chọn về cách triển khai giao diện người dùng này:

  • Ghi đè VoiceInteractionSession#onCreateContentView()
  • Khởi chạy một Hoạt động bằng VoiceInteractionSession#startAssistantActivity()

Sử dụng onCreateContentView()

Đây là cách trình bày bảng âm thanh mặc định. Lớp cơ sở VoiceInteractionSession tạo một cửa sổ và quản lý vòng đời của nó miễn là phiên thoại còn tồn tại. Ứng dụng phải ghi đè VoiceInteractionSession#onCreateContentView() và trả về chế độ xem được đính kèm với cửa sổ đó ngay khi phiên được tạo. Chế độ xem này ban đầu sẽ vô hình. Khi tương tác bằng giọng nói bắt đầu, chế độ xem này sẽ được hiển thị trên VoiceInteractionSession#onShow() và sau đó ẩn lại trên VoiceInteractionSession#onHide() .

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {
    private View mVoicePlate;
    …

    @Override
    public View onCreateContentView() {
        mVoicePlate = inflater.inflate(R.layout.voice_plate, null);
        …
   }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        // TODO: Update UI state to "listening"
        mVoicePlate.setVisibility(View.VISIBLE);
    }

    @Override
    public void onHide() {
        mVoicePlate.setVisibility(View.GONE);
    }
    …
}

Khi sử dụng phương pháp này, bạn có thể muốn điều chỉnh VoiceInteractionSession#onComputeInsets() để tính đến các vùng bị che khuất trong giao diện người dùng của mình.

Sử dụng startAssistantActivity()

Trong trường hợp này, VoiceInteractionSession ủy quyền việc xử lý giao diện người dùng bảng giọng nói cho một hoạt động thông thường. Khi tùy chọn này được sử dụng, việc triển khai VoiceInteractionSession phải tắt tính năng tạo cửa sổ nội dung mặc định của nó (xem Sử dụng onCreateContentView() ) trong lệnh gọi lại onPrepareShow() . Tại VoiceInteractionSession#onShow() , phiên sẽ bắt đầu hoạt động bảng giọng nói bằng cách sử dụng VoiceInteractionSession#startAssistantActivity() . Phương pháp này khởi tạo giao diện người dùng với các cài đặt cửa sổ và cờ hoạt động thích hợp.

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {
    …

    @Override
    public void onPrepareShow(Bundle args, int showFlags) {
        super.onPrepareShow(args, showFlags);
        setUiEnabled(false);
    }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        closeSystemDialogs();
        Intent intent = new Intent(getContext(), VoicePlateActivity.class);
        intent.putExtra(VoicePlateActivity.EXTRA_ACTION, action);
        intent.putExtra(VoicePlateActivity.EXTRA_ARGS, args);
        startAssistantActivity(intent);
    }

    …
}

Để duy trì liên lạc giữa hoạt động này và VoiceInteractionSession , có thể cần phải có một tập hợp Ý định nội bộ hoặc ràng buộc dịch vụ. Ví dụ: khi VoiceInteractionSession#onHide() được gọi, phiên phải có khả năng chuyển yêu cầu này tới hoạt động.

Quan trọng. Trong Ô tô, chỉ những hoạt động được chú thích đặc biệt hoặc những hoạt động được liệt kê trong "danh sách cho phép" UXR mới có thể hiển thị khi đang lái xe. Điều này cũng áp dụng cho các hoạt động được bắt đầu bằng VoiceInteractionSession#startAssistantActivity() . Hãy nhớ chú thích hoạt động của bạn bằng <meta-data android:name="distractionOptimized" android:value="true"/> hoặc đưa hoạt động này vào khóa systemActivityWhitelist của /packages/services/Car/service/res/values/config.xml tập tin /packages/services/Car/service/res/values/config.xml . Để biết thêm thông tin, hãy xem Hướng dẫn phân tâm khi lái xe .

Triển khai nhận dạng giọng nói

Trong phần này, bạn tìm hiểu cách triển khai nhận dạng giọng nói thông qua việc phát hiện và nhận dạng các từ nóng. Từ nóng là từ kích hoạt được sử dụng để bắt đầu một truy vấn hoặc hành động mới bằng giọng nói. Ví dụ: "OK Google" hoặc "Ok Google".

Phát hiện từ nóng DSP

Android cung cấp quyền truy cập vào trình phát hiện từ nóng luôn bật ở cấp DSP bằng AlwaysOnHotwordDetector . cách để thực hiện phát hiện từ nóng với CPU thấp. Việc sử dụng chức năng này được chia thành hai phần:

Việc triển khai VoiceInteractionService có thể tạo trình phát hiện từ nóng bằng cách sử dụng VoiceInteractionService#createAlwaysOnHotwordDetector() , chuyển cụm từ khóa và ngôn ngữ mà họ muốn sử dụng để phát hiện. Do đó, ứng dụng nhận được lệnh gọi lại onAvailabilityChanged() với một trong các giá trị có thể có sau:

  • STATE_HARDWARE_UNAVAILABLE . Khả năng DSP không có sẵn trên thiết bị. Trong trường hợp này, tính năng Phát hiện từ nóng của phần mềm được sử dụng.
  • STATE_HARDWARE_UNSUPPORTED . Hỗ trợ DSP nói chung không có sẵn, nhưng DSP không hỗ trợ kết hợp cụm từ khóa và ngôn ngữ nhất định. Ứng dụng có thể chọn sử dụng Phát hiện từ nóng phần mềm .
  • STATE_HARDWARE_ENROLLED . Tính năng phát hiện từ nóng đã sẵn sàng và có thể được bắt đầu bằng cách gọi phương thức startRecognition() .
  • STATE_HARDWARE_UNENROLLED . Không có mẫu âm thanh cho cụm từ khóa được yêu cầu nhưng có thể đăng ký.

Việc đăng ký các mô hình âm thanh phát hiện từ nóng có thể được thực hiện bằng cách sử dụng IVoiceInteractionManagerService#updateKeyphraseSoundModel() . Nhiều mô hình có thể được đăng ký trong hệ thống tại một thời điểm nhất định, nhưng chỉ một mô hình được liên kết với AlwaysOnHotwordDetector . Tính năng phát hiện từ nóng DSP có thể không khả dụng ở tất cả các thiết bị. Các nhà phát triển VIA nên kiểm tra khả năng phần cứng bằng phương thức getDspModuleProperties() . Để biết mã mẫu hiển thị cách đăng ký mô hình âm thanh, hãy xem VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java . Xem Chụp đồng thời về nhận dạng từ nóng đồng thời.

Phát hiện từ nóng phần mềm

Như đã nêu ở trên, tính năng phát hiện từ nóng DSP có thể không khả dụng ở tất cả các thiết bị (ví dụ: trình mô phỏng Android không cung cấp tính năng mô phỏng DSP). Trong trường hợp này, phần mềm nhận dạng giọng nói là giải pháp thay thế duy nhất. Để tránh can thiệp vào các ứng dụng khác có thể cần quyền truy cập vào micrô, VIA phải truy cập đầu vào âm thanh bằng cách sử dụng:

Cả hai hằng số này đều là @hide và chỉ khả dụng cho các ứng dụng đi kèm.

Quản lý đầu vào âm thanh và nhận dạng giọng nói

Đầu vào âm thanh sẽ được triển khai bằng lớp MediaRecorder . Để biết thêm thông tin về cách sử dụng API này, hãy xem Tổng quan về MediaRecorder . Các dịch vụ tương tác bằng giọng nói cũng được kỳ vọng sẽ là những triển khai của lớp RecognitionService . Bất kỳ ứng dụng nào trong hệ thống yêu cầu nhận dạng giọng nói đều sử dụng quyền truy cập vào khả năng này. Để thực hiện nhận dạng giọng nói và có quyền truy cập vào micrô, VIA phải giữ android.permission.RECORD_AUDIO . Các ứng dụng truy cập triển khai Dịch RecognitionService cũng dự kiến ​​sẽ có quyền này.

Trước Android 10, quyền truy cập micrô chỉ được cấp cho một ứng dụng tại một thời điểm (ngoại trừ tính năng phát hiện từ nóng, xem ở trên). Bắt đầu từ Android 10, quyền truy cập micrô có thể được chia sẻ. Để biết thêm thông tin, hãy xem Chia sẻ đầu vào âm thanh .

Truy cập đầu ra âm thanh

Khi VIA sẵn sàng đưa ra phản hồi bằng lời nói, điều quan trọng là phải tuân theo bộ hướng dẫn tiếp theo sau: