應用程式基礎

車輛就是你的畫布:解鎖 Android 開發人員的行車體驗

喇叭

關於

講座簡介

隨著 Android Auto 和 Android Automotive OS 車輛的車內螢幕越來越大,開發人員面臨獨特的雙重挑戰:在停車時提供豐富、自動調整的體驗,以及在駕駛時提供安全、以範本為基礎的體驗。在這場 30 分鐘的完整技術講座中,我們將探討端對端架構和開發方法,瞭解如何讓 Android 應用程式適用於車輛。

從設計車用應用程式的基本概念,到打造媒體體驗的最新方法 (例如在車輛從行駛狀態切換為停車狀態時,將音訊切換為影片),您將瞭解所有必要知識,讓應用程式在車上順利運作。

摘要

  • 車輛專用 Android 適用於 Android Auto 和 Android Automotive OS 兩個平台。一個是從手機投影,另一個則直接在車輛上執行。
  • Car App Library 提供針對駕駛情境最佳化的介面範本,可配合各種車輛硬體設定進行調整。
  • 停車時使用的應用程式仰賴標準 Android 活動,提供影片串流、遊戲和網路瀏覽器等豐富體驗。
  • Car App Library 1.9 推出全新 UI 元件和品牌自訂權杖。此外,Android Automotive OS 也全面支援媒體範本。
  • 「停車到行駛」功能會在停車時動態啟動原生影片活動,並在行駛時切換回媒體範本,確保音訊不中斷。

資源

Gemini Notebook

主題

  • android-for-cars
  • android-auto
  • android-automotive-os
  • car-app-library
  • media3
  • parked-apps

轉錄稿

車輛專用 Android 簡介

  • 現在我們來做個小測驗

  • 大家好。

  • 感謝各位參加「車輛就是你的畫布」講座。

  • 本課程將介紹如何開發 Android Auto 應用程式。

  • 我是 Paul Lammertsma。

  • 我是 Thomas Weathers。

  • 我們是車輛專用 Android 團隊的開發人員關係工程師。

  • 相信許多人都花費大量時間和精力,確保應用程式在各種螢幕和裝置 (手機、摺疊式裝置、平板電腦等) 上,都能呈現精美外觀和良好功能。

  • 今天,我們要著重介紹一個你可能沒想過的螢幕。

  • 並以獨特的方式觸及使用者。

  • 也就是車內螢幕。

  • 首先,我們來簡單介紹一下車輛專用 Android。

  • 車輛專用 Android 並非單一系統。

  • 您可以指定兩種平台。

  • 首先是 Android Auto,這是一種由手機驅動的投影系統。

  • 使用 Android Auto 時,應用程式會在手機上執行,並透過有線或無線連線將 UI 投影到車內螢幕。

  • 第二種是 Android Automotive OS,這是直接在車輛上執行的 Android 變體。

  • Android Automotive OS 獨立於手機運作,可直接存取車輛硬體,例如空調和收音機,而且重要的是,它還能管理自己的數據連線。

  • 部分搭載 Android Automotive OS 的車輛內建 Google 服務。

  • 內建 Google 服務的車輛也隨附 Google 應用程式和服務,例如 Play 商店、Gemini 和 Google 地圖。

  • 雖然有兩個平台,但我們的目標是讓您輕鬆建構一次,就能部署在兩個平台上提供優質體驗的應用程式。

  • 以下範例說明使用 Car App Library 建構的媒體應用程式,在 Android Auto 和 Android Automotive OS 上,以及在各種不同螢幕尺寸和形狀上的外觀。

  • 您可以為許多不同類型的裝置和介面建構應用程式。

  • 這就引出一個問題:為什麼要為汽車提供這項服務?

  • 首先,這裡的規模非常龐大。

  • 目前路上有超過 2.5 億輛與 Android Auto 相容的汽車,以及 16 個品牌、超過 100 款內建 Google 服務的車型。

  • 當應用程式進入車內,您就能在使用者日常通勤、往返家庭活動、辦事,甚至公路旅行時,觸及他們。

  • 根據美國汽車協會 (AAA) 2024 年美國駕駛調查,美國駕駛人平均每天開車 60 分鐘。

  • 不過,除了在使用者開車時觸及他們,

  • 以及車輛停妥時。

  • 例如在電動車充電站充電,或在學校接送區排隊。

  • 隨著乘客專用螢幕的興起,我們預期未來會有更多機會提升使用者參與度。

  • 現在我們來做個小測驗

  • 接著來看看可以為車輛打造哪些類型的體驗。

  • 如要瞭解如何建構車用應用程式,建議您先瞭解應用程式在車內執行時的兩種主要情況和狀態。

  • 首先,有些應用程式適合在開車時使用。

  • 這些體驗經過最佳化,適合在車輛行進時使用。

  • 包括畫面上列出的類別,例如音訊應用程式 (通常稱為媒體)、訊息和通訊應用程式、導航等。

  • 行車最佳化體驗必須遵循嚴格的分心防護標準。

  • 建構應用程式 UI 時,必須特別考量如何確保車輛行駛時能安全使用。

  • 目前有幾種不同的方法可以建構行車最佳化應用程式。

