إضافة توافق نظام التشغيل Android Automotive إلى تطبيق الوسائط

يتيح نظام التشغيل Android Automotive للمستخدمين تثبيت التطبيقات في السيارة. للوصول إلى مستخدمي هذا النظام الأساسي، عليك توزيع تطبيق ملائم لقائدي السيارات يتوافق مع نظام التشغيل Android Automotive. يمكنك إعادة استخدام الرمز البرمجي والموارد بالكامل تقريبًا في تطبيق Android Auto، ولكن عليك إنشاء إصدار منفصل يستوفي المتطلبات الواردة في هذه الصفحة.

نظرة عامة حول التطوير

لا تتطلّب إضافة إمكانية تشغيل التطبيق على نظام التشغيل Android Automotive سوى بضع خطوات، كما هو موضّح في الأقسام التالية:

  1. تفعيل ميزات السيارات في "استوديو Android"
  2. إنشاء وحدة سيارات
  3. تعديل الاعتماديات في Gradle
  4. اختياريًا، نفِّذ الإعدادات وأنشطة تسجيل الدخول.
  5. اختياري: قراءة تلميحات مضيف الوسائط

اعتبارات التصميم

يتولّى نظام التشغيل Android Automotive تنسيق محتوى الوسائط الذي يتلقّاه من خدمة متصفّح الوسائط في تطبيقك. وهذا يعني أنّ تطبيقك لا يرسم واجهة المستخدم ولا يبدأ أيًا من أنشطتك عندما يبدأ المستخدم تشغيل الوسائط.

في حال تنفيذ إعدادات أو أنشطة تسجيل الدخول، يجب أن تكون هذه الأنشطة محسَّنة للمركبة. يُرجى الرجوع إلى إرشادات التصميم لنظام التشغيل Android Automotive عند تصميم هذه الأجزاء من تطبيقك.

إعداد مشروعك

عليك إعداد عدّة أجزاء من مشروع تطبيقك لتفعيل إمكانية استخدامه على نظام التشغيل Android Automotive.

تفعيل ميزات Automotive في استوديو Android

استخدِم الإصدار 4.0 أو إصدارًا أحدث من "استوديو Android" للتأكّد من تفعيل جميع ميزات نظام التشغيل Automotive.

إنشاء وحدة سيارات

تتضمّن بعض مكوّنات نظام التشغيل Android Automotive، مثل ملف البيان، متطلبات خاصة بالنظام الأساسي. أنشئ وحدة يمكنها الاحتفاظ بالرمز البرمجي لهذه المكوّنات بشكل منفصل عن الرموز البرمجية الأخرى في مشروعك، مثل الرمز البرمجي المستخدَم في تطبيق الهاتف.

