Pengembangan aplikasi

Untuk menerapkan Aplikasi Interaksi Suara (VIA), Anda harus menyelesaikan langkah-langkah berikut:

  1. Buat kerangka VIA.
  2. (opsional) Terapkan alur penyiapan/login.
  3. (opsional) Terapkan layar Setelan.
  4. Deklarasikan izin yang diperlukan dalam file manifes.
  5. Menerapkan UI pelat suara.
  6. Menerapkan pengenalan suara (harus menyertakan penerapan RecognitionService API).
  7. Terapkan ucapan (secara opsional, Anda dapat menerapkan TextToSpeech API).
  8. Menerapkan pemenuhan perintah. Lihat konten ini di Memenuhi Perintah.

Bagian berikut menjelaskan cara menyelesaikan setiap langkah yang disebutkan di atas.

Membuat kerangka VIA

Manifes

Aplikasi terdeteksi sebagai aplikasi dengan Interaksi Suara jika hal berikut disertakan dalam manifes:

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>

Dalam contoh ini:

  • VIA harus mengekspos layanan yang memperluas VoiceInteractionService, dengan filter intent untuk tindakan VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService").
  • Layanan ini harus memiliki izin tanda tangan sistem BIND_VOICE_INTERACTION.
  • Layanan ini harus menyertakan file metadata android.voice_interaction untuk berisi hal berikut:

    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" />

Untuk mengetahui detail tentang setiap kolom, lihat R.styleable#VoiceInteractionService. Mengingat semua VIA juga merupakan layanan pengenalan suara, Anda juga harus menyertakan hal berikut dalam manifes Anda:

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>

Layanan pengenalan suara juga memerlukan metadata berikut:

res/xml/recognition_service.xml

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

VoiceInteractionService, VoiceInteractionSessionService, dan VoiceInteractionSession

Diagram berikut menggambarkan siklus proses setiap entitas ini:

Lifecycle

Gambar 1. Lifecycle

Seperti yang dinyatakan sebelumnya, VoiceInteractionService adalah titik entri ke VIA. Tanggung jawab utama layanan ini adalah:

  • Lakukan inisialisasi proses apa pun yang harus tetap berjalan selama VIA ini aktif. Misalnya, deteksi frasa pengaktif.
  • Melaporkan voice action yang didukung (lihat Ketuk untuk Membaca Asisten Suara).
  • Mulai sesi interaksi suara dari layar kunci (pengaman tombol).

Dalam bentuknya yang paling sederhana, implementasi VoiceInteractionService akan terlihat seperti ini:

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;
    }
    ...
}

Penerapan VoiceInteractionService#onGetSupportedVoiceActions() diperlukan untuk menangani Ketuk untuk Membaca Asisten Suara. VoiceInteractionSessionService digunakan oleh sistem untuk membuat dan berinteraksi dengan VoiceInteractionSession. Hanya memiliki satu tanggung jawab, yaitu memulai sesi baru saat diminta.

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

Terakhir, sebagian besar pekerjaan akan dilakukan di VoiceInteractionSession. Satu instance sesi dapat digunakan kembali untuk menyelesaikan beberapa interaksi pengguna. Di AAOS, ada CarVoiceInteractionSession helper, yang membantu mengimplementasikan beberapa fungsi unik otomotif.

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 memiliki banyak metode callback yang dijelaskan di bagian berikut. Lihat dokumentasi VoiceInteractionSession untuk mengetahui daftar lengkapnya.VoiceInteractionSession

Menerapkan alur penyiapan/login

Penyiapan dan login dapat terjadi:

  • Selama proses aktivasi perangkat (Wizard Penyiapan).
  • Selama penggantian layanan interaksi suara (Setelan).
  • Saat peluncuran pertama ketika aplikasi dipilih.

Untuk mengetahui detail tentang pengalaman pengguna yang direkomendasikan dan panduan visual, lihat Asisten yang Sudah Dimuat: Panduan UX.

Penyiapan selama penggantian layanan suara

Pengguna selalu dapat memilih VIA yang belum dikonfigurasi dengan benar. Hal ini dapat terjadi karena:

  • Pengguna melewati Wizard Penyiapan sepenuhnya atau pengguna melewati langkah konfigurasi interaksi suara.
  • Pengguna memilih VIA yang berbeda dengan yang dikonfigurasi selama orientasi perangkat.

Bagaimanapun juga, VoiceInteractionService memiliki beberapa cara untuk mendorong pengguna menyelesaikan penyiapan:

  • Pengingat notifikasi.
  • Balasan suara otomatis saat pengguna mencoba menggunakannya.

