Library Aplikasi Android untuk Mobil memungkinkan Anda menghadirkan aplikasi navigasi, lokasi menarik (POI), dan Internet of Things (IOT) ke mobil. Hal ini dilakukan dengan menyediakan serangkaian template yang dirancang untuk memenuhi standar gangguan bagi pengemudi dan menangani detail seperti berbagai faktor layar mobil dan modalitas input.
Panduan ini memberikan ringkasan fitur dan konsep utama library serta memandu Anda dalam proses menyiapkan aplikasi dasar.
Sebelum memulai
- Tinjau halaman Design for Driving
yang membahas Library Aplikasi Mobil
- Ringkasan kategori Aplikasi navigasi dan Aplikasi terkait mengemudi lainnya
- Ringkasan Membangun aplikasi dengan template
- Elemen penyusun yang mencakup Template dan Komponen template
- Contoh alur yang menunjukkan pola UX umum
- Persyaratan aplikasi template
- Tinjau istilah dan konsep utama di bagian berikut.
- Pelajari UI Sistem Android Auto dan desain Android Automotive OS.
- Tinjau Catatan Rilis.
- Tinjau Contoh.
Istilah dan konsep utama
- Model dan Template
- Antarmuka pengguna direpresentasikan oleh grafik objek model yang dapat diatur bersama dengan berbagai cara, seperti yang diizinkan oleh template yang mencakupnya. Template adalah subset model yang dapat bertindak sebagai root dalam grafik tersebut. Model mencakup informasi yang akan ditampilkan kepada pengguna dalam bentuk teks dan gambar, serta atribut untuk mengonfigurasi aspek tampilan visual informasi tersebut—misalnya, warna teks atau ukuran gambar. Host mengonversi model menjadi tampilan yang dirancang untuk memenuhi standar gangguan bagi pengemudi dan menangani detail seperti berbagai faktor layar mobil dan modalitas input.
- Host
- Host adalah komponen backend yang mengimplementasikan fungsi yang ditawarkan oleh API library sehingga aplikasi Anda dapat berjalan di mobil. Tanggung jawab host berkisar dari menemukan aplikasi Anda dan mengelola siklus prosesnya hingga mengubah model Anda menjadi tampilan dan memberi tahu aplikasi Anda tentang interaksi pengguna. Pada perangkat seluler, host ini diimplementasikan oleh Android Auto. Di Android Automotive OS, host ini diinstal sebagai aplikasi sistem.
- Batasan template
- Berbagai template menerapkan pembatasan pada konten model mereka. Misalnya, template daftar memiliki batasan jumlah item yang dapat ditampilkan kepada pengguna. Template juga memiliki batasan dalam cara terhubung untuk membentuk alur tugas. Misalnya, aplikasi hanya dapat mengirim hingga lima template ke stack layar. Lihat Pembatasan template untuk detail selengkapnya.
Screen
Screen
adalah class yang disediakan oleh library yang diterapkan aplikasi untuk mengelola antarmuka pengguna yang ditampilkan kepada pengguna.Screen
memiliki siklus proses dan menyediakan mekanisme bagi aplikasi untuk mengirim template agar ditampilkan saat layar terlihat. InstanceScreen
juga dapat didorong dan muncul ke dan dari stackScreen
, yang memastikan mematuhi batasan alur template.CarAppService
CarAppService
adalah classService
abstrak yang harus diterapkan dan diekspor aplikasi Anda agar dapat ditemukan dan dikelola oleh host.CarAppService
aplikasi Anda bertanggung jawab untuk memvalidasi bahwa koneksi host dapat dipercaya menggunakancreateHostValidator
lalu menyediakan instanceSession
untuk setiap koneksi menggunakanonCreateSession
.Session
Session
adalah class abstrak yang harus diimplementasikan dan ditampilkan oleh aplikasi Anda menggunakanCarAppService.onCreateSession
. Panel ini berfungsi sebagai titik entri untuk menampilkan informasi di layar mobil. Class ini memiliki siklus proses yang menginformasikan status aplikasi Anda saat ini di layar mobil, seperti saat aplikasi Anda terlihat atau tersembunyi.Saat
Session
dimulai, seperti saat aplikasi pertama kali diluncurkan, host memintaScreen
awal untuk ditampilkan menggunakan metodeonCreateScreen
.
Menginstal Library Aplikasi Mobil
Lihat halaman rilis library Jetpack untuk mendapatkan petunjuk tentang cara menambahkan library ke aplikasi Anda.
Mengonfigurasi file manifes aplikasi Anda
Sebelum dapat membuat aplikasi mobil, konfigurasikan file manifes aplikasi Anda seperti berikut.
Mendeklarasikan CarAppService Anda
Host terhubung ke aplikasi Anda melalui
implementasi CarAppService
. Anda
mendeklarasikan layanan ini dalam manifes untuk memungkinkan host menemukan dan terhubung
ke aplikasi Anda.
Anda juga harus mendeklarasikan kategori aplikasi Anda dalam
elemen <category>
dari filter intent
aplikasi Anda. Lihat daftar
kategori aplikasi yang didukung untuk nilai yang diizinkan untuk
elemen ini.
Cuplikan kode berikut menunjukkan cara mendeklarasikan layanan aplikasi mobil untuk aplikasi lokasi menarik dalam manifes Anda:
<application>
...
<service
...
android:name=".MyCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService"/>
<category android:name="androidx.car.app.category.POI"/>
</intent-filter>
</service>
...
<application>
Kategori aplikasi yang didukung
Deklarasikan kategori aplikasi Anda dengan menambahkan satu atau beberapa nilai kategori
berikut dalam filter intent saat Anda mendeklarasikan CarAppService
seperti yang dijelaskan
di bagian sebelumnya:
androidx.car.app.category.NAVIGATION
: aplikasi yang menyediakan rute navigasi belokan demi belokan. Lihat Membangun aplikasi navigasi untuk mobil guna dokumentasi tambahan tentang kategori ini.androidx.car.app.category.POI
: aplikasi yang menyediakan fungsi yang relevan untuk menemukan lokasi menarik seperti tempat parkir, SPKLU, dan SPBU. Lihat Membuat aplikasi lokasi menarik untuk mobil untuk dokumentasi tambahan tentang kategori ini.androidx.car.app.category.IOT
: Aplikasi yang memungkinkan pengguna mengambil tindakan yang relevan di perangkat terhubung dari dalam mobil. Lihat Membangun aplikasi Internet of Things untuk mobil untuk dokumentasi tambahan tentang kategori ini.
Lihat Kualitas aplikasi Android untuk mobil guna mengetahui deskripsi mendetail tentang setiap kategori dan kriteria untuk aplikasi terkait.
Menentukan nama dan ikon aplikasi
Anda perlu menentukan nama dan ikon aplikasi yang dapat digunakan oleh host untuk mewakili aplikasi Anda di UI sistem.
Anda dapat menentukan nama dan ikon aplikasi yang digunakan untuk mewakili aplikasi Anda menggunakan
atribut label
dan
icon
dari
CarAppService
Anda:
...
<service
android:name=".MyCarAppService"
android:exported="true"
android:label="@string/my_app_name"
android:icon="@drawable/my_app_icon">
...
</service>
...
Jika label atau ikon tidak dideklarasikan dalam
elemen <service>
, host
akan kembali ke nilai yang ditentukan untuk
elemen <application>
.
Menetapkan tema kustom
Guna menetapkan tema kustom untuk aplikasi mobil Anda, tambahkan
elemen <meta-data>
dalam
file manifes Anda, seperti berikut:
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
Kemudian, deklarasikan resource gaya guna menetapkan atribut berikut untuk tema aplikasi mobil kustom Anda:
<resources> <style name="MyCarAppTheme"> <item name="carColorPrimary">@layout/my_primary_car_color</item> <item name="carColorPrimaryDark">@layout/my_primary_dark_car_color</item> <item name="carColorSecondary">@layout/my_secondary_car_color</item> <item name="carColorSecondaryDark">@layout/my_secondary_dark_car_color</item> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
API Level Aplikasi Mobil
Library Aplikasi Mobil menentukan level API-nya sendiri sehingga Anda dapat mengetahui
fitur library yang didukung oleh host template di kendaraan.
Untuk mengambil API Level Aplikasi Mobil tertinggi yang didukung oleh host, gunakan
metode
getCarAppApiLevel()
.
Deklarasikan API Level Aplikasi Mobil minimum yang didukung oleh aplikasi Anda di
file AndroidManifest.xml
:
<manifest ...>
<application ...>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1"/>
</application>
</manifest>
Lihat dokumentasi untuk anotasi
RequiresCarApi
guna mengetahui detail tentang cara mempertahankan kompatibilitas mundur dan mendeklarasikan
API level minimum yang diperlukan untuk menggunakan suatu fitur. Untuk definisi level API
mana yang diperlukan untuk menggunakan fitur tertentu Library Aplikasi Mobil, lihat
dokumentasi referensi untuk
CarAppApiLevels
.
Membuat CarAppService dan Sesi
Aplikasi Anda harus memperluas
class CarAppService
dan mengimplementasikan
metode
onCreateSession
-nya, yang menampilkan instance Session
yang sesuai dengan koneksi saat ini ke host:
Kotlin
class HelloWorldService : CarAppService() { ... override fun onCreateSession(): Session { return HelloWorldSession() } ... }
Java
public final class HelloWorldService extends CarAppService { ... @Override @NonNull public Session onCreateSession() { return new HelloWorldSession(); } ... }
Instance Session
bertanggung jawab
menampilkan instance Screen
untuk digunakan
saat aplikasi pertama kali dimulai:
Kotlin
class HelloWorldSession : Session() { ... override fun onCreateScreen(intent: Intent): Screen { return HelloWorldScreen(carContext) } ... }
Java
public final class HelloWorldSession extends Session { ... @Override @NonNull public Screen onCreateScreen(@NonNull Intent intent) { return new HelloWorldScreen(getCarContext()); } ... }
Untuk menangani skenario saat aplikasi mobil harus memulai dari layar yang bukan
layar utama atau halaman landing aplikasi Anda, seperti menangani deep link, Anda dapat
melakukan pra-awal data layar sebelumnya menggunakan
ScreenManager.push
sebelum kembali dari
onCreateScreen
.
Pra-seeding memungkinkan pengguna kembali ke layar sebelumnya dari layar
pertama yang ditampilkan aplikasi Anda.
Membuat layar mulai
Anda membuat layar yang ditampilkan oleh aplikasi dengan menentukan class yang memperluas
class Screen
dan menerapkan
metode
onGetTemplate
-nya, yang menampilkan
instance Template
yang mewakili
status UI untuk ditampilkan di layar mobil.
Cuplikan berikut menunjukkan cara mendeklarasikan
Screen
yang menggunakan
template PaneTemplate
untuk
menampilkan string “Halo dunia!” sederhana:
Kotlin
class HelloWorldScreen(carContext: CarContext) : Screen(carContext) { override fun onGetTemplate(): Template { val row = Row.Builder().setTitle("Hello world!").build() val pane = Pane.Builder().addRow(row).build() return PaneTemplate.Builder(pane) .setHeaderAction(Action.APP_ICON) .build() } }
Java
public class HelloWorldScreen extends Screen { @NonNull @Override public Template onGetTemplate() { Row row = new Row.Builder().setTitle("Hello world!").build(); Pane pane = new Pane.Builder().addRow(row).build(); return new PaneTemplate.Builder(pane) .setHeaderAction(Action.APP_ICON) .build(); } }
Class CarContext
Class CarContext
adalah subclass
ContextWrapper
yang dapat diakses oleh instance Session
dan
Screen
Anda. Layanan ini memberikan akses
ke layanan mobil, seperti
ScreenManager
untuk mengelola
tumpukan layar;
AppManager
untuk fungsi umum terkait
aplikasi, seperti mengakses objek Surface
untuk menggambar peta;
dan NavigationManager
yang digunakan oleh aplikasi navigasi belokan demi belokan untuk mengomunikasikan metadata
navigasi dan
peristiwa terkait lainnya
Lihat Mengakses template navigasi untuk mengetahui daftar lengkap fungsi library yang tersedia untuk aplikasi navigasi.
CarContext
juga menawarkan fungsi
lain, seperti memungkinkan Anda memuat resource drawable menggunakan konfigurasi
dari layar mobil, memulai aplikasi di mobil menggunakan intent,
dan memberi sinyal apakah aplikasi Anda harus menampilkan petanya dalam tema gelap.
Menerapkan navigasi layar
Aplikasi sering kali menyajikan sejumlah layar yang berbeda, masing-masing mungkin menggunakan template berbeda yang dapat dibuka pengguna saat berinteraksi dengan antarmuka yang ditampilkan di layar.
Class ScreenManager
menyediakan
stack layar yang dapat digunakan untuk mendorong layar yang dapat muncul secara otomatis
saat pengguna memilih tombol kembali di layar mobil atau menggunakan tombol kembali hardware
yang tersedia di beberapa mobil.
Cuplikan berikut menunjukkan cara menambahkan tindakan kembali ke template pesan serta tindakan yang mendorong layar baru saat dipilih oleh pengguna:
Kotlin
val template = MessageTemplate.Builder("Hello world!") .setHeaderAction(Action.BACK) .addAction( Action.Builder() .setTitle("Next screen") .setOnClickListener { screenManager.push(NextScreen(carContext)) } .build()) .build()
Java
MessageTemplate template = new MessageTemplate.Builder("Hello world!") .setHeaderAction(Action.BACK) .addAction( new Action.Builder() .setTitle("Next screen") .setOnClickListener( () -> getScreenManager().push(new NextScreen(getCarContext()))) .build()) .build();
Objek Action.BACK
adalah
Action
standar yang secara otomatis
memanggil ScreenManager.pop
.
Perilaku ini dapat diganti dengan menggunakan
instance OnBackPressedDispatcher
yang tersedia dari
CarContext
.
Untuk membantu memastikan aplikasi aman digunakan saat mengemudi, stack layar dapat memiliki kedalaman maksimum lima layar. Lihat bagian Pembatasan template untuk detail selengkapnya.
Memuat ulang konten template
Aplikasi Anda dapat meminta konten
Screen
dibatalkan validasinya dengan memanggil
metode Screen.invalidate
.
Host kemudian memanggil kembali ke metode
Screen.onGetTemplate
aplikasi untuk mengambil template dengan konten baru.
Saat memuat ulang Screen
, penting untuk memahami konten tertentu dalam template yang dapat diperbarui
sehingga host tidak menghitung template baru terhadap kuota template.
Lihat bagian Pembatasan template untuk detail selengkapnya.
Sebaiknya Anda menyusun layar sehingga ada pemetaan one-to-one
antara Screen
dan jenis
template yang ditampilkan melalui implementasi onGetTemplate
.
Menggambar peta
Aplikasi navigasi dan lokasi menarik (POI) yang menggunakan template berikut dapat
menggambar peta dengan mengakses Surface
:
Template | Izin template | Panduan kategori |
---|---|---|
NavigationTemplate |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigasi |
MapWithContentTemplate |
androidx.car.app.NAVIGATION_TEMPLATES ATAU androidx.car.app.MAP_TEMPLATES |
Navigasi, POI |
MapTemplate (tidak digunakan lagi) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigasi |
PlaceListNavigationTemplate (tidak digunakan lagi) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigasi |
RoutePreviewNavigationTemplate (tidak digunakan lagi) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigasi |
Mendeklarasikan izin platform
Selain izin yang diperlukan untuk template yang digunakan aplikasi,
aplikasi Anda harus mendeklarasikan izin androidx.car.app.ACCESS_SURFACE
dalam
file AndroidManifest.xml
untuk mendapatkan akses ke platform:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
...
</manifest>
Mengakses permukaan
Untuk mengakses Surface
yang disediakan oleh host, Anda harus mengimplementasikan
SurfaceCallback
dan menyediakan
implementasi tersebut ke layanan mobil
AppManager
. Surface
saat ini diteruskan ke
SurfaceCallback
Anda dalam parameter SurfaceContainer
dari
callback onSurfaceAvailable()
dan onSurfaceDestroyed()
.
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
Memahami area permukaan yang terlihat
Host dapat menggambar elemen antarmuka pengguna untuk template di atas
peta. Host mengomunikasikan area permukaan yang dipastikan
tidak terhalang dan sepenuhnya terlihat oleh pengguna dengan memanggil
metode
SurfaceCallback.onVisibleAreaChanged
. Selain itu, untuk meminimalkan jumlah perubahan, host memanggil
metode SurfaceCallback.onStableAreaChanged
dengan kotak terkecil yang selalu terlihat berdasarkan
template saat ini.
Misalnya, saat aplikasi navigasi menggunakan
NavigationTemplate
dengan strip tindakan di atasnya, strip tindakan tersebut dapat menyembunyikan
dirinya sendiri ketika pengguna tidak berinteraksi dengan layar untuk beberapa saat guna membuat lebih banyak
ruang untuk peta. Dalam hal ini, ada callback ke onStableAreaChanged
dan
onVisibleAreaChanged
dengan kotak yang sama. Jika strip tindakan disembunyikan,
hanya onVisibleAreaChanged
yang dipanggil dengan area yang lebih besar. Jika pengguna
berinteraksi dengan layar, sekali lagi hanya onVisibleAreaChanged
yang dipanggil dengan
kotak pertama.
Mendukung tema gelap
Aplikasi harus menggambar ulang peta ke instance Surface
dengan warna gelap
yang sesuai saat diperlukan oleh kondisi yang ditentukan host, seperti yang dijelaskan dalam
Kualitas aplikasi Android untuk mobil.
Untuk memutuskan apakah Anda akan menggambar peta gelap, Anda dapat menggunakan
metode
CarContext.isDarkMode
. Setiap kali status tema gelap berubah, Anda menerima panggilan ke
Session.onCarConfigurationChanged
.
Memungkinkan pengguna berinteraksi dengan peta Anda
Saat menggunakan template berikut, Anda dapat menambahkan dukungan bagi pengguna untuk berinteraksi dengan peta yang Anda gambar, seperti mengizinkan mereka melihat berbagai bagian peta dengan memperbesar/memperkecil dan menggeser.
Template | Interaktivitas yang didukung sejak API Level Aplikasi Mobil |
---|---|
NavigationTemplate |
2 |
PlaceListNavigationTemplate (tidak digunakan lagi) |
4 |
RoutePreviewNavigationTemplate (tidak digunakan lagi) |
4 |
MapTemplate (tidak digunakan lagi) |
5 (pengantar template) |
MapWithContentTemplate |
7 (pengantar template) |
Mengimplementasikan callback interaktivitas
Antarmuka SurfaceCallback
memiliki beberapa metode callback yang dapat Anda terapkan untuk menambahkan interaktivitas ke peta yang dibuat
dengan template di bagian sebelumnya:
Interaksi | Metode SurfaceCallback |
Didukung sejak API level Aplikasi Mobil |
---|---|---|
Ketuk | onClick |
5 |
Cubit untuk zoom | onScale |
2 |
Tarik dengan satu sentuhan | onScroll |
2 |
Ayunkan jari dengan satu sentuhan | onFling |
2 |
Ketuk dua kali | onScale (dengan faktor skala yang ditentukan oleh host template) |
2 |
Sentuhan putar dalam mode geser | onScroll (dengan faktor jarak yang ditentukan oleh host template) |
2 |
Menambahkan strip tindakan peta
Template ini dapat memiliki strip tindakan peta untuk tindakan terkait peta seperti memperbesar dan memperkecil, memposisikan ulang, menampilkan kompas, dan tindakan lainnya yang Anda pilih untuk ditampilkan. Strip tindakan peta dapat memiliki hingga empat tombol khusus ikon yang dapat dimuat ulang tanpa memengaruhi kedalaman tugas. Strip tindakan peta disembunyikan selama status tidak ada aktivitas dan muncul kembali saat status aktif.
Untuk menerima callback interaktivitas peta, Anda
harus menambahkan tombol Action.PAN
di strip tindakan peta. Ketika pengguna
menekan tombol geser, host akan memasuki mode geser, seperti yang dijelaskan di bagian
berikut.
Jika aplikasi Anda menghilangkan tombol Action.PAN
di strip tindakan peta, aplikasi tidak akan menerima input pengguna dari
metode SurfaceCallback
, dan host keluar dari mode geser
yang diaktifkan sebelumnya.
Di layar sentuh, tombol geser tidak ditampilkan.
Memahami mode geser
Dalam mode geser, host template menerjemahkan input pengguna dari perangkat input non-sentuh,
seperti pengontrol putar dan touchpad, ke metode
SurfaceCallback
yang sesuai. Tanggapi tindakan pengguna untuk masuk atau keluar dari mode geser
dengan metode
setPanModeListener
di NavigationTemplate.Builder
. Host dapat menyembunyikan komponen UI lainnya
di template saat pengguna berada dalam mode geser.
Berinteraksi dengan pengguna
Aplikasi Anda dapat berinteraksi dengan pengguna menggunakan pola yang mirip dengan aplikasi seluler.
Menangani input pengguna
Aplikasi Anda dapat merespons input pengguna dengan meneruskan pendengar yang sesuai ke
model yang mendukung mereka. Cuplikan berikut menunjukkan cara membuat
model Action
yang menetapkan
OnClickListener
yang
memanggil kembali ke metode yang ditentukan oleh kode aplikasi Anda:
Kotlin
val action = Action.Builder() .setTitle("Navigate") .setOnClickListener(::onClickNavigate) .build()
Java
Action action = new Action.Builder() .setTitle("Navigate") .setOnClickListener(this::onClickNavigate) .build();
Metode onClickNavigate
kemudian dapat memulai
aplikasi mobil navigasi default
dengan menggunakan
metode
CarContext.startCarApp
:
Kotlin
private fun onClickNavigate() { val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address)) carContext.startCarApp(intent) }
Java
private void onClickNavigate() { Intent intent = new Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address)); getCarContext().startCarApp(intent); }
Untuk detail selengkapnya tentang cara memulai aplikasi, termasuk format
intent ACTION_NAVIGATE
, lihat bagian
Memulai aplikasi mobil dengan intent.
Beberapa tindakan, seperti tindakan yang mengharuskan pengguna melanjutkan
interaksi di perangkat seluler, hanya diizinkan saat mobil diparkir.
Anda dapat menggunakan
ParkedOnlyOnClickListener
untuk mengimplementasikan tindakan tersebut. Jika mobil tidak diparkir, host akan menampilkan
indikasi kepada pengguna bahwa tindakan tidak diizinkan dalam kasus ini. Jika mobil
diparkir, kode akan dieksekusi seperti biasa. Cuplikan berikut menunjukkan cara
menggunakan ParkedOnlyOnClickListener
untuk membuka layar setelan di perangkat seluler:
Kotlin
val row = Row.Builder() .setTitle("Open Settings") .setOnClickListener(ParkedOnlyOnClickListener.create(::openSettingsOnPhone)) .build()
Java
Row row = new Row.Builder() .setTitle("Open Settings") .setOnClickListener(ParkedOnlyOnClickListener.create(this::openSettingsOnPhone)) .build();
Menampilkan notifikasi
Notifikasi yang dikirim ke perangkat seluler hanya muncul di layar mobil jika
diperluas dengan
CarAppExtender
.
Beberapa atribut notifikasi, seperti judul konten, teks, ikon, dan tindakan,
dapat ditetapkan di CarAppExtender
, yang menggantikan atribut notifikasi
saat muncul di layar mobil.
Cuplikan berikut menunjukkan cara mengirim notifikasi ke layar mobil yang menampilkan judul yang berbeda dari yang ditampilkan di perangkat seluler:
Kotlin
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle(titleOnThePhone) .extend( CarAppExtender.Builder() .setContentTitle(titleOnTheCar) ... .build()) .build()
Java
Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle(titleOnThePhone) .extend( new CarAppExtender.Builder() .setContentTitle(titleOnTheCar) ... .build()) .build();
Notifikasi dapat memengaruhi bagian antarmuka pengguna berikut:
- Notifikasi pendahuluan (HUN) dapat ditampilkan kepada pengguna.
- Entri di pusat notifikasi dapat ditambahkan, secara opsional dengan badge yang terlihat di rel.
- Untuk aplikasi navigasi, notifikasi dapat ditampilkan di widget kolom samping seperti yang dijelaskan dalam Notifikasi belokan demi belokan.
Anda dapat memilih cara mengonfigurasi notifikasi aplikasi untuk memengaruhi setiap
elemen antarmuka pengguna tersebut dengan menggunakan prioritas notifikasi, seperti yang dijelaskan
dalam
dokumentasi
CarAppExtender
.
Jika
NotificationCompat.Builder.setOnlyAlertOnce
dipanggil dengan nilai true
, notifikasi berprioritas tinggi hanya ditampilkan sebagai
HUN satu kali.
Untuk informasi selengkapnya tentang cara mendesain notifikasi aplikasi mobil, lihat panduan Desain Google untuk Mengemudi tentang Notifikasi.
Menampilkan toast
Aplikasi Anda dapat menampilkan toast menggunakan
CarToast
seperti yang ditunjukkan dalam cuplikan ini:
Kotlin
CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()
Java
CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();
Meminta izin
Jika aplikasi Anda memerlukan akses ke data atau tindakan yang dibatasi—misalnya,
lokasi—aturan standar izin
Android
berlaku. Untuk meminta izin, Anda dapat menggunakan
metode
CarContext.requestPermissions()
.
Manfaat menggunakan
CarContext.requestPermissions()
, dibandingkan menggunakan
API Android standar, adalah
Anda tidak perlu meluncurkan Activity
sendiri untuk
membuat dialog izin. Selain itu, Anda dapat menggunakan kode yang sama di
Android Auto dan Android Automotive OS, tanpa harus membuat
alur yang bergantung pada platform.
Mengatur gaya dialog izin di Android Auto
Di Android Auto, dialog izin untuk pengguna akan muncul di ponsel.
Secara default, tidak akan ada latar belakang di balik dialog. Untuk menetapkan latar belakang
kustom, deklarasikan tema aplikasi mobil di
file AndroidManifest.xml
dan tetapkan atribut carPermissionActivityLayout
untuk tema aplikasi mobil Anda.
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
Kemudian, setel atribut carPermissionActivityLayout
untuk tema aplikasi mobil Anda:
<resources> <style name="MyCarAppTheme"> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
Memulai aplikasi mobil dengan intent
Anda dapat memanggil metode
CarContext.startCarApp
untuk melakukan salah satu tindakan berikut:
- Buka telepon untuk menelepon.
- Mulai navigasi belokan demi belokan ke lokasi dengan aplikasi mobil navigasi default.
- Mulai aplikasi Anda sendiri dengan intent.
Contoh berikut menunjukkan cara membuat notifikasi dengan tindakan yang
membuka aplikasi Anda dengan layar yang menampilkan detail reservasi parkir.
Anda memperluas instance notifikasi dengan intent konten yang berisi
PendingIntent
yang menggabungkan intent
eksplisit ke tindakan aplikasi Anda:
Kotlin
val notification = notificationBuilder ... .extend( CarAppExtender.Builder() .setContentIntent( PendingIntent.getBroadcast( context, ACTION_VIEW_PARKING_RESERVATION.hashCode(), Intent(ACTION_VIEW_PARKING_RESERVATION) .setComponent(ComponentName(context, MyNotificationReceiver::class.java)), 0)) .build())
Java
Notification notification = notificationBuilder ... .extend( new CarAppExtender.Builder() .setContentIntent( PendingIntent.getBroadcast( context, ACTION_VIEW_PARKING_RESERVATION.hashCode(), new Intent(ACTION_VIEW_PARKING_RESERVATION) .setComponent(new ComponentName(context, MyNotificationReceiver.class)), 0)) .build());
Aplikasi Anda juga harus mendeklarasikan
BroadcastReceiver
yang
dipanggil untuk memproses intent saat pengguna memilih tindakan dalam
antarmuka notifikasi dan memanggil
CarContext.startCarApp
dengan intent yang mencakup URI data:
Kotlin
class MyNotificationReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val intentAction = intent.action if (ACTION_VIEW_PARKING_RESERVATION == intentAction) { CarContext.startCarApp( intent, Intent(Intent.ACTION_VIEW) .setComponent(ComponentName(context, MyCarAppService::class.java)) .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction))) } } }
Java
public class MyNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String intentAction = intent.getAction(); if (ACTION_VIEW_PARKING_RESERVATION.equals(intentAction)) { CarContext.startCarApp( intent, new Intent(Intent.ACTION_VIEW) .setComponent(new ComponentName(context, MyCarAppService.class)) .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction))); } } }
Terakhir, metode
Session.onNewIntent
di aplikasi Anda menangani intent ini dengan mengirim layar reservasi parkir
di stack, jika belum berada di atas:
Kotlin
override fun onNewIntent(intent: Intent) { val screenManager = carContext.getCarService(ScreenManager::class.java) val uri = intent.data if (uri != null && MY_URI_SCHEME == uri.scheme && MY_URI_HOST == uri.schemeSpecificPart && ACTION_VIEW_PARKING_RESERVATION == uri.fragment ) { val top = screenManager.top if (top !is ParkingReservationScreen) { screenManager.push(ParkingReservationScreen(carContext)) } } }
Java
@Override public void onNewIntent(@NonNull Intent intent) { ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class); Uri uri = intent.getData(); if (uri != null && MY_URI_SCHEME.equals(uri.getScheme()) && MY_URI_HOST.equals(uri.getSchemeSpecificPart()) && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment()) ) { Screen top = screenManager.getTop(); if (!(top instanceof ParkingReservationScreen)) { screenManager.push(new ParkingReservationScreen(getCarContext())); } } }
Lihat bagian Menampilkan notifikasi untuk mengetahui informasi selengkapnya tentang cara menangani notifikasi untuk aplikasi mobil.
Batasan template
Host membatasi jumlah template yang ditampilkan untuk tugas tertentu hingga maksimum lima, dengan template terakhir harus berupa salah satu jenis berikut:
Perlu diperhatikan bahwa batas ini berlaku untuk jumlah template, bukan jumlah
instance Screen
dalam stack. Misalnya,
jika aplikasi mengirim dua template saat berada di layar A, lalu mendorong layar
B, aplikasi kini dapat mengirim tiga template lainnya. Atau, jika setiap layar disusun untuk mengirim satu template, aplikasi dapat mengirim lima instance layar ke stack ScreenManager
.
Ada beberapa kasus khusus pada pembatasan ini: refresh template serta operasi kembali dan reset.
Memuat ulang template
Pembaruan konten tertentu tidak diperhitungkan terhadap batas template. Umumnya,
jika aplikasi mengirim template baru dengan jenis yang sama dan berisi
konten utama yang sama dengan template sebelumnya, template baru tidak
akan mengurangi kuota. Misalnya, memperbarui status pengalihan baris dalam
ListTemplate
tidak
mengurangi kuota. Baca dokumentasi setiap template untuk mempelajari lebih lanjut
jenis pembaruan konten yang dapat dianggap sebagai pemuatan ulang.
Operasi kembali
Untuk mengaktifkan sub-alur dalam tugas, host mendeteksi saat aplikasi memunculkan
Screen
dari stack ScreenManager
dan memperbarui
kuota yang tersisa berdasarkan jumlah template yang digunakan aplikasi untuk
mundur.
Misalnya, jika aplikasi mengirim dua template saat berada di layar A, lalu mendorong layar B dan mengirim dua template lagi, aplikasi memiliki satu kuota yang tersisa. Jika aplikasi kemudian kembali ke layar A, host akan mereset kuota ke tiga template karena aplikasi telah mundur sebanyak dua template.
Perhatikan bahwa, saat muncul kembali ke layar, aplikasi harus mengirim template dengan jenis yang sama dengan template yang terakhir dikirim oleh layar tersebut. Mengirim jenis template lainnya akan menyebabkan error. Namun, selama jenisnya tetap sama selama operasi kembali, aplikasi dapat dengan bebas mengubah konten template tanpa memengaruhi kuota.
Operasi reset
Template tertentu memiliki semantik khusus yang menandakan akhir tugas. Misalnya, NavigationTemplate
adalah tampilan yang diharapkan akan tetap berada di layar dan diperbarui dengan petunjuk
belokan demi belokan yang baru untuk konsumsi pengguna. Saat mencapai salah satu
template tersebut, host akan mereset kuota template, memperlakukan template tersebut seolah-olah
adalah langkah pertama dari tugas baru. Hal ini memungkinkan aplikasi memulai tugas baru.
Lihat dokumentasi setiap template untuk melihat template mana yang memicu reset
di host.
Jika host menerima intent untuk memulai aplikasi dari tindakan notifikasi atau dari peluncur, kuota juga akan direset. Mekanisme ini memungkinkan aplikasi memulai alur tugas baru dari notifikasi, dan akan tetap berlaku meskipun aplikasi sudah terikat dan berada di latar depan.
Lihat bagian Menampilkan notifikasi untuk detail selengkapnya tentang cara menampilkan notifikasi aplikasi di layar mobil. Lihat bagian Memulai aplikasi mobil dengan intent untuk mengetahui informasi tentang cara memulai aplikasi dari tindakan notifikasi.
API Koneksi
Anda dapat menentukan apakah aplikasi berjalan di Android Auto atau Android
Automotive OS dengan menggunakan
CarConnection
API untuk
mengambil informasi koneksi saat runtime.
Misalnya, di Session
aplikasi mobil Anda, lakukan inisialisasi CarConnection
dan
berlangganan ke update LiveData
:
Kotlin
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
Java
new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);
Dalam observer, Anda kemudian dapat bereaksi terhadap perubahan status koneksi:
Kotlin
fun onConnectionStateUpdated(connectionState: Int) { val message = when(connectionState) { CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit" CarConnection.CONNECTION_TYPE_NATIVE -> "Connected to Android Automotive OS" CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto" else -> "Unknown car connection type" } CarToast.makeText(carContext, message, CarToast.LENGTH_SHORT).show() }
Java
private void onConnectionStateUpdated(int connectionState) { String message; switch(connectionState) { case CarConnection.CONNECTION_TYPE_NOT_CONNECTED: message = "Not connected to a head unit"; break; case CarConnection.CONNECTION_TYPE_NATIVE: message = "Connected to Android Automotive OS"; break; case CarConnection.CONNECTION_TYPE_PROJECTION: message = "Connected to Android Auto"; break; default: message = "Unknown car connection type"; break; } CarToast.makeText(getCarContext(), message, CarToast.LENGTH_SHORT).show(); }
API Constraints
Mobil yang berbeda dapat memungkinkan jumlah instance
Item
yang berbeda ditampilkan kepada
pengguna pada satu waktu. Gunakan
ConstraintManager
untuk memeriksa batas konten pada saat runtime dan menetapkan jumlah item yang sesuai
dalam template Anda.
Mulai dengan mendapatkan ConstraintManager
dari CarContext
:
Kotlin
val manager = carContext.getCarService(ConstraintManager::class.java)
Java
ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);
Selanjutnya, Anda dapat membuat kueri objek ConstraintManager
yang diambil untuk batas konten
yang relevan. Misalnya, untuk mendapatkan jumlah item yang dapat ditampilkan dalam
petak, panggil
getContentLimit
dengan
CONTENT_LIMIT_TYPE_GRID
:
Kotlin
val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)
Java
int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);
Menambahkan alur login
Jika aplikasi Anda menawarkan pengalaman login bagi pengguna, Anda dapat menggunakan template seperti
SignInTemplate
dan LongMessageTemplate
dengan Aplikasi Mobil API level 2 dan yang lebih baru untuk menangani login ke aplikasi Anda di
head unit mobil.
Untuk membuat SignInTemplate
, tentukan SignInMethod
. Library
Aplikasi Mobil saat ini mendukung metode login berikut:
InputSignInMethod
untuk login dengan nama pengguna/sandi.PinSignInMethod
untuk login dengan PIN, pengguna menautkan akun dari ponsel menggunakan PIN yang ditampilkan di head unit.ProviderSignInMethod
untuk login penyedia, seperti Login dengan Google dan Sekali Ketuk.QRCodeSignInMethod
untuk login dengan kode QR, pengguna memindai kode QR untuk menyelesaikan proses login di ponsel mereka. Fitur ini tersedia dengan Car API Level 4 dan yang lebih tinggi.
Misalnya, untuk mengimplementasikan template yang mengumpulkan sandi pengguna, mulailah dengan
membuat InputCallback
untuk memproses dan memvalidasi input pengguna:
Kotlin
val callback = object : InputCallback { override fun onInputSubmitted(text: String) { // You will receive this callback when the user presses Enter on the keyboard. } override fun onInputTextChanged(text: String) { // You will receive this callback as the user is typing. The update // frequency is determined by the host. } }
Java
InputCallback callback = new InputCallback() { @Override public void onInputSubmitted(@NonNull String text) { // You will receive this callback when the user presses Enter on the keyboard. } @Override public void onInputTextChanged(@NonNull String text) { // You will receive this callback as the user is typing. The update // frequency is determined by the host. } };
InputCallback
diperlukan untuk InputSignInMethod
Builder
.
Kotlin
val passwordInput = InputSignInMethod.Builder(callback) .setHint("Password") .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD) ... .build()
Java
InputSignInMethod passwordInput = new InputSignInMethod.Builder(callback) .setHint("Password") .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD) ... .build();
Terakhir, gunakan InputSignInMethod
baru untuk membuat SignInTemplate
.
Kotlin
SignInTemplate.Builder(passwordInput) .setTitle("Sign in with username and password") .setInstructions("Enter your password") .setHeaderAction(Action.BACK) ... .build()
Java
new SignInTemplate.Builder(passwordInput) .setTitle("Sign in with username and password") .setInstructions("Enter your password") .setHeaderAction(Action.BACK) ... .build();
Menggunakan AccountManager
Aplikasi Android Automotive OS yang memiliki autentikasi harus menggunakan AccountManager karena alasan berikut:
- UX yang lebih baik dan kemudahan pengelolaan akun: Pengguna dapat mengelola semua akun mereka dengan mudah dari menu akun di setelan sistem, termasuk login dan logout.
- Pengalaman"Tamu": Karena mobil adalah perangkat bersama, OEM dapat mengaktifkan pengalaman tamu di kendaraan, yang tidak dapat ditambahkan akun.
Menambahkan varian string teks
Ukuran layar mobil yang berbeda dapat menampilkan jumlah teks yang berbeda. Dengan Aplikasi Mobil API
level 2 dan yang lebih tinggi, Anda dapat menentukan beberapa varian string teks yang paling sesuai
dengan layar. Untuk melihat tempat varian teks diterima, cari template dan
komponen yang menggunakan CarText
.
Anda dapat menambahkan varian string teks ke CarText
dengan metode CarText.Builder.addVariant()
:
Kotlin
val itemTitle = CarText.Builder("This is a very long string") .addVariant("Shorter string") ... .build()
Java
CarText itemTitle = new CarText.Builder("This is a very long string") .addVariant("Shorter string") ... .build();
Anda kemudian dapat menggunakan CarText
ini—misalnya, sebagai teks utama
GridItem
.
Kotlin
GridItem.Builder() .addTitle(itemTitle) ... .build()
Java
new GridItem.Builder() .addTitle(itemTitle) ... build();
Tambahkan string secara berurutan dari yang paling disukai ke yang paling tidak disukai—misalnya, dari terpanjang ke terpendek. Host memilih string dengan panjang yang sesuai, bergantung pada jumlah ruang yang tersedia di layar mobil.
Menambahkan CarIcons inline untuk baris
Anda dapat menambahkan ikon yang inline dengan teks untuk memperkaya daya tarik visual aplikasi Anda menggunakan
CarIconSpan
.
Lihat dokumentasi
CarIconSpan.create
untuk mengetahui informasi selengkapnya tentang cara membuat span ini. Lihat
Gaya visual
teks spantastis dengan Span untuk ringkasan tentang cara kerja gaya visual teks dengan span.
Kotlin
val rating = SpannableString("Rating: 4.5 stars") rating.setSpan( CarIconSpan.create( // Create a CarIcon with an image of four and a half stars CarIcon.Builder(...).build(), // Align the CarIcon to the baseline of the text CarIconSpan.ALIGN_BASELINE ), // The start index of the span (index of the character '4') 8, // The end index of the span (index of the last 's' in "stars") 16, Spanned.SPAN_INCLUSIVE_INCLUSIVE ) val row = Row.Builder() ... .addText(rating) .build()
Java
SpannableString rating = new SpannableString("Rating: 4.5 stars"); rating.setSpan( CarIconSpan.create( // Create a CarIcon with an image of four and a half stars new CarIcon.Builder(...).build(), // Align the CarIcon to the baseline of the text CarIconSpan.ALIGN_BASELINE ), // The start index of the span (index of the character '4') 8, // The end index of the span (index of the last 's' in "stars") 16, Spanned.SPAN_INCLUSIVE_INCLUSIVE ); Row row = new Row.Builder() ... .addText(rating) .build();
API Hardware Mobil
Mulai dari API Aplikasi Mobil level 3, Library Aplikasi Mobil memiliki API yang dapat Anda gunakan untuk mengakses properti dan sensor kendaraan.
Persyaratan
Untuk menggunakan API tersebut dengan Android Auto, mulailah dengan menambahkan dependensi pada
androidx.car.app:app-projected
ke file build.gradle
untuk modul Android
Auto Anda. Untuk Android Automotive OS, tambahkan dependensi pada
androidx.car.app:app-automotive
ke file build.gradle
untuk modul Android
Automotive OS Anda.
Selain itu, dalam file AndroidManifest.xml
, Anda harus
mendeklarasikan izin yang relevan yang diperlukan untuk
meminta data mobil yang ingin Anda gunakan. Perhatikan bahwa izin ini juga harus diberikan kepada Anda oleh pengguna. Anda dapat menggunakan
kode yang sama di Android Auto dan Android Automotive OS, daripada
harus membuat alur yang bergantung pada platform. Namun, izin yang diperlukan
berbeda.
Info Mobil
Tabel ini menjelaskan properti yang ditampilkan oleh
CarInfo
API dan
izin yang perlu Anda minta untuk menggunakannya:
Metode | Properti | Izin Android Auto | Izin Android Automotive OS | Didukung sejak API level Aplikasi Mobil |
---|---|---|---|---|
fetchModel |
Merek, model, tahun | android.car.permission.CAR_INFO |
3 | |
fetchEnergyProfile |
Jenis konektor kendaraan listrik, jenis bahan bakar | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_INFO |
3 |
fetchExteriorDimensions
Data ini hanya tersedia di beberapa kendaraan Android Automotive OS yang menjalankan API 30 atau yang lebih tinggi |
Dimensi eksterior | T/A | android.car.permission.CAR_INFO |
7 |
addTollListener
removeTollListener |
Status kartu tol, jenis kartu tol | 3 | ||
addEnergyLevelListener
removeEnergyLevelListener |
Tingkat daya baterai, tingkat bahan bakar, tingkat bahan bakar rendah, jarak yang tersisa | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_ENERGY ,android.car.permission.CAR_ENERGY_PORTS ,android.car.permission.READ_CAR_DISPLAY_UNITS
|
3 |
addSpeedListener
removeSpeedListener |
Kecepatan mentah, kecepatan tampilan (ditampilkan di layar cluster mobil) | com.google.android.gms.permission.CAR_SPEED |
android.car.permission.CAR_SPEED ,android.car.permission.READ_CAR_DISPLAY_UNITS |
3 |
addMileageListener
removeMileageListener |
Jarak odometer | com.google.android.gms.permission.CAR_MILEAGE |
Data ini tidak tersedia di Android Automotive OS untuk aplikasi yang diinstal dari Play Store. | 3 |
Misalnya, untuk mendapatkan rentang yang tersisa, buat instance objek CarInfo
, lalu buat dan daftarkan OnCarDataAvailableListener
:
Kotlin
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo val listener = OnCarDataAvailableListener<EnergyLevel> { data -> if (data.rangeRemainingMeters.status == CarValue.STATUS_SUCCESS) { val rangeRemaining = data.rangeRemainingMeters.value } else { // Handle error } } carInfo.addEnergyLevelListener(carContext.mainExecutor, listener) … // Unregister the listener when you no longer need updates carInfo.removeEnergyLevelListener(listener)
Java
CarInfo carInfo = getCarContext().getCarService(CarHardwareManager.class).getCarInfo(); OnCarDataAvailableListener<EnergyLevel> listener = (data) -> { if(data.getRangeRemainingMeters().getStatus() == CarValue.STATUS_SUCCESS) { float rangeRemaining = data.getRangeRemainingMeters().getValue(); } else { // Handle error } }; carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(), listener); … // Unregister the listener when you no longer need updates carInfo.removeEnergyLevelListener(listener);
Jangan berasumsi bahwa data dari mobil tersedia setiap saat.
Jika terjadi error, periksa status nilai yang Anda minta untuk lebih memahami mengapa data yang Anda minta tidak dapat diambil. Lihat
dokumentasi referensi untuk
mengetahui definisi class CarInfo
lengkap.
Sensor Mobil
Class CarSensors
memberi Anda akses ke akselerometer, giroskop, kompas, dan
data lokasi kendaraan. Ketersediaan nilai ini mungkin bergantung pada
OEM. Format data dari akselerometer, giroskop, dan kompas
sama seperti yang akan Anda dapatkan dari
SensorManager
API. Misalnya,
untuk memeriksa judul kendaraan:
Kotlin
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors val listener = OnCarDataAvailableListener<Compass> { data -> if (data.orientations.status == CarValue.STATUS_SUCCESS) { val orientation = data.orientations.value } else { // Data not available, handle error } } carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, carContext.mainExecutor, listener) … // Unregister the listener when you no longer need updates carSensors.removeCompassListener(listener)
Java
CarSensors carSensors = getCarContext().getCarService(CarHardwareManager.class).getCarSensors(); OnCarDataAvailableListener<Compass> listener = (data) -> { if (data.getOrientations().getStatus() == CarValue.STATUS_SUCCESS) { List<Float> orientations = data.getOrientations().getValue(); } else { // Data not available, handle error } }; carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, getCarContext().getMainExecutor(), listener); … // Unregister the listener when you no longer need updates carSensors.removeCompassListener(listener);
Untuk mengakses data lokasi dari mobil, Anda juga perlu mendeklarasikan dan meminta
izin android.permission.ACCESS_FINE_LOCATION
.
Pengujian
Untuk menyimulasikan data sensor saat melakukan pengujian di Android Auto, lihat bagian Sensor dan Konfigurasi sensor di panduan Head Unit Desktop. Untuk menyimulasikan data sensor saat melakukan pengujian di Android Automotive OS, lihat bagian Mengemulasi status hardware di panduan emulator Android Automotive OS.
Siklus proses CarAppService, Sesi, dan Layar
Class Session
dan
Screen
menerapkan
antarmuka LifecycleOwner
. Saat
pengguna berinteraksi dengan aplikasi, callback siklus proses objek Session
dan Screen
akan dipanggil, seperti yang dijelaskan dalam diagram berikut.
Siklus proses CarAppService dan Sesi
![](https://developer.android.com/static/images/training/cars/carappservice-session-lifecycle.png?authuser=3&hl=id)
Session
.Untuk detail selengkapnya, lihat dokumentasi untuk
metode
Session.getLifecycle
.
Siklus proses Layar
![](https://developer.android.com/static/images/training/cars/screen-lifecycle.png?authuser=3&hl=id)
Screen
.Untuk detail selengkapnya, lihat dokumentasi untuk
metode Screen.getLifecycle
.
Rekam dari mikrofon mobil
Dengan menggunakan
CarAppService
dan
CarAudioRecord
API aplikasi,
Anda dapat memberi aplikasi akses ke mikrofon mobil pengguna. Pengguna harus memberikan
izin kepada aplikasi Anda untuk mengakses mikrofon mobil. Aplikasi Anda dapat merekam dan
memproses input pengguna dalam aplikasi.
Izin untuk merekam
Sebelum merekam audio apa pun, Anda harus terlebih dahulu mendeklarasikan izin untuk merekam di
AndroidManifest.xml
dan meminta pengguna untuk memberikannya.
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
...
</manifest>
Anda harus meminta izin untuk merekam pada saat runtime. Lihat bagian Meminta izin untuk mengetahui detail tentang cara meminta izin di aplikasi mobil Anda.
Merekam audio
Setelah pengguna memberikan izin untuk merekam, Anda dapat merekam audio dan memproses rekaman.
Kotlin
val carAudioRecord = CarAudioRecord.create(carContext) carAudioRecord.startRecording() val data = ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) while(carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) { // Use data array // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech } carAudioRecord.stopRecording()
Java
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext()); carAudioRecord.startRecording(); byte[] data = new byte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE]; while (carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) { // Use data array // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech } carAudioRecord.stopRecording();
Fokus audio
Saat merekam dari mikrofon mobil, dapatkan fokus audio terlebih dahulu untuk memastikan bahwa media yang sedang berlangsung dihentikan. Jika Anda kehilangan fokus audio, berhenti merekam.
Berikut adalah contoh cara memperoleh fokus audio:
Kotlin
val carAudioRecord = CarAudioRecord.create(carContext) // Take audio focus so that user's media is not recorded val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) // Use the most appropriate usage type for your use case .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) .build() val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) .setAudioAttributes(audioAttributes) .setOnAudioFocusChangeListener { state: Int -> if (state == AudioManager.AUDIOFOCUS_LOSS) { // Stop recording if audio focus is lost carAudioRecord.stopRecording() } } .build() if (carContext.getSystemService(AudioManager::class.java) .requestAudioFocus(audioFocusRequest) != AudioManager.AUDIOFOCUS_REQUEST_GRANTED ) { // Don't record if the focus isn't granted return } carAudioRecord.startRecording() // Process the audio and abandon the AudioFocusRequest when done
Java
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext()); // Take audio focus so that user's media is not recorded AudioAttributes audioAttributes = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) // Use the most appropriate usage type for your use case .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) .build(); AudioFocusRequest audioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) .setAudioAttributes(audioAttributes) .setOnAudioFocusChangeListener(state -> { if (state == AudioManager.AUDIOFOCUS_LOSS) { // Stop recording if audio focus is lost carAudioRecord.stopRecording(); } }) .build(); if (getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest) != AUDIOFOCUS_REQUEST_GRANTED) { // Don't record if the focus isn't granted return; } carAudioRecord.startRecording(); // Process the audio and abandon the AudioFocusRequest when done
Library Pengujian
Library
Pengujian Android untuk Mobil menyediakan class
tambahan yang dapat Anda gunakan untuk memvalidasi perilaku aplikasi di lingkungan pengujian.
Misalnya, SessionController
memungkinkan Anda menyimulasikan koneksi ke host dan memverifikasi bahwa
Screen
dan
Template
yang benar telah dibuat dan
ditampilkan.
Lihat Contoh untuk mengetahui contoh penggunaan.
Melaporkan masalah Library Aplikasi Android untuk Mobil
Jika Anda menemukan masalah pada library, laporkan menggunakan Issue Tracker Google. Pastikan untuk mengisi semua informasi yang diminta pada template masalah.
Sebelum mengajukan masalah baru, periksa apakah masalah tersebut sudah tercantum dalam catatan rilis library atau dilaporkan dalam daftar masalah. Anda bisa berlangganan dan memberi suara pada masalah dengan mengklik bintang untuk masalah di tracker. Untuk mengetahui informasi selengkapnya, lihat Berlangganan pada topik Masalah.