Car App Library 總覽

  • 不過,這場講座會著重在使用 Car App Library。

  • 這是一組 Jetpack 程式庫,提供範本式架構,除了提供針對駕駛情境最佳化的使用者介面,也能配合車輛專用的各種硬體設定進行調整。

  • 因此,請考量輸入模式、螢幕大小和顯示比例等因素。

  • 雖然這不是為車輛打造行車最佳化體驗的唯一方法,但我在這場演講中想著重介紹的方法,是使用車輛專用 Android 應用程式庫建構。

  • 我們通常簡稱為 CAL。

  • 如稍早所述,Car App Library 是一組程式庫,可協助您建構車輛專用的應用程式。

  • 這個程式庫提供範本式架構,除了提供針對駕駛情境最佳化的使用者介面,也能配合不同的硬體設定進行調整。

  • 您可以放心建構應用程式,無論是在 Android Auto 或 Android Automotive OS 上執行,都能在所有不同的設定中順暢運作。

  • 使用 CAL 建構的應用程式可以依賴這個主機用戶端架構。

  • 主機應用程式是系統轉譯器,可能是 Android Auto 本身,或內建 Google 服務的車輛中的 Google Automotive App Host。

  • 最終,它會控制要在使用者螢幕上顯示的內容。

  • 因此,身為應用程式開發人員,您最終不會繪製像素。

  • 而是將結構化資料和資料狀態提供給 Car App Library 範本。

  • 接著,這個主機就會接收這項資料,並以符合安全規範的方式,安全地繪製資料,並採用分心因素排除功能最佳化的版面配置。

  • 接著,我們來看看 CAL 中的類別,以及建構應用程式時需要擴充哪些類別,首先是 CarAppService。

  • 這是 Android 服務的子類別,可做為主機應用程式與用戶端應用程式通訊的進入點,用途是建立工作階段例項,供主機與其互動。

  • 您可以將工作階段視為在車輛螢幕上執行的用戶端應用程式例項。

  • 這個類別與其他 Android 元件一樣擁有專屬生命週期,可用於在整個工作階段例項存在期間初始化及拆卸各種資源。

  • CarAppService 和工作階段之間是一對多關係。

  • 舉例來說,CarAppService 可能有兩個工作階段例項,一個用於主要螢幕,另一個用於儀表板螢幕 (適用於支援儀表板螢幕的導航應用程式)。

  • 以下是範例:車輛有主要螢幕和儀表板螢幕,每個螢幕都與專屬工作階段相關聯,這也是應用程式開發人員支援多螢幕車輛的方式。

  • 在工作階段中,畫面例項負責產生由主機應用程式轉譯的使用者介面。

  • 這些使用者介面由範本類別表示,其中每個模型代表一個特定類型的版面配置,例如網格或清單。

  • 因此,每個工作階段都會管理一組畫面例項,用於處理應用程式不同部分的使用者流程。與工作階段一樣,畫面也有自己的生命週期,可供您掛鉤。

  • 不過,雖然主機負責轉譯 UI,且您使用的是 Car App Library 應用程式庫範本,但這不代表您會受到嚴格限制,或無法自訂應用程式。

  • 您可以使用豐富的範本和元件,也可以混搭使用,打造理想體驗。

  • 範本分為一般用途和特殊用途,前者適用於 Car App Library 中的所有應用程式類型,後者則專為特定應用程式體驗而設計,例如導航或搜尋點。

  • 不過,在詳細說明如何打造行車最佳化體驗之前,我想先介紹另一種在車內執行應用程式的情況:車輛停妥時。

開發可在車輛停妥時使用的應用程式

  • 某些類別的應用程式只能在車輛停妥時使用,包括影片應用程式、遊戲和瀏覽器。

  • 但車輛靜止時,駕駛人分心等級規範就會解除,您可以提供更符合現有自動調整 UI 的體驗。

  • 閒置應用程式是以活動為基礎,與其他裝置 (例如手機或平板電腦) 上使用的活動類似,甚至相同。我們會在下一節詳細介紹閒置應用程式。

  • 雖然車輛停妥時的應用程式體驗會重複使用現有的自動調整活動,但您仍須遵守車輛專屬的品質指南,包括資訊清單宣告、螢幕凹口,以及車輛開始移動時暫停播放等。

  • 為協助您自動完成這項工作,我們推出了新的 Android 技能,可處理擱置的應用程式。

  • 因此,開始之前,請確認您已安裝 Android CLI,您可以透過這個短連結找到。

  • 設定完成後,請執行 android skills list,探索可用的技能。

    android skills list
    android skills add android-for-cars-parked-apps
  • 您可以運用許多不同的技能,讓 Android 開發作業更上一層樓。

  • 如果是 Android for Cars,您可以使用 android skills add android-for-cars-parked-apps 將技能新增至代理的結構定義。

  • 現在,無論您偏好哪種 AI 代理,都能取得逐步指引,瞭解如何設定 Android Auto 或 Android Automotive OS 的資訊清單、處理車窗插邊和返回瀏覽等事項、強制執行駕駛人分心等級播放限制,甚至還能在您將影片、遊戲或瀏覽器應用程式提交至 Google Play 前,先進行稽核。

車輛應用程式類別總覽

  • 因此,由於這些應用程式類別的概念,建構車用應用程式也有些獨特之處。

  • 如前所述,某些類別的應用程式可在行車時使用,其他類別的應用程式則可在停車時使用。

  • 醒目顯示的類別可在開車時使用。

  • 其中有些會標示 CAL,如我所說,這是 Car App Library,這個類別的應用程式會使用我們剛才看到的範本。

  • 現在我會快速帶過這些內容,不會深入探討。

  • 首先是媒體應用程式,這類應用程式會播放音訊,而非影片。

  • 有兩種方法可以建立。

  • 最上方的 MediaBrowserService 是最簡單的選項。

  • 您只需提供中繼資料,資訊娛樂螢幕介面就會以車用最佳化方式,完整呈現播放和媒體瀏覽器 UI。

  • 另一個選項是使用 Car App Library 建構媒體應用程式,這樣一來,您就能進一步控管及自訂媒體應用程式的樣式和呈現方式,Thomas 稍後會進一步說明。

  • 導航應用程式當然是主要用途,可提供路線和即時路線指示。

  • 共乘司機應用程式也屬於這個類別。

  • 搜尋點應用程式可協助你尋找附近的實用地點,例如電動車充電樁或停車位。

  • 物聯網 (IoT) 應用程式可讓您隨時隨地存取智慧型裝置,例如管理住家。

  • 此外,天氣應用程式也相當實用,可提供即時雷達、暴風警報和特定地點的天氣預報等資訊。

  • 最後,通訊類別可細分為三個子類別:將基本通知延伸至車輛、訊息應用程式和視訊通話應用程式。

  • 此外,還有車輛停妥時才能使用的類別:影片串流應用程式、遊戲和網路瀏覽器。

  • 很高興宣布,幾週前,我們已開放所有開發人員在 Android Auto 和 Android Automotive OS 發布遊戲。

  • 您會發現有些類別標示為「開放」,有些標示為「Beta 版」,有些則標示為「即將推出」。

  • 「開放」表示任何開發人員都能將這個類別的應用程式直接提交至正式版。

  • Beta 版代表您可以將應用程式發布至內部或封閉測試群組,但除非您獲准加入搶先體驗計畫,否則無法發布至正式版群組。

  • 各類別的說明文件包含更多資訊,以及意願調查表的連結。

  • 「即將推出」則是指目前不支援,但我們計劃日後支援的類別。

  • 我們的最終目標是整合平台。

  • 我們希望您能透過一次編寫,同時發布至 Android Auto 和 Android Automotive OS,無論類別為何,都能建構並獲得最大觸及率。

  • 接下來由 Thomas 介紹媒體。

