مكتبة تطبيقات "Android للسيارات" يتيح لك الاستفادة من ميزات التنقّل ونقاط الاهتمام وإنترنت الأشياء (IOT) التطبيقات على السيارة. ويتم ذلك من خلال توفير مجموعة من النماذج المصمّمة لتلبية عناصر تشتيت السائق. والمعايير والاهتمام بالتفاصيل مثل مجموعة متنوعة من عوامل شاشة السيارة وأساليب الإدخال.
يقدم هذا الدليل نظرة عامة على الميزات والمفاهيم الرئيسية للمكتبة يرشدك خلال عملية إعداد تطبيق أساسي.
قبل البدء
- مراجعة التصميم المناسب للقيادة
الصفحات التي تغطي مكتبة تطبيقات السيارات
- تطبيقات التنقّل والتطبيقات الأخرى المتعلّقة بالقيادة نظرة عامة على الفئات
- نظرة عامة على إنشاء التطبيقات باستخدام النماذج
- الوحدات الأساسية تغطي النماذج ومكوّنات النماذج
- نماذج التدفقات إظهار أنماط تجربة المستخدم الشائعة
- متطلبات التطبيقات المستندة إلى نموذج
- راجع المصطلحات والمفاهيم الرئيسية في ما يلي .
- الاطّلاع على نظام Android Auto واجهة المستخدم ونظام التشغيل Android Automotive التصميم.
- راجِع ملاحظات الإصدار.
- راجِع عيّنات.
المصطلحات والمفاهيم الرئيسية
- النماذج والنماذج
- يتم تمثيل واجهة المستخدم من خلال رسم بياني لكائنات النماذج التي يمكن مرتبة معًا بطرق مختلفة، على النحو الذي يسمح به النموذج الذي تنتمي إليه إليه. النماذج هي مجموعة فرعية من النماذج التي يمكن أن تعمل كجذر في تلك والرسوم البيانية. تتضمن النماذج المعلومات التي سيتم عرضها للمستخدم في من النص والصور بالإضافة إلى الخصائص لتهيئة جوانب المظهر المرئي لهذه المعلومات، مثل ألوان النص أو الصورة مختلفة. يحوّل المضيف النماذج إلى طرق عرض مصممة لتلبية معايير تشتيت السائق ويهتم بتفاصيل مثل تنوع لعوامل شاشة السيارة وأساليب الإدخال
- استضِف أصدقاءك وعائلتك
- المضيف هو مكوِّن الخلفية الذي ينفّذ الوظائف المقدَّمة بواسطة واجهات برمجة التطبيقات للمكتبة بحيث يمكن تشغيل التطبيق في السيارة. تشير رسالة الأشكال البيانية ومسئوليات المضيف من اكتشاف تطبيقك وإدارة تحويل نماذجك إلى مشاهدات وإعلام تطبيقك من تفاعلات المستخدم. على الأجهزة الجوّالة، ينفذ نظام Android هذا المضيف تلقائي: على نظام التشغيل Android Automotive، يتم تثبيت هذا المضيف كتطبيق نظام.
- القيود على النماذج
- تفرض النماذج المختلفة قيودًا في محتوى نماذجها. بالنسبة لنفترض أن نماذج القوائم لها حدود على عدد العناصر التي يمكن تقديمه للمستخدم. هناك أيضًا قيود على النماذج في الطريقة التي مرتبطة بها لتشكيل تدفق المهمة. على سبيل المثال، يمكن للتطبيق أن يدفع ما يصل إلى خمسة قوالب إلى مكدس الشاشة. عرض قيود النماذج للاطّلاع على مزيد من التفاصيل.
Screen
Screen
هي فئة مقدَّمة من التي تنفذها التطبيقات لإدارة واجهة المستخدم المقدمة إلى المستخدم. لدىScreen
دورة حياة وتوفر الآلية التي تمكّن التطبيق من إرسال النموذج لعرضه عندما تكون الشاشة مرئية. يمكن أيضًا إرسالScreen
نسخة افتراضية. وبرزت من وإلى حزمةScreen
، التي يضمن التزامه قيود تدفق النموذجCarAppService
CarAppService
هوService
الموجزة التي التنفيذ والتصدير ليكتشفه المضيف ويديره.CarAppService
لتطبيقك عن التحقق من إمكانية الوثوق في اتصال مضيف باستخدامcreateHostValidator
وتوفيرSession
الحالات لكل اتصال باستخدامonCreateSession
.Session
Session
هي فئة مجردة يجب أن ينفذها تطبيقك ويعود باستخدامCarAppService.onCreateSession
وهو بمثابة نقطة دخول لعرض المعلومات على شاشة السيارة. أُنشأها جون هنتر، الذي كان متخصصًا تتضمن دورة حياة تحدد الحالة الحالية لتطبيقك على شاشة السيارة، مثلاً عندما يكون تطبيقك مرئية أو مخفية.عند بدء تشغيل
Session
، مثلاً عند تشغيل التطبيق لأول مرة، يطلب المضيف إدخالScreen
للعرض باستخدامonCreateScreen
.
تثبيت مكتبة تطبيقات السيارة
الاطّلاع على مكتبة Jetpack صفحة الإصدار لـ تعليمات حول كيفية إضافة المكتبة إلى تطبيقك
ضبط ملفات بيان تطبيقك
قبل أن تتمكّن من إنشاء تطبيق للسيارات، عليك ضبط ملفات البيان على النحو التالي.
الإفصاح عن CarAppService
يتصل المضيف بتطبيقك من خلال
تنفيذ CarAppService
. إِنْتَ
اذكر هذه الخدمة في ملف البيان للسماح للمضيف بالعثور على الجهاز والاتصال به.
إلى تطبيقك.
عليك أيضًا توضيح فئة تطبيقك في
العنصر <category>
في تطبيقك
فلتر الأهداف. اطّلِع على قائمة
فئات التطبيقات المتوافقة للقيم المسموح بها
لهذا العنصر.
يعرض مقتطف الرمز التالي كيفية الإشارة إلى خدمة أحد تطبيقات السيارات لنقطة في بيانك:
<application>
...
<service
...
android:name=".MyCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService"/>
<category android:name="androidx.car.app.category.POI"/>
</intent-filter>
</service>
...
<application>
فئات التطبيقات المتوافقة
يُرجى تعريف فئة تطبيقك عن طريق إضافة فئة واحدة أو أكثر من الفئة التالية:
القيم في فلتر الأهداف عند تعريف CarAppService
على النحو الموضّح
في القسم السابق:
androidx.car.app.category.NAVIGATION
: تطبيق للاطّلاع على الاتّجاهات المفصّلة واتجاهات التنقل. اطَّلِع على إنشاء تطبيقات التنقّل للسيارات للحصول على مستندات إضافية حول هذه الفئة.androidx.car.app.category.POI
: تطبيق يوفّر وظائف ذات صلة إلى العثور على نقاط اهتمام مثل مواقف السيارات ومحطات الشحن محطات الوقود. إتمام الدفع إنشاء تطبيقات نقاط الاهتمام للسيارات في مستندات إضافية حول هذه الفئة.androidx.car.app.category.IOT
: تطبيق يتيح للمستخدمين اتخاذ إجراءات ذات صلة الإجراءات التي تتم على الأجهزة المتصلة من داخل السيارة. إتمام الدفع إنشاء تطبيقات إنترنت للسيارات مستندات إضافية حول هذه الفئة.
يمكنك الاطّلاع على جودة تطبيقات Android للسيارات من أجل وصف تفصيلي لكل فئة ومعايير ينبغي أن تنتمي التطبيقات إليها.
تحديد اسم التطبيق ورمزه
يجب تحديد اسم تطبيق ورمز يمكن للمضيف استخدامهما ليمثلا تطبيقك في واجهة مستخدم النظام.
يمكنك تحديد اسم التطبيق ورمزه المُستخدَمان لتمثيل تطبيقك باستخدام
label
icon
لسمات
CarAppService
:
...
<service
android:name=".MyCarAppService"
android:exported="true"
android:label="@string/my_app_name"
android:icon="@drawable/my_app_icon">
...
</service>
...
إذا لم يتم تعريف التصنيف أو الرمز في ملف
<service>
، المضيف
إلى القيم المحددة
<application>
ضبط مظهر مخصّص
لضبط مظهر مخصّص لتطبيق السيارة، أضِف
العنصر <meta-data>
في
على النحو التالي:
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
بعد ذلك، يمكنك تحديد مورد النمط اضبط السمات التالية للمظهر المخصّص لتطبيق السيارة:
<resources> <style name="MyCarAppTheme"> <item name="carColorPrimary">@layout/my_primary_car_color</item> <item name="carColorPrimaryDark">@layout/my_primary_dark_car_color</item> <item name="carColorSecondary">@layout/my_secondary_car_color</item> <item name="carColorSecondaryDark">@layout/my_secondary_dark_car_color</item> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
مستوى واجهة برمجة تطبيقات تطبيق السيارة
تحدد مكتبة تطبيقات السيارات مستويات واجهة برمجة التطبيقات الخاصة بها حتى تتمكن من معرفة
ميزات المكتبة متاحة من خلال مضيف النماذج على المركبة.
لاسترداد أعلى مستوى لواجهة برمجة تطبيقات لتطبيق السيارة متاح من خلال المضيف، استخدِم
getCarAppApiLevel()
.
يُرجى توضيح الحد الأدنى لمستوى واجهة برمجة التطبيقات لتطبيق السيارة الذي يتيحه تطبيقك في
ملف AndroidManifest.xml
:
<manifest ...>
<application ...>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1"/>
</application>
</manifest>
اطّلِع على مستندات
RequiresCarApi
التعليق التوضيحي للحصول على تفاصيل حول كيفية الحفاظ على التوافق مع الأنظمة القديمة وتوضيح
الحد الأدنى لمستوى واجهة برمجة التطبيقات المطلوب لاستخدام إحدى الميزات. لتعريف أي واجهة برمجة تطبيقات
مطلوب لاستخدام ميزة معينة في مكتبة تطبيق السيارة، فراجع
وثائق مرجعية
CarAppApiLevels
إنشاء CarAppService والجلسة
يحتاج تطبيقك إلى تمديد
CarAppService
صف وتنفيذ
CANNOT TRANSLATE
onCreateSession
التي تُرجع Session
المثيل المقابل للاتصال الحالي بالمضيف:
Kotlin
class HelloWorldService : CarAppService() { ... override fun onCreateSession(): Session { return HelloWorldSession() } ... }
Java
public final class HelloWorldService extends CarAppService { ... @Override @NonNull public Session onCreateSession() { return new HelloWorldSession(); } ... }
يُعد المثيل Session
مسؤولاً عن
عرض مثيل Screen
لاستخدام
عند تشغيل التطبيق للمرّة الأولى:
Kotlin
class HelloWorldSession : Session() { ... override fun onCreateScreen(intent: Intent): Screen { return HelloWorldScreen(carContext) } ... }
Java
public final class HelloWorldSession extends Session { ... @Override @NonNull public Screen onCreateScreen(@NonNull Intent intent) { return new HelloWorldScreen(getCarContext()); } ... }
لمعالجة السيناريوهات التي يحتاج فيها تطبيق السيارة إلى التشغيل من شاشة غير
الشاشة الرئيسية أو المقصودة للتطبيق، مثل التعامل مع الروابط لمواضع معينة،
إعداد مسبقًا لحزمة خلفية من الشاشات باستخدام
ScreenManager.push
قبل العودة من
onCreateScreen
تسمح مرحلة التمويل المسبق للمستخدمين بالرجوع إلى الشاشات السابقة من الشاشة
التي يعرضها تطبيقك.
إنشاء شاشة البدء
يمكنك إنشاء الشاشات التي يعرضها تطبيقك عن طريق تحديد الفئات التي تعمل على توسيع نطاق
فئة واحدة (Screen
) وتنفيذها
onGetTemplate
والتي تُرجع
مثيل Template
يمثل
حالة واجهة المستخدم لعرضها على شاشة السيارة.
يعرض المقتطف التالي كيفية الإعلان عن
Screen
الذي يستخدم
PaneTemplate
من أجل
عرض رسالة بسيطة "مرحبًا بالعالم!" string:
Kotlin
class HelloWorldScreen(carContext: CarContext) : Screen(carContext) { override fun onGetTemplate(): Template { val row = Row.Builder().setTitle("Hello world!").build() val pane = Pane.Builder().addRow(row).build() return PaneTemplate.Builder(pane) .setHeaderAction(Action.APP_ICON) .build() } }
Java
public class HelloWorldScreen extends Screen { @NonNull @Override public Template onGetTemplate() { Row row = new Row.Builder().setTitle("Hello world!").build(); Pane pane = new Pane.Builder().addRow(row).build(); return new PaneTemplate.Builder(pane) .setHeaderAction(Action.APP_ICON) .build(); } }
فئة CarContext
الفئة CarContext
هي
فئة فرعية ContextWrapper
يمكن لجهاز Session
Screen
حالة. ويوفر إمكانية الوصول
إلى خدمات السيارات، مثل
ScreenManager
لإدارة
حزمة الشاشة الـ
AppManager
المتعلقة بالتطبيقات العامة
وظائف مثل الوصول إلى الكائن Surface
بغرض رسم الخرائط
وNavigationManager
تستخدمه تطبيقات التنقّل باتّجاهات مفصّلة لإبلاغ التنقل
وبيانات التعريف وغيرها
المتعلقة بالتنقل
أحداث مع
المضيف.
راجع الوصول إلى شريط التنقل النماذج الأوّلية قائمة شاملة بوظائف المكتبة المتاحة لتطبيقات التنقل.
يقدّم CarContext
أيضًا خيارات أخرى
وظيفتها، مثل إمكانية تحميل موارد قابلة للرسم باستخدام قسم
من شاشة السيارة، وتشغيل تطبيق في السيارة باستخدام الأهداف،
والإشارة إلى ما إذا كان يجب أن يعرض تطبيقك خريطته في المظهر الداكن.
تنفيذ التنقل على الشاشة
تقدم التطبيقات غالبًا عددًا من الشاشات المختلفة، وربما تستخدم كل منها القوالب المختلفة التي يمكن للمستخدم التنقل خلالها أثناء تفاعله الواجهة المعروضة على الشاشة.
توفّر الفئة ScreenManager
مكدّس شاشة يمكنك استخدامه لدفع الشاشات التي يمكن أن تظهر تلقائيًا
عندما ينقر المستخدم على زر الرجوع في شاشة السيارة أو يستخدم الجهاز مرة أخرى
في بعض السيارات.
يعرض المقتطف التالي كيفية إضافة إجراء رجوع إلى نموذج رسالة بالإضافة إلى إجراء يعرض شاشة جديدة عند تحديده من قبل المستخدم:
Kotlin
val template = MessageTemplate.Builder("Hello world!") .setHeaderAction(Action.BACK) .addAction( Action.Builder() .setTitle("Next screen") .setOnClickListener { screenManager.push(NextScreen(carContext)) } .build()) .build()
Java
MessageTemplate template = new MessageTemplate.Builder("Hello world!") .setHeaderAction(Action.BACK) .addAction( new Action.Builder() .setTitle("Next screen") .setOnClickListener( () -> getScreenManager().push(new NextScreen(getCarContext()))) .build()) .build();
الكائن Action.BACK
هو
عادي Action
يعمل تلقائيًا
يستدعي ScreenManager.pop
.
يمكن إلغاء هذا السلوك باستخدام
OnBackPressedDispatcher
المثيل المتاح من
CarContext
للمساعدة في ضمان استخدام التطبيق بأمان أثناء القيادة، يمكن أن تتضمن حزمة الشاشة حد أقصى عمق خمس شاشات. الاطّلاع على قيود النماذج لمزيد من التفاصيل.
إعادة تحميل محتوى نموذج
يمكن لتطبيقك طلب الحصول على محتوى
سيتم إبطال صلاحية Screen
من خلال استدعاء
Screen.invalidate
.
يعود المضيف بعد ذلك إلى هاتف
Screen.onGetTemplate
لاسترداد القالب بالمحتويات الجديدة.
عند إعادة تحميل Screen
، تكون
فهم المحتوى المحدد في القالب الذي يمكن تحديثه
وبالتالي لا يحتسب المضيف النموذج الجديد ضمن حصة النموذج.
راجِع قسم قيود النماذج لمعرفة مزيد من التفاصيل.
نوصي بتنظيم بنية شاشاتك بحيث تكون هناك جداول
بين Screen
ونوع
النموذج الذي يعرضه من خلال تنفيذ onGetTemplate
.
رسم الخرائط
يمكن لتطبيقات نقاط الاهتمام والتنقل التي تستخدم النماذج التالية:
رسم الخرائط من خلال الوصول إلى Surface
:
النموذج | إذن النموذج | إرشادات متعلّقة بالفئة |
---|---|---|
NavigationTemplate |
androidx.car.app.NAVIGATION_TEMPLATES |
التنقل |
MapWithContentTemplate |
androidx.car.app.NAVIGATION_TEMPLATES أو androidx.car.app.MAP_TEMPLATES |
التنقّل ونقاط الاهتمام |
MapTemplate (متوقّفة نهائيًا) |
androidx.car.app.NAVIGATION_TEMPLATES |
التنقل |
PlaceListNavigationTemplate (متوقّفة نهائيًا) |
androidx.car.app.NAVIGATION_TEMPLATES |
التنقل |
RoutePreviewNavigationTemplate (متوقّفة نهائيًا) |
androidx.car.app.NAVIGATION_TEMPLATES |
التنقل |
بيان إذن الوصول إلى مساحة العرض
بالإضافة إلى الإذن المطلوب للنموذج الذي يستخدمه تطبيقك،
يجب أن يفصح تطبيقك عن الحصول على إذن "androidx.car.app.ACCESS_SURFACE
" في
ملف واحد (AndroidManifest.xml
) للوصول إلى مساحة العرض:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
...
</manifest>
الوصول إلى سطح المكتب
للوصول إلى Surface
الذي يوفّره المضيف، يجب تنفيذ
SurfaceCallback
وتقديم
هذا التنفيذ على AppManager
خدمة السيارات. تم تمرير قيمة Surface
الحالية إلى
SurfaceCallback
في المعلمة SurfaceContainer
طلبات معاودة الاتصال onSurfaceAvailable()
وonSurfaceDestroyed()
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
معرفة المساحة المرئية للسطح
يمكن للمضيف رسم عناصر واجهة المستخدم للنماذج فوق
الخريطة. يقوم المضيف بإبلاغ مساحة السطح التي يمكن ضمان
بدون عوائق ومرئية للمستخدم بالكامل من خلال استدعاء
SurfaceCallback.onVisibleAreaChanged
. ولتقليل عدد التغييرات أيضًا، يستدعي المضيف
SurfaceCallback.onStableAreaChanged
بأصغر مستطيل، والذي يكون مرئيًا دائمًا بناءً على
القالب الحالي.
على سبيل المثال، عندما يستخدم أحد تطبيقات التنقل
NavigationTemplate
مع شريط الإجراءات في أعلى الصفحة، يمكن أن يخفي شريط الإجراءات
نفسه عندما لا يتفاعل المستخدم مع الشاشة لفترة من الوقت لإجراء المزيد
مساحة للخريطة. في هذه الحالة، هناك استدعاء إلى onStableAreaChanged
و
onVisibleAreaChanged
باستخدام المستطيل نفسه. عندما يكون شريط الإجراءات مخفيًا،
يتم استدعاء onVisibleAreaChanged
فقط مع المساحة الأكبر. إذا كان المستخدم
مع الشاشة، ثم يتم مرة أخرى الاتصال فقط بـ onVisibleAreaChanged
باستخدام
المستطيل الأول.
دعم المظهر الداكن
على التطبيقات إعادة رسم الخريطة على مثيل Surface
باستخدام الوضع الداكن المناسب
الألوان عندما يحدد المضيف الشروط التي تتطلبها، كما هو موضح في
جودة تطبيقات Android للسيارات.
لتحديد ما إذا كنت تريد رسم خريطة مظلمة، يمكنك استخدام
CarContext.isDarkMode
. كلما تغيّرت حالة المظهر الداكن، ستتلقّى مكالمة
Session.onCarConfigurationChanged
السماح للمستخدمين بالتفاعل مع خريطتك
عند استخدام النماذج التالية، يمكنك إضافة دعم للمستخدمين للتفاعل. بالخرائط التي ترسمها، مثل السماح لهم بمشاهدة أجزاء مختلفة من الخريطة من خلال التكبير والتصغير والتحريك.
النموذج | ميزة التفاعل متاحة منذ مستوى واجهة برمجة تطبيقات تطبيق السيارة |
---|---|
NavigationTemplate |
2 |
PlaceListNavigationTemplate (متوقّفة نهائيًا) |
4 |
RoutePreviewNavigationTemplate (متوقّفة نهائيًا) |
4 |
MapTemplate (متوقّفة نهائيًا) |
5 (مقدمة النموذج) |
MapWithContentTemplate |
7 (مقدمة النموذج) |
تنفيذ استدعاءات التفاعل
واجهة SurfaceCallback
تتضمن العديد من طرق معاودة الاتصال التي يمكنك تنفيذها لإضافة التفاعل إلى الخرائط التي تم إنشاؤها
مع القوالب الموجودة في القسم السابق:
التفاعل | طريقة واحدة (SurfaceCallback ) |
يتوفّر هذا الخيار منذ مستوى واجهة برمجة التطبيقات لتطبيق السيارة. |
---|---|---|
النقر | onClick |
5 |
استخدام إصبعين للتصغير | onScale |
2 |
السحب بلمسة واحدة | onScroll |
2 |
الانتقال بلمسة واحدة | onFling |
2 |
النقر مرتين | onScale (مع عامل قياس يحدّده مضيف النموذج) |
2 |
تحريك دوّار في وضع التحريك | onScroll (مع تحديد عامل المسافة من قِبل مضيف النموذج) |
2 |
إضافة شريط إجراءات للخريطة
يمكن أن تحتوي هذه النماذج على شريط إجراءات للخريطة من أجل الإجراءات ذات الصلة بالخريطة، مثل التكبير والتصغير، والتوسيط وعرض بوصلة، وإجراءات أخرى تختار عرضها. يمكن أن يحتوي شريط إجراءات الخريطة على ما يصل إلى أربعة أزرار للرموز فقط يمكن تحديثها دون التأثير على عمق المهمة. يختفي أثناء حالة عدم النشاط ويظهر مرة أخرى في حالة نشطة.
لتلقي استدعاءات التفاعل مع الخريطة، يمكنك
يجب إضافة زر Action.PAN
في شريط الإجراءات على الخريطة. عندما يجرّب
عند الضغط على زر العرض الشامل، يدخل المضيف في وضع العرض الشامل، كما هو موضح في ما يلي
.
إذا حذف تطبيقك Action.PAN
في شريط إجراءات الخريطة، فلن يتلقى إدخالات المستخدم من
SurfaceCallback
، ويخرج المضيف من أي طريقة تم تفعيلها سابقًا
وضع العرض الشامل.
لا يظهر زر "التحريك" على الشاشة التي تعمل باللمس.
التعرّف على "وضع العرض الشامل"
في وضع العرض الشامل، يترجم مضيف النموذج البيانات التي أدخلها المستخدم من الإدخال الذي لا يعمل باللمس.
مثل وحدات التحكم الدوارة ولوحات اللمس، بالعرض المناسب
SurfaceCallback
طريقة الاستجابة لإجراء المستخدم للدخول في وضع العرض الشامل أو الخروج منه
مع
setPanModeListener
في NavigationTemplate.Builder
. يمكن للمضيف إخفاء واجهة مستخدم أخرى
المكونات في القالب عندما يكون المستخدم في وضع التحريك.
التفاعل مع المستخدم
يمكن لتطبيقك التفاعل مع المستخدم باستخدام أنماط مشابهة لتطبيق الأجهزة الجوّالة.
التعامل مع البيانات التي أدخلها المستخدم
يمكن لتطبيقك الاستجابة لإدخال المستخدم من خلال تمرير المستمعين المناسبين إلى
والنماذج التي تدعمها. يوضح المقتطف التالي كيفية إنشاء
يضبط نموذج Action
OnClickListener
الذي
بالعودة إلى طريقة يحددها رمز تطبيقك:
Kotlin
val action = Action.Builder() .setTitle("Navigate") .setOnClickListener(::onClickNavigate) .build()
Java
Action action = new Action.Builder() .setTitle("Navigate") .setOnClickListener(this::onClickNavigate) .build();
ويمكن عندئذٍ للطريقة onClickNavigate
بدء
التطبيق التلقائي لسيارة التنقّل
باستخدام
CarContext.startCarApp
:
Kotlin
private fun onClickNavigate() { val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address)) carContext.startCarApp(intent) }
Java
private void onClickNavigate() { Intent intent = new Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address)); getCarContext().startCarApp(intent); }
لمزيد من التفاصيل حول كيفية بدء تشغيل التطبيقات، بما في ذلك تنسيق
ACTION_NAVIGATE
intent. يمكنك الاطّلاع على بدء تطبيق سيارة بنيّة نية.
.
بعض الإجراءات، مثل تلك التي تتطلب توجيه المستخدم لمتابعة
بالتفاعل على أجهزتهم المحمولة، لا يُسمح إلا عند ركن السيارة.
يمكنك استخدام صفحة
ParkedOnlyOnClickListener
لتنفيذ هذه الإجراءات. إذا لم تكن السيارة متوقفة، فسيعرض المضيف رمز
إشارة إلى المستخدم إلى عدم السماح بالإجراء في هذه الحالة. إذا كانت السيارة
متوقف مؤقتًا، يتم تنفيذ التعليمة البرمجية بشكل طبيعي. يوضح المقتطف التالي كيفية
استخدام ParkedOnlyOnClickListener
لفتح شاشة الإعدادات على الجهاز الجوّال:
Kotlin
val row = Row.Builder() .setTitle("Open Settings") .setOnClickListener(ParkedOnlyOnClickListener.create(::openSettingsOnPhone)) .build()
Java
Row row = new Row.Builder() .setTitle("Open Settings") .setOnClickListener(ParkedOnlyOnClickListener.create(this::openSettingsOnPhone)) .build();
عرض الإشعارات
لا تظهر الإشعارات المُرسَلة إلى الجهاز الجوّال على شاشة السيارة إلا في حال:
يتم تمديدها من خلال
CarAppExtender
تتضمن بعض سمات الإشعارات، مثل عنوان المحتوى والنص والرمز والإجراءات،
يمكن ضبطها في CarAppExtender
، ما يُلغي سمات الإشعار.
عند ظهورها على شاشة السيارة.
يوضح المقتطف التالي كيفية إرسال إشعار إلى شاشة السيارة عنوانًا مختلفًا عن العنوان المعروض على الجهاز الجوّال:
Kotlin
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle(titleOnThePhone) .extend( CarAppExtender.Builder() .setContentTitle(titleOnTheCar) ... .build()) .build()
Java
Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle(titleOnThePhone) .extend( new CarAppExtender.Builder() .setContentTitle(titleOnTheCar) ... .build()) .build();
يمكن أن تؤثر الإشعارات في الأجزاء التالية من واجهة المستخدم:
- قد يظهر إشعار تنبيه (HUN) للمستخدم.
- يمكن إضافة إدخال في مركز الإشعارات، بشكل اختياري مع شارة مرئية في السكك الحديدية.
- بالنسبة إلى تطبيقات التنقّل، قد يتم عرض الإشعار في التطبيق المصغّر لسكة الحديد على النحو التالي: موصوفة في الإشعارات المفصّلة:
يمكنك اختيار كيفية ضبط إشعارات التطبيق للتأثير في كلّ من
عناصر واجهة المستخدم هذه من خلال استخدام أولوية الإشعار، كما هو موضح
في
CarAppExtender
التوثيق.
في حال حذف
NotificationCompat.Builder.setOnlyAlertOnce
بقيمة true
، فسيتم عرض الإشعار ذي الأولوية العالية
HUN مرة واحدة فقط.
للحصول على مزيد من المعلومات حول كيفية تصميم إشعارات تطبيق السيارة، يمكنك الاطّلاع على دليل التصميم من Google للقيادة حول الإشعارات:
عرض الخبز المحمص
يمكن لتطبيقك عرض إشعار منبثق باستخدام
CarToast
كما هو موضّح في هذا المقتطف:
Kotlin
CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()
Java
CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();
طلب الأذونات
إذا كان تطبيقك يحتاج إلى الوصول إلى البيانات أو الإجراءات المحظورة، مثل
الموقع الجغرافي—القواعد العادية لنظام التشغيل Android
الأذونات
تطبيقها. لطلب إذن، يمكنك استخدام
CarContext.requestPermissions()
.
فائدة استخدام
CarContext.requestPermissions()
، على عكس استخدام
واجهات برمجة تطبيقات Android القياسية
بحيث لا تحتاج إلى تشغيل Activity
الخاص بك
لإنشاء مربع حوار الأذونات. علاوة على ذلك، يمكنك استخدام نفس الرمز على
Android Auto وAndroid Automotive، بدلاً من الحاجة إلى إنشاء
تدفقات تعتمد على النظام الأساسي.
ضبط نمط مربّع حوار الأذونات على Android Auto
في Android Auto، سيظهر مربّع حوار الأذونات للمستخدم على الهاتف.
حسب الإعدادات التلقائية، لن تكون هناك خلفية وراء مربّع الحوار. لضبط نطاق مخصّص
اذكر مظهرًا لتطبيق السيارة في
ملف AndroidManifest.xml
وضبط السمة carPermissionActivityLayout
لمظهر تطبيق سيارتك.
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
بعد ذلك، اضبط السمة carPermissionActivityLayout
لمظهر تطبيق السيارة:
<resources> <style name="MyCarAppTheme"> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
شغِّل تطبيق سيارة هادفة.
يمكنك الاتصال
CarContext.startCarApp
طريقة لتنفيذ أحد الإجراءات التالية:
- افتح برنامج الاتصال لإجراء مكالمة هاتفية.
- يمكنك بدء التنقّل باتّجاهات مفصّلة إلى موقع باستخدام التطبيق التلقائي لسيارة التنقُّل.
- أنشِئ تطبيقك الخاص بنيوية.
يوضح المثال التالي كيفية إنشاء إشعار بإجراء
فتح تطبيقك بشاشة تعرض تفاصيل حجز موقف سيارات.
يمكنك توسيع مثيل الإشعار بقصد من المحتوى يحتوي على
PendingIntent
تضمين محتوى فاضح
النية في إجراء تطبيقك:
Kotlin
val notification = notificationBuilder ... .extend( CarAppExtender.Builder() .setContentIntent( PendingIntent.getBroadcast( context, ACTION_VIEW_PARKING_RESERVATION.hashCode(), Intent(ACTION_VIEW_PARKING_RESERVATION) .setComponent(ComponentName(context, MyNotificationReceiver::class.java)), 0)) .build())
Java
Notification notification = notificationBuilder ... .extend( new CarAppExtender.Builder() .setContentIntent( PendingIntent.getBroadcast( context, ACTION_VIEW_PARKING_RESERVATION.hashCode(), new Intent(ACTION_VIEW_PARKING_RESERVATION) .setComponent(new ComponentName(context, MyNotificationReceiver.class)), 0)) .build());
يجب أن يفصح تطبيقك أيضًا عن
BroadcastReceiver
وهو
إلى معالجة الغرض عندما يختار المستخدم الإجراء في
واجهة إشعار ويستدعي
CarContext.startCarApp
بغرض تضمين عنوان URI للبيانات:
Kotlin
class MyNotificationReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val intentAction = intent.action if (ACTION_VIEW_PARKING_RESERVATION == intentAction) { CarContext.startCarApp( intent, Intent(Intent.ACTION_VIEW) .setComponent(ComponentName(context, MyCarAppService::class.java)) .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction))) } } }
Java
public class MyNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String intentAction = intent.getAction(); if (ACTION_VIEW_PARKING_RESERVATION.equals(intentAction)) { CarContext.startCarApp( intent, new Intent(Intent.ACTION_VIEW) .setComponent(new ComponentName(context, MyCarAppService.class)) .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction))); } } }
أخيرًا،
Session.onNewIntent
طريقة في تطبيقك تتعامل مع هذا الهدف من خلال دفع شاشة حجز موقف السيارات
في الحزمة، إذا لم يكن في الأعلى:
Kotlin
override fun onNewIntent(intent: Intent) { val screenManager = carContext.getCarService(ScreenManager::class.java) val uri = intent.data if (uri != null && MY_URI_SCHEME == uri.scheme && MY_URI_HOST == uri.schemeSpecificPart && ACTION_VIEW_PARKING_RESERVATION == uri.fragment ) { val top = screenManager.top if (top !is ParkingReservationScreen) { screenManager.push(ParkingReservationScreen(carContext)) } } }
Java
@Override public void onNewIntent(@NonNull Intent intent) { ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class); Uri uri = intent.getData(); if (uri != null && MY_URI_SCHEME.equals(uri.getScheme()) && MY_URI_HOST.equals(uri.getSchemeSpecificPart()) && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment()) ) { Screen top = screenManager.getTop(); if (!(top instanceof ParkingReservationScreen)) { screenManager.push(new ParkingReservationScreen(getCarContext())); } } }
راجِع قسم عرض الإشعارات لمعرفة المزيد. معلومات حول كيفية التعامل مع الإشعارات الخاصة بتطبيق السيارة.
القيود على النماذج
يضع المضيف حدًا أقصى لعدد النماذج التي يتم عرضها لمهمة معيّنة من خمسة، يجب أن يكون النموذج الأخير أحد الأنواع التالية:
لاحظ أن هذا الحد ينطبق على عدد النماذج وليس على عدد
Screen
مثيل في الحزمة. بالنسبة
على سبيل المثال، إذا أرسل أحد التطبيقات نموذجين أثناء وجوده في الشاشة A ثم دفع الشاشة
ب، يمكنها الآن إرسال ثلاثة قوالب أخرى. وبدلاً من ذلك، إذا تم تنظيم كل شاشة
لإرسال نموذج واحد، يمكن للتطبيق دفع خمس مثيلات للشاشة إلى
حزمة ScreenManager
هناك حالات خاصة لهذه القيود: عمليات إعادة تحميل النموذج والرجوع إعادة تعيين العمليات.
عمليات إعادة تحميل النموذج
لا يتم احتساب بعض تعديلات المحتوى ضمن الحدّ الأقصى لعدد النماذج. بشكل عام،
إذا فرض أحد التطبيقات نموذجًا جديدًا من النوع نفسه ويحتوي على
نفس المحتوى الرئيسي مثل القالب السابق، فإن القالب الجديد
يتم احتسابها من الحصة. على سبيل المثال، يمكن أن يؤدي تحديث حالة التبديل لصف ما في
ListTemplate
لا يتم احتسابه
مقابل الحصة. اطّلِع على مستندات النماذج الفردية لمعرفة المزيد من المعلومات.
حول أنواع تعديلات المحتوى التي يمكن اعتبارها "إعادة تحميل"
عمليات الرجوع
لتفعيل التدفقات الفرعية داخل مهمة، يرصد المضيف عندما يبرز التطبيق
ميزة "Screen
" من حزمة ScreenManager
وتحديثات
الحصة المتبقية استنادًا إلى عدد النماذج التي يعمل التطبيق عليها
إلى الخلف.
على سبيل المثال، إذا أرسل التطبيق نموذجين أثناء وجوده في الشاشة أ، فإنه يدفع الشاشة ب ويرسل نموذجين آخرين، يتبقى للتطبيق حصة واحدة. في حال حذف التطبيق ثم ينبثق مرة أخرى إلى الشاشة أ، ويعيد المضيف ضبط الحصة إلى ثلاث، لأن رجع التطبيق إلى الوراء بمقدار قالبين.
لاحظ أنه عند العودة إلى الشاشة، يجب أن يرسل التطبيق نموذجًا من نفس النوع الأخير الذي تم إرساله بواسطة هذه الشاشة. جارٍ إرسال أي رسائل أخرى إلى حدوث خطأ بسبب نوع النموذج. ومع ذلك، طالما أن النوع يظل نفسه أثناء إجراء عملية الرجوع، يمكن للتطبيق تعديل محتوى النموذج بدون التأثير في الحصة.
إعادة ضبط العمليات
تحتوي بعض القوالب على دلالات خاصة تشير إلى نهاية المهمة. بالنسبة
مثال،
NavigationTemplate
هي طريقة عرض من المفترض أن تظل معروضة على الشاشة وأن يتم تحديثها
التعليمات المفصّلة لاستهلاك المستخدم. عندما تصل إلى أحد هذه
يعيد المضيف ضبط حصة النماذج، مع مراعاة ذلك
إنها الخطوة الأولى في مهمة جديدة. يسمح هذا الإجراء للتطبيق ببدء مهمة جديدة.
اطّلِع على مستندات النماذج الفردية لمعرفة النماذج التي تؤدي إلى إعادة الضبط.
على المضيف.
إذا تلقّى المضيف نية لبدء تشغيل التطبيق من خلال إجراء إشعار أو من مشغّل التطبيقات، تتم إعادة ضبط الحصة أيضًا. وتتيح هذه الآلية للتطبيق تبدأ تدفق مهمة جديدة من الإشعارات، وتظل صحيحة حتى إذا تم مرتبطة بالفعل وفي المقدمة.
يمكنك الاطّلاع على قسم عرض الإشعارات لمعرفة المزيد من التفاصيل. حول طريقة عرض إشعارات التطبيق على شاشة السيارة يمكنك الاطّلاع على قسم تشغيل تطبيق سيارة موجّه الغرض للحصول على معلومات عن كيفية إجراء ذلك لبدء تشغيل تطبيقك من خلال إشعار
واجهة برمجة تطبيقات الاتصال
يمكنك تحديد ما إذا كان تطبيقك يعمل على Android Auto أو Android.
نظام التشغيل Automotive باستخدام
CarConnection
API من أجل
استرداد معلومات الاتصال في وقت التشغيل.
على سبيل المثال، في Session
في تطبيق السيارة، يمكنك إعداد CarConnection
الاشتراك في تحديثات LiveData
:
Kotlin
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
Java
new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);
في المراقب، يمكنك بعد ذلك التفاعل مع التغييرات في حالة الاتصال:
Kotlin
fun onConnectionStateUpdated(connectionState: Int) { val message = when(connectionState) { CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit" CarConnection.CONNECTION_TYPE_NATIVE -> "Connected to Android Automotive OS" CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto" else -> "Unknown car connection type" } CarToast.makeText(carContext, message, CarToast.LENGTH_SHORT).show() }
Java
private void onConnectionStateUpdated(int connectionState) { String message; switch(connectionState) { case CarConnection.CONNECTION_TYPE_NOT_CONNECTED: message = "Not connected to a head unit"; break; case CarConnection.CONNECTION_TYPE_NATIVE: message = "Connected to Android Automotive OS"; break; case CarConnection.CONNECTION_TYPE_PROJECTION: message = "Connected to Android Auto"; break; default: message = "Unknown car connection type"; break; } CarToast.makeText(getCarContext(), message, CarToast.LENGTH_SHORT).show(); }
واجهة برمجة التطبيقات للقيود
قد تسمح السيارات المختلفة بعدد مختلف من
Item
مثيلات سيتم عرضها
المستخدم في كل مرة. يمكنك استخدام
ConstraintManager
للتحقق من الحد الأقصى للمحتوى في وقت التشغيل وتعيين العدد المناسب من العناصر
في النماذج.
البدء بالحصول على ConstraintManager
من CarContext
:
Kotlin
val manager = carContext.getCarService(ConstraintManager::class.java)
Java
ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);
يمكنك بعد ذلك إرسال طلب بحث عن كائن ConstraintManager
الذي تم استرداده، وذلك للعثور على ما يلي:
الحد من المحتوى. على سبيل المثال، للحصول على عدد العناصر التي يمكن عرضها في
شبكة، استدعاء
getContentLimit
مع
CONTENT_LIMIT_TYPE_GRID
:
Kotlin
val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)
Java
int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);
إضافة خطوات تسجيل الدخول
إذا كان تطبيقك يوفّر تجربة تسجيل الدخول للمستخدمين، يمكنك استخدام نماذج مثل
SignInTemplate
وLongMessageTemplate
باستخدام المستوى 2 من واجهة برمجة التطبيقات Car App API أو المستويات الأعلى، لتسجيل الدخول إلى تطبيقك
الوحدة الرئيسية للسيارة.
لإنشاء SignInTemplate
، يجب تحديد SignInMethod
. السيارة
تتيح "مكتبة التطبيقات" حاليًا استخدام طرق تسجيل الدخول التالية:
InputSignInMethod
لتسجيل الدخول باسم المستخدم/كلمة المرور.PinSignInMethod
لتسجيل الدخول باستخدام رقم التعريف الشخصي، حيث يربط المستخدم حسابه من هاتفه باستخدام رقم تعريف شخصي معروض في الوحدة الرئيسية.ProviderSignInMethod
لتسجيل الدخول إلى مقدم الخدمة، مثل تسجيل الدخول باستخدام حساب Google وانقر على نقرة واحدة.QRCodeSignInMethod
لتسجيل الدخول باستخدام رمز الاستجابة السريعة، حيث يمسح المستخدم ضوئيًا رمز الاستجابة السريعة لإكمال عملية تسجيل الدخول هواتفهم. تتوفّر هذه الميزة مع المستوى 4 والأعلى من واجهة برمجة تطبيقات Car API.
على سبيل المثال، لتطبيق نموذج يجمع كلمة مرور المستخدم، ابدأ
جارٍ إنشاء InputCallback
لمعالجة البيانات التي أدخلها المستخدم والتحقق من صحتها:
Kotlin
val callback = object : InputCallback { override fun onInputSubmitted(text: String) { // You will receive this callback when the user presses Enter on the keyboard. } override fun onInputTextChanged(text: String) { // You will receive this callback as the user is typing. The update // frequency is determined by the host. } }
Java
InputCallback callback = new InputCallback() { @Override public void onInputSubmitted(@NonNull String text) { // You will receive this callback when the user presses Enter on the keyboard. } @Override public void onInputTextChanged(@NonNull String text) { // You will receive this callback as the user is typing. The update // frequency is determined by the host. } };
يجب توفير InputCallback
لـ InputSignInMethod
Builder
.
Kotlin
val passwordInput = InputSignInMethod.Builder(callback) .setHint("Password") .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD) ... .build()
Java
InputSignInMethod passwordInput = new InputSignInMethod.Builder(callback) .setHint("Password") .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD) ... .build();
وأخيرًا، يمكنك استخدام InputSignInMethod
الجديد لإنشاء SignInTemplate
.
Kotlin
SignInTemplate.Builder(passwordInput) .setTitle("Sign in with username and password") .setInstructions("Enter your password") .setHeaderAction(Action.BACK) ... .build()
Java
new SignInTemplate.Builder(passwordInput) .setTitle("Sign in with username and password") .setInstructions("Enter your password") .setHeaderAction(Action.BACK) ... .build();
استخدام مدير الحساب
في التطبيقات التي تعمل بنظام التشغيل Android Automotive وتتضمّن عملية المصادقة، يجب استخدام المصادقة. AccountManager للأسباب التالية:
- تحسين تجربة المستخدم وسهولة إدارة الحسابات: يمكن للمستخدمين إدارة جميع الحسابات بسهولة حساباتهم من قائمة الحسابات في إعدادات النظام، بما في ذلك تسجيل الدخول وتسجيل الخروج منه.
- "الضيف" التجارب: بما أنّ السيارات هي أجهزة مشتركة، يمكن للمصنّعين الأصليين للأجهزة تفعيل تجارب الضيوف في المركبة، حيث لا يمكن إضافة حسابات.
إضافة صيغ السلسلة النصية
قد تعرض أحجام شاشات السيارة المختلفة كميات مختلفة من النص. مع واجهة برمجة تطبيقات لتطبيق السيارة
2 وما فوق، يمكنك تحديد متغيرات متعددة لسلسلة نصية للحصول على أفضل
لملاءمة حجم الشاشة. للاطّلاع على الأماكن التي تقبل فيها الصيغ النصية، ابحث عن النماذج
العناصر التي تأخذ CarText
.
يمكنك إضافة صيغ السلسلة النصية إلى CarText
باستخدام
CarText.Builder.addVariant()
:
Kotlin
val itemTitle = CarText.Builder("This is a very long string") .addVariant("Shorter string") ... .build()
Java
CarText itemTitle = new CarText.Builder("This is a very long string") .addVariant("Shorter string") ... .build();
يمكنك بعد ذلك استخدام CarText
—على سبيل المثال، كنص أساسي
GridItem
Kotlin
GridItem.Builder() .addTitle(itemTitle) ... .build()
Java
new GridItem.Builder() .addTitle(itemTitle) ... build();
إضافة سلاسل بالترتيب من الأكثر إلى الأقل تفضيلاً - على سبيل المثال، من الأطول إلى الأقصر ويختار المضيف سلسلة الطول المناسبة بناءً على مقدار المساحة المتاحة على شاشة السيارة.
إضافة CarIcons مضمنة للصفوف
يمكنك إضافة رموز مضمَّنة مع نص لتحسين المظهر المرئي لتطبيقك باستخدام
CarIconSpan
راجع وثائق
CarIconSpan.create
لمزيد من المعلومات حول إنشاء هذه المسافات. عرض
سريعة
نمط النص باستخدام علامات امتداد النص للحصول على نظرة عامة حول طريقة عمل نمط النص باستخدام المسافات.
Kotlin
val rating = SpannableString("Rating: 4.5 stars") rating.setSpan( CarIconSpan.create( // Create a CarIcon with an image of four and a half stars CarIcon.Builder(...).build(), // Align the CarIcon to the baseline of the text CarIconSpan.ALIGN_BASELINE ), // The start index of the span (index of the character '4') 8, // The end index of the span (index of the last 's' in "stars") 16, Spanned.SPAN_INCLUSIVE_INCLUSIVE ) val row = Row.Builder() ... .addText(rating) .build()
Java
SpannableString rating = new SpannableString("Rating: 4.5 stars"); rating.setSpan( CarIconSpan.create( // Create a CarIcon with an image of four and a half stars new CarIcon.Builder(...).build(), // Align the CarIcon to the baseline of the text CarIconSpan.ALIGN_BASELINE ), // The start index of the span (index of the character '4') 8, // The end index of the span (index of the last 's' in "stars") 16, Spanned.SPAN_INCLUSIVE_INCLUSIVE ); Row row = new Row.Builder() ... .addText(rating) .build();
واجهات برمجة تطبيقات أجهزة السيارة
بدءًا من المستوى 3 من واجهة برمجة تطبيقات Car App Library، تحتوي مكتبة تطبيقات السيارات على واجهات برمجة تطبيقات التي يمكن استخدامها للوصول إلى خصائص المركبات وأجهزة الاستشعار.
المتطلبات
لاستخدام واجهات برمجة التطبيقات مع Android Auto، ابدأ بإضافة ملف
androidx.car.app:app-projected
إلى ملف build.gradle
لجهاز Android
وحدة تلقائية. بالنسبة إلى نظام التشغيل Android Automotive، أضِف اعتمادًا على
androidx.car.app:app-automotive
إلى ملف build.gradle
لجهاز Android
نظام التشغيل Automotive.
بالإضافة إلى ذلك، في ملف AndroidManifest.xml
، عليك إجراء ما يلي:
الإفصاح عن الأذونات ذات الصلة اللازمة
تطلب بيانات السيارة التي تريد استخدامها. لاحظ أن هذه الأذونات يجب أيضًا
التي يمنحها المستخدم لك. يمكنك استخدام صفحة
الرمز نفسه على كل من Android Auto وAndroid Automotive، بدلاً من
من الحاجة إلى إنشاء تدفقات تعتمد على النظام الأساسي. ومع ذلك، تحتاج الأذونات المطلوبة
مختلفة.
معلومات السيارة
يصف هذا الجدول السمات التي يعرضها كلّ من
واجهات برمجة التطبيقات في CarInfo
الأذونات التي تحتاج إلى طلب استخدامها:
الطرق | الخصائص | أذونات Android Auto | أذونات نظام التشغيل Android Automotive | يتوفّر هذا الخيار منذ مستوى واجهة برمجة التطبيقات لتطبيق السيارة. |
---|---|---|---|---|
fetchModel |
الماركة والطراز والسنة | android.car.permission.CAR_INFO |
3 | |
fetchEnergyProfile |
أنواع وصلات المركبات الكهربائية وأنواع الوقود | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_INFO |
3 |
fetchExteriorDimensions
تتوفّر هذه البيانات فقط على بعض المركبات التي تعمل بنظام التشغيل Android Automotive. تشغيل واجهة برمجة التطبيقات 30 أو أعلى |
الأبعاد الخارجية | لا ينطبق | android.car.permission.CAR_INFO |
7 |
addTollListener
removeTollListener |
حالة بطاقة تحصيل رسوم العبور، ونوع بطاقة رسوم العبور | 3 | ||
addEnergyLevelListener
removeEnergyLevelListener |
مستوى البطارية، مستوى الوقود، مستوى الوقود منخفض، النطاق المتبقّي | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_ENERGY ,android.car.permission.CAR_ENERGY_PORTS ,android.car.permission.READ_CAR_DISPLAY_UNITS
|
3 |
addSpeedListener
removeSpeedListener |
السرعة الأولية وسرعة العرض (يظهران على شاشة المجموعة في السيارة) | com.google.android.gms.permission.CAR_SPEED |
android.car.permission.CAR_SPEED ,android.car.permission.READ_CAR_DISPLAY_UNITS |
3 |
addMileageListener
removeMileageListener |
مسافة عدّاد المسافات | com.google.android.gms.permission.CAR_MILEAGE |
لا تتوفّر هذه البيانات على نظام التشغيل Android Automotive للتطبيقات المثبَّتة من "متجر Play". | 3 |
على سبيل المثال، للحصول على النطاق المتبقي، قم بإنشاء مثيل
CarInfo
، ثم
إنشاء OnCarDataAvailableListener
وتسجيله:
Kotlin
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo val listener = OnCarDataAvailableListener<EnergyLevel> { data -> if (data.rangeRemainingMeters.status == CarValue.STATUS_SUCCESS) { val rangeRemaining = data.rangeRemainingMeters.value } else { // Handle error } } carInfo.addEnergyLevelListener(carContext.mainExecutor, listener) … // Unregister the listener when you no longer need updates carInfo.removeEnergyLevelListener(listener)
Java
CarInfo carInfo = getCarContext().getCarService(CarHardwareManager.class).getCarInfo(); OnCarDataAvailableListener<EnergyLevel> listener = (data) -> { if(data.getRangeRemainingMeters().getStatus() == CarValue.STATUS_SUCCESS) { float rangeRemaining = data.getRangeRemainingMeters().getValue(); } else { // Handle error } }; carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(), listener); … // Unregister the listener when you no longer need updates carInfo.removeEnergyLevelListener(listener);
لا تفترض أن البيانات من السيارة متاحة في جميع الأوقات.
إذا ظهرت لك رسالة خطأ، تحقَّق من
حالة
القيمة التي طلبتها لفهم سبب إمكانية ظهور البيانات التي طلبتها
التي لا يمكن استردادها. ارجع إلى
المستندات المرجعية الخاصة بـ
تعريف الفئة CarInfo
الكامل.
أجهزة استشعار السيارات
الصف CarSensors
الوصول إلى مقياس التسارع والجيروسكوب والبوصلة
لبيانات الموقع. وقد يعتمد مدى توفُّر هذه القيم على
المصنّع الأصلي للجهاز. ويكون تنسيق البيانات من مقياس التسارع والجيروسكوب والبوصلة
نفس الشيء الذي تحصل عليه من
SensorManager
API. على سبيل المثال:
للتحقّق من عنوان المركبة:
Kotlin
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors val listener = OnCarDataAvailableListener<Compass> { data -> if (data.orientations.status == CarValue.STATUS_SUCCESS) { val orientation = data.orientations.value } else { // Data not available, handle error } } carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, carContext.mainExecutor, listener) … // Unregister the listener when you no longer need updates carSensors.removeCompassListener(listener)
Java
CarSensors carSensors = getCarContext().getCarService(CarHardwareManager.class).getCarSensors(); OnCarDataAvailableListener<Compass> listener = (data) -> { if (data.getOrientations().getStatus() == CarValue.STATUS_SUCCESS) { List<Float> orientations = data.getOrientations().getValue(); } else { // Data not available, handle error } }; carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, getCarContext().getMainExecutor(), listener); … // Unregister the listener when you no longer need updates carSensors.removeCompassListener(listener);
للوصول إلى بيانات الموقع الجغرافي من السيارة، عليك أيضًا الإفصاح عن
إذن android.permission.ACCESS_FINE_LOCATION
.
الاختبار
لمحاكاة بيانات جهاز الاستشعار عند إجراء الاختبار على Android Auto، يمكنك الاطّلاع على أجهزة الاستشعار وأدوات الاستشعار أقسام الموقع في دليل الوحدة الرئيسية لسطح المكتب لمحاكاة بيانات جهاز الاستشعار عند الاختبار على Android نظام التشغيل Automotive، راجع أجهزة المحاكاة للأجهزة State (الحالة) في Android دليل محاكي نظام التشغيل Automotive.
دورات حياة CarAppService والجلسة والشاشة
إنّ Session
تنفِّذ صفوف Screen
LifecycleOwner
. بالنسبة
يتفاعل المستخدِم مع التطبيق، وكائن Session
وScreen
مراحل النشاط
كما هو موضح في المخططات التالية.
دورات حياة CarAppService وجلسة
للحصول على التفاصيل الكاملة، يمكنك الاطّلاع على وثائق
Session.getLifecycle
.
دورة حياة الشاشة
للحصول على التفاصيل الكاملة، يمكنك الاطّلاع على وثائق
Screen.getLifecycle
.
التسجيل من ميكروفون السيارة
باستخدام ميزات
CarAppService
CarAudioRecord
واجهة برمجة التطبيقات،
يمكنك منح تطبيقك إذن الوصول إلى ميكروفون سيارة المستخدم. يحتاج المستخدمون إلى منح
منح تطبيقك إذن الوصول إلى ميكروفون السيارة. يمكن لتطبيقك تسجيل
معالجة إدخالات المستخدم في تطبيقك.
إذن بالتسجيل
قبل تسجيل أي محتوى صوتي، يجب أولاً الإفصاح عن إذن التسجيل في
عليك AndroidManifest.xml
وطلب أن يمنحها المستخدم.
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
...
</manifest>
يجب طلب إذن التسجيل في وقت التشغيل. يمكنك الاطّلاع على صفحة الطلب قسم "الأذونات" للاطّلاع على تفاصيل حول كيفية طلب الإذن في تطبيق السيارة.
تسجيل الصوت
بعد أن يمنح المستخدم إذنًا بالتسجيل، يمكنك تسجيل الصوت ومعالجته التسجيل.
Kotlin
val carAudioRecord = CarAudioRecord.create(carContext) carAudioRecord.startRecording() val data = ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) while(carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) { // Use data array // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech } carAudioRecord.stopRecording()
Java
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext()); carAudioRecord.startRecording(); byte[] data = new byte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE]; while (carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) { // Use data array // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech } carAudioRecord.stopRecording();
التركيز على الصوت
عند التسجيل من ميكروفون السيارة، عليك أولاً الحصول على الصوت. التركيز من أجل والتأكد من إيقاف أي وسائط جارية. إذا فقدت التركيز الصوتي، إيقاف التسجيل.
في ما يلي مثال على كيفية التركيز على الصوت:
Kotlin
val carAudioRecord = CarAudioRecord.create(carContext) // Take audio focus so that user's media is not recorded val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) // Use the most appropriate usage type for your use case .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) .build() val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) .setAudioAttributes(audioAttributes) .setOnAudioFocusChangeListener { state: Int -> if (state == AudioManager.AUDIOFOCUS_LOSS) { // Stop recording if audio focus is lost carAudioRecord.stopRecording() } } .build() if (carContext.getSystemService(AudioManager::class.java) .requestAudioFocus(audioFocusRequest) != AudioManager.AUDIOFOCUS_REQUEST_GRANTED ) { // Don't record if the focus isn't granted return } carAudioRecord.startRecording() // Process the audio and abandon the AudioFocusRequest when done
Java
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext()); // Take audio focus so that user's media is not recorded AudioAttributes audioAttributes = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) // Use the most appropriate usage type for your use case .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) .build(); AudioFocusRequest audioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) .setAudioAttributes(audioAttributes) .setOnAudioFocusChangeListener(state -> { if (state == AudioManager.AUDIOFOCUS_LOSS) { // Stop recording if audio focus is lost carAudioRecord.stopRecording(); } }) .build(); if (getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest) != AUDIOFOCUS_REQUEST_GRANTED) { // Don't record if the focus isn't granted return; } carAudioRecord.startRecording(); // Process the audio and abandon the AudioFocusRequest when done
مكتبة الاختبار
اختبار Android للسيارات
توفّر "المكتبة" أدوات إضافية
التي يمكنك استخدامها للتحقق من سلوك تطبيقك في بيئة اختبار.
على سبيل المثال،
SessionController
محاكاة الاتصال بالمضيف والتحقق من صحة الاتصال
Screen
و
تم إنشاء Template
عاد.
ارجع إلى عيّنات للحصول على أمثلة على الاستخدام.
الإبلاغ عن مشكلة في مكتبة تطبيقات "Android للسيارات"
إذا واجهتك مشكلة في المكتبة، يمكنك الإبلاغ عنها باستخدام أداة تتبُّع المشاكل من Google تأكَّد من ملء جميع المعلومات المطلوبة في نموذج المشكلة.
قبل تقديم أي مشكلة جديدة، يُرجى التحقق مما إذا كانت مدرجة في إصدار المكتبة. الملاحظات أو تم الإبلاغ عنها في قائمة المشكلات. يمكنك الاشتراك والتصويت على المشاكل من خلال النقر على النجمة لمشكلة في أداة التتبع. لمزيد من المعلومات، يُرجى مراجعة الاشتراك في مشكلة: