پشتیبانی از سیستم عامل Android Automotive را به برنامه رسانه خود اضافه کنید

سیستم عامل اندروید اتو به کاربران اجازه می‌دهد برنامه‌ها را در خودرو نصب کنند. برای دسترسی به کاربران در این پلتفرم، باید یک برنامه بهینه شده برای راننده که با سیستم عامل اندروید اتو سازگار است، توزیع کنید. می‌توانید تقریباً از تمام کدها و منابع موجود در برنامه اندروید اتو خود دوباره استفاده کنید، اما باید یک نسخه جداگانه ایجاد کنید که الزامات این صفحه را برآورده کند.

مرور کلی توسعه

افزودن پشتیبانی از سیستم عامل اندروید اتوموبیل تنها به چند مرحله نیاز دارد، همانطور که در بخش‌های بعدی توضیح داده شده است:

  1. فعال کردن ویژگی‌های خودرو در اندروید استودیو
  2. یک ماژول خودرو ایجاد کنید .
  3. وابستگی‌های Gradle خود را به‌روزرسانی کنید .
  4. به صورت اختیاری، تنظیمات و فعالیت‌های ورود به سیستم را پیاده‌سازی کنید .
  5. در صورت تمایل، نکات مربوط به میزبان رسانه را بخوانید .

ملاحظات طراحی

سیستم عامل اندروید اتوموتیو (Android Automotive OS) وظیفه چیدمان محتوای رسانه‌ای دریافتی از سرویس مرورگر رسانه برنامه شما را بر عهده دارد. این بدان معناست که برنامه شما رابط کاربری را ترسیم نمی‌کند و هیچ یک از فعالیت‌های شما را هنگامی که کاربر پخش رسانه را آغاز می‌کند، آغاز نمی‌کند.

اگر در حال پیاده‌سازی تنظیمات یا فعالیت‌های ورود به سیستم هستید، این فعالیت‌ها باید برای خودرو بهینه شده باشند. هنگام طراحی این بخش‌ها از برنامه خود، به دستورالعمل‌های طراحی برای سیستم عامل اندروید خودرو مراجعه کنید.

پروژه خود را تنظیم کنید

برای فعال کردن پشتیبانی از سیستم عامل اندروید اتوموتیو، باید چندین بخش از پروژه برنامه خود را تنظیم کنید.

فعال کردن ویژگی‌های خودرو در اندروید استودیو

برای اطمینان از فعال بودن تمام ویژگی‌های سیستم عامل خودرو، از اندروید استودیو ۴.۰ یا بالاتر استفاده کنید.

ایجاد ماژول خودرو

برخی از اجزای سیستم عامل اندروید اتوموتیو، مانند مانیفست، الزامات خاص پلتفرم دارند. ماژولی ایجاد کنید که بتواند کد این اجزا را از سایر کدهای پروژه شما، مانند کدی که برای برنامه تلفن شما استفاده می‌شود، جدا نگه دارد.

برای اضافه کردن ماژول خودرو به پروژه خود، این مراحل را دنبال کنید:

  1. در اندروید استودیو، روی File > New > New Module کلیک کنید.
  2. ماژول خودرو را انتخاب کنید، سپس روی بعدی کلیک کنید.
  3. یک نام برای برنامه/کتابخانه وارد کنید. این نامی است که کاربران برای برنامه شما در سیستم عامل اندروید اتوموبیل مشاهده می‌کنند.
  4. نام ماژول را وارد کنید.
  5. نام بسته (Package name) را متناسب با برنامه خود تنظیم کنید.
  6. برای Minimum SDK ، API 28: Android 9.0 (Pie) را انتخاب کنید و سپس روی Next کلیک کنید.

    تمام خودروهایی که از سیستم عامل Android Automotive پشتیبانی می‌کنند، روی اندروید ۹ (سطح API 28) یا بالاتر اجرا می‌شوند، بنابراین انتخاب این مقدار همه خودروهای سازگار را هدف قرار می‌دهد.

  7. گزینه «بدون فعالیت» را انتخاب کنید و سپس روی «پایان» کلیک کنید.

پس از ایجاد ماژول خود در اندروید استودیو، فایل 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 را اعلام می‌کند. توجه داشته باشید که هیچ فعالیتی در مانیفست اعلام نشده است.

اگر تنظیمات یا فعالیت‌های ورود به سیستم را پیاده‌سازی می‌کنید، آنها را اینجا اضافه کنید. این فعالیت‌ها توسط سیستم با استفاده از intentهای صریح فعال می‌شوند و تنها فعالیت‌هایی هستند که شما در مانیفست برای برنامه Android Automotive OS خود اعلام می‌کنید.

