הוספת תמיכה ב-Android Automotive OS לאפליקציית המדיה

מערכת ההפעלה Android Automotive OS מאפשרת למשתמשים להתקין אפליקציות במכונית. כדי להגיע למשתמשים בפלטפורמה הזו, צריך להפיץ אפליקציה מותאמת לנהגים שתואמת ל-Android Automotive OS. אפשר להשתמש כמעט בכל הקוד והמשאבים מאפליקציית Android Auto, אבל צריך ליצור גרסת build נפרדת שעומדת בדרישות שמופיעות בדף הזה.

סקירה כללית על פיתוח

כדי להוסיף תמיכה ב-Android Automotive OS, צריך לבצע רק כמה שלבים, כמו שמתואר בקטעים הבאים:

  1. הפעלת תכונות לרכב ב-Android Studio
  2. יצירת מודול לרכב
  3. מעדכנים את יחסי התלות ב-Gradle.
  4. אופציונלי: הטמעה של הגדרות ופעילויות כניסה.
  5. אפשר גם לקרוא רמזים לגבי מארחי מדיה.

שיקולים בתכנון

מערכת Android Automotive OS דואגת לפריסת תוכן המדיה שהיא מקבלת משירות דפדפן המדיה של האפליקציה. כלומר, האפליקציה לא מציירת את ממשק המשתמש ולא מתחילה אף אחת מהפעילויות שלה כשמשתמש מפעיל הפעלת מדיה.

אם אתם מטמיעים הגדרות או פעילויות כניסה, הפעילויות האלה צריכות להיות מותאמות לרכב. כדאי לעיין בהנחיות העיצוב ל-Android Automotive OS כשמעצבים את האזורים האלה באפליקציה.

הגדרת הפרויקט

כדי להפעיל תמיכה ב-Android Automotive OS, צריך להגדיר כמה חלקים בפרויקט של האפליקציה.

הפעלת תכונות לרכב ב-Android Studio

כדי לוודא שכל התכונות של Automotive OS מופעלות, צריך להשתמש ב-Android Studio בגרסה 4.0 ואילך.

יצירת מודול לרכב

לחלק מהרכיבים של מערכת ההפעלה Android Automotive, כמו קובץ המניפסט, יש דרישות ספציפיות לפלטפורמה. יוצרים מודול שיכול להפריד את הקוד של הרכיבים האלה מקוד אחר בפרויקט, כמו הקוד שמשמש את אפליקציית הטלפון.

כדי להוסיף מודול לרכב לפרויקט:

  1. ב-Android Studio, לוחצים על File > New > New Module (קובץ > חדש > מודול חדש).
  2. בוחרים באפשרות מודול לרכב ולוחצים על הבא.
  3. מזינים שם של אפליקציה או ספרייה. זה השם שהמשתמשים רואים לאפליקציה שלכם ב-Android Automotive OS.
  4. מזינים שם מודול.
  5. משנים את שם החבילה כך שיתאים לאפליקציה.
  6. בוחרים באפשרות API 28: Android 9.0 (Pie) בשדה Minimum SDK ולוחצים על Next (הבא).

    כל הרכבים שתומכים ב-Android Automotive OS פועלים על Android 9 (רמת API‏ 28) ומעלה, ולכן בחירת הערך הזה תטרגט את כל הרכבים התואמים.

  7. בוחרים באפשרות No Activity (ללא פעילות) ואז לוחצים על Finish (סיום).

אחרי שיוצרים את המודול ב-Android Studio, פותחים את AndroidManifest.xml במודול החדש לרכב:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.media">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" />

    <uses-feature
        android:name="android.hardware.type.automotive"
        android:required="true" />

</manifest>

הרכיב <application> כולל מידע סטנדרטי על האפליקציה, וגם את הרכיב <uses-feature> שבו מוצהרת תמיכה ב-Android Automotive OS. שימו לב: לא הוגדרו פעילויות במניפסט.

אם אתם מטמיעים הגדרות או פעילויות כניסה, תוכלו להוסיף אותן כאן. המערכת מפעילה את הפעילויות האלה באמצעות כוונות מפורשות, והן הפעילויות היחידות שמוצהרות במניפסט של האפליקציה ל-Android Automotive OS.

אחרי שמוסיפים הגדרות או פעולות כניסה, משלימים את קובץ המניפסט על ידי הגדרת המאפיין android:appCategory של הרכיב <application> לערך "audio".

<application
  ...
  android:appCategory="audio" />

הצהרה על דרישות התכונה

כדי להפיץ אפליקציות ל-Android Automotive OS באמצעות Google Play, הן צריכות לעמוד בדרישות מסוימות. מידע נוסף מופיע במאמר דרישות התכונות של Google Play.

הצהרה על תמיכה במדיה ב-Android Automotive OS

כדי להצהיר שהאפליקציה תומכת ב-Android Automotive OS, צריך להשתמש ברשומה הבאה במניפסט:

<application>
    ...
    <meta-data android:name="com.android.automotive"
        android:resource="@xml/automotive_app_desc"/>
    ...
</application>

רשומה במניפסט שמפנה לקובץ XML שבו מוצהרות היכולות של האפליקציה בתחום הרכב.

כדי לציין שיש לכם אפליקציית מדיה, מוסיפים קובץ XML בשם automotive_app_desc.xml לספרייה res/xml/ בפרויקט. צריך לכלול בקובץ את התוכן הבא:

