Pengembangan aplikasi

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

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

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

Buat kerangka VIA

Mewujud

Suatu 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 maksud 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 yang 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 detail tentang setiap bidang, lihat R.styleable#VoiceInteractionService . Mengingat semua VIA juga merupakan layanan pengenal 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" />

Layanan Interaksi Suara, Layanan Interaksi Suara, dan Sesi Interaksi Suara

Diagram berikut menggambarkan siklus hidup masing-masing entitas ini:

Siklus hidup

Gambar 1. Siklus Hidup

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

  • Inisialisasi proses apa pun yang harus tetap berjalan selama VIA ini aktif. Misalnya saja deteksi kata cepat.
  • Melaporkan tindakan suara yang didukung (lihat Asisten Suara Ketuk untuk Membaca ).
  • Luncurkan sesi interaksi suara dari layar kunci (pengaman tombol).

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

Implementasi VoiceInteractionService#onGetSupportedVoiceActions() diperlukan untuk menangani Voice Assistant Tap-to-Read . VoiceInteractionSessionService digunakan oleh sistem untuk membuat dan berinteraksi dengan VoiceInteractionSession . Ia hanya memiliki satu tanggung jawab, untuk memulai sesi baru bila diminta.

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

Terakhir, VoiceInteractionSession adalah tempat sebagian besar pekerjaan akan dilakukan. Satu instance sesi mungkin digunakan kembali untuk menyelesaikan beberapa interaksi pengguna. Di AAOS, ada pembantu CarVoiceInteractionSession 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 sejumlah besar metode panggilan balik yang dijelaskan di bagian berikut. lihat dokumentasi untuk VoiceInteractionSession daftar lengkapnya.

Menerapkan alur penyiapan/masuk

Penyiapan dan proses masuk dapat terjadi:

  • Selama orientasi perangkat (Setup Wizard).
  • Selama pertukaran layanan interaksi suara (Pengaturan).
  • Saat peluncuran pertama saat aplikasi dipilih.

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

Pengaturan selama pertukaran layanan suara

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

  • Pengguna melewatkan Wizard Penyiapan seluruhnya atau pengguna melewatkan langkah konfigurasi interaksi suara.
  • Pengguna memilih VIA yang berbeda dari yang dikonfigurasi selama orientasi perangkat.

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

  • Pengingat pemberitahuan.
  • Balasan suara otomatis ketika pengguna mencoba menggunakannya.

Catatan : Sangat tidak disarankan untuk menyajikan alur pengaturan VIA tanpa permintaan pengguna yang eksplisit. Ini berarti VIA harus menghindari tampilan konten secara otomatis di HU selama booting perangkat atau sebagai akibat dari peralihan atau pembukaan kunci pengguna.

Pengingat pemberitahuan

Pengingat notifikasi adalah cara yang tidak mengganggu untuk menunjukkan perlunya penyiapan, dan memberi pengguna kemampuan untuk menavigasi ke alur penyiapan asisten.

Pengingat pemberitahuan

Gambar 2. Pengingat notifikasi

Inilah cara kerja aliran ini:

Alur pengingat notifikasi

Gambar 3. Alur pengingat notifikasi

Balasan suara

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

Pengaturan pada penggunaan pertama

Selalu ada kemungkinan bagi pengguna untuk memicu VIA yang belum dikonfigurasi dengan benar. Dalam beberapa kasus:

  1. Beri tahu pengguna secara lisan tentang situasi ini (misalnya, "Agar berfungsi dengan baik, saya ingin Anda menyelesaikan beberapa langkah … ").
  2. Jika mesin pembatasan UX mengizinkan (lihat UX_RESTRICTIONS_NO_SETUP ), tanyakan kepada pengguna apakah mereka ingin memulai proses pengaturan dan kemudian buka layar Pengaturan untuk VIA.
  3. Jika tidak (misalnya, jika pengguna sedang mengemudi), tinggalkan pemberitahuan agar pengguna mengeklik opsi jika sudah aman untuk melakukannya.

Bangun layar pengaturan interaksi suara

Layar pengaturan dan masuk harus dikembangkan sebagai aktivitas rutin. Lihat UX dan pedoman visual untuk pengembangan UI di Asisten yang Dimuat Sebelumnya: Panduan UX .