Car App Library 媒體更新

  • 祝一切順心!

  • 太好了!

  • 因此,我們在去年推出 Car App Library 1.8 版,為媒體應用程式提供範本化的瀏覽 UI 和自訂動作,並支援 Android Auto。

  • 包括左側顯示的媒體播放範本。

  • 在今年的 I/O 大會上,我們透過 Car App Library 1.9 推出更多可瀏覽的 UI。

  • CAL 1.9 進入 Beta 版後,您現在可以解鎖 Android Auto 和 Android Automotive OS 的重要功能更新。

  • 重點功能包括透過應用程式運算式自訂品牌,讓您在維持安全規則的同時,使用主機轉譯的版面配置自訂顏色和形狀符記,以及新的 UI 元件,例如焦點區段、精簡清單項目、可捲動方塊和常駐迷你播放器。

  • 此外,CAL 1.9 完整支援 AAOS 的媒體範本,真正整合兩個生態系統的平台。

  • Car App Library 的下一個版本即將推出:CAL 第 10 版。

  • CAL 第 10 版將為通訊應用程式提供更多自訂範本,讓使用者在開車時享有更完善的自訂通話體驗。

  • 我們也新增了應用程式類別和範本,主打行車時的對話式體驗。

  • 最後,我們也正在開發更多功能,讓使用者能透過 Car App Library 範本,更順暢地從停車模式切換至駕駛模式。

  • 我們很快就會推出更多功能,敬請密切關注。

停車到行駛功能

  • 使用 Car App Library 的停車到駕駛功能,應用程式可在車輛靜止時動態轉換模式並顯示自動調整內容,並在駕駛時順暢切換回 Car App Library 範本。

  • 主要應用包括在車輛靜止時提供量身打造的驗證流程,或在車輛停妥時啟用專屬體驗,例如串流播放影片 Podcast 或音樂短片。

  • 這項功能會直接與媒體播放範本整合。

  • 因此,車輛靜止時,駕駛人可以完整存取應用程式的原生 Android 活動,並啟用影片串流等互動式多媒體。

  • 車輛一排檔,防分心機制就會啟動,促使應用程式切換回 Car App Library 媒體範本,確保音訊播放符合規範且不中斷。

  • 車內體驗正處於轉型階段。

  • 媒體應用程式希望超越傳統的瀏覽和播放介面,為駕駛和乘客提供更豐富、更身歷其境且互動性更高的體驗。

  • 接下來,我們將深入探討如何使用 Media3 程式庫新增原生影片活動,以便在車輛切換至停車狀態時開始播放。

  • 首先,請將影片算繪介面直接連結至背景播放例項。

    override fun onStart() {
           super.onStart()
           ...
           controllerFuture = MediaController.Builder(
             this,
             sessionToken
           ).buildAsync()
    
           controllerFuture?.addListener({
               mediaController = controllerFuture?.get()
               playerView.player = mediaController
           }, ContextCompat.getMainExecutor(this))
    }
  • 您不希望在這個活動中例項化獨立的媒體播放器,而是想在主要服務 (例如 Media3 媒體庫服務) 中維護中央 ExoPlayer 或媒體播放器,同時處理音訊和影片串流。

  • 因此,在行駛期間,如果沒有繫結任何有效服務,播放器只會解碼音訊,但當駕駛人在停車時開啟影片活動,您會想將其算繪介面直接附加至基礎服務播放器。

  • 因此,使用 Media3 時,mediaController 會以原生方式實作播放器,因此可以直接指派,如您所見,playerView set-- playerView.player 直接設定為 mediaController。

  • 接下來,您需要使用 ParkedOnlyOnClickListener 註冊原生進入點。

    val watchVideoAction = Action.Builder()
      .setTitle("Watch Video")
      .setIcon(videoCarIcon)
      .setOnClickListener(
        ParkedOnlyOnClickListener.create {
          val intent = Intent(
            carContext,
            VideoPlayerActivity::class.java
          )
            .apply {
              addFlags(
                Intent.FLAG_ACTIVITY_NEW_TASK
              )
            }
          carContext.startActivity(intent)
        })
      .build()
  • 這個包裝函式會在媒體播放介面的標頭列中提供意圖觸發條件。

  • 因此,請加入啟動影片播放的動作,並將其選取事件監聽器包裝在 ParkedOnlyOnClickListener 中。

  • 因此在行車模式下,主機應用程式會攔截這些輕觸動作,並顯示系統安全訊息,因此您無法在駕駛時進入該畫面,但當您停車時,回呼會觸發 carContext 內的 startActivity,啟動指定的全螢幕活動。

  • 請注意,在這些 Car App Library 應用程式中,您必須在資訊清單中將影片目標標記為 distractionOptimized=false,作業系統才會辨識出這只是停車工作流程。

    <activity
       android:name=".VideoPlayerActivity"
       android:exported="false"
       android:launchMode="singleTop">
       <meta-data
           android:name="distractionOptimized"
           android:value="false" />
    </activity>