<automotiveApp>
    <uses name="media"/>
</automotiveApp>

מסנני Intent

מערכת Android Automotive OS משתמשת ב-Intents מפורשים כדי להפעיל פעילויות באפליקציית המדיה שלכם. אל תכללו בקובץ המניפסט מסנני Intent מסוג CATEGORY_LAUNCHER או ACTION_MAIN.

פעילויות כמו זו שמוצגת בדוגמה הבאה מכוונות בדרך כלל לטלפון או למכשיר נייד אחר. צריך להצהיר על הפעילויות האלה במודול שבונה את האפליקציה לטלפון, ולא במודול שבונה את האפליקציה ל-Android Automotive OS.

<activity android:name=".MyActivity">
    <intent-filter>
        <!-- You can't use either of these intents for Android Automotive OS -->
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <!--
        In their place, you can include other intent filters for any activities
        that your app needs for Android Automotive OS, such as settings or
        sign-in activities.
        -->
    </intent-filter>
</activity>

עדכון יחסי התלות של Gradle

מומלץ לשמור את שירות דפדפן המדיה במודול נפרד שמשותף בין האפליקציה לטלפון לבין מודול הרכב. אם אתם משתמשים בגישה הזו, אתם צריכים לעדכן את מודול הרכב כדי לכלול את המודול המשותף, כמו שמוצג בקטע הקוד הבא:

my-auto-module/build.gradle

מגניב

buildscript {
    ...
    dependencies {
        ...
        implementation project(':shared_module_name')
    }
}

Kotlin

buildscript {
    ...
    dependencies {
        ...
        implementation(project(":shared_module_name"))
    }
}

הטמעה של הגדרות ופעילויות כניסה

בנוסף לשירות של דפדפן המדיה, אפשר גם לספק הגדרות שמותאמות לרכב ופעילויות כניסה לאפליקציה ל-Android Automotive OS. הפעילויות האלה מאפשרות לספק תכונות האפליקציה שלא נכללות בממשקי ה-API של Android Media.

צריך להטמיע את הפעילויות האלה רק אם האפליקציה שלכם ל-Android Automotive OS צריכה לאפשר למשתמשים להיכנס לחשבון או לציין הגדרות של האפליקציה. ‫Android Auto לא משתמש בפעילויות האלה.

תהליכי עבודה של פעילויות

בתרשים הבא אפשר לראות איך משתמש מקיים אינטראקציה עם ההגדרות ועם פעילויות הכניסה באמצעות מערכת ההפעלה Android Automotive:

Workflows לפעילויות שקשורות להגדרות ולכניסה

איור 1. תהליכי עבודה של הגדרות ופעילות כניסה.

איך להפחית את ההסחות בהגדרות ובפעילויות הכניסה

כדי לוודא שההגדרות ופעולות הכניסה לחשבון זמינות לשימוש רק כשהרכב של המשתמש חונה, צריך לוודא שהרכיבים <activity>לא כוללים את הרכיב <meta-data>. אם רכיב כזה קיים, האפליקציה תידחה במהלך הבדיקה.

<!-- NOT ALLOWED -->
<meta-data
  android:name="distractionOptimized"
  android:value="true"/>

הוספת פעילות של הגדרות

אתם יכולים להוסיף פעילות של הגדרות שעברו אופטימיזציה לשימוש ברכב, כדי שהמשתמשים יוכלו להגדיר את ההגדרות של האפליקציה שלכם ברכב. פעילות ההגדרות יכולה לספק גם תהליכי עבודה אחרים, כמו כניסה לחשבון של משתמש או יציאה ממנו, או מעבר בין חשבונות משתמשים. חשוב לזכור שהפעילות הזו מופעלת רק על ידי אפליקציה שפועלת ב-Android Automotive OS. אפליקציות לטלפון שמחוברות ל-Android Auto לא משתמשות בו.

הצהרה על פעילות שקשורה להגדרות

צריך להצהיר על פעילות ההגדרות בקובץ המניפסט של האפליקציה, כמו שמוצג בקטע הקוד הבא:

<application>
    ...
    <activity android:name=".AppSettingsActivity"
              android:exported="true"
              android:theme="@style/SettingsActivity"
              android:label="@string/app_settings_activity_title">
        <intent-filter>
            <action android:name="android.intent.action.APPLICATION_PREFERENCES"/>
        </intent-filter>
    </activity>
    ...
</application>

הטמעה של פעילות ההגדרות

כשמשתמש מפעיל את האפליקציה, מערכת Android Automotive OS מזהה את פעילות ההגדרות שהצהרתם עליה ומציגה אמצעי עזר, כמו סמל. המשתמש יכול להקיש על האפשרות הזו או לבחור אותה במסך של הרכב כדי לנווט לפעילות. מערכת ההפעלה Android Automotive OS שולחת את כוונת ACTION_APPLICATION_PREFERENCES שמורה לאפליקציה להתחיל את פעילות ההגדרות.

בהמשך הקטע הזה מוסבר איך אפשר להתאים קוד מאפליקציית הדוגמה Universal Android Music Player (UAMP) כדי להטמיע פעילות הגדרות באפליקציה.

כדי להתחיל, מורידים את קוד לדוגמה:

# Clone the UAMP repository
git clone https://github.com/android/uamp.git

