Untuk menerapkan Aplikasi Interaksi Suara (VIA), Anda menyelesaikan langkah-langkah ini:
- Buat kerangka VIA.
- ( opsional ) Menerapkan alur penyiapan/masuk.
- ( opsional ) Menerapkan layar Pengaturan.
- Deklarasikan izin yang diperlukan dalam file manifes.
- Menerapkan UI pelat suara.
- Menerapkan pengenalan suara (harus menyertakan implementasi API RecognitionService).
- Menerapkan ucapan (opsional, Anda dapat mengimplementasikan TextToSpeech API).
- Melaksanakan pemenuhan perintah. Lihat konten ini di Memenuhi Perintah .
Bagian berikut menjelaskan cara menyelesaikan setiap langkah yang disebutkan di atas.
Buat Kerangka VIA
Manifest
Aplikasi terdeteksi sebagai satu dengan Interaksi Suara saat berikut ini 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 tindakanVoiceInteractionService.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 bahwa semua VIA juga merupakan layanan pengenal suara, Anda juga harus menyertakan yang berikut ini 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 bagian 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 hidup masing-masing entitas ini:
Gambar 1. Siklus Hidup
Seperti yang dinyatakan sebelumnya, VoiceInteractionService
adalah titik masuk ke VIA. Tanggung jawab utama dari layanan ini adalah:
- Inisialisasi proses apa pun yang harus tetap berjalan selama VIA ini aktif. Misalnya, deteksi kata cepat.
- Melaporkan tindakan suara yang didukung (lihat Voice Assistant Tap-to-Read ).
- Luncurkan sesi interaksi suara dari layar kunci (keyguard).
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; } ... }
Implementasi VoiceInteractionService#onGetSupportedVoiceActions()
diperlukan untuk menangani Voice Assistant Tap-to-Read . VoiceInteractionSessionService digunakan oleh sistem untuk membuat dan berinteraksi dengan VoiceInteractionSession . Hanya memiliki satu tanggung jawab, untuk memulai sesi baru saat 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. Instance sesi tunggal dapat digunakan kembali untuk menyelesaikan beberapa interaksi pengguna. Di AAOS, terdapat 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 sekumpulan besar metode callback yang akan dijelaskan di bagian berikut. lihat dokumentasi untuk VoiceInterationSession
daftar lengkap.
Terapkan Alur Penyiapan/Masuk
Penyiapan dan 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 yang direkomendasikan dan panduan visual, 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 saat pengguna mencoba menggunakannya.
Catatan : Sangat tidak disarankan untuk menyajikan alur penyiapan VIA tanpa permintaan pengguna yang eksplisit. Ini berarti bahwa VIA harus menghindari secara otomatis menampilkan konten pada HU selama boot perangkat atau sebagai akibat dari peralihan atau pembukaan kunci pengguna.
1. Pengingat Pemberitahuan
Pengingat notifikasi adalah cara yang tidak mengganggu untuk menunjukkan perlunya penyiapan, dan untuk memberi pengguna kemampuan untuk menavigasi ke alur penyiapan asisten.
Gambar 2. Pengingat notifikasi
Berikut adalah bagaimana aliran ini akan bekerja:
Gambar 3. Alur pengingat notifikasi
Note
: Bergantung pada aturan Pembatasan UX (lihat Panduan Pengalihan Pengemudi ), alur pengaturan mungkin tidak diizinkan saat mengemudi. Ketika pengguna mengklik pemberitahuan dan pengaturan tidak diizinkan, aplikasi harus menggunakan ucapan untuk menjelaskan situasi kepada pengguna daripada mencoba menampilkan UI yang akan segera diblokir.
2. Balasan suara
Ini adalah alur paling sederhana untuk diterapkan, memulai ucapan pada panggilan balik VoiceInteractionSession#onShow()
, menjelaskan kepada pengguna apa yang perlu dilakukan, dan kemudian menanyakan mereka (jika penyiapan diizinkan dengan status Pembatasan UX) apakah mereka ingin memulai aliran pengaturan. Jika penyiapan tidak memungkinkan pada saat itu, jelaskan juga situasi ini.
Pengaturan Pada Penggunaan Pertama
Pengguna selalu dapat memicu VIA yang belum dikonfigurasi dengan benar. Dalam beberapa kasus:
- Informasikan secara lisan kepada pengguna tentang situasi ini (misalnya, "Agar berfungsi dengan baik, saya ingin Anda menyelesaikan beberapa langkah ... ").
- Jika mesin pembatasan UX mengizinkan (lihat UX_RESTRICTIONS_NO_SETUP ), tanyakan kepada pengguna apakah mereka ingin memulai proses penyiapan dan kemudian buka layar Pengaturan untuk VIA.
- Jika tidak (misalnya, jika pengguna mengemudi), tinggalkan pemberitahuan bagi pengguna untuk mengklik opsi saat aman untuk melakukannya.
Membangun Layar Pengaturan Interaksi Suara
Layar Penyetelan dan Masuk harus dikembangkan sebagai aktivitas reguler . Lihat UX dan panduan visual untuk pengembangan UI di Preloaded Assistants: UX Guidance .
Petunjuk umum:
- VIA harus memungkinkan pengguna untuk menginterupsi dan melanjutkan penyiapan kapan saja.
- Penyiapan tidak boleh diizinkan jika pembatasan
UX_RESTRICTIONS_NO_SETUP
berlaku. Untuk detailnya, lihat Panduan Pengalihan Pengemudi . - Layar pengaturan 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 detailnya.
Terapkan Layar 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 Manifes ). 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 harus:
- Berikan opsi untuk keluar kembali ke layar sebelumnya di tumpukan layar (misalnya, ke Pengaturan Mobil).
- Tidak diizinkan saat mengemudi. Untuk detailnya, lihat Panduan Pengalihan Pengemudi .
- Cocokkan setiap sistem desain kendaraan. Untuk 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 untuk APK yang telah diinstal sebelumnya dan ditandatangani oleh sistem. Pengguna tidak dapat memberikan izin ini, hanya OEM yang dapat memberikan izin tersebut saat membangun citra sistem mereka. Untuk informasi selengkapnya tentang mendapatkan izin tanda tangan, lihat Memberikan Izin Hak Istimewa Sistem .
- Izin berbahaya. Ini adalah izin yang harus diberikan pengguna menggunakan dialog PermissionsController. OEM dapat memberikan beberapa izin ini sebelumnya ke VoiceInteractionService default. Tetapi mengingat bahwa default ini mungkin berubah dari perangkat ke perangkat, aplikasi harus dapat meminta izin ini saat diperlukan.
- Izin lainnya. Ini semua adalah izin lain yang tidak memerlukan intervensi pengguna. Izin ini akan secara otomatis diberikan oleh sistem.
Mengingat hal di atas, bagian berikut hanya akan fokus pada meminta izin berbahaya. Izin hanya boleh diminta saat pengguna berada di layar masuk atau layar setelan.
Jika aplikasi tidak memiliki izin yang diperlukan untuk beroperasi, alur yang disarankan adalah menggunakan ucapan suara untuk menjelaskan situasi 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 .
Gambar 5. Meminta izin
Izin Pendengar Pemberitahuan
Untuk menerapkan alur TTR, VIA harus ditetapkan sebagai pendengar notifikasi. Ini bukan izin semata, melainkan konfigurasi yang memungkinkan sistem mengirim pemberitahuan ke pendengar terdaftar. Untuk mengetahui apakah VIA diberi akses ke informasi ini, aplikasi dapat:
- (Opsional) Periksa apakah ada pendengar notifikasi sebelumnya dengan menggunakan
CarAssistUtils#assistantIsNotificationListener()
. Ini dapat dilakukan, misalnya, selama alur pengaturan. - (Wajib) Bereaksi untuk menangani
CarVoiceInteractionSession#onShow()
dengan tindakanVOICE_ACTION_HANDLE_EXCEPTION
dan pengecualianEXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING
.
Jika akses ini tidak diberikan sebelumnya, VIA harus mengarahkan pengguna ke bagian Akses Pemberitahuan di Pengaturan Mobil, menggunakan kombinasi ucapan dan pemberitahuan. Kode berikut dapat digunakan untuk membuka bagian yang sesuai dari 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 panggilan balik onShow()
, itu dapat menampilkan UI pelat suara. Untuk panduan visual dan UX tentang implementasi pelat suara, lihat Asisten Termuat: Panduan UX .
Gambar 6. Menampilkan pelat suara
Ada dua opsi tentang cara mengimplementasikan UI ini:
- Ganti
VoiceInteractionSession#onCreateContentView()
- Luncurkan Aktivitas menggunakan
VoiceInteractionSession#startAssistantActivity()
Menggunakan onCreateContentView()
Ini adalah cara default untuk menampilkan pelat suara. Kelas dasar VoiceInteractionSession akan membuat jendela dan mengelola siklus hidupnya selama sesi suara masih hidup. Aplikasi harus mengganti VoiceInteractionSession#onCreateContentView()
dan mengembalikan tampilan yang akan dilampirkan ke jendela itu segera setelah sesi dibuat. Pandangan ini pada awalnya seharusnya tidak terlihat. Saat interaksi suara dimulai, tampilan ini harus dibuat 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 yang dikaburkan dari UI Anda.
Menggunakan startAssistantActivity()
Dalam hal ini, VoiceInteractionSession
akan mendelegasikan penanganan UI pelat suara ke Aktivitas reguler. Saat opsi ini digunakan, implementasi VoiceInteractionSession
harus menonaktifkan pembuatan jendela konten default (lihat Menggunakan onCreateContentView() ) pada callback onPrepareShow()
. Di VoiceInteractionSession#onShow()
, sesi akan memulai Aktivitas pelat suara menggunakan VoiceInteractionSession#startAssistantActivity()
. Metode ini memulai UI dengan pengaturan Window 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 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 Otomotif, hanya aktivitas atau aktivitas beranotasi khusus yang tercantum dalam "daftar yang diizinkan" UXR yang dapat ditampilkan saat mengemudi. Ini berlaku untuk aktivitas yang dimulai dengan VoiceInteractionSession#startAssistantActivity()
juga. 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 Pengalihan 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 kueri atau tindakan baru dengan suara. Misalnya, "OK Google" atau "Hai Google".
Deteksi Kata Cepat DSP
Android menyediakan akses ke detektor kata cepat yang selalu aktif di tingkat DSP melalui kelas AlwaysOnHotwordDetector
. Ini memberikan cara mudah untuk menerapkan deteksi kata cepat dengan CPU rendah. Penggunaan fungsi ini dibagi menjadi dua bagian:
- Instansiasi dari
AlwaysOnHotwordDetector
. - Pendaftaran model suara deteksi kata cepat.
Implementasi VoiceInteractionService dapat membuat detektor kata cepat menggunakan VoiceInteractionService#createAlwaysOnHotwordDetector()
, meneruskan frasa kunci dan lokal yang ingin mereka gunakan untuk deteksi. Akibatnya, aplikasi akan menerima callback onAvailabilityChanged()
dengan salah satu kemungkinan nilai berikut:
-
STATE_HARDWARE_UNAVAILABLE
. Kemampuan DSP tidak tersedia pada perangkat. Dalam hal ini, deteksi kata cepat Perangkat Lunak akan digunakan. -
STATE_HARDWARE_UNSUPPORTED
. Dukungan DSP tidak tersedia secara umum, tetapi DSP tidak mendukung kombinasi frasa kunci dan lokal yang diberikan. Aplikasi dapat memilih untuk menggunakan Deteksi Kata Cepat Perangkat Lunak . -
STATE_HARDWARE_ENROLLED
. Deteksi kata panas sudah siap dan dapat dimulai dengan memanggil metodestartRecognition()
. -
STATE_HARDWARE_UNENROLLED
. Model suara untuk frasa kunci yang diminta tidak tersedia, tetapi pendaftaran dimungkinkan.
Pendaftaran model suara pendeteksi kata cepat dapat dilakukan dengan menggunakan IVoiceInteractionManagerService#updateKeyphraseSoundModel()
. Beberapa model dapat didaftarkan dalam sistem pada waktu tertentu, tetapi hanya satu model yang akan dikaitkan dengan AlwaysOnHotwordDetector
. Deteksi kata cepat DSP mungkin tidak tersedia di semua perangkat. Pengembang VIA harus memeriksa kemampuan perangkat keras menggunakan metode getDspModuleProperties()
. Untuk kode contoh yang menunjukkan cara mendaftarkan model suara, lihat VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
. Lihat Pengambilan Serentak mengenai pengenalan kata cepat bersamaan.
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, pengenalan suara perangkat lunak adalah satu-satunya alternatif. Untuk menghindari gangguan dengan aplikasi lain yang mungkin memerlukan akses ke mikrofon, VIA harus mengakses input audio menggunakan:
- Pengambilan audio harus menggunakan MediaRecorder.AudioSource.HOTWORD .
- Tahan izin
android.Manifest.permission.CAPTURE_AUDIO_HOTWORD
.
Kedua konstanta ini adalah @hide
dan hanya tersedia untuk aplikasi yang dibundel.
Mengelola Input Audio dan Pengenalan Suara
Masukan audio akan diimplementasikan menggunakan MediaRecorder API . Untuk informasi selengkapnya tentang cara menggunakan API ini, lihat Ikhtisar MediaRecorder . Layanan interaksi suara juga diharapkan menjadi implementasi RecognitionService
. Aplikasi apa pun dalam sistem yang memerlukan pengenalan suara akan menggunakan SpeechRecognizer API 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
diharapkan memiliki izin ini juga.
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 .
Mengakses Keluaran Audio
Ketika VIA siap memberikan tanggapan verbal, penting untuk mengikuti pedoman berikut ini:
- Saat meminta fokus audio atau mengelola output audio, aplikasi harus menggunakan
AudioAttributes#USAGE_ASSISTANT
danAudioAttributes#CONTENT_TYPE_SPEECH
sebagai atribut audio. - Selama pengenalan ucapan, fokus audio harus diminta dengan
AudioManage#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
. Ketahuilah bahwa beberapa aplikasi media mungkin tidak bereaksi dengan benar terhadap perintah media (lihat Memenuhi Perintah Media ) saat fokus audionya dihapus.