اتّبِع الخطوات التالية لإضافة وحدة نمطية للسيارة إلى مشروعك:

  1. في "استوديو Android"، انقر على ملف > جديد > وحدة جديدة.
  2. اختَر وحدة السيارات، ثم انقر على التالي.
  3. أدخِل اسم التطبيق أو المكتبة. هذا هو الاسم الذي يظهر للمستخدمين لتطبيقك على نظام التشغيل Android Automotive.
  4. أدخِل اسم وحدة.
  5. عدِّل اسم الحزمة ليتطابق مع تطبيقك.
  6. اختَر المستوى 28 من واجهة برمجة التطبيقات: الإصدار 9.0 من نظام التشغيل Android (Pie) في الحد الأدنى من حزمة تطوير البرامج (SDK)، ثم انقر على التالي.

    تعمل جميع السيارات المتوافقة مع نظام التشغيل Android Automotive على الإصدار 9 من نظام التشغيل Android (المستوى 28 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، لذا سيؤدي اختيار هذه القيمة إلى استهداف جميع السيارات المتوافقة.

  7. انقر على ما مِن نشاط، ثمّ انقر على إنهاء.

بعد إنشاء الوحدة في "استوديو Android"، افتح ملف 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. يُرجى العِلم أنّه لم يتم تعريف أي أنشطة في البيان.

إذا كنت تنفّذ إعدادات أو أنشطة تسجيل الدخول، أضِفها هنا. يتم تشغيل هذه الأنشطة من خلال النظام باستخدام نوايا صريحة، وهي الأنشطة الوحيدة التي تحدّدها في ملف البيان لتطبيق نظام التشغيل Android Automotive.

بعد إضافة أي إعدادات أو أنشطة تسجيل دخول، أكمل ملف البيان من خلال ضبط السمة android:appCategory للعنصر <application> على "audio".

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

تحديد متطلبات الميزات

يجب أن تستوفي جميع التطبيقات المصمَّمة لنظام التشغيل Android Automotive متطلبات معيّنة ليتم توزيعها باستخدام Google Play. لمزيد من المعلومات، يُرجى الاطّلاع على استيفاء متطلبات ميزة "لقاء" في Google Play.

تعريف تطبيقات الوسائط التي تعمل على نظام التشغيل Android Automotive

استخدِم إدخال ملف البيان التالي للإشارة إلى أنّ تطبيقك متوافق مع نظام التشغيل 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>

فلاتر الأهداف

يستخدم نظام التشغيل Android Automotive OS نوايا ضمنية لتفعيل الأنشطة في تطبيق الوسائط. لا تضمِّن أي أنشطة تتضمّن فلاتر نوايا CATEGORY_LAUNCHER أو ACTION_MAIN في ملف البيان.

تستهدف الأنشطة المشابهة للمثال التالي عادةً هاتفًا أو بعض الأجهزة الجوّالة الأخرى. يجب تعريف هذه الأنشطة في الوحدة التي تنشئ تطبيق الهاتف، وليس في الوحدة التي تنشئ تطبيق نظام التشغيل Android Automotive.

<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

ننصحك بإبقاء خدمة متصفّح الوسائط في وحدة منفصلة يمكنك مشاركتها بين تطبيق الهاتف ووحدة السيارة. إذا كنت تستخدم هذا الأسلوب، عليك تعديل وحدة Android Automotive لتضمين الوحدة المشترَكة، كما هو موضّح في المقتطف التالي:

my-auto-module/build.gradle

أنيق

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

Kotlin

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

تنفيذ الإعدادات وأنشطة تسجيل الدخول

بالإضافة إلى خدمة متصفّح الوسائط، يمكنك أيضًا توفير إعدادات محسَّنة للمركبة وأنشطة تسجيل الدخول لتطبيقك على Android Automotive OS. تتيح لك هذه الأنشطة توفير وظائف التطبيق غير المضمّنة في واجهات برمجة التطبيقات الخاصة بالوسائط في Android.

لا تنفِّذ هذه الأنشطة إلا إذا كان تطبيقك المتوافق مع نظام التشغيل Android Automotive OS يحتاج إلى السماح للمستخدمين بتسجيل الدخول أو تحديد إعدادات التطبيق. ولا تستخدم Android Auto هذه الأنشطة.

مهام سير العمل المتعلقة بالنشاط

يوضّح الرسم التخطيطي التالي كيفية تفاعل المستخدم مع إعداداتك وأنشطة تسجيل الدخول باستخدام نظام التشغيل Android Automotive:

مهام سير العمل لأنشطة &quot;الإعدادات&quot; و&quot;تسجيل الدخول&quot;

الشكل 1: إعدادات ومهام سير عمل نشاط تسجيل الدخول

تجنُّب عوامل التشتيت في إعداداتك وأنشطة تسجيل الدخول

لضمان عدم إتاحة إعداداتك وأنشطة تسجيل الدخول إلا أثناء ركن المستخدم لسيارته، تأكَّد من أنّ عناصر <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>

تنفيذ نشاط الإعدادات

عندما يشغّل المستخدم تطبيقك، يرصد نظام التشغيل Android Automotive نشاط الإعدادات الذي حدّدته ويعرض عنصر تحكّم، مثل رمز. يمكن للمستخدم النقر على التلميحات المرئية هذه أو اختيارها باستخدام شاشة السيارة للتنقّل إلى النشاط. يرسل نظام التشغيل Android Automotive الغرض 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 للحصول على مزيد من المعلومات.

أثناء تنفيذ نشاط الإعدادات، ننصحك باتّباع أفضل الممارسات التالية لاستخدام بعض المكوّنات في مكتبة Preference:

  • يجب ألا يتجاوز عدد مستويات العمق مستويَين أسفل العرض الرئيسي في نشاط الإعدادات.
  • لا تستخدِم DropDownPreference. استخدِم ListPreference بدلاً من ذلك.
  • المكونات التنظيمية:
    • PreferenceScreen
      • يجب أن يكون هذا هو المستوى الأعلى في شجرة الإعدادات المفضّلة.
    • PreferenceCategory
      • تُستخدَم لتجميع عناصر Preference معًا.
      • أدرِج title.
  • أدرِج key وtitle في جميع المكوّنات التالية. يمكنك أيضًا تضمين summary أو icon أو كليهما:
    • Preference
      • خصِّص المنطق في onPreferenceTreeClick() callback لعملية التنفيذ 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. لا تستخدم تطبيقات الهاتف المتصلة بمنصة Android Auto هذه الميزة.

طلب تسجيل الدخول عند بدء تشغيل التطبيق

لفرض تسجيل الدخول على المستخدم قبل أن يتمكّن من استخدام تطبيقك، يجب أن تتوفّر في خدمة متصفّح الوسائط ما يلي:

  1. في طريقة onLoadChildren() الخاصة بالخدمة، أرسِل نتيجة null باستخدام طريقة sendResult().
  2. اضبط PlaybackStateCompat لجلسة الوسائط على STATE_ERROR باستخدام طريقة setState(). يُعلم ذلك نظام التشغيل Android Automotive أنّه لا يمكن إجراء أي عمليات أخرى إلى أن يتم حلّ الخطأ.
  3. اضبط رمز الخطأ PlaybackStateCompat لجلسة الوسائط على ERROR_CODE_AUTHENTICATION_EXPIRED. يُعلم ذلك نظام التشغيل Android Automotive بأنّ المستخدم بحاجة إلى المصادقة.
  4. اضبط رسالة الخطأ PlaybackStateCompat لجلسة الوسائط باستخدام الطريقة setErrorMessage(). بما أنّ رسالة الخطأ هذه موجّهة للمستخدم، يجب ترجمتها لتناسب اللغة الحالية للمستخدم.
  5. اضبط إضافات PlaybackStateCompat جلسة الوسائط باستخدام طريقة 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 يوجّه المستخدِم إلى نشاط تسجيل الدخول إلى "مكتبة تطبيقات السيارات". بما أنّ مضيف "مكتبة تطبيقات السيارة" محسّن للاستخدام أثناء القيادة، يتجاوز الغرض شاشة حلّ الأخطاء تلقائيًا ويعرض شاشة تسجيل الدخول على الفور. في حال ضبط هذا الخيار الإضافي، يجب ضبط الخيارَين الإضافيَّين السابقَين أيضًا لضمان التوافق مع المركبات القديمة.

يوضّح مقتطف الرمز التالي كيف يمكن لتطبيقك أن يطلب من المستخدم تسجيل الدخول قبل استخدام التطبيق:

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 من خلال استدعاء طريقة finish() في النشاط.

تنفيذ نشاط تسجيل الدخول

توفّر Google مجموعة متنوعة من أدوات تحديد الهوية التي يمكنك استخدامها لمساعدة المستخدمين في تسجيل الدخول إلى تطبيقك في سياراتهم. توفّر بعض الأدوات، مثل &quot;مصادقة Firebase&quot;، حِزم أدوات متكاملة يمكن أن تساعدك في إنشاء تجارب مصادقة مخصّصة. تستفيد أدوات أخرى من بيانات اعتماد المستخدم الحالية أو تقنيات أخرى لمساعدتك في إنشاء تجارب تسجيل دخول سلسة للمستخدمين.

يمكن أن تساعدك الأدوات التالية في إنشاء تجربة تسجيل دخول أسهل للمستخدمين الذين سبق لهم تسجيل الدخول على جهاز آخر:

  • ميزة "تسجيل الدخول بنقرة واحدة" و"الاشتراك بنقرة واحدة": إذا سبق لك تنفيذ تسجيل الدخول بنقرة واحدة لأجهزة أخرى، مثل تطبيق الهاتف، عليك تنفيذها لتطبيق Android Automotive OS من أجل إتاحة الميزة للمستخدمين الحاليين.
  • تسجيل الدخول باستخدام حساب Google: إذا سبق لك تنفيذ تسجيل الدخول باستخدام حساب Google لأجهزة أخرى، مثل تطبيق الهاتف، عليك تنفيذ هذه الميزة في تطبيقك على نظام التشغيل Android Automotive لتوفيرها للمستخدمين الحاليين.
  • الملء التلقائي من Google: إذا فعّل المستخدمون ميزة "الملء التلقائي من Google" على أجهزة Android الأخرى، يتم حفظ بيانات اعتمادهم في مدير كلمات المرور في Google. عندما يسجّل هؤلاء المستخدمون الدخول إلى تطبيقك على نظام التشغيل Android Automotive، تقترح ميزة "الملء التلقائي من Google" بيانات الاعتماد المحفوظة ذات الصلة. لا يتطلّب استخدام ميزة "الملء التلقائي من Google" أي جهد لتطوير التطبيق. ومع ذلك، يمكن لمطوّري التطبيقات تحسين تطبيقاتهم للحصول على نتائج أفضل من حيث الجودة. تتوفّر ميزة "الملء التلقائي من Google" على جميع الأجهزة التي تعمل بالإصدار 8.0 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 26) أو الإصدارات الأحدث، بما في ذلك نظام التشغيل Android Automotive.