Catatan: Sangat tidak disarankan untuk menampilkan alur penyiapan VIA tanpa permintaan pengguna yang eksplisit. Artinya, VIA harus menghindari penayangan konten secara otomatis di HU selama booting perangkat atau sebagai akibat dari peralihan atau pembukaan kunci pengguna.

Pengingat notifikasi

Pengingat notifikasi adalah cara yang tidak mengganggu untuk menunjukkan kebutuhan penyiapan, dan untuk memberi pengguna kemampuan untuk membuka alur penyiapan asisten.

Pengingat notifikasi

Gambar 2. Pengingat notifikasi

Berikut cara kerja alur ini:

Alur pengingat notifikasi

Gambar 3. Alur pengingat notifikasi

Balasan suara

Ini adalah alur paling sederhana untuk diterapkan, yang memulai ucapan pada callback VoiceInteractionSession#onShow(), menjelaskan kepada pengguna apa yang perlu dilakukan, lalu menanyakan kepada mereka (jika penyiapan diizinkan mengingat status Pembatasan UX) apakah mereka ingin memulai alur penyiapan. Jika penyiapan tidak memungkinkan saat itu, jelaskan juga situasi ini.

Penyiapan saat penggunaan pertama

Pengguna selalu dapat memicu VIA yang belum dikonfigurasi dengan benar. Dalam kasus tersebut:

  1. Memberi tahu pengguna secara lisan tentang situasi ini (misalnya, "Agar berfungsi dengan benar, saya perlu Anda menyelesaikan beberapa langkah … ").
  2. Jika mesin pembatasan UX mengizinkan (lihat UX_RESTRICTIONS_NO_SETUP), tanyakan kepada pengguna apakah mereka ingin memulai proses penyiapan, lalu buka layar Setelan untuk VIA.
  3. Jika tidak (misalnya, jika pengguna sedang mengemudi), tinggalkan notifikasi agar pengguna dapat mengklik opsi saat aman untuk melakukannya.

Membangun layar penyiapan interaksi suara

Layar penyiapan dan login harus dikembangkan sebagai aktivitas reguler. Lihat panduan UX dan visual untuk pengembangan UI di Asisten yang Sudah Dimuat: Panduan UX.

Pedoman umum:

  • VIA harus mengizinkan pengguna untuk menghentikan dan melanjutkan penyiapan kapan saja.
  • Penyiapan tidak boleh diizinkan jika batasan UX_RESTRICTIONS_NO_SETUP berlaku. Untuk mengetahui detailnya, lihat Panduan Gangguan Pengemudi.
  • Layar penyiapan harus sesuai dengan sistem desain untuk setiap kendaraan. Tata letak layar umum, ikon, warna, dan aspek lainnya harus konsisten dengan UI lainnya. Lihat Penyesuaian untuk mengetahui detailnya.

Menerapkan layar setelan

Integrasi setelan

Gambar 4. Integrasi setelan

Layar setelan adalah aktivitas Android biasa. Jika diterapkan, titik entri mereka harus dideklarasikan di res/xml/interaction_service.xml sebagai bagian dari manifes VIA (lihat Manifes). Bagian Setelan adalah tempat yang tepat untuk melanjutkan penyiapan dan login (jika pengguna belum menyelesaikannya) atau menawarkan opsi logout atau ganti pengguna jika diperlukan. Mirip dengan layar Penyiapan yang dijelaskan di atas, layar ini harus:

  • Menyediakan opsi untuk keluar kembali ke layar sebelumnya dalam stack layar (misalnya, ke Setelan Mobil).
  • Tidak diizinkan saat mengemudi. Untuk mengetahui detailnya, lihat Panduan Gangguan Pengemudi.
  • Cocokkan setiap sistem desain kendaraan. Untuk mengetahui detailnya, lihat Penyesuaian.

Deklarasikan izin yang diperlukan dalam file manifes

Izin yang diperlukan oleh VIA dapat dibagi menjadi tiga kategori:

  • Izin tanda tangan sistem. Ini adalah izin yang hanya diberikan ke APK yang telah diinstal sebelumnya dan ditandatangani sistem. Pengguna tidak dapat memberikan izin ini, hanya OEM yang dapat memberikan izin tersebut saat membangun image sistem mereka. Untuk mengetahui informasi selengkapnya tentang cara mendapatkan izin tanda tangan, lihat Memberikan Izin dengan Hak Istimewa Sistem.
  • Izin berbahaya. Ini adalah izin yang harus diberikan pengguna menggunakan dialog PermissionsController. OEM dapat memberikan izin ini sebelumnya ke VoiceInteractionService default. Namun, mengingat default ini dapat berubah dari perangkat ke perangkat, aplikasi harus dapat meminta izin ini jika diperlukan.
  • Izin lain. Ini adalah semua izin lainnya yang tidak memerlukan intervensi pengguna. Izin ini diberikan secara otomatis oleh sistem.

