تتيح لك مكتبة تطبيقات Android for Cars إمكانية نقل تطبيقات التنقّل ونقاط الاهتمام وتطبيقات إنترنت الأشياء (IOT) إلى السيارة. ويتم ذلك من خلال توفير مجموعة من النماذج المصممة لتلبية معايير تشتيت السائق ومراعاة التفاصيل مثل مجموعة متنوعة من عوامل شاشة السيارة وأساليب الإدخال.
يقدم هذا الدليل نظرة عامة على الميزات والمفاهيم الرئيسية في المكتبة ويرشدك خلال عملية إعداد تطبيق بسيط. للحصول على مقدمة كاملة خطوة بخطوة، يمكنك الاطّلاع على الدرس التطبيقي حول الترميز حول أساسيات "مكتبة تطبيقات السيارة".
قبل البدء
- يمكنك مراجعة صفحات التصميم للقيادة
التي تغطي مكتبة تطبيق السيارة
- تطبيقات التنقّل والتطبيقات الأخرى المتعلّقة بالقيادة نظرة عامة حول فئة
- نظرة عامة على إنشاء تطبيقات باستخدام النماذج
- الوحدات الأساسية التي تشمل النماذج ومكوّنات النموذج
- أمثلة التدفقات التي توضح أنماط تجربة المستخدم الشائعة
- متطلبات التطبيقات المُصمَّمة وفقًا لنموذج
- راجع المصطلحات والمفاهيم الرئيسية في القسم التالي.
- تعرَّف على واجهة مستخدم نظام Android Auto وتصميم نظام التشغيل Android Automotive.
- راجِع ملاحظات الإصدار.
- راجِع عيّنات.
المصطلحات والمفاهيم الرئيسية
- الطُرز والقوالب
- يتم تمثيل واجهة المستخدم برسم بياني يعرض عناصر نماذج يمكن ترتيبها معًا بطرق مختلفة، على النحو الذي يسمح به النموذج الخاص بها. القوالب هي مجموعة فرعية من النماذج التي يمكن أن تكون بمثابة جذر في تلك الرسوم البيانية. تتضمن النماذج المعلومات التي سيتم عرضها للمستخدم في شكل نص وصور بالإضافة إلى سمات لإعداد جوانب المظهر المرئي لهذه المعلومات، مثل ألوان النص أو أحجام الصور. ويحوّل المضيف النماذج إلى طرق عرض مصمّمة لتلبية معايير تشتيت السائق ومراعاة التفاصيل مثل مجموعة متنوّعة من عوامل شاشة السيارة وأساليب الإدخال.
- المضيف
- المضيف هو مكوِّن الخلفية الذي ينفّذ الوظائف التي توفّرها واجهات برمجة التطبيقات للمكتبة كي يمكن تشغيل تطبيقك في السيارة. تتراوح مسؤوليات المضيف بين اكتشاف التطبيق وإدارة مراحل نشاطه وتحويل نماذجك إلى مشاهدات وإبلاغ التطبيق بتفاعلات المستخدمين. ويتم تنفيذ هذا المضيف من خلال Android Auto على الأجهزة الجوّالة. على نظام التشغيل 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>
مستوى واجهة برمجة تطبيقات Car App API
تحدّد "مكتبة تطبيقات السيارة" مستويات واجهة برمجة التطبيقات الخاصة بها لتتمكّن من معرفة ميزات المكتبة التي يوفّرها مضيف النماذج في السيارة.
لاسترداد أعلى مستوى لواجهة برمجة تطبيقات Car App API يتيحها المضيف، استخدِم الطريقة
getCarAppApiLevel()
.
يُرجى توضيح الحدّ الأدنى لمستوى واجهة برمجة التطبيقات Car App API الذي يتيحه تطبيقك في
ملف AndroidManifest.xml
:
<manifest ...>
<application ...>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1"/>
</application>
</manifest>
راجِع المواد الخاصة بالتعليق التوضيحي RequiresCarApi
لمعرفة تفاصيل حول كيفية الحفاظ على التوافق مع الأنظمة القديمة وتوضيح الحد الأدنى لمستوى واجهة برمجة التطبيقات المطلوب لاستخدام الميزة. للحصول على تعريف لمستوى واجهة برمجة التطبيقات المطلوب لاستخدام ميزة معيّنة في "مكتبة تطبيقات السيارة"، يُرجى الاطّلاع على المستندات المرجعية للسمة
CarAppApiLevels
.
إنشاء CarAppService والجلسة
يحتاج تطبيقك إلى توسيع فئة CarAppService
وتنفيذ طريقة 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
لعرض سلسلة "Hello world!" بسيطة:
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
.
التفاعل مع المستخدم
يمكن لتطبيقك التفاعل مع المستخدم باستخدام أنماط مشابهة لتطبيق الأجهزة الجوّالة.
التعامل مع البيانات التي أدخلها المستخدم
يمكن لتطبيقك الاستجابة لإدخالات المستخدم من خلال تمرير المستمعين المناسبين إلى
النماذج التي تدعمها. يوضِّح المقتطف التالي كيفية إنشاء نموذج
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
بهدف تضمين معرّف الموارد المنتظم للبيانات:
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
في الحزمة. على سبيل المثال، إذا أرسل تطبيق ما نموذجين أثناء وجوده في الشاشة "أ" ثم دفع الشاشة "ب"، يمكنه الآن إرسال ثلاثة نماذج أخرى. بدلاً من ذلك، إذا تم تنظيم كل شاشة لإرسال نموذج واحد، يمكن للتطبيق إرسال خمس مثيلات شاشة إلى حزمة ScreenManager
.
هناك حالات خاصة لهذه القيود: إعادة تحميل النموذج وعمليات الرجوع وإعادة الضبط.
عدد مرات إعادة تحميل النموذج
لا يتم احتساب بعض تعديلات المحتوى ضمن الحدّ الأقصى المسموح به للنماذج. بشكل عام، إذا دفع أحد التطبيقات نموذجًا جديدًا من النوع نفسه ويحتوي على المحتوى الرئيسي نفسه المضمَّن في النموذج السابق، لن يتم احتساب النموذج الجديد ضمن الحصة. على سبيل المثال، لا يتم احتساب تعديل حالة تبديل أحد الصفوف في ListTemplate
ضمن الحصة المحدّدة. راجع وثائق النماذج الفردية لمعرفة المزيد حول أنواع تحديثات المحتوى التي يمكن اعتبارها تحديثًا.
عمليات الظهر
لتفعيل التدفقات الفرعية في إحدى المهام، يرصد المضيف الحالات التي يبث فيها تطبيق ما
Screen
من حزمة ScreenManager
ويعدّل
الحصة المتبقية استنادًا إلى عدد النماذج التي يرجع إليها
التطبيق.
على سبيل المثال، إذا أرسل التطبيق نموذجَين أثناء انتقاله إلى الشاشة "أ"، ثم دفع الشاشة "ب" وأرسل نموذجَين آخرَين، يتبقّى في التطبيق حصة واحدة. إذا عاد التطبيق إلى الشاشة "أ"، فسيعيد المضيف ضبط الحصة إلى ثلاثة، لأن التطبيق تراجع بمقدار نموذجين.
لاحظ أنه عند العودة إلى الشاشة، يجب أن يرسل التطبيق نموذجًا من نفس نوع النموذج الأخير الذي تم إرساله من خلال تلك الشاشة. يؤدي إرسال أي نوع نموذج آخر إلى حدوث خطأ. ومع ذلك، ما دام النوع كما هو أثناء إجراء عملية للخلف، يمكن للتطبيق تعديل محتوى النموذج بحرية بدون التأثير على الحصة.
إعادة ضبط العمليات
تحتوي بعض القوالب على دلالات خاصة تشير إلى نهاية المهمة. على سبيل المثال، تشكّل NavigationTemplate
طريقة عرض من المتوقّع أن تبقى معروضة على الشاشة وستتمّ إعادة تحميلها مع تعليمات جديدة مفصّلة حول استهلاك المستخدم. وعندما يصل النموذج إلى أحد هذه النماذج، يعيد المضيف ضبط حصة النموذج، مع التعامل مع هذا النموذج كما لو كان الخطوة الأولى من مهمة جديدة. يسمح هذا الإذن للتطبيق ببدء مهمة جديدة.
يمكنك الاطّلاع على وثائق النماذج الفردية لمعرفة النماذج التي تؤدي إلى إعادة الضبط على المضيف.
إذا تلقّى المضيف غرضًا لتشغيل التطبيق من خلال إجراء إشعار أو من مشغّل التطبيقات، تتم أيضًا إعادة ضبط الحصة. تتيح هذه الآلية للتطبيق بدء تدفق مهمة جديدة من الإشعارات، وتكون صحيحة حتى إذا كان التطبيق محددًا بالفعل وفي المقدمة.
يمكنك الانتقال إلى قسم عرض الإشعارات للاطّلاع على مزيد من التفاصيل حول طريقة عرض إشعارات تطبيقك على شاشة السيارة. راجِع قسم بدء تشغيل تطبيق للسيارة للحصول على معلومات عن طريقة تشغيل تطبيقك من خلال إجراء إشعار.
واجهة برمجة تطبيقات الاتصال
يمكنك معرفة ما إذا كان تطبيقك يعمل على نظام التشغيل Android Auto أو Android Automotive من خلال استخدام واجهة برمجة تطبيقات CarConnection
لاسترداد معلومات الاتصال في وقت التشغيل.
على سبيل المثال، في 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(); }
واجهة برمجة تطبيقات Constraints
قد تسمح السيارات المختلفة بعرض عدد مختلف من مثيلات
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 من واجهة برمجة تطبيقات السيارة أو مستوى أعلى للتعامل مع تسجيل الدخول إلى التطبيق في
الوحدة الرئيسية للسيارة.
لإنشاء SignInTemplate
، حدِّد SignInMethod
. تتيح مكتبة تطبيقات السيارة حاليًا طرق تسجيل الدخول التالية:
InputSignInMethod
لتسجيل الدخول باسم المستخدم/كلمة المرور.PinSignInMethod
لتسجيل الدخول باستخدام رقم التعريف الشخصي، حيث يربط المستخدم حسابه من هاتفه باستخدام رقم تعريف شخصي معروض في الوحدة الرئيسية.ProviderSignInMethod
لتسجيل الدخول إلى حسابك، مثل تسجيل الدخول بحساب Google ونقرة واحدة.QRCodeSignInMethod
لتسجيل الدخول باستخدام رمز الاستجابة السريعة، حيث يمسح المستخدم رمز الاستجابة السريعة ضوئيًا لإكمال عملية تسجيل الدخول على هاتفه. تتوفّر هذه الميزة مع المستوى 4 من واجهة برمجة تطبيقات السيارة وما فوق.
على سبيل المثال، لتنفيذ نموذج يجمع كلمة مرور المستخدم، ابدأ بإنشاء 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 من واجهة برمجة تطبيقات السيارة، ويمكنك استخدامها للوصول إلى خصائص المركبات وأدوات الاستشعار فيها.
الشروط
لاستخدام واجهات برمجة التطبيقات مع Android Auto، ابدأ بإضافة عنصر يعتمد على androidx.car.app:app-projected
إلى ملف build.gradle
الخاص بوحدة Android Auto. بالنسبة إلى نظام التشغيل 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 |
|
fetchEnergyProfile |
أنواع وصلات المركبات الكهربائية وأنواع الوقود | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_INFO |
addTollListener
removeTollListener |
حالة بطاقة تحصيل رسوم العبور ونوع بطاقة تحصيل رسوم العبور | ||
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 |
addSpeedListener
removeSpeedListener |
سرعة العرض الأولية وسرعة العرض (على شاشة العرض العنقودي في السيارة) | com.google.android.gms.permission.CAR_SPEED |
android.car.permission.CAR_SPEED ،android.car.permission.READ_CAR_DISPLAY_UNITS |
addMileageListener
removeMileageListener |
مسافة عدّاد المسافات | com.google.android.gms.permission.CAR_MILEAGE |
لا تتوفّر هذه البيانات على نظام التشغيل Android Automotive للتطبيقات المثبَّتة من "متجر Play". |
على سبيل المثال، للحصول على النطاق المتبقي، أنشئ مثيلاً لكائن 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
. على سبيل المثال،
للتحقق من عنوان المركبة:
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، يُرجى الرجوع إلى قسم محاكاة حالة الأجهزة في دليل محاكي نظام التشغيل 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 for Cars فئات إضافية يمكنك استخدامها للتحقّق من سلوك التطبيق في بيئة الاختبار.
على سبيل المثال، تتيح لك السمة
SessionController
محاكاة الاتصال بالمضيف والتحقّق من إنشاء
Screen
و
Template
الصحيحتَين وإرجاعهما.
راجِع عيّنات للاطّلاع على أمثلة على الاستخدام.
الإبلاغ عن مشكلة في مكتبة تطبيقات Android للسيارات
إذا عثرت على مشكلة في المكتبة، يُرجى الإبلاغ عنها باستخدام أداة تتبّع المشاكل من Google. احرص على ملء كل المعلومات المطلوبة في نموذج المشكلة.
قبل تقديم مشكلة جديدة، يُرجى التحقق مما إذا كان العدد مدرَجًا في ملاحظات إصدار المكتبة أو تم الإبلاغ عنه في قائمة المشاكل. يمكنك الاشتراك والتصويت للمشكلات من خلال النقر على النجمة لمشكلة في أداة التتبع. لمزيد من المعلومات، راجع الاشتراك في مشكلة.