پس از افزودن هرگونه تنظیمات یا فعالیت‌های ورود به سیستم، فایل مانیفست خود را با تنظیم ویژگی android:appCategory عنصر <application> به "audio" تکمیل کنید.

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

الزامات ویژگی را اعلام کنید

تمام برنامه‌های ساخته شده برای سیستم عامل اندروید اتوموبیل باید الزامات خاصی را برای توزیع با استفاده از گوگل پلی برآورده کنند. برای اطلاعات بیشتر به «ملاقات با الزامات ویژگی گوگل پلی» مراجعه کنید.

اعلام پشتیبانی رسانه‌ای برای سیستم عامل اندروید اتوموبیل

برای اعلام اینکه برنامه شما از سیستم عامل Android Automotive پشتیبانی می‌کند، از ورودی مانیفست زیر استفاده کنید:

<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>

فیلترهای هدف

سیستم عامل اندروید اتوموتیو از اینتنت‌های صریح برای فعال کردن فعالیت‌ها در برنامه رسانه‌ای شما استفاده می‌کند. هیچ فعالیتی را که فیلترهای اینتنت CATEGORY_LAUNCHER یا ACTION_MAIN دارد، در فایل مانیفست قرار ندهید.

فعالیت‌هایی مانند آنچه در مثال زیر آمده است، معمولاً یک تلفن یا دستگاه تلفن همراه دیگر را هدف قرار می‌دهند. این فعالیت‌ها را در ماژولی که برنامه تلفن را می‌سازد، تعریف کنید، نه در ماژولی که برنامه سیستم عامل اندروید خودرو شما را می‌سازد.

<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')
    }
}

کاتلین

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

پیاده‌سازی تنظیمات و فعالیت‌های ورود به سیستم

علاوه بر سرویس مرورگر رسانه، می‌توانید تنظیمات بهینه‌شده برای خودرو و فعالیت‌های ورود به سیستم را نیز برای برنامه سیستم عامل اندروید خودرو خود ارائه دهید. این فعالیت‌ها به شما امکان می‌دهند قابلیت‌هایی را در برنامه ارائه دهید که در APIهای رسانه اندروید گنجانده نشده است.

فقط در صورتی این فعالیت‌ها را پیاده‌سازی کنید که برنامه سیستم عامل اندروید اتو شما نیاز به اجازه ورود کاربران یا تعیین تنظیمات برنامه داشته باشد. این فعالیت‌ها توسط اندروید اتو استفاده نمی‌شوند.

گردش‌های کاری فعالیت

نمودار زیر نحوه تعامل کاربر با تنظیمات و فعالیت‌های ورود به سیستم شما را با استفاده از سیستم عامل اندروید اتوموتیو نشان می‌دهد:

گردش‌های کاری برای تنظیمات و فعالیت‌های ورود به سیستم

شکل ۱. تنظیمات و گردش‌های کاری فعالیت ورود به سیستم.

در تنظیمات و فعالیت‌های ورود به سیستم، از عوامل حواس‌پرتی جلوگیری کنید

برای اطمینان از اینکه تنظیمات و فعالیت‌های ورود به سیستم شما فقط در زمانی که وسیله نقلیه کاربر پارک شده است، قابل استفاده هستند، تأیید کنید که عنصر (های) <activity> شامل عنصر <meta-data> زیر نباشد. در صورت وجود چنین عنصری، برنامه شما در طول بررسی رد خواهد شد.

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

افزودن فعالیت تنظیمات

شما می‌توانید یک فعالیت تنظیمات بهینه‌شده برای خودرو اضافه کنید تا کاربران بتوانند تنظیمات برنامه شما را در ماشین خود پیکربندی کنند. فعالیت تنظیمات شما همچنین می‌تواند گردش‌های کاری دیگری مانند ورود یا خروج از حساب کاربری یا تغییر حساب‌های کاربری را فراهم کند. به یاد داشته باشید که این فعالیت فقط توسط برنامه‌ای که روی سیستم عامل Android Automotive اجرا می‌شود، فعال می‌شود. برنامه‌های تلفن متصل به 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>

فعالیت تنظیمات خود را پیاده‌سازی کنید