Berdasarkan hal di atas, bagian berikut hanya berfokus pada permintaan izin berbahaya. Izin hanya boleh diminta saat pengguna berada di layar login atau setelan.

Jika aplikasi tidak memiliki izin yang diperlukan untuk beroperasi, alur yang direkomendasikan adalah menggunakan ucapan suara untuk menjelaskan situasi kepada pengguna, dan notifikasi untuk memberikan kemampuan yang dapat digunakan pengguna untuk kembali ke layar setelan VIA. Untuk mengetahui detailnya, lihat 1. Pengingat notifikasi.

Meminta izin sebagai bagian dari layar setelan

Izin berbahaya diminta menggunakan metode ActivityCompat#requestPermission() biasa (atau yang setara). Untuk mengetahui detail tentang cara meminta izin, lihat Meminta Izin Aplikasi.

Meminta izin

Gambar 5. Meminta izin

Izin pendengar notifikasi

Untuk menerapkan alur TTR, VIA harus ditetapkan sebagai pemroses notifikasi. Ini bukan izin itu sendiri, melainkan konfigurasi yang memungkinkan sistem mengirim notifikasi ke pendengar terdaftar. Untuk mengetahui apakah VIA diberi akses ke informasi ini, aplikasi dapat:

Jika akses ini tidak diberikan sebelumnya, VIA harus mengarahkan pengguna ke bagian Akses Notifikasi di Setelan Mobil, menggunakan kombinasi ucapan dan notifikasi. Kode berikut dapat digunakan untuk membuka bagian yang sesuai di aplikasi setelan:

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

Menerapkan UI pelat suara

Saat menerima callback onShow(), VoiceInteractionSession dapat menampilkan UI pelat suara. Untuk panduan visual dan UX tentang penerapan pelat suara,lihat Asisten yang Sudah Dimuat: Panduan UX.

Menampilkan pelat suara

Gambar 6. Menampilkan pelat suara

Ada dua opsi tentang cara menerapkan UI ini:

  • Mengganti VoiceInteractionSession#onCreateContentView()
  • Meluncurkan Aktivitas menggunakan VoiceInteractionSession#startAssistantActivity()

Menggunakan onCreateContentView()

Ini adalah cara default untuk menampilkan pelat suara. Class dasar VoiceInteractionSession membuat jendela dan mengelola siklus prosesnya selama sesi suara masih aktif. Aplikasi harus mengganti VoiceInteractionSession#onCreateContentView() dan menampilkan tampilan yang dilampirkan ke jendela tersebut segera setelah sesi dibuat. Tampilan ini awalnya tidak terlihat. Saat interaksi suara dimulai, tampilan ini harus dibuat terlihat di VoiceInteractionSession#onShow() lalu dibuat tidak terlihat lagi di 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);
    }
    
}

Saat menggunakan metode ini, Anda mungkin ingin menyesuaikan VoiceInteractionSession#onComputeInsets() untuk memperhitungkan wilayah UI yang tertutup.

Menggunakan startAssistantActivity()

Dalam hal ini, VoiceInteractionSession mendelegasikan penanganan UI pelat suara ke aktivitas reguler. Jika opsi ini digunakan, penerapan VoiceInteractionSession harus menonaktifkan pembuatan jendela konten defaultnya (lihat Menggunakan onCreateContentView()) pada callback onPrepareShow(). Pada VoiceInteractionSession#onShow(), sesi akan memulai aktivitas voice plate menggunakan VoiceInteractionSession#startAssistantActivity(). Metode ini memulai UI dengan setelan jendela dan flag aktivitas yang tepat.

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);
    }

    
}

Untuk mempertahankan komunikasi antara aktivitas ini dan VoiceInteractionSession, serangkaian Intent internal atau pengikatan layanan mungkin diperlukan. Misalnya, saat VoiceInteractionSession#onHide() dipanggil, sesi harus dapat meneruskan permintaan ini ke aktivitas.