استخدام AccountManager

يجب أن تستخدم التطبيقات التي تعمل بنظام التشغيل Android Automotive والتي تتطلّب مصادقة 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، وإجراء بحث عن "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)

لتحسين تجربة تطبيق الوسائط على أجهزة نظام التشغيل Android Automotive، يمكنك إضافة إمكانية استخدام الروابط العميقة إلى تطبيقك. يتيح ذلك للمستخدمين، على سبيل المثال، فتح تطبيقك مباشرةً من المتصفّح أو عند تلقّي عنوان URL تمت مشاركته من هاتف باستخدام ميزة Quick Share.

إضافة فلاتر أهداف الروابط لصفحات في التطبيق

لإعلام نظام التشغيل بأنّ تطبيقك يمكنه التعامل مع الروابط لصفحات معيّنة، يجب أن يتضمّن أنشطة تتضمّن فلاتر الأهداف المناسبة. راجِع إضافة فلاتر الأهداف للروابط الواردة للحصول على إرشادات حول تنسيق فلاتر الأهداف المستخدَمة للروابط لصفحات في التطبيق.

لتقديم أفضل تجربة للمستخدم، يجب توفير جميع الروابط لصفحات في التطبيق التي يتيحها تطبيقك على الأجهزة الجوّالة، إذا كان من الممكن توفيرها بشكل معقول في تطبيقك المتوافق مع السيارات. وإذا كان تطبيقك يتضمّن إعدادات أو أنشطة تسجيل الدخول، يجب الإعلان عن فلاتر الأهداف لمعالجة الإعدادات وروابط تسجيل الدخول لصفحات في التطبيق ضمن عناصر البيان <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()
  }
}