وقتی کاربری برنامه شما را اجرا می‌کند، سیستم عامل اندروید اتوموتیو اکتیویتی تنظیماتی که شما اعلام کرده‌اید را شناسایی کرده و یک گزینه مانند یک آیکون را نمایش می‌دهد. کاربر می‌تواند با استفاده از صفحه نمایش ماشین خود روی این گزینه ضربه بزند یا آن را انتخاب کند تا به اکتیویتی مورد نظر هدایت شود. سیستم عامل اندروید اتوموتیو اینتنت 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 را در ماژول automotive خود کپی کنید.
  2. یک درخت تنظیمات مانند automotive/src/main/res/xml/preferences.xml تعریف کنید.
  3. یک PreferenceFragmentCompat پیاده‌سازی کنید که فعالیت تنظیمات شما آن را نمایش دهد. برای اطلاعات بیشتر به فایل‌های SettingsFragment.kt و SettingsActivity.kt در UAMP و راهنمای تنظیمات اندروید مراجعه کنید.

هنگام پیاده‌سازی فعالیت تنظیمات خود، این بهترین شیوه‌ها را برای استفاده از برخی از اجزای موجود در کتابخانه Preference در نظر بگیرید:

  • در فعالیت تنظیمات خود، بیش از دو سطح عمق زیر نمای اصلی نداشته باشید.
  • از DropDownPreference استفاده نکنید. در عوض از ListPreference استفاده کنید.
  • اجزای سازمانی:
    • PreferenceScreen
      • این باید بالاترین سطح درخت تنظیمات شما باشد.
    • PreferenceCategory
      • برای گروه‌بندی اشیاء Preference با هم استفاده می‌شود.
      • یک title درج کنید.
  • در تمام اجزای زیر، یک key و title قرار دهید. همچنین می‌توانید یک summary ، یک icon یا هر دو را قرار دهید:
    • Preference
      • منطق موجود در تابع فراخوانی onPreferenceTreeClick() از پیاده‌سازی PreferenceFragmentCompat خود را سفارشی‌سازی کنید.
    • CheckBoxPreference
      • می‌تواند به جای summary برای متن شرطی summaryOn یا summaryOff داشته باشد.
    • SwitchPreference
      • می‌تواند به جای summary برای متن شرطی summaryOn یا summaryOff داشته باشد.
      • می‌تواند 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 اجرا می‌شود، فعال می‌شود. برنامه‌های تلفن متصل به Android Auto از آن استفاده نمی‌کنند.

الزام ورود به سیستم در شروع برنامه

برای اینکه کاربر قبل از استفاده از برنامه شما، ملزم به ورود به سیستم باشد، سرویس مرورگر رسانه شما باید موارد زیر را انجام دهد:

  1. در متد onLoadChildren() سرویس خود، با استفاده از متد sendResult() نتیجه null را ارسال کنید.
  2. با استفاده از متد setState() PlaybackStateCompat مربوط به جلسه رسانه را روی STATE_ERROR تنظیم کنید. این به سیستم عامل Android Automotive می‌گوید که تا زمان رفع خطا، هیچ عملیات دیگری نمی‌تواند انجام شود.
  3. کد خطای PlaybackStateCompat مربوط به جلسه رسانه را روی ERROR_CODE_AUTHENTICATION_EXPIRED تنظیم کنید. این به سیستم عامل Android Automotive می‌گوید که کاربر باید احراز هویت شود.
  4. پیام خطای PlaybackStateCompat مربوط به جلسه رسانه را با استفاده از متد setErrorMessage() تنظیم کنید. از آنجا که این پیام خطا مربوط به کاربر است، آن را برای زبان فعلی کاربر بومی‌سازی کنید.
  5. با استفاده از متد setExtras() موارد اضافی PlaybackStateCompat مربوط به جلسه رسانه را تنظیم کنید. دو یا سه کلید زیر را وارد کنید:

    • 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 که کاربر را به فعالیت ورود به سیستم Car App Library شما هدایت می‌کند. از آنجا که میزبان Car App Library برای رانندگی بهینه شده است، این intent به طور خودکار صفحه حل خطا را دور می‌زند و بلافاصله صفحه ورود به سیستم شما را نمایش می‌دهد. اگر این مورد اضافی را تنظیم کردید، دو مورد اضافی قبلی را نیز تنظیم کنید تا سازگاری با خودروهای قدیمی‌تر تضمین شود.

قطعه کد زیر نشان می‌دهد که چگونه برنامه شما می‌تواند از کاربر بخواهد قبل از استفاده از برنامه، وارد سیستم شود:

کاتلین

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)