# Fetch the appropriate pull request to your local repository
git fetch origin pull/323/head:NEW_LOCAL_BRANCH_NAME

# Switch to the new branch
git checkout NEW_LOCAL_BRANCH_NAME

כדי להטמיע את הפעילות:

  1. מעתיקים את התיקייה automotive/automotive-lib למודול הרכב.
  2. מגדירים עץ העדפות כמו בדוגמה ב-automotive/src/main/res/xml/preferences.xml.
  3. מטמיעים PreferenceFragmentCompat כך שפעילות ההגדרות תוצג. מידע נוסף זמין בקבצים SettingsFragment.kt ו-SettingsActivity.kt ב-UAMP ובמדריך ההגדרות ל-Android.

כשמטמיעים את פעילות ההגדרות, כדאי לפעול לפי השיטות המומלצות הבאות לשימוש בחלק מהרכיבים בספריית ההעדפות:

  • לא יהיו יותר משתי רמות עומק מתחת לתצוגה הראשית בפעילות ההגדרות.
  • אל תשתמשו ב-DropDownPreference. במקום זאת, צריך להשתמש ב-ListPreference.
  • רכיבים ארגוניים:
    • PreferenceScreen
      • ההגדרה הזו חייבת להיות ברמה העליונה של עץ ההעדפות.
    • PreferenceCategory
      • משמש לקיבוץ של אובייקטים Preference.
      • צריך לכלול title.
  • צריך לכלול key וtitle בכל הרכיבים הבאים. אפשר גם לכלול summary, icon או את שניהם:
    • Preference
      • אפשר להתאים אישית את הלוגיקה ב-callback‏ onPreferenceTreeClick() של ההטמעה של PreferenceFragmentCompat.
    • CheckBoxPreference
      • אפשר להשתמש ב-summaryOn או ב-summaryOff במקום ב-summary לטקסט מותנה.
    • SwitchPreference
      • אפשר להשתמש ב-summaryOn או ב-summaryOff במקום ב-summary לטקסט מותנה.
      • הערך יכול להיות switchTextOn או switchTextOff.
    • SeekBarPreference
      • כולל min,‏ max ו-defaultValue.
    • EditTextPreference
      • כולל dialogTitle,‏ positiveButtonText ו-negativeButtonText.
      • יכול להכיל את התכונות dialogMessage ו-dialogLayoutResource, או רק אחת מהן.
    • com.example.android.uamp.automotive.lib.ListPreference
      • הנתונים נגזרים בעיקר מ-ListPreference.
      • התג הזה משמש להצגת רשימה של Preference אובייקטים עם אפשרות בחירה אחת.
      • חייב לכלול מערך של entries ו-entryValues תואמים.
    • com.example.android.uamp.automotive.lib.MultiSelectListPreference
      • מקורות המידע העיקריים הם MultiSelectListPreference
      • התג הזה משמש להצגת רשימה של אובייקטים מסוג Preference לבחירה מתוך כמה אפשרויות.
      • חייב לכלול מערך של entries ו-entryValues תואמים.

הוספת פעילות כניסה

אם האפליקציה שלכם דורשת מהמשתמשים להתחבר לפני שהם יכולים להשתמש בה, אתם יכולים להוסיף פעילות כניסה שמותאמת לרכב ומטפלת בכניסה לאפליקציה וביציאה ממנה. אתם יכולים גם להוסיף תהליכי עבודה של כניסה ויציאה לפעילות הגדרות, אבל כדאי להשתמש בפעילות כניסה ייעודית אם אי אפשר להשתמש באפליקציה עד שהמשתמש מתחבר. חשוב לזכור שהפעילות הזו מופעלת רק על ידי אפליקציה שפועלת ב-Android Automotive OS. אפליקציות בטלפון שמחוברות ל-Android Auto לא משתמשות בו.

דרישת כניסה בתחילת השימוש באפליקציה

כדי לדרוש ממשתמשים להיכנס לחשבון לפני שהם יכולים להשתמש באפליקציה שלכם, שירות הדפדפן למדיה צריך לבצע את הפעולות הבאות:

  1. ב-method ‏onLoadChildren() של השירות, שולחים את התוצאה null באמצעות ה-method ‏sendResult().
  2. מגדירים את PlaybackStateCompat של סשן המדיה ל-STATE_ERROR באמצעות ה-method‏ setState(). ההודעה הזו מציינת ל-Android Automotive OS שלא ניתן לבצע פעולות אחרות עד שהשגיאה תיפתר.
  3. מגדירים את קוד השגיאה PlaybackStateCompat של סשן המדיה לערך ERROR_CODE_AUTHENTICATION_EXPIRED. הפעולה הזו מציינת למערכת ההפעלה Android Automotive OS שהמשתמש צריך לעבור אימות.
  4. מגדירים את הודעת השגיאה של סשן המדיה באמצעות ה-method‏ setErrorMessage().PlaybackStateCompat מכיוון שהודעת השגיאה הזו גלויה למשתמשים, התאימו אותה לשילוב של השפה והאזור הנוכחיים של המשתמש.
  5. מגדירים את הנתונים הנוספים של סשן המדיה PlaybackStateCompat באמצעות ה-method‏ setExtras(). צריך לכלול את שני המפתחות הבאים או את שלושתם:

    • PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL: מחרוזת שמוצגת בלחצן שמתחיל את תהליך הכניסה. מכיוון שהמחרוזת הזו מוצגת למשתמש, צריך להתאים אותה ללוקאל הנוכחי של המשתמש.
    • PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT: ‫PendingIntent שמפנה את המשתמש לפעילות הכניסה שלו כשהוא מקיש על הלחצן שמצוין על ידי PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL.
    • PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_USING_CAR_APP_LIBRARY_INTENT: ‫PendingIntent שמפנה את המשתמש לפעילות הכניסה לספריית אפליקציות לרכב. מארח ספריית אפליקציות לרכב מותאם לנהיגה, ולכן ה-Intent עוקף אוטומטית את מסך פתרון השגיאות ומציג מיד את מסך הכניסה. אם מגדירים את התוסף הזה, צריך להגדיר גם את שני התוספים הקודמים כדי להבטיח תאימות לאחור עם כלי רכב ישנים יותר.

בקטע הקוד הבא אפשר לראות איך האפליקציה יכולה לדרוש מהמשתמשים להיכנס לחשבון לפני השימוש באפליקציה:

Kotlin

import androidx.media.utils.MediaConstants

val signInIntent = Intent(this, SignInActivity::class.java)
val signInActivityPendingIntent = PendingIntent.getActivity(this, 0,
    signInIntent, 0)
val extras = Bundle().apply {
    putString(
        MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL,
        "Sign in"
    )
    putParcelable(
        MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT,
        signInActivityPendingIntent
    )
}

val playbackState = PlaybackStateCompat.Builder()
        .setState(PlaybackStateCompat.STATE_ERROR, 0, 0f)
        .setErrorMessage(
            PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED,
            "Authentication required"
        )
        .setExtras(extras)
        .build()
mediaSession.setPlaybackState(playbackState)

Java

import androidx.media.utils.MediaConstants;

Intent signInIntent = new Intent(this, SignInActivity.class);
PendingIntent signInActivityPendingIntent = PendingIntent.getActivity(this, 0,
    signInIntent, 0);
Bundle extras = new Bundle();
extras.putString(
    MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL,
    "Sign in");
extras.putParcelable(
    MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT,
    signInActivityPendingIntent);

PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder()
    .setState(PlaybackStateCompat.STATE_ERROR, 0, 0f)
    .setErrorMessage(
            PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED,
            "Authentication required"
    )
    .setExtras(extras)
    .build();
mediaSession.setPlaybackState(playbackState);

אחרי שהמשתמש מאומת בהצלחה, צריך להגדיר את PlaybackStateCompat בחזרה למצב שאינו STATE_ERROR, ואז להחזיר את המשתמש ל-Android Automotive OS באמצעות קריאה לשיטה finish() של הפעילות.

הטמעה של פעילות הכניסה

‫Google מציעה מגוון כלים לניהול זהויות שבהם אפשר להשתמש כדי לעזור למשתמשים להיכנס לאפליקציה ברכב. יש כלים, כמו אימות ב-Firebase, שמספקים ערכות כלים מלאות שיכולות לעזור לכם ליצור חוויות אימות בהתאמה אישית. כלים אחרים מסתמכים על פרטי הכניסה הקיימים של המשתמש או על טכנולוגיות אחרות כדי לעזור לכם ליצור חוויית כניסה חלקה למשתמשים.

הכלים הבאים יכולים לעזור לכם ליצור חוויית כניסה קלה יותר למשתמשים שנכנסו בעבר לחשבון במכשיר אחר:

  • כניסה והרשמה בהקשה אחת: אם כבר הטמעתם את התכונה 'הקשה אחת' במכשירים אחרים, כמו באפליקציית הטלפון, כדאי להטמיע אותה גם באפליקציית Android Automotive OS כדי לתמוך במשתמשים קיימים של התכונה.
  • כניסה באמצעות חשבון Google: אם כבר הטמעתם כניסה באמצעות חשבון Google במכשירים אחרים, כמו באפליקציה לטלפון, כדאי להטמיע כניסה באמצעות חשבון Google באפליקציה שלכם ל-Android Automotive OS כדי לתמוך במשתמשים קיימים של כניסה באמצעות חשבון Google.
  • מילוי אוטומטי של Google: אם המשתמשים הפעילו את המילוי האוטומטי של Google במכשירי Android אחרים שלהם, פרטי הכניסה שלהם נשמרים במנהל הסיסמאות של Google. כשמשתמשים כאלה נכנסים לאפליקציית Android Automotive OS שלכם, התכונה 'מילוי אוטומטי עם Google' מציעה פרטי כניסה רלוונטיים ששמורים במערכת. השימוש במילוי אוטומטי של Google לא דורש פיתוח אפליקציות. עם זאת, מפתחי אפליקציות יכולים לבצע אופטימיזציה לאפליקציות שלהם כדי לקבל תוצאות באיכות טובה יותר. התכונה 'מילוי אוטומטי של Google' נתמכת בכל המכשירים עם Android מגרסה 8.0 (רמת API‏ 26) ומעלה, כולל Android Automotive OS.

שימוש ב-AccountManager

אפליקציות ל-Android Automotive OS שכוללות אימות חייבות להשתמש ב-AccountManager, מהסיבות הבאות:

  • חוויית משתמש משופרת וניהול חשבונות קל יותר: המשתמשים יכולים לנהל את כל החשבונות שלהם מתפריט החשבונות בהגדרות המערכת, כולל כניסה ויציאה.
  • חוויות 'אורח': מכוניות הן מכשירים משותפים, ולכן יצרני ציוד מקורי יכולים להפעיל חוויות 'אורח' ברכב, שבהן אי אפשר להוסיף חשבונות. ההגבלה הזו מתבצעת באמצעות DISALLOW_MODIFY_ACCOUNTS עבור AccountManager.

הרשאות

אם אתם צריכים לבקש הרשאות מהמשתמש, אתם יכולים להשתמש באותו תהליך כמו בפעילות האימות או בפעילות ההגדרות בתרשים של תהליכי העבודה של הפעילות שמוצג בקטע הקודם.

הטמעה של יציאה מהחשבון

לא משנה איך בחרתם להטמיע את הכניסה, כשמשתמש מתנתק, חובה לקרוא ל-MediaBrowserServiceCompat#notifyChildrenChanged(rootId) כדי לבטל את העץ של הדפדפן, כך שאפליקציית המארח של המדיה תנקה את כל המידע שקשור למשתמש (כמו שאילתת החיפוש האחרונה).

מפעילים את אפליקציית המארח של המדיה

אתם יכולים ליצור כוונות לפתוח את אפליקציית המארח של המדיה באפליקציה שלכם או בתוכן בתוך האפליקציה שלכם. לדוגמה:

  • האפליקציה יכולה לפרסם התראה עם intent בהמתנה שמאפשרת למשתמש לפתוח את האפליקציה כדי להאזין לתוכן חדש.
  • האפליקציה יכולה לטפל בקישורי עומק ולפתוח את אפליקציית המארח בתצוגה המתאימה ביותר.

קביעת היכולות של מארח המדיה

גרסאות של אפליקציית המארח של המדיה תומכות ביכולות שונות. מארחים מציינים תמיכה ביכולות שונות על ידי הכללת מסנני כוונות לפעולות הכוונה הבאות:

כל האפליקציות של מארחי מדיה תומכות בכוונות MEDIA_TEMPLATE. כדי לבדוק אם מארח המדיה תומך בכוונות MEDIA_TEMPLATE_V2, אפשר להשתמש ב-queryIntentActivities() באופן הבא:

val isMediaTemplateV2Supported = packageManager.queryIntentActivities(
  Intent(MediaIntentExtras.ACTION_MEDIA_TEMPLATE_V2),
  //  MATCH_DEFAULT_ONLY  since the host should be started with implicit intents
  //  MATCH_SYSTEM_ONLY  excludes any apps that aren't preinstalled
  PackageManager.MATCH_DEFAULT_ONLY or PackageManager.MATCH_SYSTEM_ONLY
).size > 0

יצירה של כוונת משתמש ושימוש בה

בהתאם לפעולות הכוונה שנתמכות על ידי מארח המדיה ולתרחיש השימוש הספציפי שלכם, אתם יכולים לספק את התוספים הבאים כשאתם יוצרים את הכוונה שבה אתם משתמשים כדי להפעיל את אפליקציית מארח המדיה.

מפתח נוסף סוג תיאור פעולות נתמכות
EXTRA_KEY_MEDIA_COMPONENT String שם הרכיב המפושט של MediaBrowserService אפליקציית המארח של המדיה שאליה האפליקציה צריכה להתחבר – בדרך כלל האפליקציה שלכם. אם לא מציינים את התוסף הזה, אפליקציית המארח של המדיה תוגדר כברירת מחדל כמקור המדיה הפעיל. MEDIA_TEMPLATE, MEDIA_TEMPLATE_V2
EXTRA_KEY_SEARCH_QUERY String שאילתת החיפוש שבה יש להשתמש כשמתקשרים MEDIA_TEMPLATE, MEDIA_TEMPLATE_V2
EXTRA_KEY_MEDIA_ID String מזהה המדיה שרוצים לפתוח בתצוגת העיון. MEDIA_TEMPLATE_V2
EXTRA_KEY_SEARCH_ACTION Integer הפעולה שיש לבצע אחרי שהחיפוש של EXTRA_KEY_SEARCH_QUERY מסתיים. MEDIA_TEMPLATE_V2

לדוגמה, אם המארח תומך בפעולות MEDIA_TEMPLATE_V2, הקוד הבא יפתח את אפליקציית מארח המדיה, יתחבר אל MyMediaBrowserService, יבצע חיפוש של 'ג'אז' ואז יפעיל את הפריט הראשון מתוצאות החיפוש. בכל המארחים האחרים, רק תיפתח אפליקציית המארח של המדיה ויתבצע חיפוש של 'ג'אז', והמשתמש יצטרך לבחור פריט להפעלה מתוך התוצאות.

val startMediaHostIntent = Intent(ACTION_MEDIA_TEMPLATE)
  .putExtra(MediaIntentExtras.EXTRA_KEY_MEDIA_COMPONENT, MyMediaBrowserService::class.java)
  .putExtra(MediaIntentExtras.EXTRA_KEY_SEARCH_QUERY, "Jazz")
  .putExtra(MediaIntentExtras.EXTRA_KEY_SEARCH_ACTION, MediaIntentExtras.EXTRA_VALUE_PLAY_FIRST_ITEM_FROM_SEARCH)

context.startActivity(startMediaHostIntent)

כדי לשפר את חוויית השימוש באפליקציית המדיה במכשירי Android Automotive OS, אפשר להוסיף לאפליקציה תמיכה בקישורי עומק. לדוגמה, כך המשתמשים יכולים לפתוח את האפליקציה ישירות מדפדפן או כשמתקבלת כתובת URL ששותפה מטלפון באמצעות שיתוף מהיר.

הוספה של מסנני Intent לקישורי עומק

כדי להודיע למערכת ההפעלה שהאפליקציה יכולה לטפל בקישורי עומק, צריך להגדיר בה פעילויות עם מסנני Intent מתאימים. במאמר הוספת מסנני Intent לקישורים נכנסים מפורט מידע על הפורמט של מסנני ה-Intent שמשמשים לקישורים עמוקים.

כדי לספק את חוויית המשתמש הכי טובה, כדאי לתמוך בכל קישורי העומק שהאפליקציה לנייד תומכת בהם, אם אפשר לתמוך בהם באופן סביר באפליקציה לרכב. אם באפליקציה יש הגדרות או פעילויות של כניסה לחשבון, צריך להצהיר על מסנני Intent לטיפול בהגדרות ובקישורי עומק של כניסה לחשבון ברכיבי המניפסט <activity> המתאימים. כדי להפעיל קישורי עומק להפעלת מדיה ולגלישה, אפשר להשתמש בפעילות מסוג trampoline, כפי שמתואר בהמשך הקטע הזה.

במאמר קריאת נתונים מ-Intents נכנסים מוסבר איך לקרוא את ה-Intent ששימש להפעלת הפעילות של האפליקציה ולהגיב אליו.

מכיוון שממשק המשתמש לגלישה ולהפעלה מצויר על ידי אפליקציית המארח, לפעילות שמשמשת לטיפול בקישורי עומק להפעלה ולפעולות גלישה לא צריך להיות ממשק משתמש משלה.

במקום זאת, צריך להשתמש בו בעיקר כדי ליצור כוונה (intent) ולקבל גישה לאפליקציית המדיה המארחת. אם יש צורך, הוא יכול גם לטפל בשינויים נוספים במצב האפליקציה, כמו הוספת פריטי מדיה לתור. בקטע הקוד הבא מוצגת הטמעה לדוגמה של פעילות בטרמפולינה:

fun DeepLinkTrampolineActivity : ComponentActivity() {

  override fun onCreate() {
    handleIntent(intent)
  }

  override fun onNewIntent(intent: Intent) {
    handleIntent(intent)
  }

  private fun handleIntent(intent: Intent) {
    // Handle any side effects, such as adding a song to the queue
    ...
    // Build the intent used to start the media host app
    val startMediaHostIntent = ...
    startActivity(intent)
    // Finish the activity immediately so it isn't shown on screen
    finish()
  }
}

קריאה של רמזים לגבי מארחי מדיה

בהתאם לאפליקציית המערכת (כולל הגרסה שלה) שמקושרת לשירות דפדפן המדיה, האפליקציה שלכם עשויה לקבל את התוספות הבאות:

טיפול בשגיאות

שגיאות באפליקציות מדיה ב-Android Automotive OS מועברות באמצעות PlaybackStateCompat של פעולת המדיה. לכל השגיאות, צריך להגדיר קוד שגיאה מתאים והודעת שגיאה ב-PlaybackStateCompat. כתוצאה מכך, Toast מופיע בממשק המשתמש.

אם מתרחשת שגיאה אבל ההפעלה יכולה להימשך, צריך להנפיק שגיאה לא קריטית. לדוגמה, יכול להיות שמשתמש יוכל להפעיל מוזיקה באפליקציה לפני שהוא נכנס לחשבון, אבל הוא יצטרך להיכנס לחשבון כדי לדלג על שיר. כשמשתמשים בשגיאה לא קריטית, המערכת יכולה להציע למשתמש להיכנס לחשבון בלי להפריע להפעלה של פריט המדיה הנוכחי.

כשמנפיקים שגיאה לא קריטית, צריך לשמור את שאר הנתונים של PlaybackStateCompat כמו שהם, מלבד קוד השגיאה והודעת השגיאה. הגישה הזו מאפשרת להמשיך בהפעלה של פריט המדיה הנוכחי בזמן שהמשתמש מחליט אם להיכנס לחשבון.

אם אי אפשר להפעיל את התוכן, למשל כשאין חיבור לאינטרנט ואין תוכן אופליין, צריך להגדיר את המצב PlaybackStateCompat ל-STATE_ERROR.

בעדכונים הבאים של PlaybackStateCompat, צריך לנקות את קודי השגיאה ואת הודעות השגיאה כדי למנוע הצגה של אזהרות מרובות לגבי אותה שגיאה.

אם בשלב כלשהו לא ניתן לטעון עץ של דפדפן – לדוגמה, אם נדרש אימות והמשתמש לא מחובר – צריך לשלוח עץ של דפדפן ריק. כדי לציין זאת, מחזירים תוצאת null מהפונקציה onLoadChildren() עבור צומת המדיה הבסיסי. במקרה כזה, המערכת מציגה שגיאה במסך מלא עם הודעת השגיאה שמוגדרת ב-PlaybackStateCompat.

שגיאות שדורשות פעולה

אם השגיאה דורשת פעולה, צריך להגדיר גם את שני התוספים הבאים ב-PlaybackStateCompat:

שגיאות שדורשות פעולה מופיעות כסמל Dialog והמשתמשים יכולים לפתור אותן רק כשהרכב בעצירה.

בדיקת תרחישי שגיאה

חשוב לוודא שהאפליקציה מטפלת בשגיאות בצורה תקינה בכל התרחישים, כולל:

  • רמות שונות של המוצר: לדוגמה, חינם לעומת פרימיום או כניסה לחשבון לעומת יציאה מהחשבון
  • מצבי נסיעה שונים: למשל, חנייה לעומת נסיעה
  • מצבי קישוריות שונים: לדוגמה, אונליין לעומת אופליין

שיקולים נוספים

כשמפתחים אפליקציה ל-Android Automotive OS, חשוב לזכור את השיקולים הבאים:

תוכן לא מקוון

אם רלוונטי, מטמיעים תמיכה בהפעלה במצב אופליין. במכוניות עם Android Automotive OS אמורה להיות קישוריות נתונים משלהן, כלומר חבילת גלישה כלולה במחיר הרכב או שהמשתמש משלם עליה. עם זאת, צפוי שלמכוניות יהיה חיבור משתנה יותר מאשר למכשירים ניידים.

ריכזנו כמה דברים שכדאי לזכור כשחושבים על אסטרטגיית התמיכה אופליין:

  • הזמן הכי טוב להוריד תוכן הוא בזמן השימוש באפליקציה.
  • אל תניחו שרשת Wi-Fi זמינה. יכול להיות שהרכב אף פעם לא יהיה בטווח של Wi-Fi, או שיצרן הציוד המקורי השבית את ה-Wi-Fi לטובת רשת סלולרית.
  • אפשר לשמור במטמון את התוכן שהמשתמשים צפויים להשתמש בו, אבל מומלץ לאפשר למשתמשים לשנות את ההתנהגות הזו דרך פעילות ההגדרות.
  • נפח הדיסק במכוניות משתנה, לכן כדאי לתת למשתמשים דרך למחוק תוכן אופליין, למשל באמצעות אפשרות בהגדרות הפעילות.

תמיכה ב-WebView

‫WebViews נתמכים ב-Android Automotive OS, אבל מותר להשתמש בהם רק בפעילויות שקשורות להגדרות ולכניסה לחשבון. בפעילויות שמשתמשות ב-WebView צריך להיות אמצעי לחיצה מסוג 'סגירה' או 'חזרה' מחוץ ל-WebView.

הנה כמה דוגמאות לתרחישי שימוש קבילים ב-WebViews:

  • הצגת קישורים למדיניות הפרטיות, לתנאים ולהגבלות או לקישורים אחרים שקשורים לדינים ולחוקים בפעילות ההגדרות.
  • תהליך מבוסס-אינטרנט בפעילות הכניסה שלכם.

כשמשתמשים ב-WebView, אפשר להפעיל JavaScript.

אבטחת WebView

חשוב לנקוט בכל אמצעי הזהירות האפשריים כדי לוודא ש-WebView לא משמש כנקודת כניסה לאינטרנט הרחב. בדוגמה הבאה של קטע קוד אפשר לראות איך לנעול את WebView לכתובת ה-URL שמשמשת בקריאה loadUrl() ולמנוע הפניות אוטומטיות. מומלץ מאוד להטמיע אמצעי הגנה כאלה כשזה אפשרי, למשל כשמציגים קישורים שקשורים לנושאים משפטיים.

Kotlin

override fun shouldOverrideUrlLoading(webView: WebView,
                             webResourceRequest: WebResourceRequest): Boolean {
  val originalUri: Uri = Uri.parse(webView.originalUrl)
  // Check for allowed URLs
  if (originalUri.equals(Uri.parse(BLANK_URL))
      || originalUri.equals(webResourceRequest.url)) {
    return false
  }
  if (webResourceRequest.isRedirect) {
    logger.w("Redirect detected, not following")
    return true
  }
  setupWizardWebViewClientListener.onUriBlocked(webResourceRequest.url)
  logger.w(
    String.format(
      "Navigation prevented to %s original is %s", webResourceRequest.url, originalUri))
  return true
}

Java

@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest webResourceRequest) {
  Uri originalUri = Uri.parse(webView.getOriginalUrl());
  // Check for allowed URLs
  if (originalUri.equals(Uri.parse(BLANK_URL))
      || originalUri.equals(webResourceRequest.getUrl())) {
    return false;
  }
  if (webResourceRequest.isRedirect()) {
    logger.w("Redirect detected, not following");
    return true;
  }
  setupWizardWebViewClientListener.onUriBlocked(webResourceRequest.getUrl());
  logger.w(
      String.format(
          "Navigation prevented to %s original is %s", webResourceRequest.getUrl(), originalUri));
  return true;
}

שמות של חבילות

מכיוון שאתם מפיצים חבילת Android Package Kit (APK) נפרדת ל-Android Automotive OS, אתם יכולים להשתמש מחדש בשם החבילה מהאפליקציה לנייד או ליצור שם חבילה חדש. אם משתמשים בשם חבילה אחר, לאפליקציה יש שני דפי מוצר נפרדים ב-חנות Play. אם תשתמשו שוב בשם החבילה הנוכחי, לאפליקציה שלכם יהיה רישום אחד בשתי הפלטפורמות.

זו בעיקר החלטה עסקית. לדוגמה, אם יש לכם צוות אחד שעובד על האפליקציה לנייד וצוות נפרד שעובד על האפליקציה שלכם ל-Android Automotive OS, יכול להיות שיהיה הגיוני להשתמש בשמות חבילות נפרדים ולאפשר לכל צוות לנהל את הדף שלו בחנות Play. אין הבדל גדול בין שתי הגישות מבחינת המאמץ הטכני שנדרש כדי להשתמש בהן.

בטבלה הבאה מפורטים כמה הבדלים חשובים נוספים בין שמירה על שם החבילה הנוכחי לבין שימוש בשם חבילה חדש:

תכונה שם חבילה זהה שם חבילה חדש
רישום חנות יחיד יותר מאחת
התקנה משוכפלת כן: 'התקנה מחדש מהירה של אפליקציות' במהלך אשף ההגדרה לא
תהליך הביקורת בחנות Play חסימת ביקורות: אם ביקורת נכשלת עבור קובץ APK אחד, קובצי APK אחרים שנשלחו באותה גרסה נחסמים ביקורות ספציפיות
נתונים סטטיסטיים, מדדים ונתונים חיוניים משולב: אפשר לסנן נתונים ספציפיים לתחום הרכב. הפרדה
הוספה לאינדקס ודירוג בחיפוש התבססות על המיקום הנוכחי אין אפשרות להעברה
שילוב עם אפליקציות אחרות ככל הנראה לא צריך לבצע שינויים, בהנחה שקוד המדיה משותף לשני קובצי ה-APK יכול להיות שתצטרכו לעדכן את האפליקציה המתאימה, למשל כדי להפעיל URI באמצעות Google Assistant.

שאלות נפוצות

בקטעים הבאים מופיעות תשובות לכמה שאלות נפוצות בנושא Android Automotive OS.

חומרה

האם האפליקציה שלי יכולה לקבל גישה למיקרופון

אם האפליקציות מטרגטות ל-Android מגרסה 10 (רמת API‏ 29) ואילך, אפשר לעיין במסמכי התיעוד בנושא שיתוף קלט אודיו. אי אפשר לעשות את זה לפני רמת API‏ 29.

באילו ממשקי API של רכב אפשר להשתמש ואיך?

הגישה שלכם מוגבלת לממשקי ה-API שנחשפים על ידי יצרן הציוד המקורי. אנחנו מפתחים תהליכים כדי ליצור סטנדרטיזציה של הגישה לממשקי ה-API האלה.

אפליקציות יכולות לגשת לממשקי API של מכוניות באמצעות SetProperty() ו-GetProperty() ב-CarPropertyManager. כדי לראות רשימה של כל המאפיינים הזמינים, אפשר לעיין בקוד המקור או במסמכי העזר. אם הנכס מתויג ב-@SystemApi, הוא מוגבל לאפליקציות מערכת שנטענו מראש.

אילו סוגים של קודקים לאודיו נתמכים?

פרטים נוספים זמינים במסמך ההגדרה של תאימות (CDD) של Android.

האם יש תמיכה ב-Widevine DRM?

כן. יש תמיכה ב-Widevine DRM.

פיתוח ובדיקה

יש הגבלות או המלצות לשימוש בספריות ובערכות SDK של צד שלישי?

אין לנו הנחיות ספציפיות לגבי שימוש בערכות SDK ובספריות של צד שלישי. אם אתם בוחרים להשתמש בערכות SDK ובספריות של צד שלישי, אתם עדיין אחראים לעמידה בכל דרישות האיכות של אפליקציות לרכב.

האם אפשר להשתמש בשירות שפועל בחזית?

התרחיש היחיד שבו מותר להשתמש בשירות שפועל בחזית הוא הורדת תוכן לשימוש אופליין. אם יש לכם מקרה שימוש אחר בשירות שפועל בחזית ואתם רוצים שנספק לו תמיכה, אתם יכולים ליצור איתנו קשר באמצעות קבוצת הדיון בנושא Android Automotive OS.

פרסום אפליקציות ל-Android Automotive OS

איך מפרסמים אפליקציה ל-Android Automotive OS באמצעות Google Play Console?

פרטים על פרסום אפליקציה ל-Android Automotive OS באמצעות Google Play Console זמינים במאמר בנושא הפצה למכוניות.

מקורות מידע נוספים

מידע נוסף על Android Automotive OS זמין במקורות המידע הבאים.

דוגמאות

מדריכים

בלוגים

סרטונים

דיווח על בעיה במדיה ב-Android Automotive OS

אם נתקלתם בבעיה במהלך פיתוח אפליקציית מדיה ל-Android Automotive OS, אתם יכולים לדווח עליה באמצעות Google Issue Tracker. חשוב למלא את כל הפרטים הנדרשים בתבנית הבעיה.

יצירת דיווח על בעיה חדשה

לפני ששולחים דיווח על בעיה חדשה, כדאי לבדוק אם היא כבר מופיעה ברשימת הבעיות. כדי להירשם לעדכונים על בעיות ולהצביע על בעיות, לוחצים על הכוכב של הבעיה בכלי המעקב. מידע נוסף מופיע במאמר בנושא הרשמה לבעיה.