قراءة تلميحات مضيف الوسائط

بناءً على تطبيق النظام (بما في ذلك إصداره) الذي يتصل بخدمة متصفّح الوسائط، قد يتلقّى تطبيقك الإضافات التالية:

معالجة الأخطاء

يتم إبلاغ المستخدمين بالأخطاء في تطبيقات الوسائط على نظام التشغيل Android Automotive باستخدام PlaybackStateCompat لجلسة الوسائط. بالنسبة إلى جميع الأخطاء، اضبط رمز الخطأ ورسالة الخطأ المناسبَين في PlaybackStateCompat. يؤدي ذلك إلى ظهور Toast في واجهة المستخدم.

عند حدوث خطأ ولكن يمكن مواصلة التشغيل، أرسِل خطأ غير فادح. على سبيل المثال، قد يتمكّن المستخدم من تشغيل الموسيقى في تطبيق قبل تسجيل الدخول، ولكن عليه تسجيل الدخول قبل أن يتمكّن من تخطّي أغنية. عند استخدام خطأ غير فادح، يمكن للنظام أن يقترح على المستخدم تسجيل الدخول بدون مقاطعة تشغيل عنصر الوسائط الحالي.

عند حدوث خطأ غير فادح، احتفِظ ببقية PlaybackStateCompat كما هي، باستثناء رمز الخطأ ورسالة الخطأ. يتيح هذا الأسلوب مواصلة تشغيل عنصر الوسائط الحالي بينما يقرّر المستخدم ما إذا كان يريد تسجيل الدخول.

عندما لا يكون التشغيل ممكنًا، مثلاً في حال عدم توفّر اتصال بالإنترنت وعدم توفّر محتوى متاح بلا إنترنت، اضبط حالة PlaybackStateCompat على STATE_ERROR.

عند إجراء تحديثات لاحقة على PlaybackStateCompat، عليك محو أي رموز خطأ ورسائل خطأ لتجنُّب عرض تحذيرات متعددة للخطأ نفسه.

إذا تعذّر عليك في أي وقت تحميل شجرة تصفّح، مثلاً إذا كنت بحاجة إلى مصادقة ولم يسجّل المستخدم الدخول، أرسِل شجرة تصفّح فارغة. للإشارة إلى ذلك، يجب عرض نتيجة فارغة من onLoadChildren() لعقدة وسائط الجذر. عند حدوث ذلك، يعرض النظام خطأ بملء الشاشة مع رسالة الخطأ التي تم ضبطها في PlaybackStateCompat.

الأخطاء القابلة للتنفيذ

إذا كان الخطأ قابلاً للتنفيذ، اضبط أيضًا الإضافتين التاليتين في PlaybackStateCompat:

تظهر الأخطاء التي تتطلّب اتّخاذ إجراء على شكل Dialog ولا يمكن للمستخدمين حلّها إلا عندما تكون السيارة متوقّفة.

اختبار حالات الأخطاء

تأكَّد من أنّ تطبيقك يتعامل مع الأخطاء بشكل سليم في جميع السيناريوهات، بما في ذلك:

  • مستويات مختلفة من منتجك: على سبيل المثال، مجاني مقابل مميّز أو تسجيل الدخول مقابل عدم تسجيل الدخول
  • حالات القيادة المختلفة: على سبيل المثال، الركن مقابل القيادة
  • حالات الاتصال المختلفة: على سبيل المثال، الاتصال بالإنترنت أو عدم الاتصال به

اعتبارات أخرى

ضَع في اعتبارك الاعتبارات الأخرى التالية عند تطوير تطبيقك لنظام التشغيل Android Automotive:

محتوى بلا اتصال

إذا كان ذلك منطبقًا، يمكنك توفير إمكانية تشغيل المحتوى بلا إنترنت. من المتوقّع أن تتوفّر في السيارات التي تعمل بنظام التشغيل Android Automotive اتصالات بيانات خاصة بها، ما يعني أنّ خطة البيانات مضمّنة في تكلفة السيارة أو يدفعها المستخدم. ومع ذلك، من المتوقّع أن تكون إمكانية الاتصال في السيارات أكثر تفاوتًا من الأجهزة الجوّالة.

في ما يلي بعض الأمور التي يجب وضعها في الاعتبار عند التفكير في استراتيجية توفير الدعم بلا إنترنت:

  • أفضل وقت لتنزيل المحتوى هو أثناء استخدام تطبيقك.
  • لا تفترض أنّ شبكة WiFi متاحة. قد لا تكون السيارة ضمن نطاق شبكة Wi-Fi أبدًا، أو قد يكون مصنّع المعدات الأصلية قد أوقف شبكة Wi-Fi لصالح شبكة الجوّال.
  • مع أنّه لا بأس بتخزين المحتوى مؤقتًا الذي تتوقّع أن يستخدمه المستخدمون، ننصحك بالسماح للمستخدم بتغيير هذا السلوك من خلال نشاط الإعدادات.
  • تختلف مساحة القرص المتوفّرة في السيارات، لذا يجب توفير طريقة للمستخدمين لحذف المحتوى المتوفّر بلا إنترنت، مثلاً من خلال خيار في نشاط الإعدادات.

التوافق مع WebView

تتوافق WebViews مع نظام التشغيل Android Automotive، ولكن لا يُسمح باستخدامها إلا في إعداداتك وأنشطة تسجيل الدخول. يجب أن تتضمّن الأنشطة التي تستخدم 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 (APK) منفصلة لنظام التشغيل Android Automotive، يمكنك إعادة استخدام اسم الحزمة من تطبيقك على الأجهزة الجوّالة أو إنشاء اسم حزمة جديد. إذا كنت تستخدم اسم حزمة مختلفًا، سيتضمّن تطبيقك بطاقتَي بيانات منفصلتَين على &quot;متجر Play&quot;. في حال إعادة استخدام اسم الحزمة الحالي، سيظهر تطبيقك في بطاقة بيانات واحدة على كلتا المنصّتين.

هذا القرار يعود بشكل أساسي إلى النشاط التجاري. على سبيل المثال، إذا كان لديك فريق يعمل على تطبيق الأجهزة الجوّالة وفريق آخر يعمل على تطبيق نظام التشغيل Android Automotive، قد يكون من المنطقي أن يكون لكل تطبيق اسم حزمة منفصل وأن يدير كل فريق بطاقة بيانات المتجر الخاصة به على متجر Play. لا يوجد فرق كبير في الجهد التقني المطلوب لاستخدام أيّ من الطريقتين.

يلخّص الجدول التالي بعض الاختلافات الرئيسية الأخرى بين الاحتفاظ باسم الحزمة الحالي واستخدام اسم حزمة جديد:

الميزة اسم الحزمة نفسه اسم الحزمة الجديد
بطاقة بيانات المتجر أغنية فردية عدة تعليقات
التثبيت المتطابق نعم: "إعادة تثبيت التطبيقات بسرعة" أثناء معالج الإعداد لا
عملية المراجعة في "متجر Play" حظر المراجعات: إذا لم تجتَز المراجعة إحدى حِزم APK، سيتم حظر حِزم APK الأخرى التي تم إرسالها في الإصدار نفسه. المراجعات الفردية
الإحصاءات والمقاييس والمؤشرات الحيوية مجمّعة: يمكنك فلترة البيانات الخاصة بالسيارات. فصل
الفهرسة والترتيب ضمن نتائج البحث الاستفادة من الترتيب الحالي لا يمكن نقل البيانات
التكامل مع تطبيقات أخرى على الأرجح، لن تحتاج إلى إجراء أي تغييرات، على افتراض أنّ رمز الوسائط تتم مشاركته بين حزمتَي APK. قد تحتاج إلى تحديث التطبيق المعنيّ، مثلاً لتشغيل URI باستخدام "مساعد Google".

الأسئلة الشائعة

يمكنك الاطّلاع على الأقسام التالية للحصول على إجابات عن بعض الأسئلة الشائعة حول نظام التشغيل Android Automotive.

الأجهزة

هل يمكن لتطبيقي الوصول إلى الميكروفون؟

بالنسبة إلى التطبيقات التي تستهدف الإصدار 10 من نظام التشغيل Android (المستوى 29 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يُرجى الرجوع إلى مستندات مشاركة إدخال الصوت. ولا يمكن إجراء ذلك قبل مستوى واجهة برمجة التطبيقات 29.

ما هي واجهات برمجة التطبيقات الخاصة بالسيارات التي يمكننا الوصول إليها وكيف؟

تقتصر على واجهات برمجة التطبيقات التي يوفّرها المصنّع الأصلي للجهاز. ويجري حاليًا تطوير عمليات لتحديد طريقة موحّدة للوصول إلى واجهات برمجة التطبيقات هذه.

يمكن للتطبيقات الوصول إلى واجهات برمجة التطبيقات الخاصة بالسيارات باستخدام SetProperty() وGetProperty() في CarPropertyManager. راجِع رمز المصدر أو المستندات المرجعية للاطّلاع على قائمة بجميع الخصائص المتاحة. إذا كانت السمة مشروحة باستخدام @SystemApi، ستقتصر على تطبيقات النظام المحمَّلة مسبقًا.

ما هي أنواع برامج ترميز الصوت المتوافقة؟

يُرجى الرجوع إلى تفاصيل برنامج ترميز الصوت في مستند تعريف التوافق (CDD) لنظام التشغيل Android.

هل تتوافق معيار Widevine لإدارة الحقوق الرقمية؟

نعم. يتوافق الجهاز مع Widevine DRM.

التطوير والاختبار

هل هناك أي قيود أو اقتراحات لاستخدام حِزم تطوير البرامج والمكتبات التابعة لجهات خارجية؟

ليس لدينا أي إرشادات محدّدة بشأن استخدام حِزم تطوير البرامج والمكتبات التابعة لجهات خارجية. إذا اخترت استخدام حِزم SDK ومكتبات تابعة لجهات خارجية، ستظل مسؤولاً عن استيفاء جميع متطلبات جودة تطبيقات السيارات.

هل يمكنني استخدام خدمة تعمل في المقدّمة؟

حالة الاستخدام الوحيدة المسموح بها للخدمة التي تعمل في المقدّمة هي تنزيل المحتوى لاستخدامه بلا إنترنت. إذا كان لديك حالة استخدام أخرى لخدمة تعمل في المقدّمة وتريد أن تتوفّر لها إمكانية الدعم، يُرجى التواصل معنا باستخدام مجموعة مناقشة نظام التشغيل Android Automotive.

نشر تطبيقات نظام التشغيل Android Automotive

كيف يمكنني نشر تطبيق نظام التشغيل Android Automotive باستخدام Google Play Console؟

للحصول على تفاصيل حول كيفية نشر تطبيقك على نظام التشغيل Android Automotive باستخدام Google Play Console، يُرجى الاطّلاع على مقالة التوزيع على السيارات.

مراجع إضافية

لمزيد من المعلومات حول نظام التشغيل Android Automotive، يُرجى الاطّلاع على المَراجع الإضافية التالية.

نماذج

الأدلّة

المدوّنات

الفيديوهات

الإبلاغ عن مشكلة في الوسائط على نظام التشغيل Android Automotive

إذا واجهت مشكلة أثناء تطوير تطبيق وسائط لنظام التشغيل Android Automotive، يمكنك الإبلاغ عنها باستخدام Google Issue Tracker. احرص على ملء جميع المعلومات المطلوبة في نموذج المشكلة.

إنشاء مشكلة جديدة

قبل تسجيل مشكلة جديدة، تحقَّق مما إذا تم الإبلاغ عنها من قبل في قائمة المشاكل. يمكنك الاشتراك في المشاكل والتصويت عليها من خلال النقر على النجمة الخاصة بمشكلة في أداة التتبُّع. لمزيد من المعلومات، اطّلِع على مقالة الاشتراك في مشكلة.