جاوا

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 تنظیم کنید، سپس با فراخوانی متد finish() در activity، کاربر را به سیستم عامل Android Automotive برگردانید.

فعالیت ورود به سیستم خود را پیاده‌سازی کنید

گوگل ابزارهای هویتی متنوعی را ارائه می‌دهد که می‌توانید از آنها برای کمک به کاربران در ورود به برنامه شما در خودروهایشان استفاده کنید. برخی از ابزارها، مانند Firebase Authentication، ابزارهای کاملی را ارائه می‌دهند که می‌توانند به شما در ساخت تجربیات احراز هویت سفارشی کمک کنند. ابزارهای دیگر از اعتبارنامه‌های موجود کاربر یا سایر فناوری‌ها برای کمک به شما در ساخت تجربیات ورود به سیستم یکپارچه برای کاربران استفاده می‌کنند.

ابزارهای زیر می‌توانند به شما در ایجاد یک تجربه ورود آسان‌تر برای کاربرانی که قبلاً از دستگاه دیگری وارد سیستم شده‌اند، کمک کنند:

  • ورود و ثبت‌نام با یک لمس: اگر قبلاً قابلیت «وان‌تاپ» را برای دستگاه‌های دیگر، مانند برنامه تلفن خود، پیاده‌سازی کرده‌اید، آن را برای برنامه سیستم عامل اندروید اتوموبیل خود نیز پیاده‌سازی کنید تا از کاربران فعلی «وان‌تاپ» نیز پشتیبانی کند.
  • ورود به سیستم با گوگل: اگر قبلاً ورود به سیستم با گوگل را برای دستگاه‌های دیگر، مانند برنامه تلفن خود، پیاده‌سازی کرده‌اید، ورود به سیستم با گوگل را برای برنامه سیستم عامل اندروید خودرو خود نیز پیاده‌سازی کنید تا از کاربران فعلی ورود به سیستم با گوگل پشتیبانی کند.
  • تکمیل خودکار با گوگل: اگر کاربران در سایر دستگاه‌های اندروید خود، تکمیل خودکار با گوگل را انتخاب کرده باشند، اطلاعات ورود آنها در مدیریت رمز عبور گوگل ذخیره می‌شود. وقتی این کاربران وارد برنامه سیستم عامل اندروید خودرو شما می‌شوند، تکمیل خودکار با گوگل، اطلاعات ورود ذخیره شده مرتبط را پیشنهاد می‌دهد. استفاده از تکمیل خودکار با گوگل نیازی به تلاش برای توسعه برنامه ندارد. با این حال، توسعه‌دهندگان برنامه می‌توانند برنامه‌های خود را برای نتایج با کیفیت بهتر بهینه کنند . تکمیل خودکار با گوگل توسط همه دستگاه‌هایی که اندروید ۸.۰ (سطح API ۲۶) یا بالاتر دارند، از جمله سیستم عامل اندروید خودرو، پشتیبانی می‌شود.

استفاده از AccountManager

برنامه‌های سیستم عامل اندروید اتوموبیل که دارای احراز هویت هستند، به دلایل زیر باید از AccountManager استفاده کنند:

  • تجربه کاربری بهتر و سهولت مدیریت حساب کاربری: کاربران می‌توانند تمام حساب‌های کاربری خود را از منوی حساب‌ها در تنظیمات سیستم، از جمله ورود و خروج، مدیریت کنند.
  • تجربیات «مهمان»: خودروها دستگاه‌های اشتراکی هستند، به این معنی که تولیدکنندگان اصلی تجهیزات (OEM) می‌توانند تجربیات «مهمان» را در خودرو فعال کنند، جایی که امکان اضافه کردن حساب‌ها وجود ندارد. این محدودیت با استفاده از DISALLOW_MODIFY_ACCOUNTS برای AccountManager اعمال می‌شود.

مجوزها

اگر نیاز به درخواست مجوز از کاربر دارید، از همان جریانی که در فعالیت احراز هویت یا فعالیت تنظیمات در نمودار گردش کار فعالیت نشان داده شده در بخش قبلی استفاده شده است، استفاده کنید.

پیاده‌سازی خروج از سیستم

صرف نظر از اینکه چگونه ورود به سیستم را پیاده‌سازی کرده‌اید، وقتی کاربر از سیستم خارج می‌شود، باید MediaBrowserServiceCompat#notifyChildrenChanged(rootId) را فراخوانی کنید تا درخت مرور شما نامعتبر شود تا برنامه میزبان رسانه هرگونه اطلاعات مرتبط با کاربر (مانند آخرین عبارت جستجو) را پاک کند.