Petunjuk umum:

  • VIA harus memungkinkan pengguna untuk menghentikan dan melanjutkan pengaturan kapan saja.
  • Penyiapan tidak boleh diizinkan jika pembatasan UX_RESTRICTIONS_NO_SETUP berlaku. Untuk detailnya, lihat Pedoman Gangguan Pengemudi .
  • Layar pengaturan harus sesuai dengan sistem desain untuk setiap kendaraan. Tata letak layar secara umum, ikon, warna, dan aspek lainnya harus konsisten dengan UI lainnya. Lihat Kustomisasi untuk detailnya.

Terapkan layar pengaturan

Integrasi pengaturan

Gambar 4. Integrasi pengaturan

Layar pengaturan adalah aktivitas Android biasa. Jika diterapkan, titik masuknya harus dideklarasikan di res/xml/interaction_service.xml sebagai bagian dari manifes VIA (lihat Manifests ). Bagian Pengaturan adalah tempat yang baik untuk melanjutkan penyiapan dan masuk (jika pengguna tidak menyelesaikannya) atau menawarkan opsi keluar atau beralih pengguna jika diperlukan. Mirip dengan layar Pengaturan yang dijelaskan di atas, layar ini seharusnya:

  • Berikan opsi untuk keluar kembali ke layar sebelumnya di tumpukan layar (misalnya, ke Pengaturan Mobil).
  • Tidak diperbolehkan saat mengemudi. Untuk detailnya, lihat Pedoman Gangguan Pengemudi .
  • Cocokkan setiap sistem desain kendaraan. Untuk detailnya, lihat Kustomisasi .

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 kepada APK yang telah diinstal sebelumnya dan ditandatangani oleh sistem. Pengguna tidak dapat memberikan izin ini, hanya OEM yang dapat memberikan izin tersebut saat membuat image sistem mereka. Untuk informasi lebih lanjut tentang cara mendapatkan izin tanda tangan, lihat Memberikan Izin Istimewa Sistem .
  • Izin berbahaya. Ini adalah izin yang harus diberikan pengguna menggunakan dialog PermissionsController. OEM dapat memberikan terlebih dahulu beberapa izin ini ke VoiceInteractionService default. Namun mengingat default ini mungkin berubah dari satu perangkat ke perangkat lainnya, aplikasi seharusnya dapat meminta izin ini bila diperlukan.
  • Izin lainnya. Ini semua adalah izin lain yang tidak memerlukan intervensi pengguna. Izin ini secara otomatis diberikan oleh sistem.

Mengingat hal di atas, bagian berikut hanya berfokus pada permintaan izin berbahaya. Izin hanya boleh diminta saat pengguna berada di layar masuk atau layar pengaturan.

Jika aplikasi tidak memiliki izin yang diperlukan untuk beroperasi, alur yang disarankan adalah menggunakan ucapan suara untuk menjelaskan situasinya kepada pengguna, dan pemberitahuan untuk memberikan kemampuan yang dapat digunakan pengguna untuk menavigasi kembali ke layar pengaturan VIA . Untuk detailnya, lihat 1. Pengingat notifikasi .

Minta izin sebagai bagian dari layar pengaturan

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

Minta izin

Gambar 5. Meminta izin

Izin pendengar notifikasi

Untuk mengimplementasikan aliran TTR, VIA harus ditunjuk sebagai pendengar notifikasi. Ini bukan izin semata, melainkan konfigurasi yang memungkinkan sistem mengirimkan 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 pada Pengaturan Mobil, menggunakan kombinasi ucapan dan notifikasi. Kode berikut dapat digunakan untuk membuka bagian yang sesuai pada aplikasi pengaturan:

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 VoiceInteractionSession menerima callback onShow() , VoiceInteractionSession dapat menampilkan UI pelat suara. Untuk pedoman visual dan UX mengenai penerapan pelat suara, lihat Asisten yang Dimuat Sebelumnya: Panduan UX .

Menampilkan pelat suara

Gambar 6. Menampilkan pelat suara

Ada dua opsi tentang cara mengimplementasikan UI ini:

  • Ganti VoiceInteractionSession#onCreateContentView()
  • Luncurkan Aktivitas menggunakan VoiceInteractionSession#startAssistantActivity()

Gunakan onCreateContentView()

Ini adalah cara default menampilkan pelat suara. Kelas dasar VoiceInteractionSession membuat jendela dan mengelola siklus hidupnya selama sesi suara masih aktif. Aplikasi harus mengganti VoiceInteractionSession#onCreateContentView() dan mengembalikan tampilan yang dilampirkan ke jendela tersebut segera setelah sesi dibuat. Pandangan ini pada awalnya seharusnya tidak terlihat. Saat interaksi suara dimulai, tampilan ini akan terlihat di VoiceInteractionSession#onShow() dan kemudian 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 Anda yang tidak jelas.

Gunakan startAssistantActivity()

Dalam hal ini, VoiceInteractionSession mendelegasikan penanganan UI pelat suara ke aktivitas reguler. Jika opsi ini digunakan, implementasi VoiceInteractionSession harus menonaktifkan pembuatan jendela konten defaultnya (lihat Menggunakan onCreateContentView() ) pada callback onPrepareShow() . Di VoiceInteractionSession#onShow() , sesi akan memulai aktivitas pelat suara menggunakan VoiceInteractionSession#startAssistantActivity() . Metode ini memulai UI dengan pengaturan jendela dan tanda 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 menjaga komunikasi antara aktivitas ini dan VoiceInteractionSession , serangkaian Intent internal atau pengikatan layanan mungkin diperlukan. Misalnya, ketika VoiceInteractionSession#onHide() dipanggil, sesi harus dapat meneruskan permintaan ini ke aktivitas.

Penting. Di Otomotif, 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() . Ingatlah untuk memberi anotasi pada aktivitas Anda dengan <meta-data android:name="distractionOptimized" android:value="true"/> atau sertakan aktivitas ini dalam kunci systemActivityWhitelist dari /packages/services/Car/service/res/values/config.xml file /packages/services/Car/service/res/values/config.xml . Untuk informasi lebih lanjut, lihat Pedoman Gangguan Pengemudi .

Menerapkan pengenalan suara

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

Deteksi kata cepat DSP

Android menyediakan akses ke pendeteksi kata cepat yang selalu aktif di tingkat DSP melalui AlwaysOnHotwordDetector . cara untuk mengimplementasikan deteksi kata cepat dengan CPU rendah. Penggunaan fungsi ini dibagi menjadi dua bagian:

Implementasi VoiceInteractionService dapat membuat pendeteksi kata cepat menggunakan VoiceInteractionService#createAlwaysOnHotwordDetector() , meneruskan frasa kunci dan lokal yang ingin mereka gunakan 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, perangkat lunak pendeteksi kata cepat digunakan.
  • STATE_HARDWARE_UNSUPPORTED . Dukungan DSP tidak tersedia secara umum, namun DSP tidak mendukung kombinasi frasa kunci dan lokal tertentu. Aplikasi ini dapat memilih untuk menggunakan Deteksi Kata Cepat Perangkat Lunak .
  • STATE_HARDWARE_ENROLLED . Deteksi kata panas sudah siap dan dapat dimulai dengan memanggil metode startRecognition() .
  • STATE_HARDWARE_UNENROLLED . Model suara untuk frasa kunci yang diminta tidak tersedia, namun pendaftaran dapat dilakukan.

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

Deteksi kata cepat perangkat lunak

Seperti yang ditunjukkan di atas, deteksi kata cepat DSP mungkin tidak tersedia di semua perangkat (misalnya, emulator Android tidak menyediakan emulasi DSP). Dalam hal ini, perangkat lunak pengenalan suara adalah satu-satunya alternatif. Untuk menghindari interferensi dengan 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 dibundel.

Kelola input audio dan pengenalan suara

Input audio akan diimplementasikan menggunakan kelas MediaRecorder . Untuk informasi selengkapnya tentang cara menggunakan API ini, lihat Ikhtisar MediaRecorder . Layanan interaksi suara juga diharapkan menjadi implementasi kelas RecognitionService . Aplikasi apa pun di sistem yang memerlukan pengenalan suara menggunakan untuk mengakses kemampuan ini. Untuk melakukan pengenalan suara dan memiliki akses ke mikrofon, VIA harus memiliki android.permission.RECORD_AUDIO . Aplikasi yang mengakses implementasi RecognitionService juga diharapkan memiliki izin ini.

Sebelum Android 10, akses mikrofon hanya diberikan ke satu aplikasi dalam satu waktu (dengan pengecualian deteksi kata cepat, lihat di atas). Dimulai dengan Android 10, akses mikrofon dapat dibagikan. Untuk informasi lebih lanjut lihat Berbagi Input Audio .

Akses keluaran audio

Ketika VIA siap memberikan tanggapan verbal, penting untuk mengikuti serangkaian pedoman berikut ini: