Membuat aplikasi navigasi

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

Bagian ini menjelaskan berbagai fitur library yang dapat Anda manfaatkan untuk menerapkan fungsi aplikasi navigasi belokan demi belokan.

Mendeklarasikan dukungan navigasi dalam manifes Anda

Aplikasi navigasi Anda harus mendeklarasikan kategori aplikasi mobil androidx.car.app.category.NAVIGATION dalam filter intent CarAppService-nya:

<application>
    ...
   <service
       ...
        android:name=".MyNavigationCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.NAVIGATION"/>
      </intent-filter>
    </service>
    ...
<application>

Mendukung intent navigasi

Untuk mendukung Intent navigasi ke aplikasi Anda, termasuk intent yang berasal dari Asisten Google menggunakan kueri suara, aplikasi Anda perlu menangani intent CarContext.ACTION_NAVIGATE dalam Session.onCreateScreen dan Session.onNewIntent-nya.

Lihat dokumentasi CarContext.startCarApp untuk detail tentang format intent.

Mengakses template navigasi

Aplikasi navigasi dapat mengakses template berikut yang dirancang khusus untuk aplikasi navigasi. Semua template ini menampilkan permukaan di latar belakang yang dapat diakses oleh aplikasi Anda untuk menggambar peta Anda, beserta informasi lain yang disediakan oleh aplikasi Anda yang bervariasi per template.

  • NavigationTemplate: menampilkan peta bersama dengan pesan informasi opsional atau petunjuk pemilihan rute dan perkiraan perjalanan selama navigasi aktif.
  • PlaceListNavigationTemplate: menampilkan daftar tempat yang dapat digambar dengan penanda yang sesuai di peta.
  • RoutePreviewNavigationTemplate: menampilkan daftar rute yang salah satunya dapat dipilih dan disorot di peta.

Untuk detail selengkapnya tentang cara mendesain antarmuka pengguna aplikasi navigasi menggunakan template tersebut, lihat Panduan Desain Library Aplikasi Android untuk Mobil.

Untuk mendapatkan akses ke template navigasi, aplikasi Anda harus mendeklarasikan izin androidx.car.app.NAVIGATION_TEMPLATES di AndroidManifest.xml:

<uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>

Menggambar Peta

Aplikasi navigasi dapat mengakses Surface untuk menggambar peta pada template yang relevan.

Objek SurfaceContainer kemudian dapat diakses dengan menyetel instance SurfaceCallback ke layanan mobil AppManager:

Kotlin

carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)

Java

carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

SurfaceCallback memberikan callback saat SurfaceContainer tersedia bersama dengan callback lainnya saat properti Surface berubah.

Agar dapat mengakses ke permukaan, aplikasi Anda harus mendeklarasikan izin androidx.car.app.ACCESS_SURFACE dalam AndroidManifest.xml-nya:

<uses-permission android:name="androidx.car.app.ACCESS_SURFACE"/>

Area peta yang terlihat

Host dapat menggambar elemen antarmuka pengguna untuk berbagai template di atas peta. Host akan mengomunikasikan area yang dijamin tidak akan kosong dan sepenuhnya terlihat oleh pengguna dengan memanggil metode SurfaceCallback.onVisibleAreaChanged. Selain itu, untuk meminimalkan jumlah perubahan, host juga akan memanggil metode SurfaceCallback.onStableAreaChanged dengan kotak terkecil yang akan 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, akan ada callback ke onStableAreaChanged dan onVisibleAreaChanged dengan kotak yang sama. Jika strip tindakan disembunyikan, hanya onVisibleAreaChanged yang akan dipanggil dengan area yang lebih besar. Jika pengguna berinteraksi dengan layar, sekali lagi hanya onVisibleAreaChanged yang dipanggil dengan kotak pertama.

Mode gelap

Aplikasi navigasi harus menggambar ulang peta ke instance Surface dengan warna gelap yang sesuai saat host menentukan bahwa kondisi menjaminnya, seperti yang dijelaskan dalam pedoman kualitas aplikasi Android Auto.

Untuk memutuskan apakah Anda harus menggambar peta gelap, Anda dapat menggunakan metode CarContext.isDarkMode. Setiap kali status mode gelap berubah, Anda akan menerima panggilan ke Session.onCarConfigurationChanged.

Aplikasi navigasi harus mengomunikasikan metadata navigasi tambahan dengan host. Host menggunakan informasi tersebut untuk menyediakan informasi bagi head unit kendaraan dan untuk mencegah aplikasi navigasi bentrok karena menggunakan resource bersama.

Metadata navigasi disediakan melalui layanan mobil NavigationManager yang dapat diakses dari CarContext:

Kotlin

val navigationManager = carContext.getCarService(NavigationManager::class.java)

Java

NavigationManager navigationManager = carContext.getCarService(NavigationManager.class);

Memulai, mengakhiri, dan menghentikan navigasi

Agar dapat mengelola beberapa aplikasi navigasi, notifikasi pemilihan rute, dan data cluster kendaraan, host harus mengetahui status navigasi saat ini. Saat pengguna memulai navigasi, aplikasi harus memanggil NavigationManager.navigationStarted. Demikian pula, saat navigasi berakhir, misalnya saat pengguna tiba di tujuan atau pengguna membatalkan navigasi, aplikasi harus memanggil NavigationManager.navigationEnded.

Anda hanya boleh memanggil NavigationManager.navigationEnded saat pengguna selesai menavigasi. Misalnya, jika Anda perlu menghitung ulang rute di tengah perjalanan, gunakan Trip.Builder.setLoading(true) sebagai gantinya.

Terkadang, host memerlukan aplikasi untuk menghentikan navigasi dan memanggil stopNavigation dalam objek NavigationManagerListener yang disediakan oleh aplikasi Anda melalui NavigationManager.setListener. Aplikasi harus berhenti menampilkan informasi belokan berikutnya dalam tampilan cluster, notifikasi navigasi, dan panduan suara.

Informasi perjalanan

Selama navigasi aktif, aplikasi harus memanggil NavigationManager.updateTrip. Informasi yang diberikan dalam panggilan ini akan digunakan di cluster kendaraan dan heads-up display. Tidak semua informasi dapat ditampilkan kepada pengguna bergantung pada kendaraan tertentu yang sedang dikemudikan. Misalnya, Head Unit Desktop menampilkan Step yang ditambahkan ke Trip, tetapi tidak menampilkan informasi Destination.

Untuk menguji apakah informasi tersebut telah menjangkau cluster, alat Head Unit Desktop (DHU) dapat dikonfigurasi untuk menampilkan tampilan cluster sederhana. Buat file cluster.ini dengan konten berikut:

[general]
instrumentcluster = true

Kemudian, Anda dapat memanggil DHU dengan parameter command line tambahan:

dhu -c cluster.ini

Menyesuaikan TravelEstimate dengan teks dan/atau ikon

Untuk menyesuaikan estimasi perjalanan dengan teks dan/atau ikon, gunakan metode setTripIcon dan/atau setTripText TravelEstimate.Builder. NavigationTemplate menggunakan TravelEstimate untuk menyetel teks dan ikon secara opsional, atau sebagai pengganti perkiraan waktu tiba, waktu tersisa, dan jarak tersisa.

Gambar 1. Estimasi perjalanan dengan teks dan ikon khusus

Cuplikan berikut menggunakan metode setTripIcon dan setTripText TravelEstimate.Builder untuk menyesuaikan estimasi perjalanan:

Kotlin

TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build()

Java

new TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build();

Notifikasi belokan demi belokan

Petunjuk navigasi belokan demi belokan (TBT) dapat diberikan dengan notifikasi navigasi yang sering diperbarui. Agar diperlakukan sebagai notifikasi navigasi di layar mobil, builder notifikasi Anda harus melakukan hal berikut:

  1. Tandai notifikasi sebagai sedang berlangsung dengan metode NotificationCompat.Builder.setOngoing.
  2. Tetapkan kategori notifikasi ke Notification.CATEGORY_NAVIGATION.
  3. Perluas notifikasi dengan CarAppExtender.

Notifikasi navigasi akan ditampilkan di widget rel di bagian bawah layar mobil. Jika tingkat kepentingan notifikasi disetel ke IMPORTANCE_HIGH, notifikasi juga akan ditampilkan sebagai notifikasi pendahuluan (HUN). Jika nilai penting tidak ditetapkan dengan metode CarAppExtender.Builder.setImportance, nilai penting saluran notifikasi akan digunakan.

Aplikasi dapat menyetel PendingIntent di CarAppExtender yang akan dikirim ke aplikasi saat pengguna mengetuk HUN atau widget rel.

Jika NotificationCompat.Builder.setOnlyAlertOnce dipanggil dengan nilai true, notifikasi dengan nilai penting yang tinggi akan dikirim hanya sekali di HUN.

Cuplikan berikut ini menunjukkan cara membuat notifikasi navigasi:

Kotlin

NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    Intent(ACTION_OPEN_APP).setComponent(
                        ComponentName(context, MyNotificationReceiver::class.java)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build()

Java

new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    new Intent(ACTION_OPEN_APP).setComponent(
                        new ComponentName(context, MyNotificationReceiver.class)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build();

Panduan untuk notifikasi belokan demi belokan

Aplikasi navigasi harus memperbarui notifikasi TBT secara teratur tentang perubahan jarak, yang memperbarui widget rel, dan hanya menampilkan notifikasi sebagai HUN. Aplikasi dapat mengontrol perilaku HUN dengan menetapkan nilai penting notifikasi dengan metode CarAppExtender.Builder.setImportance. Menetapkan nilai penting ke IMPORTANCE_HIGH akan menampilkan HUN, dan menyetelnya ke nilai lain hanya akan memperbarui widget kolom samping.

Memuat ulang konten PlaceListNavigationTemplate

Anda dapat mengizinkan pengemudi memuat ulang konten dengan mengetuk tombol saat menjelajahi daftar tempat yang dibuild dengan PlaceListNavigationTemplate. Implementasikan metode onContentRefreshRequested antarmuka OnContentRefreshListener, lalu gunakan PlaceListNavigationTemplate.Builder.setOnContentRefreshListener untuk menetapkan pemroses pada template guna mengaktifkan muat ulang daftar.

Cuplikan berikut menunjukkan setelan pemroses pada template:

Kotlin

PlaceListNavigationTemplate.Builder()
    ...
    .setOnContentRefreshListener {
        // Execute any desired logic
        ...
        // Then call invalidate() so onGetTemplate() is called again
        invalidate()
    }
    .build()

Java

new PlaceListNavigationTemplate.Builder()
        ...
        .setOnContentRefreshListener(() -> {
            // Execute any desired logic
            ...
            // Then call invalidate() so onGetTemplate() is called again
            invalidate();
        })
        .build();

Tombol muat ulang hanya ditampilkan dalam header PlaceListNavigationTemplate jika pemroses memiliki nilai.

Saat pengemudi mengklik tombol muat ulang, metode onContentRefreshRequested dari implementasi OnContentRefreshListener Anda akan dipanggil. Dalam onContentRefreshRequested, panggil metode Screen.invalidate. Host kemudian memanggil kembali ke metode Screen.onGetTemplate aplikasi untuk mengambil template dengan konten yang dimuat ulang. Lihat Memuat ulang konten template untuk informasi selengkapnya tentang memuat ulang template. Asalkan template berikutnya yang ditampilkan oleh onGetTemplate memiliki jenis yang sama, template tersebut dianggap sebagai pemuatan ulang dan tidak termasuk dalam template kuota.

Panduan suara

Untuk memutar panduan navigasi melalui speaker mobil, aplikasi Anda harus meminta fokus audio. Sebagai bagian dari AudioFocusRequest, Anda harus menyetel penggunaan sebagai AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE. Anda juga harus menyetel peningkatan fokus sebagai AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.

Menyimulasikan navigasi

Untuk memverifikasi fungsi navigasi aplikasi Anda saat mengirimkannya ke Google Play Store, aplikasi Anda harus menerapkan callback NavigationManagerCallback.onAutoDriveEnabled. Saat callback ini dipanggil, aplikasi Anda harus menyimulasikan navigasi ke tujuan yang dipilih saat pengguna memulai navigasi. Aplikasi Anda dapat keluar dari mode ini setiap kali siklus proses Session saat ini mencapai status Lifecycle.Event.ON_DESTROY.

Anda dapat menguji apakah implementasi onAutoDriveEnabled dipanggil dengan menjalankan perintah berikut dari command line:

adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE

Contoh:

adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE

Aplikasi mobil navigasi default

Di Android Auto, aplikasi mobil navigasi default sesuai dengan aplikasi navigasi terakhir yang diluncurkan pengguna. Ini adalah aplikasi yang, misalnya, akan menerima intent navigasi saat pengguna memanggil perintah navigasi melalui asisten atau saat aplikasi lain mengirim intent untuk memulai navigasi.

Mengizinkan pengguna untuk berinteraksi dengan peta Anda

Anda dapat menambahkan dukungan bagi pengguna untuk berinteraksi dengan peta, misalnya, memperbesar/memperkecil dan menggeser peta, sehingga pengguna dapat melihat berbagai bagian peta. Setiap template memiliki persyaratan minimum yang berbeda untuk API Level Aplikasi Mobil. Lihat tabel di bawah ini untuk level minimum template yang ingin Anda implementasikan.

TemplateInteraktivitas didukung sejak API Level Aplikasi Mobil
NavigationTemplate2
PlaceListNavigationTemplate4
RoutePreviewNavigationTemplate4
MapTemplate5

Metode SurfaceCallback

SurfaceCallback memiliki beberapa metode callback yang memungkinkan Anda menambahkan interaktivitas peta ke peta Anda yang dibuat dengan NavigationTemplate, PlaceListNavigationTemplate, RoutePreviewNavigationTemplate, atau template MapTemplate: onClick, onScroll, onScale, dan onFling. Lihat tabel di bawah untuk mengetahui kaitan callback ini dengan interaksi pengguna.

Interaksi Metode SurfaceCallback Didukung sejak API level Aplikasi Mobil
Ketuk onClick 5
Cubit (zoom) onScale 2
Tarik dengan satu sentuhan onScroll 2
Ayunkan 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

Strip tindakan peta

Template NavigationTemplate, PlaceListNavigationTemplate, RoutePreviewNavigationTemplate, dan MapTemplate dapat memiliki strip tindakan peta untuk tindakan terkait peta seperti memperbesar dan memperkecil, memusatkan kembali, menampilkan kompas, atau tindakan lain yang dapat Anda pilih untuk ditampilkan oleh aplikasi. Strip tindakan peta dapat memiliki hingga empat tombol khusus ikon yang dapat dimuat ulang tanpa memengaruhi kedalaman tugas. Serupa dengan Strip Tindakan, strip tindakan peta akan 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. Jika aplikasi Anda menghilangkan tombol Action.PAN di strip tindakan peta, Anda tidak akan menerima input pengguna dari metode SurfaceCallback dan host akan keluar dari mode geser yang diaktifkan sebelumnya. Saat pengguna menekan tombol geser, host akan memasuki mode geser. Di layar sentuh, tombol geser tidak akan ditampilkan.

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.

Area stabil

Area stabil diperbarui antara status tidak ada aktivitas dan aktif. Aplikasi Anda harus mengambil informasi terkait mengemudi seperti kecepatan, batas kecepatan, atau peringatan jalan, bergantung pada ukuran area stabil, sehingga informasi penting pada peta tidak terhalang oleh strip tindakan peta.

Notifikasi navigasi dalam konteks

Alert menampilkan informasi penting kepada pengemudi dengan tindakan opsional, tanpa keluar dari konteks layar navigasi. Untuk memberikan pengalaman terbaik kepada pengemudi, Alert berfungsi di dalam NavigationTemplate untuk menghindari pemblokiran rute navigasi dan untuk meminimalkan gangguan bagi pengemudi.

Alert hanya tersedia dalam NavigationTemplate. Untuk memberi tahu pengguna di luar NavigationTemplate, pertimbangkan untuk menggunakan notifikasi pendahuluan (HUN) seperti yang dijelaskan dalam Notifikasi tampilan.

Misalnya, gunakan Alert untuk:

  • Memberi tahu pengemudi tentang informasi terbaru yang relevan dengan navigasi saat ini, seperti perubahan kondisi lalu lintas.
  • Meminta pengemudi untuk memberikan informasi terbaru terkait navigasi saat ini, seperti adanya alat pengukur kecepatan.
  • Mengusulkan tugas mendatang dan menanyakan apakah pengemudi akan menerima atau tidak, misalnya apakah pengemudi bersedia menjemput seseorang dalam perjalanan mereka.

Dalam bentuk dasarnya, Alert terdiri dari judul dan waktu durasi Alert. Waktu durasi direpresentasikan oleh status progres. Jika ingin, Anda dapat menambahkan subtitel, ikon, dan maksimal dua Action.

Gambar 1. Notifikasi navigasi dalam konteks

Setelah ditampilkan, Alert tidak akan dibawa ke template lain jika interaksi pengemudi mengakibatkan NavigationTemplate keluar. Data tetap dalam versi NavigationTemplate asli hingga waktu tunggu Alert habis, pengguna mengambil tindakan, atau aplikasi menutup Alert.

Mengonfigurasi durasi notifikasi

Pilih durasi Alert yang sesuai dengan kebutuhan aplikasi Anda. Durasi yang direkomendasikan untuk navigasi Alert adalah 10 detik. Baca Panduan Desain Android untuk Mobil guna mendapatkan panduan.

Membuat notifikasi

Gunakan Alert.Builder untuk membuat instance Alert.

Kotlin

Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build()

Java

new Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build();

Jika Anda ingin memproses pembatalan atau penutupan Alert, buat implementasi antarmuka AlertCallback. Jalur panggilan AlertCallback adalah:

Menampilkan notifikasi

Untuk menampilkanAlert, panggil metode AppManager.showAlert yang tersedia melalui CarContext aplikasi Anda.

// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)

Menutup notifikasi

Meskipun Alert otomatis ditutup karena waktu tunggu habis atau interaksi pengemudi, Anda juga dapat menutup Alert secara manual. Misalnya, Anda ingin menutup Alert karena informasinya sudah tidak berlaku. Untuk menutup Alert, panggil metodedismissAlert dengan alertId dari Alert.

// Dismiss the same alert
carContext.getCarService(AppManager.class).dismissAlert(alert.getId())

Memanggil dismissAlert dengan alertId yang tidak cocok dengan Alert yang saat ini ditampilkan (jika ada), tidak akan melakukan apa pun. (Perintah ini tidak memberikan pengecualian).