برنامه میزبان رسانه را شروع کنید

شما می‌توانید اینتنت‌هایی (intents) ایجاد کنید تا برنامه میزبان رسانه را به برنامه یا محتوای درون برنامه شما باز کند. برای مثال:

  • برنامه شما می‌تواند یک اعلان با یک هدف در حال انتظار ارسال کند که به کاربر اجازه می‌دهد برنامه شما را باز کند تا به یک محتوای جدید گوش دهد.
  • برنامه شما می‌تواند لینک‌های عمیق را مدیریت کند و برنامه میزبان را به مناسب‌ترین حالت نمایش باز کند.

تعیین قابلیت‌های میزبان رسانه

نسخه‌های برنامه میزبان رسانه از قابلیت‌های مختلفی پشتیبانی می‌کنند. میزبان‌ها با گنجاندن فیلترهای intent برای اقدامات intent زیر، پشتیبانی از قابلیت‌های مختلف را نشان می‌دهند:

همه برنامه‌های میزبان رسانه از intentهای MEDIA_TEMPLATE پشتیبانی می‌کنند. برای تعیین اینکه آیا میزبان رسانه از intentهای 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

ساخت و استفاده از یک intent

بسته به اینکه کدام اقدامات اینتنت توسط میزبان رسانه پشتیبانی می‌شود و مورد استفاده خاص شما چیست، می‌توانید موارد اضافی زیر را هنگام ساخت اینتنت مورد استفاده برای شروع برنامه میزبان رسانه ارائه دهید.

کلید اضافی نوع توضیحات اقدامات پشتیبانی شده
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 متصل می‌کند، جستجویی برای "Jazz" انجام می‌دهد و سپس اولین مورد را از نتایج جستجو پخش می‌کند. در تمام هاست‌های دیگر، فقط برنامه‌ی میزبان رسانه را باز می‌کند و جستجویی برای "Jazz" انجام می‌دهد و کاربر را مجبور می‌کند تا موردی را برای پخش از نتایج انتخاب کند.

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)

برای بهبود تجربه برنامه رسانه‌ای خود در دستگاه‌های دارای سیستم عامل اندروید اتوموتیو، می‌توانید پشتیبانی از لینک‌های عمیق را به برنامه خود اضافه کنید. به عنوان مثال، این به کاربران اجازه می‌دهد تا برنامه شما را مستقیماً از یک مرورگر یا هنگام دریافت URL به اشتراک گذاشته شده از تلفن با استفاده از Quick Share باز کنند.

فیلترهای هدف لینک عمیق را اضافه کنید

برای اینکه به سیستم عامل اطلاع دهید که برنامه شما قادر به مدیریت لینک‌های عمیق است، باید فعالیت‌هایی با فیلترهای هدف مناسب داشته باشد. برای راهنمایی در مورد قالب فیلترهای هدف مورد استفاده برای لینک‌های عمیق، به بخش «افزودن فیلترهای هدف برای لینک‌های ورودی» مراجعه کنید.

برای بهترین تجربه کاربری، از تمام لینک‌های عمیقی که برنامه تلفن همراه شما پشتیبانی می‌کند، در صورتی که به طور منطقی توسط برنامه درون ماشین شما پشتیبانی شوند، پشتیبانی کنید. اگر برنامه شما دارای تنظیمات یا فعالیت‌های ورود به سیستم است، فیلترهای اینتنت برای مدیریت تنظیمات و لینک‌های عمیق ورود به سیستم باید در عناصر مانیفست <activity> مربوطه تعریف شوند. برای پخش رسانه و مرور لینک‌های عمیق، می‌توانید از یک اکتیویتی ترامپولین همانطور که در ادامه این بخش توضیح داده شده است، استفاده کنید.

برای راهنمایی در مورد نحوه خواندن و واکنش به intent ای که برای شروع activity برنامه شما استفاده شده است، به بخش Read data from incoming intents مراجعه کنید.

از آنجا که رابط کاربری برای مرور و پخش توسط برنامه میزبان ترسیم می‌شود، فعالیتی که برای مدیریت لینک‌های عمیق برای اقدامات پخش و مرور استفاده می‌شود، نباید هیچ رابط کاربری مخصوص به خود داشته باشد.

در عوض، در درجه اول باید برای ساخت و استفاده از یک intent برای شروع برنامه میزبان رسانه استفاده شود. در صورت لزوم، می‌تواند هرگونه تغییر اضافی در وضعیت برنامه شما، مانند اضافه کردن آیتم‌های رسانه به صف، را نیز مدیریت کند. قطعه کد زیر نمونه‌ای از پیاده‌سازی activity ترامپولین را نشان می‌دهد:

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()
  }
}

نکات مربوط به مجری رسانه را بخوانید

بسته به برنامه سیستم (از جمله نسخه آن) که به سرویس مرورگر رسانه شما متصل می‌شود، برنامه شما ممکن است موارد اضافی زیر را دریافت کند:

مدیریت خطا

خطاها در برنامه‌های رسانه‌ای در سیستم عامل اندروید اتوموبیل با استفاده از PlaybackStateCompat مربوط به جلسه رسانه‌ای ارسال می‌شوند. برای همه خطاها، یک کد خطا و پیام خطای مناسب در PlaybackStateCompat تنظیم کنید. این باعث می‌شود یک Toast در رابط کاربری ظاهر شود.

وقتی خطایی رخ می‌دهد اما پخش می‌تواند ادامه یابد، یک خطای غیرمهلک صادر کنید. برای مثال، ممکن است کاربر بتواند قبل از ورود به سیستم، موسیقی را در یک برنامه پخش کند، اما قبل از اینکه بتواند آهنگی را رد کند، باید وارد سیستم شود. وقتی از یک خطای غیرمهلک استفاده می‌کنید، سیستم می‌تواند بدون ایجاد وقفه در پخش مورد رسانه فعلی، به کاربر پیشنهاد دهد که وارد سیستم شود.

وقتی خطایی غیرمهلک رخ می‌دهد، بقیه‌ی PlaybackStateCompat را به همان صورت که هست، به جز کد خطا و پیام خطا، حفظ کنید. استفاده از این رویکرد به کاربر اجازه می‌دهد تا زمانی که تصمیم می‌گیرد وارد سیستم شود یا خیر، پخش آیتم رسانه‌ی فعلی ادامه یابد.

وقتی پخش امکان‌پذیر نیست، مثلاً وقتی اتصال اینترنت و محتوای آفلاین وجود ندارد، وضعیت PlaybackStateCompat را روی STATE_ERROR تنظیم کنید.

در به‌روزرسانی‌های بعدی PlaybackStateCompat ، هرگونه کد خطا و پیام خطا را پاک کنید تا از نمایش چندین هشدار برای یک خطا جلوگیری شود.

اگر در هر مرحله‌ای نتوانستید درخت مرور را بارگذاری کنید - برای مثال، اگر نیاز به احراز هویت دارید و کاربر وارد سیستم نشده است - یک درخت مرور خالی ارسال کنید. برای نشان دادن این موضوع، یک نتیجه تهی از onLoadChildren() برای گره رسانه ریشه برگردانید. وقتی این اتفاق می‌افتد، سیستم یک خطای تمام صفحه با پیام خطای تنظیم شده در PlaybackStateCompat نمایش می‌دهد.

خطاهای قابل پیگیری

اگر خطایی قابل پیگیری است، دو مورد اضافی زیر را نیز در PlaybackStateCompat تنظیم کنید:

خطاهای قابل پیگیری به صورت یک Dialog ظاهر می‌شوند و تنها زمانی که خودرو متوقف شود، توسط کاربران قابل رفع هستند.

موارد خطای آزمایش

تأیید کنید که برنامه شما به طور صحیح خطاها را در همه سناریوها، از جمله موارد زیر، مدیریت می‌کند:

  • سطوح مختلف محصول شما: برای مثال، رایگان در مقابل ویژه یا وارد شده در مقابل خارج شده
  • حالت‌های مختلف رانندگی: برای مثال، پارک شده در مقابل در حال رانندگی
  • حالت‌های مختلف اتصال: برای مثال، آنلاین در مقابل آفلاین

ملاحظات دیگر

هنگام توسعه برنامه سیستم عامل اندروید خودرو خود، این ملاحظات دیگر را نیز در نظر داشته باشید:

محتوای آفلاین

در صورت لزوم، پشتیبانی از پخش آفلاین را پیاده‌سازی کنید. انتظار می‌رود خودروهای دارای سیستم عامل اندروید اتوموتیو، اتصال داده مخصوص به خود را داشته باشند، به این معنی که طرح داده در هزینه خودرو گنجانده شده یا توسط کاربر پرداخت می‌شود. با این حال، انتظار می‌رود خودروها نسبت به دستگاه‌های تلفن همراه، اتصال متغیرتری نیز داشته باشند.

در هنگام بررسی استراتژی پشتیبانی آفلاین خود، چند نکته را باید در نظر داشته باشید:

  • بهترین زمان برای دانلود محتوا، زمانی است که برنامه شما در حال استفاده است.
  • فرض نکنید که وای‌فای در دسترس است. ممکن است یک ماشین هرگز به محدوده وای‌فای نرسد، یا ممکن است سازنده اصلی (OEM) وای‌فای را به نفع یک شبکه تلفن همراه غیرفعال کرده باشد.
  • اگرچه ذخیره کردن محتوایی که انتظار دارید کاربران از آن استفاده کنند اشکالی ندارد، اما توصیه می‌کنیم به کاربر اجازه دهید این رفتار را از طریق فعالیت تنظیمات شما تغییر دهد.
  • فضای دیسک در خودروها متفاوت است، بنابراین به کاربران راهی برای حذف محتوای آفلاین بدهید، مثلاً از طریق گزینه‌ای در فعالیت تنظیمات خود.

پشتیبانی از وب ویو

WebViewها در سیستم عامل اندروید اتوموبیل پشتیبانی می‌شوند، اما فقط برای تنظیمات و فعالیت‌های ورود به سیستم شما مجاز هستند. فعالیت‌هایی که از WebView استفاده می‌کنند باید یک «بستن» یا «بازگشت» خارج از WebView داشته باشند.

در اینجا چند نمونه از موارد استفاده قابل قبول برای WebViews آورده شده است:

  • نمایش سیاست حفظ حریم خصوصی، شرایط خدمات یا سایر پیوندهای مرتبط با قانون در فعالیت تنظیمات شما.
  • یک جریان مبتنی بر وب در فعالیت ورود به سیستم شما.

هنگام استفاده از WebView، می‌توانید جاوا اسکریپت را فعال کنید .

وب ویو خود را ایمن کنید

تمام اقدامات احتیاطی ممکن را انجام دهید تا مطمئن شوید که WebView شما نقطه ورود به اینترنت بزرگتر نیست. برای مثال در مورد نحوه قفل کردن WebView به URL استفاده شده در فراخوانی loadUrl() و جلوگیری از تغییر مسیرها، به قطعه کد زیر مراجعه کنید. ما اکیداً توصیه می‌کنیم که در صورت امکان، مانند نمایش پیوندهای مرتبط با قانون، اقدامات حفاظتی مانند این را پیاده‌سازی کنید.

کاتلین

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
}

جاوا

@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;
}

نام بسته‌ها

از آنجا که شما یک کیت بسته اندروید (APK) جداگانه برای سیستم عامل اندروید خودرو توزیع می‌کنید، می‌توانید نام بسته را از برنامه تلفن همراه خود دوباره استفاده کنید یا یک نام بسته جدید ایجاد کنید. اگر از نام بسته متفاوتی استفاده کنید، برنامه شما دو لیست جداگانه در فروشگاه Play دارد. اگر از نام بسته فعلی خود دوباره استفاده کنید، برنامه شما یک لیست واحد در هر دو پلتفرم دارد.

این عمدتاً یک تصمیم تجاری است. برای مثال، اگر یک تیم روی اپلیکیشن موبایل و یک تیم جداگانه روی اپلیکیشن اندروید اتوموبیل او اس شما کار می‌کنند، منطقی است که نام بسته‌های جداگانه‌ای داشته باشید و به هر تیم اجازه دهید لیست فروشگاه پلی استور خود را مدیریت کند. تفاوت زیادی در تلاش فنی مورد نیاز برای استفاده از هر دو رویکرد وجود ندارد.

جدول زیر خلاصه‌ای از تفاوت‌های کلیدی دیگر بین حفظ نام بسته فعلی و استفاده از نام بسته جدید را نشان می‌دهد:

ویژگی نام بسته یکسان نام بسته جدید
فهرست فروشگاه مجرد چندگانه
نصب آینه‌ای بله: "نصب مجدد سریع برنامه" در طول جادوگر راه اندازی خیر
فرآیند بررسی فروشگاه Play مسدود کردن بررسی‌ها: اگر بررسی یک APK با شکست مواجه شود، سایر APK های ارائه شده در همان نسخه مسدود می‌شوند. بررسی‌های فردی
آمار، معیارها و اطلاعات حیاتی ترکیبی: می‌توانید داده‌های خاص خودرو را فیلتر کنید. جدا کردن
ایندکس گذاری و رتبه بندی جستجو از جایگاه فعلی خود بسازید بدون انتقال
ادغام با برنامه‌های دیگر به احتمال زیاد نیازی به تغییر نیست، با فرض اینکه کد رسانه بین هر دو APK به اشتراک گذاشته شده باشد ممکن است لازم باشد برنامه مربوطه را به‌روزرسانی کنید، مثلاً برای پخش URI با دستیار گوگل.

سوالات متداول

برای پاسخ به برخی از سوالات متداول در مورد سیستم عامل اندروید اتوموبیل، به بخش‌های زیر مراجعه کنید.

سخت‌افزار

آیا برنامه من می‌تواند به میکروفون دسترسی داشته باشد؟

برای برنامه‌هایی که اندروید ۱۰ (سطح API ۲۹) یا بالاتر را هدف قرار می‌دهند، به مستندات ورودی صوتی اشتراک‌گذاری مراجعه کنید. این کار قبل از سطح API ۲۹ امکان‌پذیر نیست.

به کدام API های خودرو می‌توانیم دسترسی داشته باشیم و چگونه؟

شما محدود به APIهایی هستید که توسط OEM ارائه می‌شوند. فرآیندهایی برای استانداردسازی نحوه دسترسی شما به این APIها در حال توسعه هستند.

برنامه‌ها می‌توانند با استفاده از SetProperty() و GetProperty() در CarPropertyManager به APIهای خودرو دسترسی داشته باشند. برای مشاهده لیستی از تمام ویژگی‌های موجود، به کد منبع یا مستندات مرجع مراجعه کنید. اگر ویژگی با @SystemApi حاشیه‌نویسی شده باشد، محدود به برنامه‌های سیستمی از پیش بارگذاری شده است.

چه نوع کدک‌های صوتی پشتیبانی می‌شوند؟

به جزئیات کدک صوتی در CDD اندروید مراجعه کنید.

آیا Widevine DRM پشتیبانی می‌شود؟

بله. Widevine DRM پشتیبانی می‌شود.

توسعه و آزمایش

آیا محدودیت یا توصیه‌ای برای استفاده از SDKها و کتابخانه‌های شخص ثالث وجود دارد؟

ما هیچ دستورالعمل خاصی در مورد استفاده از SDK ها و کتابخانه های شخص ثالث نداریم. اگر تصمیم به استفاده از SDK ها و کتابخانه های شخص ثالث دارید، همچنان مسئول رعایت تمام الزامات کیفیت برنامه خودرو هستید.

آیا می‌توانم از سرویس پیش‌زمینه استفاده کنم؟

تنها مورد استفاده مجاز برای یک سرویس پیش‌زمینه، دانلود محتوا برای استفاده آفلاین است. اگر مورد استفاده دیگری برای یک سرویس پیش‌زمینه دارید که می‌خواهید پشتیبانی از آن را ببینید، با استفاده از گروه بحث سیستم عامل اندروید خودرو با ما تماس بگیرید.

انتشار برنامه‌های اندروید سیستم عامل خودرو

چگونه می‌توانم برنامه Android Automotive OS خود را با استفاده از کنسول Google Play منتشر کنم؟

برای جزئیات بیشتر در مورد نحوه انتشار برنامه Android Automotive OS خود با استفاده از کنسول Google Play، به بخش «توزیع در خودروها» مراجعه کنید.

منابع اضافی

برای کسب اطلاعات بیشتر در مورد سیستم عامل اندروید اتوموبیل، به منابع تکمیلی زیر مراجعه کنید.

نمونه‌ها

راهنماها

وبلاگ‌ها

ویدیوها

گزارش مشکل رسانه‌ای سیستم عامل اندروید اتوموبیل

اگر هنگام توسعه برنامه رسانه‌ای خود برای سیستم عامل اندروید اتوموبیل با مشکلی مواجه شدید، می‌توانید آن را با استفاده از ردیاب مشکلات گوگل گزارش دهید. حتماً تمام اطلاعات درخواستی را در الگوی مشکل پر کنید.

ایجاد یک مسئله جدید

قبل از ثبت یک مشکل جدید، بررسی کنید که آیا قبلاً در لیست مشکلات گزارش شده است یا خیر. می‌توانید با کلیک روی ستاره برای یک مشکل در ردیاب، مشترک شوید و به مشکلات رأی دهید. برای اطلاعات بیشتر، به «اشتراک در یک مشکل» مراجعه کنید.