Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Build apps for Cars

Build apps for Cars

Keishin Yokomaku

July 08, 2023
Tweet

More Decks by Keishin Yokomaku

Other Decks in Technology

Transcript

  1. Build apps for Cars About me ▸ Keishin Yokomaku -

    @KeithYokoma ▸ GitHub / Twitter / Stack Over fl ow ▸ Giftmall, Inc. / Android App Engineer DroidKaigi.collect { #5@Nagoya }
  2. Build apps for Cars Android Auto / Automotive OS ▸

    Android Auto ▸ ंࡌγεςϜ (Head Unit) ʹઐ༻ͷ UI Λදࣔ͢ΔϞόΠϧ୺຤ͷ࢓૊Έ ▸ ंࡌγεςϜͱϞόΠϧ୺຤͕ Android Auto ʹରԠ͍ͯ͠Δඞཁ͕͋Δ ▸ Android Automotive OS ▸ Android ϕʔεͷΠϯϑΥςΠϯϝϯτγεςϜ༻ͷ OS ▸ ं͕ Android Automotive OS Λ౥ࡌ͍ͯ͠Δඞཁ͕͋Δ DroidKaigi.collect { #5@Nagoya }
  3. ▸ ϞόΠϧ୺຤ʹ౥ࡌ͞Ε͍ͯΔ Android Auto ͕த৺ (Host) ▸ Android Auto ͕ରԠͨ͠ΞϓϦͱ΍ΓऔΓ

    (IPC) ͢Δ ▸ Android Auto ͕ंࡌγεςϜͷ UI Λ੍ޚ Build apps for Cars Android Auto DroidKaigi.collect { #5@Nagoya } Icons: https://icons8.com/icon/1oqfhfFvXU8c/starbucks
  4. Build apps for Cars Android Automotive OS DroidKaigi.collect { #5@Nagoya

    } ▸ ंʹ౥ࡌ͞Ε͍ͯΔ Android Automotive OS ͕த৺ (Host) ▸ Android Automotive OS ͸ Android ͷѥछ ▸ Google PlayStore ͔ΒΞϓϦͷΠϯετʔϧ͕Մೳ Icons: https://icons8.com/icon/1oqfhfFvXU8c/starbucks
  5. Build apps for Cars Features DroidKaigi.collect { #5@Nagoya } ▸

    Turn by turn φϏήʔγϣϯ / POI ▸ ࠶ੜίϯτϩʔϧ ▸ ϝοηʔδϯά
  6. Build apps for Cars Features DroidKaigi.collect { #5@Nagoya } ▸

    Turn by turn φϏήʔγϣϯ ▸ ໨త஍ͷݕࡧͱԻ੠Ҋ಺ ▸ ަ௨ঢ়گͷදࣔ ▸ Point of Interest (POI) ▸ ߦ͖ઌΛφϏήʔγϣϯΞϓϦʹఏڙ͢Δ Icons: https://icons8.com/icon/1oqfhfFvXU8c/starbucks
  7. Build apps for Cars Features DroidKaigi.collect { #5@Nagoya } ▸

    ࠶ੜίϯτϩʔϧ ▸ Ի੠ɾಈըϝσΟΞͷ࠶ੜ ▸ ϓϨΠϦετͷมߋ
  8. Build apps for Cars Features DroidKaigi.collect { #5@Nagoya } ▸

    ϝοηʔδϯά ▸ ৽ணϝοηʔδͷԻ੠ಡΈ্͛ ▸ Ի੠ೖྗʹΑΔฦ৴
  9. Build apps for Cars AndroidX Libraries DroidKaigi.collect { #5@Nagoya }

    ▸ φϏήʔγϣϯ / POI ▸ Car App Library ▸ ࠶ੜίϯτϩʔϧ ▸ AndroidX Media3 ▸ ϝοηʔδϯά ▸ AnroidX Core
  10. Build apps for Cars Media Playback with AndroidX Media3 DroidKaigi.collect

    { #5@Nagoya } ▸ Android Auto / Automotive OS ରԠͰ࢖͏ओཁͳΫϥε ▸ MediaBrowserServiceCompat ▸ MediaSessionCompat ▸ MediaControllerCompat
  11. Build apps for Cars Media Playback with AndroidX Media3 DroidKaigi.collect

    { #5@Nagoya } ▸ MediaBrowserServiceCompat ▸ ΞϓϦ಺ʹ͋Δ࠶ੜՄೳͳϝσΟΞίϯςϯπͷ৘ใΛ 
 Android Auto / Automotive OS ʹఏڙ͢Δ
  12. Build apps for Cars Media Playback with AndroidX Media3 DroidKaigi.collect

    { #5@Nagoya } ▸ MediaBrowserServiceCompat ▸ Android Auto / Automotive OS ͕ࣗ෼ͷΞϓϦͷ 
 MediaBrowserService ʹόΠϯυ͠ʹ͘Δ Icons: https://icons8.com/icon/0dttLEPe98bJ/ fi at-500 onGetRoot ίϯςϯπ֊૚࠷্Ґͷ৘ใ onLoadChildren ࢠ֊૚ͷίϯςϯπ৘ใ MediaBrowserService MediaBrowser
  13. Build apps for Cars Media Playback with AndroidX Media3 DroidKaigi.collect

    { #5@Nagoya } ▸ MediaSessionCompmat ▸ ϝσΟΞίϯςϯπͷ࠶ੜঢ়گΛఏڙ͢Δ ▸ MediaBrowserService ͕ಈ͖࢝ΊͨΒ͸͡ΊʹॳظԽ͢Δ Icons: https://icons8.com/icon/0dttLEPe98bJ/ fi at-500 ίϯςϯπ֊૚࠷্Ґͷ৘ใ MediaBrowserService MediaBrowser onCreate: MediaSession ͷॳظԽ bindService connected onGetRoot
  14. Build apps for Cars Media Playback with AndroidX Media3 DroidKaigi.collect

    { #5@Nagoya } ▸ MediaControllerCompat ▸ ϝσΟΞίϯςϯπͷ࠶ੜঢ়گΛૢ࡞͢Δ ▸ Android Auto / Automotive OS ͷ UI ૢ࡞͕ى఺ Icons: https://icons8.com/icon/0dttLEPe98bJ/ fi at-500 ίϯςϯπ֊૚࠷্Ґͷ৘ใ MediaBrowserService MediaBrowser onCreate: MediaSession ͷॳظԽ bindService connected onGetRoot MediaController ͷॳظԽ MediaController.play ࠶ੜΛ։࢝ ࠶ੜΛ։࢝
  15. Build apps for Cars Media Playback with AndroidX Media3 DroidKaigi.collect

    { #5@Nagoya } ▸ Caveats ▸ MediaBrowser ͸୭Ͱ΋࣮૷Ͱ͖Δ ▸ MediaBrowserService ͸ bind ͖ͯͨ͠ΞϓϦͷݕূΛ͢΂͖ Icons: https://icons8.com/icon/EQ0QKBwiUSDM/pennywise ۭͷϦετΛฦ͢ MediaBrowserService MediaBrowser onGetRoot ύοέʔδΛݕূ: ෆڐՄ
  16. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } ▸ Android Auto / Automotive OS ͕ϝοηʔδΛಡΈ্͛Δ࢓૊Έ Noti fi cationManager Noti fi cationListenerService app Icons: https://icons8.com/icon/0dttLEPe98bJ/ fi at-500 / https://icons8.com/icon/wT8BPIITf9UK/android-phone notify(): Noti fi cation Λදࣔ ৽͍͠ Noti fi cation Λ௨஌ Noti fi cation ΛಡΈऔΔ ϝοηʔδΛಡΈ্͛Δ طಡʹ͢Δ ฦ৴͢Δ Ի੠ೖྗΛड͚෇͚Δ
  17. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } ▸ ࣍ʹ্͛ΔཁٻΛຬͨ͢௨஌ΛදࣔՄೳ ▸ Noti fi cation.MessagingStyle Λ࢖͍ͬͯΔ ▸ CATEGORY_MESSAGE ΧςΰϦʹଐ͢Δ ▸ ະಡϝοηʔδͷΈΛอ࣋͢Δ ▸ طಡʹ͢ΔΞΫγϣϯϘλϯ͕͋Δ ▸ SEMANTIC_ACTION_MARK_AS_READ ▸ ΞΫγϣϯϘλϯͷΠϕϯτॲཧʹ௥Ճͷ UI ͕ଘࡏ͠ͳ͍
  18. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } ▸ ฦ৴ػೳΛ࢖͏৔߹͸௥ՃͰ࣍ͷཁٻ΋ຬͨ͢ ▸ ฦ৴ઐ༻ͷΞΫγϣϯϘλϯΛઃఆ͢Δ ▸ SEMANTIC_ACTION_REPLY ▸ ΞΫγϣϯϘλϯͷΠϕϯτॲཧʹ௥Ճͷ UI ͕ଘࡏ͠ͳ͍ ▸ RemoteInput ΦϒδΣΫτΛ͍࣋ͬͯΔ
  19. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } val sender = Person.Builder() .setName("John Doe") .build() val style = NotificationCompat.MessagingStyle(sender) .addMessage("hello!", System.currentTimeMillis(), sender) val markAsReadIntent = PendingIntent.getBroadcast(/* */) val markAsReadAction = NotificationCompat.Action.Builder(R.drawable.ic_mark_as_read, "Mark as read", markAsReadIntent) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) .build() val replyPendingIntent = PendingIntent.getBroadcast(/* */) val replyInput = RemoteInput.Builder("input") .build() val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, "Reply", replyPendingIntent) .addRemoteInput(replyInput) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) .build() val notification = NotificationCompat.Builder(context, "notification_channel") .setContentTitle("title") .setContentText("message") .setCategory(NotificationCompat.CATEGORY_MESSAGE) .addAction(markAsReadAction) .addAction(replyAction) .setStyle(style) .build()
  20. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } val sender = Person.Builder() .setName("John Doe") .build() val style = NotificationCompat.MessagingStyle(sender) .addMessage("hello!", System.currentTimeMillis(), sender) val markAsReadIntent = PendingIntent.getBroadcast(/* */) val markAsReadAction = NotificationCompat.Action.Builder(R.drawable.ic_mark_as_read, "Mark as read", markAsReadIntent) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) .build() val replyPendingIntent = PendingIntent.getBroadcast(/* */) val replyInput = RemoteInput.Builder("input") .build() val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, "Reply", replyPendingIntent) .addRemoteInput(replyInput) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) .build() val notification = NotificationCompat.Builder(context, "notification_channel") .setContentTitle("title") .setContentText("message") .setCategory(NotificationCompat.CATEGORY_MESSAGE) .addAction(markAsReadAction) .addAction(replyAction) .setStyle(style) .build()
  21. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } val sender = Person.Builder() .setName("John Doe") .build() val style = NotificationCompat.MessagingStyle(sender) .addMessage("hello!", System.currentTimeMillis(), sender) val markAsReadIntent = PendingIntent.getBroadcast(/* */) val markAsReadAction = NotificationCompat.Action.Builder(R.drawable.ic_mark_as_read, "Mark as read", markAsReadIntent) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) .build() val replyPendingIntent = PendingIntent.getBroadcast(/* */) val replyInput = RemoteInput.Builder("input") .build() val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, "Reply", replyPendingIntent) .addRemoteInput(replyInput) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) .build() val notification = NotificationCompat.Builder(context, "notification_channel") .setContentTitle("title") .setContentText("message") .setCategory(NotificationCompat.CATEGORY_MESSAGE) .addAction(markAsReadAction) .addAction(replyAction) .setStyle(style) .build()
  22. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } val sender = Person.Builder() .setName("John Doe") .build() val style = NotificationCompat.MessagingStyle(sender) .addMessage("hello!", System.currentTimeMillis(), sender) val markAsReadIntent = PendingIntent.getBroadcast(/* */) val markAsReadAction = NotificationCompat.Action.Builder(R.drawable.ic_mark_as_read, "Mark as read", markAsReadIntent) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) .build() val replyPendingIntent = PendingIntent.getBroadcast(/* */) val replyInput = RemoteInput.Builder("input") .build() val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, "Reply", replyPendingIntent) .addRemoteInput(replyInput) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) .build() val notification = NotificationCompat.Builder(context, "notification_channel") .setContentTitle("title") .setContentText("message") .setCategory(NotificationCompat.CATEGORY_MESSAGE) .addAction(markAsReadAction) .addAction(replyAction) .setStyle(style) .build()
  23. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } ▸ CarExtender ▸ Android Auto / Automotive OS ޲͚ʹ௨஌Λ֦ு͢ΔͨΊͷศརΫϥε ▸ ௨஌ͷࡉ͔͍ઃఆΛ೚͍ͤͨͱ͖͸ CarExtender Λ࢖͏
  24. Build apps for Cars Messaging with AndroidX Core DroidKaigi.collect {

    #5@Nagoya } ▸ Caveats ▸ Noti fi cationListenerService ͸୭Ͱ΋࣮૷Մೳ ▸ MediaBrowserService ͷΑ͏ʹύοέʔδͷݕূ͸ෆՄ ▸ ௨ৗͷ Permission ͱ͸ผͷೝՄͷ࢓૊Έ͕༻ҙ͞Ε͍ͯΔ ▸ ref: https://www.jssec.org/dl/android_securecoding.pdf ▸ ௨஌ʹ͓͚ΔϓϥΠόγʔ؅ཧͷϦϑΝϨϯε
  25. Build apps for Cars ৄղ Android Auto DroidKaigi.collect { #5@Nagoya

    } ▸ https://www.youtube.com/watch?v=0ffNY26f-q4 ▸ DroidKaigi 2018 ▸ ࠶ੜίϯτϩʔϧ΍ϝοηʔδϯάʹ͍ͭͯղઆ
  26. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ Android Auto / Automotive OS ޲͚ͷػೳ։ൃϥΠϒϥϦ ▸ ݱࡏ͸φϏήʔγϣϯͱ POI ޲͚ͷػೳΛ࣮૷͢ΔͨΊͷ API Λఆٛ ▸ UI Λߏங͢ΔͨΊͷπʔϧΩοτ΋ఏڙ ▸ ςϯϓϨʔτϕʔεͷ UI ▸ YouTube: https://www.youtube.com/watch?v=watUEk6_i-4 ▸ Codelab: https://developer.android.com/codelabs/car-app-library- fundamentals
  27. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ Car App Library ͰఏڙՄೳͳػೳ ▸ φϏήʔγϣϯ ▸ POI ▸ IOT (experimental)
  28. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ Android Auto / Automotive OS ޲͚ΞϓϦͷ API Ϩϕϧ ▸ Android OS ͷόʔδϣϯͱ͸ผͷ API Ϩϕϧఆ͕ٛଘࡏ͢Δ ▸ API ϨϕϧʹΑͬͯ Car App Library Ͱఏڙ͞ΕΔػೳʹ͕ࠩ͋ΔͨΊ
  29. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } <manifest> <application> <meta-data android:name="androidx.car.app.minCarApiLevel" android:value="1" /> </application> </manifest>
  30. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ ΞϓϦ͕࣋ͭ CarAppService Λܦ༝ͯ͠ Android Auto / Automotive OS ͱ௨৴ ▸ CarAppService Ͱ Session Λੜ੒͠ɺSession ʹඥͮ͘ Screen Λ࡞Δ Android Auto / Automotive OS CarAppService bindService Session ύοέʔδΛݕূ Session ͔Βը໘Λߏங
  31. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ ंʹ͸ෳ਺ͷσΟεϓϨΠΛ౥ࡌՄೳ ▸ σΟεϓϨΠ͝ͱݸผʹ CarAppService ʹ bind ͠ʹ͘Δ Android Auto / Automotive OS 
 Dispay 1 CarAppService bindService Android Auto / Automotive OS 
 Dispay 2 bindService
  32. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ ंʹ͸ෳ਺ͷσΟεϓϨΠΛ౥ࡌՄೳ ▸ σΟεϓϨΠ͝ͱݸผʹ Session Λͭ͘Δ Android Auto / Automotive OS 
 Dispay 1 CarAppService Session Android Auto / Automotive OS 
 Dispay 2 Session
  33. Build apps for Cars CarAppService DroidKaigi.collect { #5@Nagoya } class

    MyCarAppService : CarAppService() { override fun createHostValidator(): HostValidator { return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR } override fun onCreateSession(): Session { return MyCarAppSession() } }
  34. Build apps for Cars Session Implementation DroidKaigi.collect { #5@Nagoya }

    class MyCarAppSession : Session() { override fun onCreateScreen(intent: Intent): Screen { return MyCarAppScreen(carCotnext) } }
  35. Build apps for Cars Screen implementation DroidKaigi.collect { #5@Nagoya }

    class MyCarAppScreen( 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() } }
  36. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ ༷ʑͳςϯϓϨʔτ͕ϥΠϒϥϦ಺ʹ͋Δ ▸ Google Maps Λදࣔ͢ΔςϯϓϨʔτ ▸ ೝূը໘Λදࣔ͢ΔςϯϓϨʔτ ▸ etc…
  37. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } ▸ Automotive OS ޲͚ʹ͸ઐ༻ͷରԠ͕ඞཁ ▸ app Ϟδϡʔϧͱ͸ผʹ automotive ༻ͷϞδϡʔϧ͕ඞཁ ▸ app ϞδϡʔϧΛ run ͢Δͱී௨ͷΞϓϦ͕ͦͷ·· deploy ͞Εͯ͠·͏ ▸ automotive ༻ͷϞδϡʔϧͰઐ༻ͷ apk Λు͖ग़͢ ▸ uses-feature Ͱ Automotive OS ޲͚ͷ΋ͷΛ required ʹ͢Δ ▸ automotive ༻ͷ Activity Λ࢖͏
  38. Build apps for Cars Car App Library DroidKaigi.collect { #5@Nagoya

    } <manifest> <uses-feature android:name="android.hardware.type.automotive" android:required="true" /> <uses-feature android:name="android.software.car.templates_host" android:required="true" /> <application> <activity android:name="androidx.car.app.activity.CarAppActivity" android:exported="true" android:launchMode="singleTask" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="distractionOptimized" android:value="true" /> </activity> <meta-data android:name="androidx.car.app.minCarApiLevel" android:value="1" /> </application> </manifest>
  39. Build apps for Cars Emulators: Android Auto ▸ Android Auto

    Desktop Head Unit (DHU) Emulator ▸ Android Virtual Device (AVD) Ͱ͸ͳ͍͜ͱʹؾΛ͚ͭΔ ▸ ࣍ͷίϚϯυͰ DHU Λىಈ͢Δ ▸ PC ʹ USB Ͱܨ͍ͩ୺຤Λ࢖͏৔߹ DroidKaigi.collect { #5@Nagoya } $SDK_LOCATION/extras/google/auto/desktop-head-unit $SDK_LOCATION/extras/google/auto/desktop-head-unit -u
  40. Build apps for Cars Emulators: Android Automotive OS ▸ ઐ༻

    AVD ͕͋Δ ▸ Play Store ෇ଐͷΤϛϡϨʔλΛ࢖͏ DroidKaigi.collect { #5@Nagoya }
  41. Build apps for Cars Emulators: Android Automotive OS ▸ Google

    Assistant / Google Maps ͳͲϓϦΠϯετʔϧࡁΈ ▸ ηϯαʔ৘ใ (ं଎΍ΪΞ౳) ΋ΤϛϡϨʔγϣϯͰ͖Δ ▸ ηϯαʔ৘ใΛ·ͱΊͯ import ͯ͠ϦϓϨʔ΋Մ ▸ λονૢ࡞ / ෺ཧϘλϯૢ࡞྆ํରԠ DroidKaigi.collect { #5@Nagoya }
  42. Build apps for Cars Emulators: Android Automotive OS ▸ Caveats

    ▸ AndroidStudio ͷ Tool Window ಺Ͱ͸ಈ͔ͳ͍ ▸ ىಈ͸Ͱ͖Δ͕ද͕ࣔͰ͖ͳ͍… ▸ ඞͣ Standalone Ͱಈ͔͢͜ͱ DroidKaigi.collect { #5@Nagoya }
  43. Build apps for Cars Emulators: Android Automotive OS ▸ ࣗಈंϝʔΧʔ͕࡞͍ͬͯΔ

    system image ΋͋Δ ▸ GM ▸ Honda ▸ Polestar ▸ Volvo DroidKaigi.collect { #5@Nagoya }
  44. Build apps for Cars Emulators: Android Automotive OS ▸ Caveats

    ▸ x86 system images ͔͠ͳ͍৔߹ Apple Silicon Ͱಈ͔ͳ͍͜ͱ͕͋Δ DroidKaigi.collect { #5@Nagoya }
  45. Build apps for Cars Wrap up DroidKaigi.collect { #5@Nagoya }

    ▸ Android Auto / Automotive OS ʹରԠ͢Δ࢓૊Έ ▸ AndroidX Media3 ▸ AndroidX Core ▸ Car App Library ▸ ಉ͡ϥΠϒϥϦͰ Android Auto / Automotive OS ͲͪΒʹ΋ରԠՄೳ ▸ Ұ෦ Automotive OS ઐ༻ͷରԠ͕͋Δ