Untuk menerapkan Aplikasi Interaksi Suara (VIA), Anda harus menyelesaikan langkah-langkah berikut:
- Membuat kerangka VIA.
- (opsional) Terapkan alur penyiapan/login.
- (opsional) Terapkan layar Setelan.
- Deklarasikan izin yang diperlukan dalam file manifes.
- Mengimplementasikan UI pelat suara.
- Mengimplementasikan pengenalan suara (harus menyertakan implementasi RecognitionService API).
- Terapkan ucapan (secara opsional, Anda dapat menerapkan TextToSpeech API).
- Terapkan fulfillment 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 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
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 bahwa semua VIA juga merupakan layanan pengenal suara, Anda juga harus
menyertakan hal berikut dalam manifes:
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 proses setiap entitas ini:
Gambar 1. Lifecycle
Seperti yang dinyatakan sebelumnya, VoiceInteractionService
adalah titik entri
ke VIA. Tanggung jawab utama layanan ini adalah:
- Lakukan inisialisasi pada proses apa pun yang harus terus berjalan selama VIA ini aktif. Misalnya, deteksi frasa pengaktif.
- Melaporkan voice action yang didukung (lihat Ketuk untuk Membaca Asisten Suara).
- Meluncurkan sesi interaksi suara dari layar kunci (pelindung kunci).
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. Fungsi ini 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, VoiceInteractionSession adalah tempat sebagian besar pekerjaan
akan dilakukan. Satu instance sesi dapat digunakan kembali untuk menyelesaikan beberapa interaksi pengguna. Di AAOS, terdapat CarVoiceInteractionSession
helper,
yang membantu menerapkan 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 kumpulan besar metode callback yang
dijelaskan di bagian berikut. lihat dokumentasi untuk VoiceInteractionSession
daftar lengkap.
Menerapkan alur penyiapan/login
Penyiapan dan login dapat terjadi:
- Selama aktivasi perangkat (Wizard Penyiapan).
- Selama pertukaran layanan interaksi suara (Setelan).
- Saat pertama kali diluncurkan saat aplikasi dipilih.
Untuk mengetahui detail tentang pengalaman pengguna yang direkomendasikan dan panduan visual, lihat Asisten yang Dimuat Sebelumnya: Panduan UX.
Penyiapan selama pertukaran 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 aktivasi perangkat.
Apa pun yang terjadi, VoiceInteractionService
memiliki beberapa cara untuk mendorong pengguna
menyelesaikan penyiapan:
- Pengingat notifikasi.
- Balasan suara otomatis saat pengguna mencoba menggunakannya.
Catatan: Sebaiknya jangan tampilkan alur penyiapan VIA tanpa permintaan pengguna yang eksplisit. Artinya, VIA harus menghindari tampilan konten secara otomatis di HU selama booting perangkat atau sebagai akibat dari tombol pengguna atau kunci terbuka.
Pengingat notifikasi
Pengingat notifikasi adalah cara yang tidak mengganggu untuk menunjukkan kebutuhan penyiapan, dan memberi pengguna kemampuan untuk membuka alur penyiapan asisten.
Gambar 2. Pengingat notifikasi
Berikut cara kerja alur ini:
Gambar 3. Alur pengingat notifikasi
Balasan suara
Ini adalah alur paling sederhana untuk diterapkan, memulai ucapan pada
callback VoiceInteractionSession#onShow()
, menjelaskan kepada pengguna apa
yang perlu dilakukan, lalu menanyakan kepada mereka (jika penyiapan diizinkan mengingat status Batasan UX)
apakah mereka ingin memulai alur penyiapan. Jika penyiapan tidak dapat dilakukan pada saat itu, jelaskan situasi
ini juga.
Penyiapan saat pertama kali digunakan
Pengguna selalu dapat memicu VIA yang belum dikonfigurasi dengan benar. Dalam kasus tersebut:
- Beri tahu pengguna secara lisan tentang situasi ini (misalnya, "Agar berfungsi dengan benar, Anda harus menyelesaikan beberapa langkah … ").
- Jika mesin batasan UX mengizinkan (lihat UX_RESTRICTIONS_NO_SETUP), tanyakan kepada pengguna apakah mereka ingin memulai proses penyiapan, lalu buka layar Setelan untuk VIA.
- Jika tidak (misalnya, jika pengguna sedang mengemudi), biarkan notifikasi agar pengguna mengklik opsi tersebut saat aman untuk melakukannya.
Membuat layar penyiapan interaksi suara
Layar penyiapan dan login harus dikembangkan sebagai aktivitas reguler. Lihat panduan UX dan visual untuk pengembangan UI di Asisten yang Dimuat Sebelumnya: Panduan UX.
Panduan umum:
- VIA harus memungkinkan pengguna untuk mengganggu 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 cocok 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
Gambar 4. Integrasi setelan
Layar setelan adalah aktivitas Android reguler. Jika diterapkan, titik entrinya
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 tidak menyelesaikannya) atau menawarkan opsi logout atau ganti pengguna jika diperlukan. Serupa dengan layar
Penyiapan yang dijelaskan di atas, layar ini harus:
- Berikan opsi untuk keluar kembali ke layar sebelumnya dalam kelompok 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.
Mendeklarasikan 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 ditandatangani sistem dan telah diinstal sebelumnya. Pengguna tidak dapat memberikan izin ini, hanya OEM yang dapat memberikannya saat mem-build image sistem. Untuk 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 beberapa izin ini secara default ke VoiceInteractionService. Namun, mengingat setelan default ini dapat berubah dari perangkat ke perangkat, aplikasi harus dapat meminta izin ini jika diperlukan.
- Izin lainnya. Ini adalah semua izin lain yang tidak memerlukan intervensi pengguna. Izin ini 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 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()
reguler (atau yang setara). Untuk mengetahui detail tentang cara meminta izin, lihat
Meminta Izin Aplikasi.
Gambar 5. Meminta izin
Izin pemroses notifikasi
Untuk menerapkan alur TTR, VIA harus ditetapkan sebagai pemroses notifikasi. Ini bukan izin per se, tetapi merupakan konfigurasi yang memungkinkan sistem mengirim notifikasi ke pemroses terdaftar. Untuk mengetahui apakah VIA diberi akses ke informasi ini, aplikasi dapat:
- (Opsional) Periksa apakah ada pemroses notifikasi terlebih dahulu dengan menggunakan
CarAssistUtils#assistantIsNotificationListener()
. Hal ini dapat dilakukan, misalnya, selama alur penyiapan. - (Wajib) Bereaksi terhadap penanganan
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 Notifikasi di Setelan Mobil, menggunakan kombinasi ucapan dan notifikasi. Kode berikut dapat digunakan untuk membuka bagian aplikasi setelan yang sesuai:
private void requestNotificationListenerAccess() { Intent intent = new Intent(Settings .ACTION_NOTIFICATION_LISTENER_SETTINGS); intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); startActivity(intent); }
Mengimplementasikan 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 Dimuat Sebelumnya: Panduan UX.
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 aktif. Aplikasi harus mengganti VoiceInteractionSession#onCreateContentView()
dan menampilkan tampilan yang dilampirkan ke jendela tersebut segera setelah sesi
dibuat. Tampilan ini awalnya tidak akan terlihat. Saat interaksi suara dimulai,
tampilan ini harus terlihat di VoiceInteractionSession#onShow()
lalu 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, sebaiknya sesuaikan VoiceInteractionSession#onComputeInsets()
untuk memperhitungkan area UI yang diburamkan.
Menggunakan startAssistantActivity()
Dalam hal ini, VoiceInteractionSession
mendelegasikan penanganan UI
plat suara ke aktivitas reguler. Saat opsi ini digunakan, implementasi VoiceInteractionSession
harus menonaktifkan pembuatan jendela konten defaultnya (lihat Menggunakan onCreateContentView()) pada callback
onPrepareShow()
. Di VoiceInteractionSession#onShow()
, sesi akan memulai aktivitas
plat suara 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 binding layanan mungkin
diperlukan. Misalnya, saat VoiceInteractionSession#onHide()
dipanggil, sesi harus dapat meneruskan permintaan ini ke aktivitas.
Penting. Di Automotive, hanya aktivitas yang dianotasi secara 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
menambahkan anotasi pada aktivitas dengan <meta-data
android:name="distractionOptimized" android:value="true"/>
atau menyertakan
aktivitas ini dalam kunci systemActivityWhitelist
file
/packages/services/Car/service/res/values/config.xml
. Untuk informasi selengkapnya, lihat Pedoman Distraksional
Pengemudi.
Mengimplementasikan pengenalan suara
Di bagian ini, Anda akan mempelajari cara menerapkan pengenalan suara melalui deteksi dan pengenalan kata kunci. Kata kunci 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 level DSP melalui
AlwaysOnHotwordDetector
.
cara menerapkan deteksi frasa pengaktif dengan CPU rendah. Penggunaan fungsi ini dibagi menjadi dua bagian:
- Pembuatan instance
AlwaysOnHotwordDetector
. - Pendaftaran model suara deteksi frasa pengaktif.
Implementasi VoiceInteractionService dapat membuat detektor kata panas menggunakan
VoiceInteractionService#createAlwaysOnHotwordDetector()
,
yang 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 tidak tersedia secara umum, 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 siap dan dapat dimulai dengan memanggil metodestartRecognition()
.STATE_HARDWARE_UNENROLLED
. Model suara untuk frasa kunci yang diminta tidak tersedia, tetapi pendaftaran dapat dilakukan.
Pendaftaran model suara deteksi frasa pengaktif dapat dilakukan 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 contoh kode yang menunjukkan
cara mendaftarkan model suara, lihat VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
.
Lihat Perekaman serentak terkait
pengenalan kata cepat serentak.
Deteksi frasa pengaktif software
Seperti yang ditunjukkan di atas, deteksi kata kunci panas 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:
- Perekaman audio harus menggunakan MediaRecorder.AudioSource.HOTWORD.
- Memiliki izin
android.Manifest.permission.CAPTURE_AUDIO_HOTWORD
.
Kedua konstanta ini adalah @hide
dan hanya tersedia untuk aplikasi yang dipaketkan.
Mengelola input audio dan pengenalan suara
Input audio akan diterapkan menggunakan class MediaRecorder.
Untuk informasi selengkapnya tentang cara menggunakan API ini, lihat Ringkasan MediaRecorder. Layanan interaksi suara juga diharapkan menjadi implementasi
class RecognitionService
. Setiap aplikasi dalam sistem yang memerlukan pengenalan suara menggunakan
untuk mengakses kemampuan ini. Untuk melakukan pengenalan suara dan memiliki akses ke mikrofon, VIA
harus menyimpan android.permission.RECORD_AUDIO
.
Aplikasi yang mengakses penerapan
RecognitionService
juga diharapkan memiliki izin ini.
Sebelum Android 10, akses mikrofon hanya diberikan ke satu aplikasi sekaligus (kecuali deteksi kata kunci panas, 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:
- 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
. Perhatikan bahwa beberapa aplikasi media mungkin tidak bereaksi dengan benar terhadap perintah media (lihat Memenuhi Perintah Media) saat fokus audionya dihapus.