Penting. Di Automotive, hanya aktivitas yang diberi anotasi khusus atau aktivitas yang tercantum dalam "daftar yang diizinkan" UXR yang dapat ditampilkan saat mengemudi. Hal ini juga berlaku untuk aktivitas yang dimulai dengan VoiceInteractionSession#startAssistantActivity(). Jangan lupa untuk memberi anotasi pada aktivitas Anda dengan <meta-data android:name="distractionOptimized" android:value="true"/> atau menyertakan aktivitas ini dalam kunci systemActivityWhitelist pada file /packages/services/Car/service/res/values/config.xml. Untuk mengetahui informasi selengkapnya, lihat Pedoman Perilaku Mengemudi yang Aman.

Menerapkan pengenalan suara

Di bagian ini, Anda akan mempelajari cara menerapkan pengenalan suara melalui deteksi dan pengenalan kata pemicu. Kata pemicu adalah kata pemicu yang digunakan untuk memulai kueri atau tindakan baru dengan suara. Misalnya, "OK Google" atau "Hai Google".

Deteksi frasa pengaktif DSP

Android menyediakan akses ke detektor frasa pengaktif selalu aktif di tingkat DSP dengan menggunakan AlwaysOnHotwordDetector. cara menerapkan deteksi frasa pengaktif dengan CPU rendah. Penggunaan fungsi ini dibagi menjadi dua bagian:

Implementasi VoiceInteractionService dapat membuat detektor hotword menggunakan VoiceInteractionService#createAlwaysOnHotwordDetector(), dengan meneruskan frasa kunci dan lokalitas yang ingin digunakan untuk deteksi. Akibatnya, aplikasi menerima callback onAvailabilityChanged() dengan salah satu kemungkinan nilai berikut:

  • STATE_HARDWARE_UNAVAILABLE. Kemampuan DSP tidak tersedia di perangkat. Dalam hal ini, deteksi frasa pengaktif Software digunakan.
  • STATE_HARDWARE_UNSUPPORTED. Dukungan DSP umumnya tidak tersedia, tetapi DSP tidak mendukung kombinasi frasa kunci dan lokalitas tertentu. Aplikasi dapat memilih untuk menggunakan Deteksi Frasa Pengaktif Software.
  • STATE_HARDWARE_ENROLLED. Deteksi frasa pengaktif sudah siap dan dapat dimulai dengan memanggil metode startRecognition().
  • STATE_HARDWARE_UNENROLLED. Model suara untuk frasa kunci yang diminta tidak tersedia, tetapi pendaftaran dapat dilakukan.

Pendaftaran model suara deteksi frasa pengaktif dapat dilakukan dengan menggunakan IVoiceInteractionManagerService#updateKeyphraseSoundModel(). Beberapa model dapat didaftarkan dalam sistem pada waktu tertentu, tetapi hanya satu model yang dikaitkan dengan AlwaysOnHotwordDetector. Deteksi frasa pengaktif DSP mungkin tidak tersedia di semua perangkat. Developer VIA harus memeriksa kemampuan hardware menggunakan metode getDspModuleProperties(). Untuk kode contoh yang menunjukkan cara mendaftarkan model suara, lihat VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java. Lihat Pengambilan serentak terkait pengenalan kata cepat serentak.

Deteksi frasa pengaktif software

Seperti yang ditunjukkan di atas, deteksi hotword DSP mungkin tidak tersedia di semua perangkat (misalnya, emulator Android tidak menyediakan emulasi DSP). Dalam hal ini, pengenalan suara software adalah satu-satunya alternatif. Untuk menghindari gangguan pada aplikasi lain yang mungkin memerlukan akses ke mikrofon, VIA harus mengakses input audio menggunakan:

Kedua konstanta ini adalah @hide dan hanya tersedia untuk aplikasi yang di-bundle.

Mengelola input audio dan pengenalan suara

Input audio akan diterapkan menggunakan class MediaRecorder. Untuk mengetahui informasi selengkapnya tentang cara menggunakan API ini, lihat Ringkasan MediaRecorder. Layanan interaksi suara juga diharapkan menjadi penerapan kelas RecognitionService class. Setiap aplikasi dalam sistem yang memerlukan pengenalan suara menggunakan untuk mengakses kemampuan ini. Untuk melakukan pengenalan suara dan memiliki akses ke mikrofon, VIA harus menahan android.permission.RECORD_AUDIO. Aplikasi yang mengakses penerapan RecognitionService diharapkan juga memiliki izin ini.

Sebelum Android 10, akses mikrofon hanya diberikan ke satu aplikasi dalam satu waktu (kecuali deteksi hotword, lihat di atas). Mulai Android 10, akses mikrofon dapat dibagikan. Untuk mengetahui informasi selengkapnya, lihat Berbagi Input Audio.

Mengakses output audio

Saat VIA siap memberikan respons verbal, penting untuk mengikuti serangkaian panduan berikutnya ini: