Communitygithub.com

android/skills

Passen Sie bestehende Android-Apps für Videostreaming, Spiele und Webbrowser an, damit sie als geparkte Apps auf Android Auto und Android Automotive OS laufen.

Was ist skills?

Diese Skill-Anleitung beschreibt, wie bestehende Android-Apps für Videostreaming, Spiele und Webbrowser als sogenannte „Parked Apps“ auf Android Auto und Android Automotive OS (AAOS) ausgeführt werden können. Sie behandelt die Konfiguration des AndroidManifests, Hardware-Feature-Deklarationen für Google Play, den Kompatibilitätsmodus, Rücknavigation, Ausrichtung und Display-Kontinuität, steuerbare Systemleisten, unregelmäßige Display-Aussparungen, die Behandlung von Fahrerablenkung (Driver Distraction) mittels Lifecycle-Ereignissen, die MediaSession-Playback-Steuerung mit CarUxRestrictionsManager und Hintergrundaudio während der Fahrt. Die Anleitung ist relevant für Entwickler, die Apps für Autos migrieren, erstellen oder prüfen, um die Car App Quality Guidelines zu erfüllen. Sie ist nicht für Audio-Medien-Apps, Navigations-Apps basierend auf der Car App Library, POI-, IoT-, Wetter- oder Kommunikations-Apps gedacht, die während der Fahrt verwendet werden. Unterstützte Plattformen sind Android Auto und Android Automotive OS.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/android/skills/tree/HEAD/cars/android-for-cars-parked-apps

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Passen Sie bestehende Android-Video-Apps, Spiele und Webbrowser an, damit sie als geparkte Apps auf Android Auto und Android Automotive OS laufen. Befolgen Sie diese Schritte, um die Qualitätsrichtlinien für Auto-Apps für die Verteilung über Google Play zu erfüllen.

Voraussetzungen

  • Beginnen Sie mit einer bestehenden adaptiven Android-App aus einer der unterstützten Kategorien für geparkte Apps: Videostreaming-Apps, Spiele oder Webbrowser.

Glossar

  • Geparkte Apps: Geparkte Apps laufen auf Android Auto und Android Automotive OS nur, während das Fahrzeug geparkt ist. Die drei Kategorien sind Video, Spiele und Browser; andere Kategorien können nicht als geparkte Apps veröffentlicht werden.
  • Android Auto: Android Auto ist ein telefonbasiertes Projektionssystem. Apps werden auf dem Telefon des Benutzers ausgeführt und über eine Kabel- oder Drahtlosverbindung auf das Fahrzeugdisplay projiziert. Android Auto ist eine separate Plattform von Android Automotive OS.
  • Android Automotive OS: Android Automotive OS (AAOS) ist eine Android-Variante, die direkt auf dem Fahrzeug läuft. Android Automotive OS ist eine separate Plattform von Android Auto.
  • Kategorie Video: Video-Apps zeigen gestreamte Videos an, während das Fahrzeug geparkt ist. Im Allgemeinen auf Android Automotive OS verfügbar; auf Android Auto nicht unterstützt.
  • Kategorie Spiele: Spiele-Apps bieten Spielmöglichkeiten, während das Fahrzeug geparkt ist. Im Allgemeinen auf Android Automotive OS und Android Auto verfügbar.
  • Kategorie Browser: Webbrowser ermöglichen Benutzern das Surfen im Internet, während das Fahrzeug geparkt ist. In der Beta auf Android Automotive OS verfügbar; auf Android Auto nicht unterstützt.
  • Kategorie Medien: Keine geparkte Kategorie. Medien-Apps spielen Audioinhalte (Musik, Radio, Hörbücher, ohne Video) während der Fahrt oder im geparkten Zustand ab.
  • Android for Cars-Plattform: Android for Cars ist ein Oberbegriff, der Android Auto und Android Automotive OS umfasst.
  • Allgemein verfügbare Kategorien: Erlaubt auf den Google Play-Tracks für internes Testen, geschlossenes Testen, offenes Testen und Produktion für eine unterstützte Plattform.
  • Beta-Kategorien: Erlaubt auf Tracks für internes oder geschlossenes Testen; offene Test- und Produktionstracks erfordern die Aufnahme in ein Early-Access-Programm.
  • Audio während der Fahrt: Eine Beta-Funktion auf Android Automotive OS, die Video-Apps erlaubt, Audio abzuspielen, während das Fahrzeug in Bewegung ist.
  • Qualitätsrichtlinien für Auto-Apps: Wenn Sie eine App anhand der Kriterien der Stufe 3 (Car ready), Stufe 2 (Car optimized) oder Stufe 1 (Car differentiated) prüfen, MÜSSEN Sie die Qualitätsrichtlinien für Auto-Apps überprüfen.
  • Kompatibilitätsmodus von Android Automotive OS: Der Kompatibilitätsmodus (android.software.car.display_compatibility) ist eine Systemfunktion auf ausgewählten Fahrzeugen, die eine systemweite Zurück-Geste, sichere Darstellungsbereiche, Dichteskalierung und eine undurchsichtige Blockade im Fahrbetrieb (Verschieben von Aktivitäten in den Zustand Stopped) bereitstellt. Der Kompatibilitätsmodus ist nur für Apps relevant, die Android Automotive OS unterstützen; er ist nicht relevant für Apps, die nur Android Auto unterstützen.

Codebase-Erkundung

Durchsuchen Sie die Codebase nach AndroidManifest.xml (oder erstellen Sie Assets/Plugins/Android/AndroidManifest.xml in Unity-Projekten), res/xml/automotive_app_desc.xml, build.gradle, build.gradle.kts, oder gradle/libs.versions.toml-Dateien. Finden Sie vorhandene Videoplayer, MediaSession-Klassen, requestedOrientation-Aufrufe und WindowInsets- Handler. Fragen Sie, sofern nicht anders vom Benutzer angewiesen, um Erlaubnis, bevor Sie Abhängigkeiten hinzufügen.

Schritt 1: Konfigurieren des App-Manifests

Deklarieren Sie die App-Kategorie, Zielplattformen, Hardware-Feature-Anforderungen und Aktivitätskonfiguration in AndroidManifest.xml.

1.1: Identifizieren der App-Kategorie

  • Video-Apps : Video-Apps MÜSSEN android:appCategory="video" auf <application> setzen und DÜRFEN NICHT app/src/main/res/xml/automotive_app_desc.xml mit uses name="video" einfügen.
  • Spiele : Spiele MÜSSEN android:appCategory="game" auf <application> setzen. Deklarieren Sie android.hardware.gamepad mit android:required="false", wenn die App Controller-Eingabe unterstützt.
  • Browser : Browser MÜSSEN <category android:name="android.intent.category.APP_BROWSER"/> im MAIN <intent-filter> einer exportierten <activity> (android:exported="true") enthalten.

1.2: Zielplattformen und Hardware-Features identifizieren

  • Android Auto : Apps, die auf Android Auto (Android 15+) abzielen, MÜSSEN <category android:name="android.intent.category.CAR_LAUNCHER"/> zu einem <intent-filter> in der AndroidManifest.xml hinzufügen. Fügen Sie es zum MAIN <intent-filter> hinzu, es sei denn, der Benutzer gibt einen anderen Intent-Filter an. FÜGEN SIE DIESE KATEGORIE NIE HINZU, wenn die App ausschließlich auf Android Automotive OS abzielt.
  • Android Automotive OS : Apps, die auf Android Automotive OS abzielen, MÜSSEN <uses-feature android:name="android.hardware.type.automotive" android:required="false"/> ("false" für Mobil- oder Multi-Formfaktor-Tracks; "true" nur, wenn die App auf dem dedizierten Automotive OS-Track veröffentlicht wird) in der AndroidManifest.xml deklarieren. FÜGEN SIE DIESES FEATURE-TAG NIE HINZU, wenn die App ausschließlich auf Android Auto abzielt.
  • Nicht erforderliche Hardware-Features (DO-1) : Um die Google Play-Feature-Anforderungen und DO-1 zu erfüllen, deklarieren Sie nicht unterstützte Features (android.hardware.wifi, android.hardware.screen.portrait, android.hardware.screen.landscape, android.hardware.camera) mit android:required="false" und entfernen Sie android:required="true" bei Features, die in Autos nicht vorhanden sind.
  • Display-Kontinuität (LS-C1) : Konfigurieren Sie android:configChanges für screenSize, smallestScreenSize, orientation, screenLayout und density auf <activity>, damit ein Wechsel zu oder von einem entfernten Display die Aktivität nicht neu erstellt oder die Wiedergabe stottert.
  • Kompatibilitätsmodus und Ablenkung : Die Deklaration des Kompatibilitätsmodus ist optional und nur für Apps relevant, die Android Automotive OS unterstützen. FÜGEN SIE DEN KOMPATIBILITÄTSMODUS NIE für Apps hinzu, die nur Android Auto unterstützen. Das Hinzufügen von android.hardware.type.automotive deaktiviert den Kompatibilitätsmodus, es sei denn, <meta-data android:name="android.software.car.display_compatibility" android:value="true"/> wird zu <application> hinzugefügt. Wenn eine App android.software.car.display_compatibility in AndroidManifest.xml deklariert, MUSS die App zur Laufzeit PackageManager.hasSystemFeature("android.software.car.display_compatibility") prüfen und doppelte app-interne Zurück- oder Schließen-Elemente ausblenden, wenn true zurückgegeben wird. Geparkte Apps DÜRFEN NICHT <meta-data android:name="distractionOptimized" android:value="true"/> auf irgendeiner <activity> enthalten (DD-2, DD-3).

Schritt 2: Bereitstellen von Rücknavigation und Ausrichtungsunterstützung

2.1: App-interne Zurück- und Schließen-Elemente hinzufügen

Android Automotive OS-Fahrzeuge müssen keine Hardware- oder Software- Zurück-Taste oder Gestennavigation haben (AN-1). Stellen Sie explizite UI- Zurück- und Schließen-Steuerelemente auf jedem nicht-root-Bildschirm bereit, einschließlich Detailbildschirmen und Vollbild-Playern:

  • Wenn AndroidManifest.xml nicht android.software.car.display_compatibility deklariert: Zeigen Sie bedingungslos explizite app-interne Zurück- und Schließen-Steuerelemente an.
  • Wenn AndroidManifest.xml android.software.car.display_compatibility mit android:value="true" deklariert: Zeigen Sie app-interne Zurück- und Schließen-Steuerelemente nur an, wenn PackageManager.hasSystemFeature("android.software.car.display_compatibility") false zurückgibt.

2.2: Laufzeit-Ausrichtungsanfragen absichern

Fahrzeugdisplays haben feste Ausrichtungen. Das Anfordern von Querformat auf einem display mit festem Hochformat verursacht Letterboxing oder Endlosschleifen (DO-1). Entfernen Sie hartcodierte android:screenOrientation-Manifestattribute und prüfen Sie PackageManager.FEATURE_SCREEN_LANDSCAPE und PackageManager.FEATURE_SCREEN_PORTRAIT, bevor Sie requestedOrientation setzen.

Schritt 3: An Systemleisten und unregelmäßige Display-Aussparungen anpassen

3.1: Steuerbare Systemleisten-Einzüge verfolgen

Auf Android Automotive OS dürfen OEMs Systemleisten sichtbar sperren, damit Klima- und Fahrzeugsteuerungen zugänglich bleiben (AR-1). Verfolgen Sie steuerbare Einzüge mit OnControllableInsetsChangedListener, blenden Sie nur steuerbare Leisten aus und wenden Sie windowInsetsPadding für nicht steuerbare statusBars, navigationBars und displayCutout-Einzüge an.

3.2: Sicheres Rendern in unregelmäßige Display-Aussparungen

Um das Kriterium der Stufe 1 AR-2 auf gebogenen oder nicht-rechteckigen Fahrzeugdisplays zu erfüllen, VERWENDEN SIE NIE LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT (0) oder LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES (1). Konfigurieren Sie LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS (3) oder LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER (2) mit dem car-Ressourcenqualifizierer in res/values-car-v30/integers.xml:

<integer name="windowLayoutInDisplayCutoutMode">3</integer>

Schützen Sie interaktive UI, App-Leisten und scrollbare Listen mit WindowInsets.safeDrawing.

Schritt 4: Anforderungen an Fahrerablenkung und Medienwiedergabe erfüllen

4.1: Wiedergabe bei Lebenszyklusübergängen pausieren und Wiederaufnahme während der Fahrt blockieren

Wenn ein Fahrzeug zu fahren beginnt, überlagert das Betriebssystem geparkte Aktivitäten mit einer blockierenden Überlagerung und löst onPause (und onStop bei Fahrzeugen im Kompatibilitätsmodus) aus. Um DD-2, DD-3 und MC-1 zu erfüllen:

  1. Pausieren Sie die Wiedergabe bei ON_PAUSE oder ON_STOP mit LifecycleEventEffect aus androidx.lifecycle:lifecycle-runtime-compose.
  2. Machen Sie eine MediaSession (androidx.media3:media3-session) mit Play-, Pause- oder Stop-Befehlen und Elementmetadaten (MC-1) verfügbar und geben Sie sie in onCleared frei.
  3. Fügen Sie useLibrary("android.car") in build.gradle.kts hinzu, umschließen Sie ExoPlayer in ForwardingSimpleBasePlayer, hören Sie auf CarUxRestrictionsManager, pausieren Sie die Wiedergabe, wenn isRequiresDistractionOptimization true wird, und entfernen Sie COMMAND_PLAY_PAUSE in getState, damit externe MediaSession-Steuerungen die Wiedergabe während der Fahrt nicht fortsetzen können:
@UnstableApi
class CarAwarePlayer(context: Context) :
    ForwardingSimpleBasePlayer(ExoPlayer.Builder(context).build()) {
    private var shouldPreventPlay = false
    private var pausedByUxRestrictions = false
    private lateinit var carUxRestrictionsManager: CarUxRestrictionsManager

    init {
        if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
            val car = Car.createCar(context)
            carUxRestrictionsManager =
                car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE) as CarUxRestrictionsManager
            shouldPreventPlay =
                carUxRestrictionsManager.currentCarUxRestrictions.isRequiresDistractionOptimization
            invalidateState()

            carUxRestrictionsManager.registerListener { restrictions: CarUxRestrictions ->
                shouldPreventPlay = restrictions.isRequiresDistractionOptimization
                if (!shouldPreventPlay && pausedByUxRestrictions) {
                    handleSetPlayWhenReady(true)
                    invalidateState()
                } else if (shouldPreventPlay && isPlaying) {
                    pausedByUxRestrictions = true
                    handleSetPlayWhenReady(false)
                    invalidateState()
                }
            }
        }
    }

    override fun getState(): State {
        val state = super.getState()
        return state.buildUpon()
            .setAvailableCommands(
                state.availableCommands.buildUpon()
                    .removeIf(COMMAND_PLAY_PAUSE, shouldPreventPlay)
                    .build()
            )
            .build()
    }

    override fun handleRelease(): ListenableFuture<*> {
        if (::carUxRestrictionsManager.isInitialized) {
            carUxRestrictionsManager.unregisterListener()
        }
        return super.handleRelease()
    }
}

4.2: Hintergrundaudio während der Fahrt unterstützen (optionale Beta-Funktion)

Da dies eine optionale Beta-Funktion ist, IMPLEMENTIEREN SIE DIESE FUNKTION NIE, es sei denn, der Benutzer fordert sie an. So implementieren Sie die Funktion:

  1. Deklarieren Sie <uses-feature android:name="com.android.car.background_audio_while_driving" android:required="false" /> in AndroidManifest.xml, zusammen mit FOREGROUND_SERVICE- und FOREGROUND_SERVICE_MEDIA_PLAYBACK-Berechtigungen.
  2. Prüfen Sie die Fahrzeugunterstützung zur Laufzeit mit CarFeatures.isFeatureEnabled(context, CarFeatures.FEATURE_BACKGROUND_AUDIO_WHILE_DRIVING) aus androidx.car.app:app. Setzen Sie shouldPreventPlay nur, wenn !isBackgroundAudioWhileDrivingSupported && restrictions.isRequiresDistractionOptimization.
  3. Hostet die MediaSession und den Player in einem exportierten MediaSessionService mit android:foregroundServiceType="mediaPlayback" und verbinden Sie sich von der UI mit MediaController.Builder und buildAsync.

Schritt 5: Schützen sensibler Daten in Browser-Apps

Da Fahrzeuge gemeinsam genutzte Geräte sind, MÜSSEN Browser den Zugriff auf gespeicherte Passwörter und Zahlungsmethoden blockieren, es sei denn, sie sind durch eine Profilsperre geschützt (SD-1). Vor dem Synchronisieren von Passwörtern oder Zahlungsdaten mit dem Fahrzeug MÜSSEN Browser den Benutzer zur Authentifizierung auffordern und eine Mitteilung auf dem Fahrzeugbildschirm anzeigen, dass seine Daten mit dem Auto synchronisiert werden (SD-2).

Prüfen Sie, ob eine PIN, ein Muster oder ein Passwort mit KeyguardManager festgelegt ist, öffnen Sie Settings.ACTION_SECURITY_SETTINGS, falls nicht, und authentifizieren Sie sich mit BiometricPrompt mit nur BiometricManager.Authenticators.DEVICE_CREDENTIAL (Fahrzeuge haben keine biometrische Hardware):

val keyguardManager = context.getSystemService<KeyguardManager>()
val isDeviceSecure = keyguardManager?.isDeviceSecure == true
lateinit var biometricPrompt: BiometricPrompt

if (!isDeviceSecure) {
    context.startActivity(
        Intent(Settings.ACTION_SECURITY_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    )
} else {
    val promptInfo = BiometricPrompt.PromptInfo.Builder()
        .setTitle(context.getString(R.string.auth_title))
        .setSubtitle(context.getString(R.string.sync_data_to_car_notice))
        .setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
        .build()
    biometricPrompt.authenticate(promptInfo)
}

Schritt 6: Implementierung überprüfen

Erstellen Sie die App mit ./gradlew assembleDebug. Finden und beheben Sie alle Build-Fehler.

Nach der Implementierung

…

[truncated for translation]

Verwandte Skills