處理從停車到駕駛的轉換

  • 最後,我們來看看駕駛人從停車檔切換到前進檔時會發生什麼事。

  • 如果活動未排除分心因素,且在車輛行駛時仍保持啟用狀態,AAOS 會顯示系統封鎖疊加層,基本上就是要求你停車才能繼續使用應用程式。

  • 為避免畫面遭到封鎖,我們的目標是順暢返回媒體播放範本,不中斷音訊。

  • 因此,當 isRequiresDistractionOptimization 在這裡評估為 true 時,我們基本上會從基礎媒體工作階段清除影片轉譯介面,並在播放器活動上呼叫 finish,因為它是在 CAL 體驗之上啟動,完成後會直接返回媒體播放範本,並繼續播放音訊。

    class VideoPlayerActivity : ComponentActivity(){
      override fun onStart() {
    
        …
    
        if (uxRestrictionsManager?
            .currentCarUxRestrictions?
            .isRequiresDistractionOptimization
                == true) {
          revertToCarAppTemplate()
        }
      }
    
      private fun revertToCarAppTemplate() {
        mediaControllerCompat
          .sendCommand("CMD_CLEAR_VIDEO_SURFACE",
                       null, null)
        finish()
      }
    }
  • 維持音訊不中斷播放是提供良好使用者體驗的關鍵,因此只要將媒體工作階段保持為前景服務,音訊就能在這些狀態變更期間持續播放。

    <activity
            android:name="androidx.car.app.activity.CarAppActivity"
            android:exported="true"
            android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
    
            <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK" />
        </intent-filter>
        <meta-data
                android:name="distractionOptimized"
                android:value="true" />
    </activity>
  • 您也應覆寫 CAL 畫面中的 onNewIntent,擷取 SHOW_MEDIA_PLAYBACK 意圖。

    class MyCarAppSession : Session() {
        override fun onCreateScreen(intent: Intent): Screen {
            // 1. Link your active MediaSession token with Car App Library's MediaPlaybackManager
            val mediaPlaybackManager = carContext.getCarService(MediaPlaybackManager::class.java)
            mediaPlaybackManager.registerMediaPlaybackToken(mediaSessionToken)
    
            // 2. Handle deep link if cold-started from the vehicle's media widget
            handlePlaybackIntent(intent)
            return HomeScreen(carContext)
        }
        override fun onNewIntent(intent: Intent) {
            super.onNewIntent(intent)
    
            // 3. Handle deep link when the session is already running
            handlePlaybackIntent(intent)
        }
    }
  • 這樣一來,每當使用者與車輛主畫面上的車輛系統媒體小工具互動時,深層連結就會將他們直接導向 Car App Library 中的「現正播放」檢視畫面。

  • 因此,在整個開發過程中驗證這些轉場效果非常簡單。

  • 您可以在 AAOS 上執行 ADB 指令。

  • 在本例中,當您準備好在活動之間切換時,會是 emulate-driving-state drive 或 emulate-driving-state park。

  • 以下範例使用全新的 Media3 媒體範例應用程式,並搭配 Car App Library,在車輛從停車狀態切換至行駛狀態時播放影片。

  • 歡迎前往樓下的 Android 自動調整式版面配置攤位,或在 GitHub 上的 car-samples 存放區查看。

  • Android Automotive OS 目前提供停車到駕駛功能,媒體應用程式只要整合車輛 CAL,就能提供駕駛體驗,並在停車時提供更強大的體驗。

  • 請密切關注 developer.android.com,我們很快就會在說明文件中介紹這項功能。如果您想在應用程式中加入這項功能,請在該網站上表達意願。

  • Paul。

車輛應用程式庫即將推出的功能

  • 太好了!

  • 謝謝,Thomas。

  • 在結束之前,我想分享幾種方法,讓大家進一步瞭解今年稍晚推出的新功能。

  • 正如 Thomas 所說,CAL 1.9 目前為 Alpha 版。

  • 很快就會進入 Beta 版階段。

  • CAL 1.10 將在年底前進入 Alpha 測試階段,屆時您就能開始評估對話式 UI,以及最新的通訊和停車到駕駛功能。

  • 最後,很高興能與大家分享,Android Auto 和 Android Automotive OS 現已支援遊戲,因此現在正是為車輛最佳化遊戲的最佳時機。

  • 如要進一步瞭解實作細節,請務必參閱「打造車用遊戲」指南中的說明文件。

  • 如要進一步瞭解如何調整遊戲以適用於車輛,並掌握 Android for Cars 的其他新功能和異動,請參閱「新功能」頁面。

  • 希望您已瞭解車輛和使用者已準備好使用您的應用程式。

  • 您可以在現有的自動調整式應用程式上,建構豐富的停車體驗,並使用各種車輛應用程式庫範本,打造安全駕駛體驗。

  • 發布前,您可以使用電腦版車用運算主機、模擬器、在 Pixel Tablet 上執行的 AAOS,或 Firebase Test Lab 進行全面測試。

  • 您已具備為這個生態系統建構應用程式的技能,而且有數百萬輛車等著使用您的應用程式,因此請立即著手開發。

程式碼

程式碼片段

「Developing apps for parked cars」影片 09:03 處的殼層程式碼片段
android skills list
android skills add android-for-cars-parked-apps
「Park-to-drive capabilities」影片 15:20 處的 Kotlin 程式碼片段
override fun onStart() {
       super.onStart()
       ...
       controllerFuture = MediaController.Builder(
         this,
         sessionToken
       ).buildAsync()

       controllerFuture?.addListener({
           mediaController = controllerFuture?.get()
           playerView.player = mediaController
       }, ContextCompat.getMainExecutor(this))
}
「Park-to-drive capabilities」影片 16:06 處的 Kotlin 程式碼片段
val watchVideoAction = Action.Builder()
  .setTitle("Watch Video")
  .setIcon(videoCarIcon)
  .setOnClickListener(
    ParkedOnlyOnClickListener.create {
      val intent = Intent(
        carContext,
        VideoPlayerActivity::class.java
      )
        .apply {
          addFlags(
            Intent.FLAG_ACTIVITY_NEW_TASK
          )
        }
      carContext.startActivity(intent)
    })
  .build()
「Park-to-drive capabilities」影片 16:42 處的 XML 程式碼片段
<activity
   android:name=".VideoPlayerActivity"
   android:exported="false"
   android:launchMode="singleTop">
   <meta-data
       android:name="distractionOptimized"
       android:value="false" />
</activity>
「Handling transitions from park to drive」影片 17:17 處的 Kotlin 程式碼片段
class VideoPlayerActivity : ComponentActivity(){
  override fun onStart() {

    …

    if (uxRestrictionsManager?
        .currentCarUxRestrictions?
        .isRequiresDistractionOptimization
            == true) {
      revertToCarAppTemplate()
    }
  }

  private fun revertToCarAppTemplate() {
    mediaControllerCompat
      .sendCommand("CMD_CLEAR_VIDEO_SURFACE",
                   null, null)
    finish()
  }
}
「Handling transitions from park to drive」中 17:36 的 XML 程式碼片段
<activity
        android:name="androidx.car.app.activity.CarAppActivity"
        android:exported="true"
        android:launchMode="singleTask">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />

        <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK" />
    </intent-filter>
    <meta-data
            android:name="distractionOptimized"
            android:value="true" />
</activity>
「Handling transitions from park to drive」影片 17:49 處的 Kotlin 程式碼片段
class MyCarAppSession : Session() {
    override fun onCreateScreen(intent: Intent): Screen {
        // 1. Link your active MediaSession token with Car App Library's MediaPlaybackManager
        val mediaPlaybackManager = carContext.getCarService(MediaPlaybackManager::class.java)
        mediaPlaybackManager.registerMediaPlaybackToken(mediaSessionToken)

        // 2. Handle deep link if cold-started from the vehicle's media widget
        handlePlaybackIntent(intent)
        return HomeScreen(carContext)
    }
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)

        // 3. Handle deep link when the session is already running
        handlePlaybackIntent(intent)
    }
}