رابط کاربری با نموداری از اشیاء مدل نشان داده میشود که میتوانند به روشهای مختلف با هم مرتب شوند، همانطور که توسط قالبی که به آن تعلق دارند مجاز است. قالب ها زیرمجموعه ای از مدل ها هستند که می توانند به عنوان ریشه در آن نمودارها عمل کنند. مدلها شامل اطلاعاتی هستند که در قالب متن و تصویر به کاربر نمایش داده میشوند و همچنین ویژگیهایی برای پیکربندی جنبههای ظاهر بصری چنین اطلاعاتی - برای مثال رنگهای متن یا اندازههای تصویر. میزبان مدل ها را به نماهایی تبدیل می کند که برای مطابقت با استانداردهای حواس پرتی راننده طراحی شده اند و از جزئیاتی مانند انواع فاکتورهای صفحه نمایش خودرو و روش های ورودی مراقبت می کند.
میزبان
میزبان جزء پشتیبان است که عملکرد ارائه شده توسط APIهای کتابخانه را پیاده سازی می کند تا برنامه شما بتواند در ماشین اجرا شود. مسئولیتهای میزبان از کشف برنامه شما و مدیریت چرخه عمر آن گرفته تا تبدیل مدلهای شما به نماها و اطلاعرسانی به برنامه شما از تعاملات کاربر متغیر است. در دستگاه های تلفن همراه، این میزبان توسط Android Auto پیاده سازی شده است. در سیستم عامل Android Automotive، این میزبان به عنوان یک برنامه سیستمی نصب شده است.
محدودیت های قالب
قالب های مختلف محدودیت هایی را در محتوای مدل های خود اعمال می کنند. به عنوان مثال، قالبهای فهرست محدودیتهایی در تعداد مواردی دارند که میتوانند به کاربر ارائه شوند. الگوها همچنین محدودیت هایی در نحوه اتصال آنها برای شکل دادن به جریان یک کار دارند. به عنوان مثال، این برنامه تنها می تواند تا پنج الگو را به پشته صفحه نمایش دهد. برای جزئیات بیشتر به محدودیت های الگو مراجعه کنید.
Screen
Screen کلاسی است که توسط کتابخانه ارائه می شود که برنامه ها برای مدیریت رابط کاربری ارائه شده به کاربر پیاده سازی می کنند. یک Screen یک چرخه حیات دارد و مکانیزمی را برای برنامه برای ارسال الگو برای نمایش زمانی که صفحه نمایش قابل مشاهده است فراهم می کند. نمونه های Screen همچنین می توانند به پشته Screen داده شوند و از آن خارج شوند، که تضمین می کند آنها به محدودیت های جریان الگو پایبند هستند.
CarAppService
CarAppService یک کلاس Service انتزاعی است که برنامه شما باید آن را پیاده سازی و صادر کند تا توسط میزبان کشف و مدیریت شود. CarAppService برنامه شما مسئول تأیید اعتبار اتصال میزبان با استفاده از createHostValidator است و متعاقباً با استفاده از onCreateSession نمونههای Session را برای هر اتصال ارائه میکند.
Session
Session یک کلاس انتزاعی است که برنامه شما باید آن را پیاده سازی کند و با استفاده از CarAppService.onCreateSession آن را برگرداند. این به عنوان نقطه ورود برای نمایش اطلاعات بر روی صفحه نمایش ماشین عمل می کند. این یک چرخه عمر دارد که وضعیت فعلی برنامه شما را در صفحه ماشین، مانند زمانی که برنامه شما قابل مشاهده یا پنهان است، اطلاع می دهد.
هنگامی که یک Session شروع می شود، مانند زمانی که برنامه برای اولین بار راه اندازی می شود، میزبان درخواست می کند که Screen اولیه با استفاده از روش onCreateScreen نمایش داده شود.
کتابخانه برنامه ماشین را نصب کنید
برای دستورالعملهایی درباره نحوه افزودن کتابخانه به برنامه خود، به صفحه انتشار کتابخانه Jetpack مراجعه کنید.
فایل های مانیفست برنامه خود را پیکربندی کنید
قبل از اینکه بتوانید برنامه ماشین خود را ایجاد کنید، فایل های مانیفست برنامه خود را به صورت زیر پیکربندی کنید.
CarAppService خود را اعلام کنید
میزبان از طریق اجرای CarAppService شما به برنامه شما متصل می شود. شما این سرویس را در مانیفست خود اعلام میکنید تا میزبان برنامه شما را کشف کرده و به آن متصل شود.
هنگامی که CarAppService خود را همانطور که در بخش قبل توضیح داده شد، با اضافه کردن یک یا چند مورد از مقادیر دسته زیر در فیلتر intent، دسته برنامه خود را اعلام کنید:
androidx.car.app.category.POI : برنامه ای که عملکردهای مرتبط با یافتن نقاط مورد علاقه مانند مکان های پارکینگ، ایستگاه های شارژ و پمپ بنزین را ارائه می دهد. به برنامه های ساخت نقطه مورد علاقه برای اتومبیل ها مراجعه کنید.
androidx.car.app.category.IOT : برنامهای که به کاربران امکان میدهد اقدامات مربوطه را در دستگاههای متصل از داخل خودرو انجام دهند. به ساخت برنامههای اینترنت اشیا برای اتومبیلها مراجعه کنید.
androidx.car.app.category.WEATHER : برنامه ای که به کاربران امکان می دهد اطلاعات مربوط به آب و هوا مربوط به مکان فعلی یا در طول مسیر خود را مشاهده کنند. به ساخت برنامه های هواشناسی برای اتومبیل ها مراجعه کنید.
Car App Library سطوح API خود را تعریف میکند تا بتوانید بدانید کدام ویژگیهای کتابخانه توسط میزبان الگو در خودرو پشتیبانی میشود. برای بازیابی بالاترین سطح API Car App پشتیبانی شده توسط یک میزبان، از متد getCarAppApiLevel() استفاده کنید.
حداقل سطح API Car App را که توسط برنامه شما پشتیبانی می شود در فایل AndroidManifest.xml خود اعلام کنید:
برای جزئیات بیشتر در مورد نحوه حفظ سازگاری به عقب و اعلام حداقل سطح API مورد نیاز برای استفاده از یک ویژگی، به مستندات حاشیه نویسی RequiresCarApi مراجعه کنید. برای تعریف اینکه کدام سطح API برای استفاده از ویژگی خاصی از کتابخانه برنامه خودرو لازم است، مستندات مرجع CarAppApiLevels را بررسی کنید.
CarAppService و Session خود را ایجاد کنید
برنامه شما باید کلاس CarAppService را گسترش دهد و روش onCreateSession خود را پیاده سازی کند، که نمونه Session مربوط به اتصال فعلی به هاست را برمی گرداند:
برای رسیدگی به سناریوهایی که برنامه ماشین شما باید از صفحهای شروع شود که صفحه اصلی یا صفحه اصلی برنامه شما نیست، مانند مدیریت پیوندهای عمیق، میتوانید قبل از بازگشت از onCreateScreen ، پشتهای از صفحهها را با استفاده از ScreenManager.push پیشبینی کنید. Pre-seeding به کاربران امکان می دهد از اولین صفحه ای که برنامه شما نشان می دهد به صفحه های قبلی برگردند.
صفحه شروع خود را ایجاد کنید
شما صفحات نمایش داده شده توسط برنامه خود را با تعریف کلاس هایی ایجاد می کنید که کلاس Screen را گسترش می دهند و روش onGetTemplate آن را پیاده سازی می کند، که نمونه Template را نشان دهنده وضعیت رابط کاربری برای نمایش در صفحه ماشین برمی گرداند.
قطعه زیر نشان می دهد که چگونه می توان Screen اعلام کرد که از یک الگوی PaneTemplate برای نمایش یک "Hello world!" ساده استفاده می کند. رشته:
برای فهرست جامعی از عملکردهای کتابخانه در دسترس برنامه های ناوبری، به الگوهای پیمایش دسترسی پیدا کنید.
CarContext همچنین قابلیتهای دیگری را ارائه میکند، مانند اینکه به شما اجازه میدهد منابع قابل ترسیم را با استفاده از پیکربندی از صفحه ماشین بارگیری کنید، برنامهای را در ماشین با استفاده از intent راهاندازی کنید ، و نشان دهید که آیا برنامه شما باید نقشهاش را با تم تیره نمایش دهد یا خیر.
پیاده سازی ناوبری صفحه
برنامهها اغلب صفحههای مختلفی را ارائه میدهند، که هر کدام احتمالاً از الگوهای مختلفی استفاده میکنند که کاربر میتواند در تعامل با رابط نمایش داده شده در صفحه، در میان آنها حرکت کند.
کلاس ScreenManager یک پشته صفحه نمایش را ارائه می دهد که می توانید از آن برای فشار دادن صفحه نمایش ها استفاده کنید که می تواند به طور خودکار هنگامی که کاربر دکمه برگشت را در صفحه ماشین انتخاب می کند یا از دکمه سخت افزاری برگشت موجود در برخی از اتومبیل ها استفاده می کند ظاهر شود.
قطعه زیر نشان می دهد که چگونه می توان یک اکشن برگشتی را به یک الگوی پیام اضافه کرد و همچنین عملکردی را نشان می دهد که هنگام انتخاب کاربر، صفحه جدیدی را فشار می دهد:
برای اطمینان از ایمن بودن استفاده از برنامه در حین رانندگی، پشته صفحه نمایش می تواند حداکثر عمق پنج صفحه داشته باشد. برای جزئیات بیشتر به بخش محدودیت های الگو مراجعه کنید.
محتویات یک الگو را تازه کنید
برنامه شما می تواند با فراخوانی روش Screen.invalidate درخواست کند محتوای یک Screen را باطل کند. میزبان متعاقباً با روش Screen.onGetTemplate برنامه شما تماس می گیرد تا الگو را با محتویات جدید بازیابی کند.
هنگام بازخوانی یک Screen ، مهم است که محتوای خاصی را در قالب درک کنید که میتواند بهروزرسانی شود، بنابراین میزبان، الگوی جدید را در سهمیه الگو به حساب نمیآورد. برای جزئیات بیشتر به بخش محدودیت های الگو مراجعه کنید.
توصیه میکنیم صفحههای خود را طوری ساختار دهید که یک نگاشت یک به یک بین یک Screen و نوع قالبی که از طریق اجرای onGetTemplate آن برمیگرداند وجود داشته باشد.
ترسیم نقشه ها
برنامههای ناوبری، نقاط مورد علاقه (POI) و آب و هوا با استفاده از الگوهای زیر میتوانند با دسترسی به یک Surface نقشهها را ترسیم کنند.
برای استفاده از الگوهای زیر، برنامه شما باید یکی از مجوزهای مربوطه را در عنصر <uses-permission> در فایل AndroidManifest.xml خود داشته باشد.
علاوه بر مجوز مورد نیاز برای قالبی که برنامه شما از آن استفاده میکند، برنامه شما باید مجوز androidx.car.app.ACCESS_SURFACE در فایل AndroidManifest.xml خود برای دسترسی به سطح اعلام کند:
برای دسترسی به Surface که میزبان ارائه میکند، باید یک SurfaceCallback را پیادهسازی کنید و آن پیادهسازی را در اختیار سرویس ماشین AppManager قرار دهید. Surface فعلی به SurfaceCallback شما در پارامتر SurfaceContainer در فراخوانهای onSurfaceAvailable() و onSurfaceDestroyed() ارسال میشود.
میزبان می تواند عناصر رابط کاربری را برای الگوهای بالای نقشه بکشد. میزبان با فراخوانی متد SurfaceCallback.onVisibleAreaChanged ، ناحیهای از سطح را که تضمین شده است بدون مانع و کاملاً برای کاربر قابل مشاهده است، ارتباط برقرار میکند. همچنین برای به حداقل رساندن تعداد تغییرات، میزبان متد SurfaceCallback.onStableAreaChanged را با کوچکترین مستطیل فراخوانی می کند که همیشه بر اساس الگوی فعلی قابل مشاهده است.
به عنوان مثال، هنگامی که یک برنامه ناوبری از NavigationTemplate با یک نوار اقدام در بالا استفاده می کند، زمانی که کاربر برای مدتی با صفحه تعامل نداشته باشد، نوار اقدام می تواند خود را پنهان کند تا فضای بیشتری برای نقشه ایجاد کند. در این حالت، یک تماس به onStableAreaChanged و onVisibleAreaChanged با همان مستطیل وجود دارد. وقتی نوار اقدام پنهان است، فقط onVisibleAreaChanged با ناحیه بزرگتر فراخوانی می شود. اگر کاربر با صفحه تعامل داشته باشد، دوباره فقط onVisibleAreaChanged با اولین مستطیل فراخوانی می شود.
پشتیبانی از تم تیره
برنامهها باید نقشه خود را روی نمونه Surface با رنگهای تیره مناسب، زمانی که میزبان تعیین میکند، آنطور که در کیفیت برنامه Android برای خودروها توضیح داده شده است، دوباره ترسیم کنند.
به کاربران اجازه دهید با نقشه شما تعامل داشته باشند
هنگام استفاده از الگوهای زیر، میتوانید برای تعامل کاربران با نقشههایی که ترسیم میکنید، پشتیبانی اضافه کنید، مانند اینکه به آنها اجازه دهید قسمتهای مختلف نقشه را با بزرگنمایی و جابجایی ببینند.
الگو
تعامل از سطح API برنامه Car پشتیبانی می شود
NavigationTemplate
2
PlaceListNavigationTemplate ( منسوخ شده )
4
RoutePreviewNavigationTemplate ( منسوخ شده )
4
MapTemplate ( منسوخ شده )
5 (معرفی قالب)
MapWithContentTemplate
7 (معرفی قالب)
اجرای تماس های تعاملی
رابط SurfaceCallback چندین روش پاسخ به تماس دارد که میتوانید برای افزودن تعامل به نقشههای ساخته شده با الگوهای بخش قبل پیادهسازی کنید:
onScale (با ضریب مقیاس تعیین شده توسط میزبان الگو)
2
حرکت چرخشی در حالت پان
onScroll (با فاکتور فاصله تعیین شده توسط میزبان الگو)
2
یک نوار اقدام نقشه اضافه کنید
این الگوها میتوانند یک نوار عملکرد نقشه برای اقدامات مرتبط با نقشه مانند بزرگنمایی و کوچکنمایی، نمایش مجدد قطبنما و سایر اقداماتی که برای نمایش انتخاب میکنید داشته باشند. نوار اکشن نقشه میتواند تا چهار دکمه فقط دارای نماد داشته باشد که میتوانند بدون تأثیر بر عمق کار، بهروزرسانی شوند. در حالت بیکار پنهان می شود و در حالت فعال دوباره ظاهر می شود.
برای دریافت تماسهای تعاملی نقشه، باید یک دکمه Action.PAN را در نوار اقدام نقشه اضافه کنید. هنگامی که کاربر دکمه پان را فشار می دهد، میزبان وارد حالت پان می شود، همانطور که در قسمت زیر توضیح داده شده است.
اگر برنامه شما دکمه Action.PAN را در نوار اقدام نقشه حذف کند، ورودی کاربر را از روشهای SurfaceCallback دریافت نمیکند و میزبان از حالت پان که قبلاً فعال شده است خارج میشود.
در صفحه لمسی، دکمه پان نمایش داده نمی شود.
حالت پان را درک کنید
در حالت پان، میزبان الگو ورودی های کاربر را از دستگاه های ورودی غیر لمسی، مانند کنترلرهای چرخشی و پد لمسی، به روش های SurfaceCallback مناسب ترجمه می کند. به اقدام کاربر برای ورود یا خروج از حالت پان با متد setPanModeListener در NavigationTemplate.Builder پاسخ دهید. وقتی کاربر در حالت پان است، میزبان میتواند سایر اجزای رابط کاربری را در قالب پنهان کند.
با کاربر تعامل داشته باشید
برنامه شما می تواند با استفاده از الگوهای مشابه یک برنامه تلفن همراه با کاربر تعامل داشته باشد.
کنترل ورودی کاربر
برنامه شما میتواند با ارسال شنوندگان مناسب به مدلهایی که از آنها پشتیبانی میکنند، به ورودیهای کاربر پاسخ دهد. قطعه زیر نحوه ایجاد یک Action Model را نشان می دهد که یک OnClickListener را تنظیم می کند که متدی را که توسط کد برنامه شما تعریف شده است، فراخوانی می کند:
برای جزئیات بیشتر درباره نحوه راهاندازی برنامهها، از جمله قالب هدف ACTION_NAVIGATE ، به بخش Start a car with a intent مراجعه کنید.
برخی از اقدامات، مانند اقداماتی که نیاز به هدایت کاربر برای ادامه تعامل در دستگاه های تلفن همراه خود دارند، تنها زمانی مجاز هستند که خودرو پارک شده باشد. برای اجرای این اقدامات می توانید از ParkedOnlyOnClickListener استفاده کنید. اگر ماشین پارک نشده باشد، میزبان نشانه ای را به کاربر نشان می دهد که در این مورد عمل مجاز نیست. اگر ماشین پارک شده باشد، کد به طور معمول اجرا می شود. قطعه زیر نحوه استفاده از ParkedOnlyOnClickListener را برای باز کردن صفحه تنظیمات در دستگاه تلفن همراه نشان می دهد:
اعلانهای ارسال شده به دستگاه تلفن همراه تنها در صورتی روی صفحه ماشین نشان داده میشوند که با CarAppExtender گسترش داده شوند. برخی از ویژگیهای اعلان، مانند عنوان محتوا، متن، نماد و کنشها را میتوان در CarAppExtender تنظیم کرد و ویژگیهای اعلان را هنگامی که روی صفحه ماشین ظاهر میشوند لغو کرد.
قطعه زیر نحوه ارسال اعلان به صفحه ماشین را نشان می دهد که عنوانی متفاوت از عنوان نشان داده شده در دستگاه تلفن همراه را نشان می دهد:
اعلان ها می توانند بخش های زیر از رابط کاربری را تحت تاثیر قرار دهند:
ممکن است یک اعلان heads-up (HUN) به کاربر نمایش داده شود.
ممکن است یک ورودی در مرکز اعلان اضافه شود، که به صورت اختیاری یک نشان قابل مشاهده در راه آهن است.
برای برنامه های ناوبری، اعلان ممکن است در ویجت راه آهن همانطور که در اعلان های مرحله به مرحله توضیح داده شده است، نمایش داده شود.
همانطور که در مستندات CarAppExtender توضیح داده شده است، می توانید نحوه پیکربندی اعلان های برنامه خود را برای تأثیرگذاری بر هر یک از آن عناصر رابط کاربری با استفاده از اولویت اعلان انتخاب کنید.
مزیت استفاده از CarContext.requestPermissions() ، بر خلاف استفاده از APIهای استاندارد Android ، این است که برای ایجاد گفتگوی مجوزها نیازی به راه اندازی Activity خود ندارید. علاوه بر این، میتوانید از کد یکسانی در Android Auto و Android Automotive OS استفاده کنید، نه اینکه نیاز به ایجاد جریانهای وابسته به پلتفرم داشته باشید.
به گفتگوی مجوزها در Android Auto سبک دهید
در Android Auto، گفتگوی مجوزها برای کاربر در تلفن ظاهر می شود. به طور پیش فرض، هیچ پس زمینه ای در پشت دیالوگ وجود نخواهد داشت. برای تنظیم پسزمینه سفارشی، یک طرح زمینه برنامه ماشین را در فایل AndroidManifest.xml خود اعلام کنید و ویژگی carPermissionActivityLayout را برای طرح زمینه برنامه ماشین خود تنظیم کنید.
مثال زیر نحوه ایجاد اعلان را با عملکردی که برنامه شما را با صفحهای که جزئیات رزرو پارکینگ را نشان میدهد باز میکند، نشان میدهد. شما نمونه اعلان را با هدف محتوایی گسترش می دهید که حاوی یک PendingIntent است که یک هدف صریح را به عملکرد برنامه شما می بندد:
برنامه شما همچنین باید BroadcastReceiver را اعلام کند که برای پردازش هدف فراخوانی می شود، زمانی که کاربر اقدامی را در رابط اعلان انتخاب می کند و CarContext.startCarApp را با هدف شامل URI داده فراخوانی می کند:
توجه داشته باشید که این محدودیت برای تعداد الگوها اعمال می شود و نه تعداد نمونه های Screen در پشته. به عنوان مثال، اگر یک برنامه در حالی که در صفحه A است، دو الگو ارسال کند و سپس صفحه B را فشار دهد، اکنون می تواند سه الگوی دیگر ارسال کند. متناوبا، اگر ساختار هر صفحه برای ارسال یک الگو باشد، برنامه میتواند پنج نمونه صفحه را در پشته ScreenManager قرار دهد.
موارد خاصی برای این محدودیت ها وجود دارد: بازخوانی قالب و عملیات بازگشت و بازنشانی.
الگو به روز می شود
برخی از بهروزرسانیهای محتوایی در محدودیت قالب حساب نمیشوند. به طور کلی، اگر یک برنامه یک الگوی جدید را که از همان نوع است و حاوی محتوای اصلی قالب قبلی است را فشار دهد، الگوی جدید در سهمیه حساب نمیشود. به عنوان مثال، بهروزرسانی وضعیت جابجایی یک ردیف در یک ListTemplate در سهمیه حساب نمیشود. برای آشنایی بیشتر با انواع بهروزرسانیهای محتوا، به مستندات تک تک قالبها مراجعه کنید.
عملیات پشت
برای فعال کردن جریانهای فرعی در یک کار، میزبان تشخیص میدهد که یک برنامه در حال نمایش یک Screen از پشته ScreenManager است و سهمیه باقیمانده را بر اساس تعداد الگوهایی که برنامه به عقب برمیگردد، بهروزرسانی میکند.
برای مثال، اگر برنامه در حالی که در صفحه A است، دو الگو ارسال کند، سپس صفحه B را فشار دهد و دو الگوی دیگر ارسال کند، برنامه یک سهمیه باقی مانده است. اگر برنامه به صفحه A بازگردد، میزبان سهمیه را به سه بازنشانی میکند، زیرا برنامه با دو الگو به عقب رفته است.
توجه داشته باشید که زمانی که یک برنامه به صفحه نمایش باز می گردد، باید یک الگو را ارسال کند که از همان نوع قالبی باشد که آخرین بار توسط آن صفحه ارسال شده است. ارسال هر نوع قالب دیگری باعث ایجاد خطا می شود. با این حال، تا زمانی که نوع آن در طول عملیات برگشت یکسان باقی بماند، یک برنامه میتواند آزادانه محتویات الگو را بدون تأثیر بر سهمیه تغییر دهد.
بازنشانی عملیات
برخی از الگوها دارای معنای خاصی هستند که به معنای پایان یک کار است. به عنوان مثال، NavigationTemplate یک نمای است که انتظار می رود روی صفحه باقی بماند و با دستورالعمل های گام به گام جدید برای مصرف کاربر به روز شود. هنگامی که به یکی از این الگوها می رسد، میزبان سهمیه الگو را بازنشانی می کند و با آن الگو به گونه ای رفتار می کند که گویی اولین مرحله از یک کار جدید است. این به برنامه اجازه می دهد تا یک کار جدید را شروع کند. به مستندات تک تک الگوها مراجعه کنید تا ببینید کدام یک بازنشانی را در میزبان ایجاد می کنند.
اگر میزبان قصد شروع برنامه را از طریق یک اقدام اعلان یا از راهانداز دریافت کند، سهمیه نیز بازنشانی میشود. این مکانیسم به برنامه اجازه میدهد تا یک کار جدید را از اعلانها شروع کند، و حتی اگر برنامهای از قبل محدود شده باشد و در پیشزمینه باشد، صادق است.
برای جزئیات بیشتر در مورد نحوه نمایش اعلانهای برنامه خود در صفحه ماشین، به بخش نمایش اعلانها مراجعه کنید. برای اطلاعات در مورد نحوه راهاندازی برنامه از طریق یک اقدام اعلان، به بخش Start a car with a intent مراجعه کنید.
اتصال API
با استفاده از CarConnection API برای بازیابی اطلاعات اتصال در زمان اجرا، می توانید تعیین کنید که آیا برنامه شما روی Android Auto یا Android Automotive OS اجرا می شود.
به عنوان مثال، در Session برنامه خودروی خود، CarConnection راهاندازی کنید و در بهروزرسانیهای LiveData مشترک شوید:
در مشاهده گر، می توانید به تغییرات در وضعیت اتصال واکنش نشان دهید:
کاتلین
funonConnectionStateUpdated(connectionState:Int){valmessage=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()}
جاوا
privatevoidonConnectionStateUpdated(intconnectionState){Stringmessage;switch(connectionState){caseCarConnection.CONNECTION_TYPE_NOT_CONNECTED:message="Not connected to a head unit";break;caseCarConnection.CONNECTION_TYPE_NATIVE:message="Connected to Android Automotive OS";break;caseCarConnection.CONNECTION_TYPE_PROJECTION:message="Connected to Android Auto";break;default:message="Unknown car connection type";break;}CarToast.makeText(getCarContext(),message,CarToast.LENGTH_SHORT).show();}
محدودیتهای API
ماشینهای مختلف ممکن است اجازه دهند تعداد متفاوتی از نمونههای Item در یک زمان به کاربر نمایش داده شود. از ConstraintManager برای بررسی محدودیت محتوا در زمان اجرا استفاده کنید و تعداد مناسبی از موارد را در قالبهای خود تنظیم کنید.
با گرفتن ConstraintManager از CarContext شروع کنید:
سپس می توانید شی ConstraintManager بازیابی شده را برای محدودیت محتوای مربوطه پرس و جو کنید. به عنوان مثال، برای به دست آوردن تعداد مواردی که می توان در یک شبکه نمایش داد، getContentLimit با CONTENT_LIMIT_TYPE_GRID تماس بگیرید:
اگر برنامه شما تجربه ورود به سیستم را برای کاربران ارائه میدهد، میتوانید از الگوهایی مانند SignInTemplate و LongMessageTemplate با Car App API سطح 2 و بالاتر برای ورود به برنامه خود در قسمت اصلی خودرو استفاده کنید.
برای ایجاد یک SignInTemplate ، یک SignInMethod تعریف کنید. کتابخانه برنامه خودرو در حال حاضر از روشهای ورود به سیستم زیر پشتیبانی میکند:
QRCodeSignInMethod برای ورود به سیستم کد QR، جایی که کاربر یک کد QR را اسکن می کند تا ورود به سیستم را در تلفن خود کامل کند. این با Car API سطح 4 و بالاتر در دسترس است.
به عنوان مثال، برای پیاده سازی قالبی که رمز عبور کاربر را جمع آوری می کند، با ایجاد یک InputCallback برای پردازش و اعتبارسنجی ورودی کاربر شروع کنید:
کاتلین
valcallback=object:InputCallback{overridefunonInputSubmitted(text:String){// You will receive this callback when the user presses Enter on the keyboard.}overridefunonInputTextChanged(text:String){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}}
جاوا
InputCallbackcallback=newInputCallback(){@OverridepublicvoidonInputSubmitted(@NonNullStringtext){// You will receive this callback when the user presses Enter on the keyboard.}@OverridepublicvoidonInputTextChanged(@NonNullStringtext){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}};
یک InputCallback برای InputSignInMethodBuilder مورد نیاز است.
در نهایت، از InputSignInMethod جدید خود برای ایجاد یک SignInTemplate استفاده کنید.
کاتلین
SignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build()
جاوا
newSignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build();
از AccountManager استفاده کنید
برنامههای سیستمعامل Android Automotive که دارای احراز هویت هستند، به دلایل زیر باید از AccountManager استفاده کنند:
تجربه کاربری بهتر و سهولت مدیریت حساب : کاربران می توانند به راحتی تمام حساب های خود را از منوی حساب ها در تنظیمات سیستم مدیریت کنند، از جمله ورود به سیستم و خروج از سیستم.
تجربههای «مهمان» : از آنجایی که خودروها دستگاههای مشترک هستند، OEMها میتوانند تجربههای مهمان را در خودرو فعال کنند، جایی که نمیتوان حسابها را اضافه کرد.
انواع رشته متن را اضافه کنید
اندازه های مختلف صفحه نمایش ماشین ممکن است مقادیر متفاوتی از متن را نشان دهد. با Car App API سطح 2 و بالاتر، میتوانید انواع مختلفی از یک رشته متنی را مشخص کنید تا به بهترین نحو با صفحه نمایش مطابقت داشته باشد. برای دیدن مکانهایی که انواع متن پذیرفته میشوند، به دنبال الگوها و مؤلفههایی باشید که CarText میگیرند.
رشته ها را به ترتیب از بیشترین به کمترین ترجیح اضافه کنید - برای مثال، از طولانی ترین به کوتاه ترین. میزبان رشته با طول مناسب را بسته به میزان فضای موجود روی صفحه ماشین انتخاب می کند.
CarIcon های درون خطی را برای ردیف ها اضافه کنید
با استفاده از CarIconSpan میتوانید نمادهایی را به صورت متنی اضافه کنید تا جذابیت بصری برنامه خود را تقویت کنید. برای اطلاعات بیشتر در مورد ایجاد این دهانه ها به مستندات CarIconSpan.create مراجعه کنید. برای یک نمای کلی از نحوه عملکرد استایل نوشتار با دهانه، استایلسازی متن Spantastic با Spans را ببینید.
کاتلین
valrating=SpannableString("Rating: 4.5 stars")rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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)valrow=Row.Builder()....addText(rating).build()
جاوا
SpannableStringrating=newSpannableString("Rating: 4.5 stars");rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsnewCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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);Rowrow=newRow.Builder()....addText(rating).build();
API های سخت افزار خودرو
با شروع API سطح 3 Car App، کتابخانه برنامه Car دارای APIهایی است که می توانید از آنها برای دسترسی به ویژگی ها و حسگرهای خودرو استفاده کنید.
الزامات
برای استفاده از APIها با Android Auto، با افزودن یک وابستگی به androidx.car.app:app-projected به فایل build.gradle ماژول Android Auto خود شروع کنید. برای سیستم عامل Android Automotive، یک وابستگی به androidx.car.app:app-automotive به فایل build.gradle ماژول سیستم عامل Android Automotive خود اضافه کنید.
اخطار: متد getOdometerMeters از کلاس Mileage به اشتباه نامگذاری شده است و کیلومترها را برمی گرداند نه مترها.
فاصله کیلومتر شمار
com.google.android.gms.permission.CAR_MILEAGE
این دادهها در سیستم عامل Android Automotive برای برنامههای نصبشده از فروشگاه Play در دسترس نیست.
3
به عنوان مثال، برای بدست آوردن محدوده باقیمانده، یک شی CarInfo نمونه سازی کنید، سپس یک OnCarDataAvailableListener ایجاد و ثبت کنید:
کاتلین
valcarInfo=carContext.getCarService(CarHardwareManager::class.java).carInfovallistener=OnCarDataAvailableListener<EnergyLevel>{data->
if(data.rangeRemainingMeters.status==CarValue.STATUS_SUCCESS){valrangeRemaining=data.rangeRemainingMeters.value}else{// Handle error}}carInfo.addEnergyLevelListener(carContext.mainExecutor,listener)…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener)
جاوا
CarInfocarInfo=getCarContext().getCarService(CarHardwareManager.class).getCarInfo();OnCarDataAvailableListener<EnergyLevel>listener=(data)->{if(data.getRangeRemainingMeters().getStatus()==CarValue.STATUS_SUCCESS){floatrangeRemaining=data.getRangeRemainingMeters().getValue();}else{// Handle error}};carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(),listener);…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener);
فرض نکنید که داده های ماشین همیشه در دسترس هستند. اگر خطایی دریافت کردید، وضعیت مقدار درخواستی را بررسی کنید تا بهتر متوجه شوید که چرا دادههای درخواستی شما بازیابی نشدند. برای تعریف کامل کلاس CarInfo به مستندات مرجع مراجعه کنید.
حسگرهای خودرو
کلاس CarSensors به شما امکان دسترسی به شتاب سنج، ژیروسکوپ، قطب نما و داده های موقعیت مکانی خودرو را می دهد. در دسترس بودن این مقادیر ممکن است به OEM بستگی داشته باشد. فرمت داده های حاصل از شتاب سنج ، ژیروسکوپ و قطب نما همان است که از API SensorManager دریافت می کنید. به عنوان مثال ، برای بررسی عنوان وسیله نقلیه:
کاتلین
valcarSensors=carContext.getCarService(CarHardwareManager::class.java).carSensorsvallistener=OnCarDataAvailableListener<Compass>{data->
if(data.orientations.status==CarValue.STATUS_SUCCESS){valorientation=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 updatescarSensors.removeCompassListener(listener)
جاوا
CarSensorscarSensors=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 updatescarSensors.removeCompassListener(listener);
برای دسترسی به داده های مکان از خودرو ، شما همچنین باید مجوز android.permission.ACCESS_FINE_LOCATION را اعلام و درخواست کنید.
تست کردن
برای شبیه سازی داده های سنسور هنگام تست در Android Auto ، به بخش سنسورها و پیکربندی سنسور راهنمای واحد سر دسک تاپ مراجعه کنید. برای شبیه سازی داده های سنسور هنگام آزمایش در سیستم عامل Android Automobile ، به بخش Emulate Hardware State از راهنمای Emulator OS Android Automobile Os مراجعه کنید.
چرخه های حیات Carappservice ، Session و Screen
کلاس های Session و Screen رابط LifecycleOwner پیاده سازی می کنند. از آنجا که کاربر با برنامه در تعامل است ، همانطور که در نمودارهای زیر توضیح داده شده است ، از تماس های چرخه عمر Session و Screen اشیاء استفاده می شود.
با استفاده از CarAppService برنامه و API CarAudioRecord ، می توانید برنامه خود را به میکروفون ماشین کاربر دسترسی دهید. کاربران برای دسترسی به میکروفون خودرو باید به برنامه شما اجازه دهند. برنامه شما می تواند ورودی کاربر را در برنامه شما ضبط و پردازش کند.
اجازه ضبط
قبل از ضبط هرگونه صدا ، ابتدا باید اجازه ضبط در AndroidManifest.xml خود را اعلام کنید و درخواست کنید که کاربر آن را اعطا کند.
شما باید در زمان اجرا مجوز ضبط را درخواست کنید. برای جزئیات بیشتر در مورد نحوه درخواست مجوز در برنامه ماشین خود ، به بخش مجوزهای درخواست مراجعه کنید.
ضبط صدا
بعد از اینکه کاربر اجازه ضبط را می دهد ، می توانید صدا را ضبط کرده و ضبط را پردازش کنید.
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)carAudioRecord.startRecording()valdata=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()
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());carAudioRecord.startRecording();byte[]data=newbyte[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();
تمرکز صوتی
هنگام ضبط از میکروفون خودرو ، ابتدا فوکوس صوتی را به دست می آورید تا اطمینان حاصل شود که هر رسانه در حال انجام است. اگر تمرکز صوتی را از دست دادید ، ضبط را متوقف کنید.
در اینجا نمونه ای از نحوه دستیابی به تمرکز صوتی آورده شده است:
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)// Take audio focus so that user's media is not recordedvalaudioAttributes=AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build()valaudioFocusRequest=AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener{state:Int->
if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording()}}.build()if(carContext.getSystemService(AudioManager::class.java).requestAudioFocus(audioFocusRequest)!=AudioManager.AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn}carAudioRecord.startRecording()// Process the audio and abandon the AudioFocusRequest when done
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());// Take audio focus so that user's media is not recordedAudioAttributesaudioAttributes=newAudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build();AudioFocusRequestaudioFocusRequest=newAudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener(state->{if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording();}}).build();if(getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)!=AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn;}carAudioRecord.startRecording();// Process the audio and abandon the AudioFocusRequest when done
کتابخانه تست
کتابخانه تست Android for Cars کلاس های کمکی را ارائه می دهد که می توانید برای اعتبارسنجی رفتار برنامه خود در یک محیط آزمایش استفاده کنید. به عنوان مثال ، SessionController به شما امکان می دهد اتصال به میزبان را شبیه سازی کنید و تأیید کنید که Screen و Template صحیح ایجاد و بازگردانده شده است.
قبل از تشکیل مسئله جدید ، لطفاً بررسی کنید که آیا در یادداشت های انتشار کتابخانه ذکر شده است یا در لیست شماره ها گزارش شده است. با کلیک بر روی ستاره برای مسئله در ردیاب می توانید مشترک شوید و به موضوعات رای دهید. برای اطلاعات بیشتر ، به عضویت در یک موضوع مراجعه کنید.
رابط کاربری توسط نمودار از اشیاء مدل که می توانند به روش های مختلف با هم چیده شوند ، نشان داده شده است ، همانطور که توسط الگوی متعلق به آنها مجاز است. قالب ها زیر مجموعه ای از مدل ها هستند که می توانند به عنوان ریشه در آن نمودارها عمل کنند. مدل ها شامل اطلاعاتی هستند که به شکل متن و تصاویر به کاربر نمایش داده می شوند و همچنین ویژگی هایی برای پیکربندی جنبه های ظاهر بصری چنین اطلاعاتی - برای مثال ، رنگ های متن یا اندازه تصویر. میزبان مدل ها را به نمایی که برای رعایت استانداردهای حواس پرتی راننده طراحی شده اند تبدیل می کند و از جزئیات مانند انواع فاکتورهای صفحه نمایش خودرو و روشهای ورودی مراقبت می کند.
میزبان
میزبان مؤلفه باطن است که عملکردی ارائه شده توسط API های کتابخانه را پیاده سازی می کند تا برنامه شما بتواند در ماشین اجرا شود. مسئولیت های میزبان از کشف برنامه شما و مدیریت چرخه عمر آن تا تبدیل مدل های خود به نمایش و اطلاع برنامه تعامل کاربر است. در دستگاه های تلفن همراه ، این میزبان توسط Android Auto اجرا می شود. در سیستم عامل Android Automobile ، این میزبان به عنوان یک برنامه سیستم نصب شده است.
محدودیت های الگو
الگوهای مختلف محدودیت هایی را در محتوای مدل های خود اعمال می کنند. به عنوان مثال ، الگوهای لیست محدودیت هایی در تعداد مواردی دارند که می توانند به کاربر ارائه شوند. الگوهای همچنین محدودیت هایی در نحوه اتصال آنها برای تشکیل جریان یک کار دارند. به عنوان مثال ، برنامه فقط می تواند حداکثر پنج قالب را به پشته صفحه منتقل کند. برای اطلاعات بیشتر به محدودیت های الگو مراجعه کنید.
Screen
Screen یک کلاس ارائه شده توسط کتابخانه است که برنامه ها برای مدیریت رابط کاربری ارائه شده به کاربر پیاده سازی می کنند. یک Screen دارای چرخه عمر است و مکانیسم برنامه را برای ارسال الگوی برای نمایش در هنگام نمایش صفحه فراهم می کند. نمونه های Screen همچنین می توانند به یک پشته صفحه نمایش و از یک پشته Screen داده شوند و این امر را تضمین می کند که آنها به محدودیت های جریان الگوی پایبند هستند.
CarAppService
CarAppService یک کلاس Service انتزاعی است که برنامه شما باید توسط میزبان کشف و صادرات کند. CarAppService برنامه شما وظیفه تأیید این را دارد که به یک اتصال میزبان با استفاده از createHostValidator و متعاقباً ارائه نمونه های Session برای هر اتصال با استفاده از onCreateSession می توان اعتماد کرد.
Session
Session یک کلاس انتزاعی است که برنامه شما باید با استفاده از CarAppService.onCreateSession اجرا و بازگردد. این به عنوان نقطه ورود برای نمایش اطلاعات در صفحه ماشین است. این یک چرخه حیات دارد که وضعیت فعلی برنامه شما را در صفحه ماشین آگاه می کند ، مانند زمانی که برنامه شما قابل مشاهده یا پنهان است.
هنگامی که یک Session آغاز شد ، مانند زمان راه اندازی برنامه ، میزبان درخواست می کند تا Screen اولیه با استفاده از روش onCreateScreen نمایش داده شود.
کتابخانه برنامه ماشین را نصب کنید
برای راهنمایی در مورد نحوه اضافه کردن کتابخانه به برنامه خود ، به صفحه انتشار کتابخانه JetPack مراجعه کنید.
پرونده های مانیفست برنامه خود را پیکربندی کنید
قبل از اینکه بتوانید برنامه اتومبیل خود را ایجاد کنید ، پرونده های مانیفست برنامه خود را به شرح زیر پیکربندی کنید.
سرویس کار خود را اعلام کنید
میزبان از طریق اجرای CarAppService شما به برنامه شما متصل می شود. شما این سرویس را در مانیفست خود اعلام می کنید تا میزبان به برنامه خود کشف و متصل شود.
شما همچنین باید دسته برنامه خود را در عنصر <category> فیلتر قصد برنامه خود اعلام کنید. برای مقادیر مجاز برای این عنصر به لیست دسته های برنامه پشتیبانی شده مراجعه کنید.
قطعه کد زیر نحوه اعلام سرویس برنامه خودرو را برای یک برنامه مورد علاقه در مانیفست شما نشان می دهد:
با افزودن یک یا چند مورد از مقادیر زیر در فیلتر CarAppService ، هنگامی که در بخش قبلی توضیح داده می شوید ، دسته برنامه خود را اعلام کنید:
androidx.car.app.category.NAVIGATION : برنامه ای که مسیرهای ناوبری نوبت به نوبه خود را ارائه می دهد. به ساخت برنامه های ناوبری برای اتومبیل مراجعه کنید.
androidx.car.app.category.POI : برنامه ای که عملکردی را برای یافتن نقاط مورد علاقه مانند نقاط پارکینگ ، ایستگاه های شارژ و پمپ بنزین فراهم می کند. برنامه های مورد علاقه خود را برای اتومبیل ها مشاهده کنید.
androidx.car.app.category.IOT : برنامه ای که کاربران را قادر می سازد از طریق دستگاه های متصل اقدامات مربوطه را در دستگاه های متصل انجام دهند. به ساخت برنامه های اینترنت چیزها برای اتومبیل مراجعه کنید.
androidx.car.app.category.WEATHER : برنامه ای که به کاربران امکان می دهد اطلاعات مربوط به آب و هوا مربوط به مکان فعلی یا مسیر خود را مشاهده کنند. به ساخت برنامه های هواشناسی برای اتومبیل مراجعه کنید.
کتابخانه برنامه Car سطح API خود را تعریف می کند تا بتوانید بدانید که کدام ویژگی های کتابخانه توسط میزبان الگوی روی یک وسیله نقلیه پشتیبانی می شود. برای بازیابی بالاترین سطح API برنامه اتومبیل پشتیبانی شده توسط یک میزبان ، از روش getCarAppApiLevel() استفاده کنید.
حداقل سطح API برنامه اتومبیل را که توسط برنامه خود در پرونده AndroidManifest.xml پشتیبانی می شود ، اعلام کنید:
برای جزئیات بیشتر در مورد نحوه حفظ سازگاری به عقب و اعلام حداقل سطح API مورد نیاز برای استفاده از یک ویژگی ، به اسناد مربوط به حاشیه نویسی RequiresCarApi مراجعه کنید. برای تعریفی که سطح API برای استفاده از ویژگی خاصی از کتابخانه برنامه خودرو مورد نیاز است ، مستندات مرجع را برای CarAppApiLevels بررسی کنید.
سرویس و جلسه خود را ایجاد کنید
برنامه شما باید کلاس CarAppService را گسترش داده و روش onCreateSession خود را اجرا کند ، که یک نمونه Session مربوط به اتصال فعلی به میزبان را برمی گرداند:
برای رسیدگی به سناریوهایی که برنامه ماشین شما باید از صفحه نمایش شروع کند که صفحه اصلی برنامه شما نیست ، مانند دستیابی به پیوندهای عمیق ، می توانید قبل از بازگشت از onCreateScreen ، یک صفحه پشتی از صفحه نمایش را با استفاده از ScreenManager.push از قبل بفرستید. قبل از بذر به کاربران امکان می دهد از اولین صفحه ای که برنامه شما در حال نمایش است به صفحه های قبلی برگردند.
صفحه شروع خود را ایجاد کنید
شما صفحه نمایش های نمایش داده شده توسط برنامه خود را با تعریف کلاس هایی که کلاس Screen را گسترش می دهند و روش onGetTemplate آن را اجرا می کنند ، ایجاد می کنید ، که نمونه Template را نشان می دهد که وضعیت UI را برای نمایش در صفحه نمایش خودرو نشان می دهد.
قطعه زیر نشان می دهد که چگونه می توان Screen اعلام کرد که از یک الگوی PaneTemplate استفاده می کند تا یک "سلام جهان!" رشته:
CarContext همچنین عملکردهای دیگری را ارائه می دهد ، مانند این که به شما اجازه می دهد منابع قابل ترسیم را با استفاده از پیکربندی از صفحه نمایش خودرو بارگیری کنید ، یک برنامه را در خودرو با استفاده از اهداف شروع کنید و سیگنال دهید که آیا برنامه شما باید نقشه خود را در موضوع تاریک نمایش دهد.
اجرای ناوبری صفحه
برنامه ها غالباً تعدادی صفحه نمایش مختلف را ارائه می دهند ، هر یک احتمالاً با استفاده از الگوهای مختلفی که کاربر می تواند از طریق آن حرکت کند ، زیرا با رابط نمایش داده شده در صفحه تعامل دارند.
کلاس ScreenManager یک پشته صفحه نمایش را فراهم می کند که می توانید برای فشار دادن صفحه نمایش هایی که می توانند به طور خودکار ظاهر شوند ، هنگام انتخاب کاربر یک دکمه پشتی را در صفحه ماشین یا از دکمه پشت سخت افزار موجود در برخی از اتومبیل ها استفاده کنید.
قطعه زیر نشان می دهد که چگونه می توان یک عمل پشتی را به یک الگوی پیام و همچنین عملی اضافه کرد که هنگام انتخاب توسط کاربر ، یک صفحه جدید را تحت فشار قرار می دهد:
برای کمک به اطمینان از استفاده از برنامه در هنگام رانندگی ، پشته صفحه می تواند حداکثر عمق پنج صفحه را داشته باشد. برای اطلاعات بیشتر به بخش محدودیت های الگو مراجعه کنید.
محتوای یک الگوی را تازه کنید
برنامه شما می تواند با فراخوانی روش Screen.invalidate ، محتوای یک Screen را باطل کند. میزبان متعاقباً برای بازیابی الگوی با محتوای جدید ، به روش Screen.onGetTemplate شما باز می گردد.
هنگام طراوت یک Screen ، درک محتوای خاص موجود در الگوی که می تواند به روز شود ، مهم است تا میزبان الگوی جدید را در برابر سهمیه الگو بشمارد. برای اطلاعات بیشتر به بخش محدودیت های الگو مراجعه کنید.
ما توصیه می کنیم که صفحه های خود را ساختار دهید ، بنابراین یک نقشه برداری یک به یک بین Screen و نوع الگویی که از طریق اجرای onGetTemplate خود باز می گردد وجود دارد.
نقشه ها
ناوبری ، نقطه مورد علاقه (POI) و برنامه های آب و هوایی با استفاده از الگوهای زیر می توانند با دسترسی به یک Surface نقشه ها را ترسیم کنند.
برای استفاده از الگوهای زیر ، برنامه شما باید یکی از مجوزهای مربوطه اعلام شده در یک عنصر <uses-permission> در پرونده AndroidManifest.xml خود را داشته باشد.
علاوه بر مجوز مورد نیاز برای الگوی مورد استفاده شما برنامه ، برنامه شما باید اجازه androidx.car.app.ACCESS_SURFACE را در پرونده AndroidManifest.xml خود اعلام کند تا به سطح دسترسی پیدا کند:
برای دسترسی به Surface که میزبان در اختیار شما قرار می دهد ، باید یک SurfaceCallback پیاده سازی کرده و آن را به سرویس اتومبیل AppManager ارائه دهید. Surface فعلی در پارامتر SurfaceContainer از تماسهای برگشتی onSurfaceAvailable() و onSurfaceDestroyed() به SurfaceCallback شما منتقل می شود.
میزبان می تواند عناصر رابط کاربری را برای الگوهای موجود در بالای نقشه ترسیم کند. میزبان با فراخوانی با استفاده از روش SurfaceCallback.onVisibleAreaChanged ، مساحت سطح را که تضمین می شود بدون مانع و کاملاً قابل مشاهده برای کاربر ارتباط برقرار می کند ، ارتباط برقرار می کند. همچنین ، برای به حداقل رساندن تعداد تغییرات ، میزبان روش SurfaceCallback.onStableAreaChanged را با کوچکترین مستطیل فراخوانی می کند ، که همیشه بر اساس الگوی فعلی قابل مشاهده است.
به عنوان مثال ، هنگامی که یک برنامه ناوبری از NavigationTemplate با یک نوار اکشن در بالا استفاده می کند ، نوار عمل می تواند خود را پنهان کند وقتی کاربر مدتی با صفحه تعامل نداشته باشد تا فضای بیشتری برای نقشه ایجاد کند. در این حالت ، یک تماس تلفنی برای onStableAreaChanged و onVisibleAreaChanged با همان مستطیل وجود دارد. هنگامی که نوار اکشن پنهان است ، فقط onVisibleAreaChanged با منطقه بزرگتر فراخوانی می شود. اگر کاربر با صفحه تعامل داشته باشد ، دوباره فقط onVisibleAreaChanged با اولین مستطیل فراخوانی می شود.
حمایت از موضوع تاریک
برنامه ها باید نقشه خود را بر روی نمونه Surface با رنگ های تیره مناسب مجدداً تنظیم کنند ، هنگامی که میزبان شرایط را تعیین می کند ، آن را ضمانت می کند ، همانطور که در کیفیت برنامه Android برای اتومبیل ها توضیح داده شده است.
به کاربران اجازه دهید با نقشه شما ارتباط برقرار کنند
هنگام استفاده از الگوهای زیر ، می توانید پشتیبانی را برای کاربران اضافه کنید تا با نقشه هایی که شما ترسیم می کنید در تعامل باشند ، مانند این که به آنها اجازه دهید قسمت های مختلف نقشه را با بزرگنمایی و پوشیدن مشاهده کنند.
الگو
تعامل از سطح API برنامه اتومبیل پشتیبانی می شود
NavigationTemplate
2
PlaceListNavigationTemplate ( مستهلک )
4
RoutePreviewNavigationTemplate ( مستهلک )
4
MapTemplate ( مستهلک )
5 (معرفی الگو)
MapWithContentTemplate
7 (معرفی الگو)
پاسخ های تعاملی را اجرا کنید
رابط SurfaceCallback دارای چندین روش پاسخ به تماس است که می توانید برای اضافه کردن تعامل به نقشه های ساخته شده با الگوهای موجود در بخش قبلی ، استفاده کنید:
onScale (با فاکتور مقیاس تعیین شده توسط میزبان الگو)
2
گنگ دوار در حالت تابه
onScroll (با ضریب فاصله تعیین شده توسط میزبان الگو)
2
نوار عمل نقشه اضافه کنید
این الگوها می توانند یک نوار اکشن نقشه برای اقدامات مرتبط با نقشه مانند بزرگنمایی در داخل و خارج ، اخیر ، نمایش قطب نما و سایر اقداماتی که برای نمایش انتخاب می کنید داشته باشد. نوار عمل نقشه می تواند حداکثر چهار دکمه فقط نماد داشته باشد که بدون تأثیرگذاری بر عمق کار می توانند تازه شوند. در حین حالت بیکار پنهان می شود و دوباره در حالت فعال ظاهر می شود.
برای دریافت مکالمه های تعامل MAP ، باید یک دکمه Action.PAN را در نوار عملکرد نقشه اضافه کنید. هنگامی که کاربر دکمه PAN را فشار می دهد ، میزبان همانطور که در بخش زیر توضیح داده شده است ، وارد حالت PAN می شود.
اگر برنامه شما از دکمه Action.PAN در نوار عمل نقشه خارج شده است ، ورودی کاربر را از روش های SurfaceCallback دریافت نمی کند ، و میزبان از هر حالت PAN فعال شده قبلی خارج می شود.
در صفحه لمسی ، دکمه PAN نمایش داده نمی شود.
حالت تابه را درک کنید
در حالت PAN ، میزبان الگوی ورودی کاربر را از دستگاه های ورودی غیر لمسی مانند کنترل کننده های چرخشی و لمسی به روشهای مناسب SurfaceCallback ترجمه می کند. به عمل کاربر برای وارد کردن یا خروج از حالت PAN با روش setPanModeListener در NavigationTemplate.Builder پاسخ دهید. میزبان می تواند سایر اجزای UI را در الگوی پنهان کند در حالی که کاربر در حالت PAN است.
تعامل با کاربر
برنامه شما می تواند با استفاده از الگوهای مشابه با یک برنامه تلفن همراه با کاربر ارتباط برقرار کند.
ورودی کاربر را اداره کنید
برنامه شما می تواند با انتقال شنوندگان مناسب به مدلهایی که از آنها پشتیبانی می کنند ، به ورودی کاربر پاسخ دهند. قطعه زیر نحوه ایجاد یک مدل Action را نشان می دهد که یک OnClickListener تنظیم می کند که به روشی تعریف شده توسط کد برنامه شما باز می گردد:
برخی از اقدامات ، مانند مواردی که نیاز به کارگردانی کاربر برای ادامه تعامل در دستگاه های تلفن همراه خود دارند ، فقط در هنگام پارک کردن ماشین مجاز است. برای اجرای این اقدامات می توانید از ParkedOnlyOnClickListener استفاده کنید. اگر ماشین پارک نشده باشد ، میزبان نشانه ای را برای کاربر نشان می دهد که در این مورد این عمل مجاز نیست. اگر ماشین پارک شده باشد ، کد به طور عادی اجرا می شود. قطعه زیر نحوه استفاده از ParkedOnlyOnClickListener را برای باز کردن صفحه تنظیمات روی دستگاه تلفن همراه نشان می دهد:
اعلان های ارسال شده به دستگاه تلفن همراه فقط در صورت گسترش با یک CarAppExtender ، روی صفحه نمایش خودرو نشان داده می شوند. برخی از ویژگی های اعلان ، مانند عنوان محتوا ، متن ، نماد و اقدامات را می توان در CarAppExtender تنظیم کرد و ویژگی های اعلان را هنگام ظاهر شدن در صفحه خودرو بر عهده داشت.
قطعه زیر نحوه ارسال اعلان را به صفحه نمایش اتومبیل نشان می دهد که عنوانی متفاوت از نمونه ای که در دستگاه تلفن همراه نشان داده شده است نشان می دهد:
اعلان ها می توانند قسمتهای زیر رابط کاربری را تحت تأثیر قرار دهند:
اعلان Heads-Up (HUN) ممکن است به کاربر نمایش داده شود.
ورود به مرکز اعلان ممکن است به صورت اختیاری با نشان قابل مشاهده در راه آهن اضافه شود.
برای برنامه های ناوبری ، اعلان ممکن است در ویجت ریلی نمایش داده شود ، همانطور که در اعلان های نوبت به نوبه خود توضیح داده شده است.
شما می توانید نحوه پیکربندی اعلان های برنامه خود را برای تأثیرگذاری بر هر یک از آن عناصر رابط کاربری با استفاده از اولویت اعلان ، همانطور که در مستندات CarAppExtender توضیح داده شده است ، انتخاب کنید.
فایده استفاده از CarContext.requestPermissions() ، بر خلاف استفاده از API های استاندارد Android ، این است که برای ایجاد گفتگوی مجوزها نیازی به Activity خود ندارید. علاوه بر این ، شما می توانید به جای ایجاد جریان وابسته به پلتفرم ، از همان کد Android Auto و Android Automobile Out استفاده کنید.
گفتگوی مجوزها را در Android Auto سبک کنید
در Android Auto ، گفتگوی مجوزها برای کاربر از طریق تلفن ظاهر می شود. به طور پیش فرض ، هیچ زمینه ای در پشت گفتگو وجود نخواهد داشت. برای تنظیم یک پس زمینه سفارشی ، یک موضوع برنامه خودرو را در پرونده AndroidManifest.xml خود اعلام کنید و ویژگی carPermissionActivityLayout را برای موضوع برنامه خودرو خود تنظیم کنید.
مثال زیر نحوه ایجاد یک اعلان با عملی را نشان می دهد که برنامه شما را با صفحه نمایش باز می کند که جزئیات رزرو پارکینگ را نشان می دهد. شما نمونه اعلان را با یک هدف محتوا که حاوی بسته بندی PendingIntent ، قصد صریح عمل برنامه خود را گسترش می دهید:
برنامه شما همچنین باید یک BroadcastReceiver اعلام کند که برای پردازش هدف وقتی کاربر اقدام را در رابط اعلان انتخاب می کند و CarContext.startCarApp را با یک هدف از جمله داده URI فراخوانی می کند:
سرانجام ، روش Session.onNewIntent در برنامه شما با فشار دادن صفحه رزرو پارکینگ روی پشته ، این هدف را انجام می دهد ، اگر قبلاً در بالای صفحه قرار نگرفته است:
توجه داشته باشید که این حد مربوط به تعداد قالب ها و نه تعداد نمونه های Screen در پشته است. به عنوان مثال ، اگر یک برنامه دو الگوی را در هنگام صفحه A ارسال کند و سپس صفحه B را فشار دهد ، اکنون می تواند سه الگوی دیگر را ارسال کند. از طرف دیگر ، اگر هر صفحه برای ارسال یک الگوی واحد ساختار یافته باشد ، برنامه می تواند پنج نمونه صفحه را روی پشته ScreenManager سوق دهد.
موارد خاصی برای این محدودیت ها وجود دارد: الگوهای تازه و عملیات پشت و تنظیم مجدد.
الگوی تازه کردن
به روزرسانی های خاص محتوا به حد الگوی شمارش نمی شوند. به طور کلی ، اگر یک برنامه الگوی جدیدی را تحت فشار قرار دهد که از همان نوع باشد و حاوی همان محتوای اصلی الگوی قبلی باشد ، الگوی جدید در برابر سهمیه حساب نمی شود. به عنوان مثال ، به روزرسانی حالت ضامن یک ردیف در یک ListTemplate در برابر سهمیه حساب نمی شود. برای کسب اطلاعات بیشتر در مورد اینکه چه نوع به روزرسانی های محتوا را می توان یک تازه کردن در نظر گرفت ، به مستندات الگوهای فردی مراجعه کنید.
عملیات پشتی
برای فعال کردن جریان های زیر در یک کار ، میزبان هنگامی که یک برنامه در حال نمایش Screen از ScreenManager است ، تشخیص می دهد و سهمیه باقی مانده را بر اساس تعداد الگوهایی که برنامه به عقب می رود ، به روز می کند.
به عنوان مثال ، اگر برنامه دو الگوی را در هنگام صفحه A ارسال کند ، صفحه B را فشار می دهد و دو الگوی دیگر را ارسال می کند ، برنامه یک سهمیه باقی مانده است. اگر برنامه پس از آن به صفحه نمایش A برگردد ، میزبان سهمیه را به سه بازگرداند ، زیرا این برنامه توسط دو قالب به عقب رفته است.
توجه داشته باشید که ، هنگام بازگشت به صفحه ، یک برنامه باید الگویی را ارسال کند که از همان نوع آخرین ارسال شده توسط آن صفحه باشد. ارسال هر نوع الگوی دیگر باعث ایجاد خطایی می شود. با این حال ، تا زمانی که نوع در حین عملکرد عقب یکسان باشد ، یک برنامه می تواند آزادانه محتوای الگوی را بدون تأثیرگذاری بر سهمیه اصلاح کند.
بازنشانی عملیات
برخی از الگوهای خاص دارای معناشناسی ویژه ای هستند که نشانگر پایان یک کار است. به عنوان مثال ، NavigationTemplate منظره ای است که انتظار می رود روی صفحه بماند و با دستورالعمل های جدید نوبت به نوبه خود برای مصرف کاربر ، تازه شود. هنگامی که به یکی از این الگوها رسید ، میزبان سهمیه الگوی را تنظیم می کند و آن الگو را درمان می کند که گویی این اولین قدم از یک کار جدید است. این به برنامه اجازه می دهد تا یک کار جدید را آغاز کند. به مستندات الگوهای فردی مراجعه کنید تا ببینید کدام یک از آنها باعث تنظیم مجدد میزبان می شوند.
اگر میزبان قصد شروع برنامه را از یک اقدام اعلان یا از پرتابگر دریافت کند ، سهمیه نیز تنظیم مجدد می شود. این مکانیسم به یک برنامه اجازه می دهد تا جریان کار جدیدی را از اعلان ها آغاز کند ، و حتی اگر یک برنامه قبلاً محدود باشد و در پیش زمینه باشد ، صادق است.
برای اطلاعات بیشتر در مورد نحوه نمایش اعلان های برنامه خود در صفحه اتومبیل ، به بخش اعلان های نمایشگر مراجعه کنید. برای اطلاعات در مورد نحوه شروع برنامه خود از یک اقدام اعلان ، برنامه Start a Car را با یک بخش قصد مشاهده کنید.
API اتصال
می توانید با استفاده از API CarConnection برای بازیابی اطلاعات اتصال در زمان اجرا ، تعیین کنید که آیا برنامه شما در سیستم عامل Android Auto یا Android Automobile OS کار می کند.
به عنوان مثال ، در Session برنامه خودرو خود ، یک CarConnection آغاز کنید و در به روزرسانی های LiveData مشترک شوید:
در Observer ، سپس می توانید نسبت به تغییرات در حالت اتصال واکنش نشان دهید:
کاتلین
funonConnectionStateUpdated(connectionState:Int){valmessage=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()}
جاوا
privatevoidonConnectionStateUpdated(intconnectionState){Stringmessage;switch(connectionState){caseCarConnection.CONNECTION_TYPE_NOT_CONNECTED:message="Not connected to a head unit";break;caseCarConnection.CONNECTION_TYPE_NATIVE:message="Connected to Android Automotive OS";break;caseCarConnection.CONNECTION_TYPE_PROJECTION:message="Connected to Android Auto";break;default:message="Unknown car connection type";break;}CarToast.makeText(getCarContext(),message,CarToast.LENGTH_SHORT).show();}
محدودیت های API
اتومبیل های مختلف ممکن است امکان نمایش تعداد متفاوتی از موارد Item را در یک زمان به کاربر نشان دهند. برای بررسی حد محتوا در زمان اجرا از ConstraintManager استفاده کنید و تعداد مناسب موارد را در قالب های خود تنظیم کنید.
با دریافت یک ConstraintManager از CarContext شروع کنید:
سپس می توانید برای محدودیت محتوای مربوطه ، از شیء ConstraintManager بازیابی شده استفاده کنید. به عنوان مثال ، برای به دست آوردن تعداد مواردی که می توانند در یک شبکه نمایش داده شوند ، با CONTENT_LIMIT_TYPE_GRID با getContentLimit تماس بگیرید:
اگر برنامه شما یک تجربه امضا شده را برای کاربران ارائه می دهد ، می توانید از قالب هایی مانند SignInTemplate و LongMessageTemplate با برنامه اتومبیل API سطح 2 و بالاتر استفاده کنید تا وارد سیستم خود شوید.
برای ایجاد یک SignInTemplate ، یک SignInMethod را تعریف کنید. کتابخانه برنامه اتومبیل در حال حاضر از روشهای ورود به سیستم پشتیبانی می کند:
QRCodeSignInMethod برای ورود به سیستم QR ، جایی که کاربر برای تکمیل ورود به سیستم ، کد QR را اسکن می کند. این با API سطح 4 و بالاتر در دسترس است.
به عنوان مثال ، برای پیاده سازی الگویی که رمز عبور کاربر را جمع می کند ، با ایجاد یک InputCallback برای پردازش و اعتبارسنجی ورودی کاربر شروع کنید:
کاتلین
valcallback=object:InputCallback{overridefunonInputSubmitted(text:String){// You will receive this callback when the user presses Enter on the keyboard.}overridefunonInputTextChanged(text:String){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}}
جاوا
InputCallbackcallback=newInputCallback(){@OverridepublicvoidonInputSubmitted(@NonNullStringtext){// You will receive this callback when the user presses Enter on the keyboard.}@OverridepublicvoidonInputTextChanged(@NonNullStringtext){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}};
برای BuilderInputSignInMethod یک InputCallback لازم است.
در آخر ، از InputSignInMethod جدید خود استفاده کنید تا یک SignInTemplate ایجاد کنید.
کاتلین
SignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build()
جاوا
newSignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build();
از حساب کاربری استفاده کنید
برنامه های سیستم عامل Android Automobile که دارای احراز هویت هستند باید به دلایل زیر از AccountManager استفاده کنند:
UX بهتر و سهولت در مدیریت حساب : کاربران می توانند به راحتی تمام حساب های خود را از منوی حساب ها در تنظیمات سیستم ، از جمله ورود به سیستم و ورود به سیستم ، مدیریت کنند.
تجربیات "مهمان" : از آنجا که اتومبیل ها دستگاه های مشترک هستند ، OEM ها می توانند تجربیات مهمان را در وسیله نقلیه فعال کنند ، جایی که نمی توان حساب ها را اضافه کرد.
انواع رشته های متن را اضافه کنید
اندازه های مختلف صفحه نمایش اتومبیل ممکن است مقادیر مختلفی از متن را نشان دهد. با استفاده از API API API سطح 2 و بالاتر ، می توانید انواع مختلفی از یک رشته متن را مشخص کنید تا به بهترین وجه متناسب با صفحه باشد. برای دیدن اینکه انواع متن در آن پذیرفته شده است ، به دنبال الگوها و مؤلفه هایی باشید که یک CarText می گیرند.
Add strings in order from most to least preferred—for example, from longest to shortest. The host picks the appropriate-length string depending on the amount of space available on the car screen.
Add inline CarIcons for rows
You can add icons inline with text to enrich your app's visual appeal using CarIconSpan . See the documentation for CarIconSpan.create for more information on creating these spans. See Spantastic text styling with Spans for an overview of how text styling with spans work.
کاتلین
valrating=SpannableString("Rating: 4.5 stars")rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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)valrow=Row.Builder()....addText(rating).build()
جاوا
SpannableStringrating=newSpannableString("Rating: 4.5 stars");rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsnewCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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);Rowrow=newRow.Builder()....addText(rating).build();
Car Hardware APIs
Starting with Car App API level 3, the Car App Library has APIs that you can use to access vehicle properties and sensors.
الزامات
To use the APIs with Android Auto, start by adding a dependency on androidx.car.app:app-projected to the build.gradle file for your Android Auto module. For Android Automotive OS, add a dependency on androidx.car.app:app-automotive to the build.gradle file for your Android Automotive OS module.
Additionally, in your AndroidManifest.xml file, you need to declare the relevant permissions needed to request the car data you want to use. Note that these permissions must also be granted to you by the user. You can use the same code on both Android Auto and Android Automotive OS, rather than having to create platform-dependent flows. However, the permissions needed are different.
CarInfo
This table describes the properties surfaced by the CarInfo APIs and the permissions you need to request to use them:
Warning: the getOdometerMeters method of the Mileage class is inaccurately named and returns kilometers, not meters.
Odometer distance
com.google.android.gms.permission.CAR_MILEAGE
This data is not available on Android Automotive OS to apps installed from the Play Store.
3
For example, to get the remaining range, instantiate a CarInfo object, then create and register an OnCarDataAvailableListener :
کاتلین
valcarInfo=carContext.getCarService(CarHardwareManager::class.java).carInfovallistener=OnCarDataAvailableListener<EnergyLevel>{data->
if(data.rangeRemainingMeters.status==CarValue.STATUS_SUCCESS){valrangeRemaining=data.rangeRemainingMeters.value}else{// Handle error}}carInfo.addEnergyLevelListener(carContext.mainExecutor,listener)…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener)
جاوا
CarInfocarInfo=getCarContext().getCarService(CarHardwareManager.class).getCarInfo();OnCarDataAvailableListener<EnergyLevel>listener=(data)->{if(data.getRangeRemainingMeters().getStatus()==CarValue.STATUS_SUCCESS){floatrangeRemaining=data.getRangeRemainingMeters().getValue();}else{// Handle error}};carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(),listener);…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener);
Don't assume that the data from the car is available at all times. If you get an error, check the status of the value you requested to better understand why the data you requested could not be retrieved. Refer to the reference documentation for the full CarInfo class definition.
CarSensors
The CarSensors class gives you access to the vehicle's accelerometer, gyroscope, compass, and location data. The availability of these values may depend on the OEM. The format for the data from the accelerometer, gyroscope, and compass is the same as you would get from the SensorManager API . For example, to check the vehicle's heading:
کاتلین
valcarSensors=carContext.getCarService(CarHardwareManager::class.java).carSensorsvallistener=OnCarDataAvailableListener<Compass>{data->
if(data.orientations.status==CarValue.STATUS_SUCCESS){valorientation=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 updatescarSensors.removeCompassListener(listener)
جاوا
CarSensorscarSensors=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 updatescarSensors.removeCompassListener(listener);
To access location data from the car, you also need to declare and request the android.permission.ACCESS_FINE_LOCATION permission.
تست کردن
To simulate sensor data when testing on Android Auto, refer to the Sensors and Sensor configuration sections of the Desktop Head Unit guide. To simulate sensor data when testing on Android Automotive OS, refer to the Emulate hardware state section of the Android Automotive OS emulator guide.
The CarAppService, Session and Screen lifecycles
The Session and Screen classes implement the LifecycleOwner interface. As the user interacts with the app, your Session and Screen objects' lifecycle callbacks are invoked, as described in the following diagrams.
Using your app's CarAppService and the CarAudioRecord API, you can give your app access to the user's car microphone. Users need to give your app permission to access the car microphone. Your app can record and process the user's input within your app.
Permission to record
Before recording any audio, you must first declare the permission to record in your AndroidManifest.xml and request that the user grant it.
You need to request the permission to record at runtime. See the Request permissions section for details on how to request a permission in your car app.
ضبط صدا
After the user gives permission to record, you can record the audio and process the recording.
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)carAudioRecord.startRecording()valdata=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()
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());carAudioRecord.startRecording();byte[]data=newbyte[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();
Audio focus
When recording from the car microphone, first acquire audio focus to ensure that any ongoing media is stopped. If you lose audio focus, stop recording.
Here is an example of how to acquire audio focus:
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)// Take audio focus so that user's media is not recordedvalaudioAttributes=AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build()valaudioFocusRequest=AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener{state:Int->
if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording()}}.build()if(carContext.getSystemService(AudioManager::class.java).requestAudioFocus(audioFocusRequest)!=AudioManager.AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn}carAudioRecord.startRecording()// Process the audio and abandon the AudioFocusRequest when done
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());// Take audio focus so that user's media is not recordedAudioAttributesaudioAttributes=newAudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build();AudioFocusRequestaudioFocusRequest=newAudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener(state->{if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording();}}).build();if(getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)!=AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn;}carAudioRecord.startRecording();// Process the audio and abandon the AudioFocusRequest when done
Testing Library
The Android for Cars Testing Library provides auxiliary classes that you can use to validate your app's behavior in a test environment. For example, the SessionController lets you simulate a connection to the host and verify that the correct Screen and Template are created and returned.
If you find an issue with the library, report it using the Google Issue Tracker . Be sure to fill out all the requested information in the issue template.
Before filing a new issue, please check whether it is listed in the library's release notes or reported in the issues list. You can subscribe and vote for issues by clicking the star for an issue in the tracker. For more information, see Subscribing to an Issue .
The user interface is represented by a graph of model objects that can be arranged together in different ways, as allowed by the template they belong to. Templates are a subset of the models that can act as a root in those graphs. Models include the information to be displayed to the user in the form of text and images as well as attributes to configure aspects of the visual appearance of such information—for example, text colors or image sizes. The host converts the models to views that are designed to meet driver distraction standards and takes care of details like the variety of car screen factors and input modalities.
میزبان
The host is the backend component that implements the functionality offered by the library's APIs so your app can run in the car. The responsibilities of the host range from discovering your app and managing its lifecycle to converting your models into views and notifying your app of user interactions. On mobile devices, this host is implemented by Android Auto. On Android Automotive OS, this host is installed as a system app.
Template restrictions
Different templates enforce restrictions in the content of their models. For example, list templates have limits on the number of items that can be presented to the user. Templates also have restrictions in the way they can be connected to form the flow of a task. For example, the app can only push up to five templates to the screen stack. See Template restrictions for more details.
Screen
Screen is a class provided by the library that apps implement to manage the user interface presented to the user. A Screen has a lifecycle and provides the mechanism for the app to send the template to display when the screen is visible. Screen instances can also be pushed and popped to and from a Screen stack , which ensures they adhere to the template flow restrictions .
CarAppService
CarAppService is an abstract Service class that your app must implement and export to be discovered and managed by the host. Your app's CarAppService is responsible for validating that a host connection can be trusted using createHostValidator and subsequently providing Session instances for each connection using onCreateSession .
Session
Session is an abstract class that your app must implement and return using CarAppService.onCreateSession . It serves as the entry point to display information on the car screen. It has a lifecycle that informs the current state of your app on the car screen, such as when your app is visible or hidden.
When a Session is started, such as when the app is first launched, the host requests for the initial Screen to display using the onCreateScreen method.
Install the Car App Library
See the Jetpack library release page for instructions on how to add the library to your app.
Configure your app's manifest files
Before you can create your car app, configure your app's manifest files as follows.
Declare your CarAppService
The host connects to your app through your CarAppService implementation. You declare this service in your manifest to let the host discover and connect to your app.
You also need to declare your app's category in the <category> element of your app's intent filter. See the list of supported app categories for the values allowed for this element.
The following code snippet shows how to declare a car app service for a point of interest app in your manifest:
Declare your app's category by adding one or more of the following category values in the intent filter when you declare your CarAppService as described in the preceding section :
androidx.car.app.category.NAVIGATION : an app that provides turn-by-turn navigation directions. See Build navigation apps for cars .
androidx.car.app.category.POI : an app that provides functionality relevant to finding points of interest such as parking spots, charging stations, and gas stations. See Build point of interest apps for cars .
androidx.car.app.category.IOT : an app that enables users to take relevant actions on connected devices from within the car. See Build internet of things apps for cars .
androidx.car.app.category.WEATHER : an app that lets users see relevant weather information related to their current location or along their route. See Build weather apps for cars .
See Android app quality for cars for detailed descriptions of each category and criteria for apps to belong to them.
Specify the app name and icon
You need to specify an app name and icon that the host can use to represent your app in the system UI.
You can specify the app name and icon that is used to represent your app using the label and icon attributes of your CarAppService :
The Car App Library defines its own API levels so that you can know which library features are supported by the template host on a vehicle. To retrieve the highest Car App API Level supported by a host, use the getCarAppApiLevel() method.
Declare the minimum Car App API Level supported by your app in your AndroidManifest.xml file:
See the documentation for the RequiresCarApi annotation for details on how to maintain backward compatibility and declare the minimum API level required to use a feature. For a definition of which API level is required to use a certain feature of the Car App Library, check the reference documentation for CarAppApiLevels .
Create your CarAppService and Session
Your app needs to extend the CarAppService class and implement its onCreateSession method, which returns a Session instance corresponding to the current connection to the host:
To handle scenarios where your car app needs to start from a screen that is not the home or landing screen of your app, such as handling deep links, you can pre-seed a back stack of screens using ScreenManager.push before returning from onCreateScreen . Pre-seeding allows users to navigate back to previous screens from the first screen that your app is showing.
Create your start screen
You create the screens displayed by your app by defining classes that extend the Screen class and implementing its onGetTemplate method, which returns the Template instance representing the state of the UI to display in the car screen.
The following snippet shows how to declare a Screen that uses a PaneTemplate template to display a simple “Hello world!” string:
CarContext also offers other functionality, such as letting you load drawable resources using the configuration from the car screen, starting an app in the car using intents, and signaling whether your app should display its map in dark theme .
Implement screen navigation
Apps often present a number of different screens, each possibly using different templates the user can navigate through as they interact with the interface displayed in the screen.
The ScreenManager class provides a screen stack you can use to push screens that can be popped automatically when the user selects a back button in the car screen or uses the hardware back button available in some cars.
The following snippet shows how to add a back action to a message template as well as an action that pushes a new screen when selected by the user:
To help ensure the app is safe to use while driving, the screen stack can have a maximum depth of five screens. See the Template restrictions section for more details.
Refresh the contents of a template
Your app can request the content of a Screen to be invalidated by calling the Screen.invalidate method. The host subsequently calls back into your app's Screen.onGetTemplate method to retrieve the template with the new contents.
When refreshing a Screen , it is important to understand the specific content in the template that can be updated so the host does not count the new template against the template quota. See the Template restrictions section for more details.
We recommended that you structure your screens so there is a one-to-one mapping between a Screen and the type of template it returns through its onGetTemplate implementation.
Draw maps
Navigation, point of interest (POI), and weather apps using the following templates can draw maps by accessing a Surface .
To use the following templates, your app must have one of the corresponding permissions declared in a <uses-permission> element in its AndroidManifest.xml file.
In addition to the permission required for the template that you app is using, your app must declare the androidx.car.app.ACCESS_SURFACE permission in its AndroidManifest.xml file to get access to the surface:
To access the Surface that the host provides, you must implement a SurfaceCallback and provide that implementation to the AppManager car service. The current Surface is passed to your SurfaceCallback in the SurfaceContainer parameter of the onSurfaceAvailable() and onSurfaceDestroyed() callbacks.
The host can draw user interface elements for the templates on top of the map. The host communicates the area of the surface that is guaranteed to be unobstructed and fully visible to the user by calling the SurfaceCallback.onVisibleAreaChanged method. Also, to minimize the number of changes, the host calls the SurfaceCallback.onStableAreaChanged method with the smallest rectangle, which is always visible based on the current template.
For example, when a navigation app uses the NavigationTemplate with an action strip on top, the action strip can hide itself when the user has not interacted with the screen for a while to make more space for the map. In this case, there is a callback to onStableAreaChanged and onVisibleAreaChanged with the same rectangle. When the action strip is hidden, only onVisibleAreaChanged is called with the larger area. If the user interacts with the screen, then again only onVisibleAreaChanged is called with the first rectangle.
Support dark theme
Apps must redraw their map onto the Surface instance with the proper dark colors when the host determines conditions warrant it, as described in Android app quality for cars .
When using the following templates, you can add support for users to interact with the maps you draw, such as letting them see different parts of a map by zooming and panning.
الگو
Interactivity supported since Car App API Level
NavigationTemplate
2
PlaceListNavigationTemplate ( deprecated )
4
RoutePreviewNavigationTemplate ( deprecated )
4
MapTemplate ( deprecated )
5 (introduction of template)
MapWithContentTemplate
7 (introduction of template)
Implement interactivity callbacks
The SurfaceCallback interface has several callback methods you can implement to add interactivity to maps built with the templates in the preceding section:
onScale (with scale factor determined by template host)
2
Rotary nudge in pan mode
onScroll (with distance factor determined by template host)
2
Add a map action strip
These templates can have a map action strip for map-related actions such as zooming in and out, recentering, displaying a compass, and other actions you choose to display. The map action strip can have up to four icon-only buttons that can be refreshed without impacting task depth. It hides during idle state and reappears on active state.
To receive map interactivity callbacks , you must add an Action.PAN button in the map action strip. When the user presses the pan button, the host enters pan mode, as described in the following section.
If your app omits the Action.PAN button in the map action strip, it doesn't receive user input from the SurfaceCallback methods, and the host exits any previously activated pan mode.
On a touchscreen, the pan button is not displayed.
Understand pan mode
In pan mode, the template host translates user input from non-touch input devices, such as rotary controllers and touchpads, into the appropriate SurfaceCallback methods. Respond to the user action to enter or exit pan mode with the setPanModeListener method in the NavigationTemplate.Builder . The host can hide other UI components in the template while the user is in pan mode.
Interact with the user
Your app can interact with the user using patterns similar to a mobile app.
Handle user input
Your app can respond to user input by passing the appropriate listeners to the models that support them. The following snippet shows how to create an Action model that sets an OnClickListener that calls back to a method defined by your app's code:
For more details on how to start apps, including the format of the ACTION_NAVIGATE intent, see the Start a car app with an intent section.
Some actions, such as those that require directing the user to continue the interaction on their mobile devices, are only allowed when the car is parked. You can use the ParkedOnlyOnClickListener to implement those actions. If the car is not parked, the host displays an indication to the user that the action is not allowed in this case. If the car is parked, the code executes normally. The following snippet shows how to use the ParkedOnlyOnClickListener to open a settings screen on the mobile device:
Notifications sent to the mobile device only show up on the car screen if they are extended with a CarAppExtender . Some notification attributes, such as content title, text, icon, and actions, can be set in the CarAppExtender , overriding the notification's attributes when they appear on the car screen.
The following snippet shows how to send a notification to the car screen that displays a different title than the one shown on the mobile device:
Notifications can affect the following parts of the user interface:
A heads-up notification (HUN) may be displayed to the user.
An entry in the notification center may be added, optionally with a badge visible in the rail.
For navigation apps, the notification may be displayed in the rail widget as described in Turn-by-turn notifications .
You can choose how to configure your app's notifications to affect each of those user interface elements by using the notification's priority, as described in the CarAppExtender documentation.
The benefit of using CarContext.requestPermissions() , as opposed to using standard Android APIs , is that you don't need to launch your own Activity to create the permissions dialog. Moreover, you can use the same code on both Android Auto and Android Automotive OS, rather than having to create platform-dependent flows.
Style the permissions dialog on Android Auto
On Android Auto, the permissions dialog for the user will appear on the phone. By default, there will be no background behind the dialog. To set a custom background, declare a car app theme in your AndroidManifest.xml file and set the carPermissionActivityLayout attribute for your car app theme.
The following example shows how to create a notification with an action that opens your app with a screen that shows the details of a parking reservation. You extend the notification instance with a content intent that contains a PendingIntent wrapping an explicit intent to your app's action:
Your app must also declare a BroadcastReceiver that is invoked to process the intent when the user selects the action in the notification interface and invokes CarContext.startCarApp with an intent including the data URI:
Finally, the Session.onNewIntent method in your app handles this intent by pushing the parking reservation screen on the stack, if it's not already on top:
See the Display notifications section for more information on how to handle notifications for the car app.
Template restrictions
The host limits the number of templates to display for a given task to a maximum of five, of which the last template must be one of the following types:
Note that this limit applies to the number of templates and not the number of Screen instances in the stack. For example, if an app sends two templates while in screen A and then pushes screen B, it can now send three more templates. Alternatively, if each screen is structured to send a single template, then the app can push five screen instances onto the ScreenManager stack.
There are special cases to these restrictions: template refreshes and back and reset operations.
Template refreshes
Certain content updates are not counted toward the template limit. In general, if an app pushes a new template that is of the same type and contains the same main content as the previous template, the new template is not counted against the quota. For example, updating the toggle state of a row in a ListTemplate does not count against the quota. See the documentation of individual templates to learn more about what types of content updates can be considered a refresh.
Back operations
To enable sub-flows within a task, the host detects when an app is popping a Screen from the ScreenManager stack and updates the remaining quota based on the number of templates that the app is going backward by.
For example, if the app sends two templates while in screen A, then pushes screen B and sends two more templates, the app has one quota remaining. If the app then pops back to screen A, the host resets the quota to three, because the app has gone backward by two templates.
Note that, when popping back to a screen, an app must send a template that is of the same type as the one last sent by that screen. Sending any other template type causes an error. However, as long as the type remains the same during a back operation, an app can freely modify the contents of the template without affecting the quota.
Reset operations
Certain templates have special semantics that signify the end of a task. For example, the NavigationTemplate is a view that is expected to stay on the screen and be refreshed with new turn-by-turn instructions for the user's consumption. When it reaches one of these templates, the host resets the template quota, treating that template as if it is the first step of a new task. This allows the app to begin a new task. See the documentation of individual templates to see which ones trigger a reset on the host.
If the host receives an intent to start the app from a notification action or from the launcher, the quota is also reset. This mechanism lets an app begin a new task flow from notifications, and it holds true even if an app is already bound and in the foreground.
See the Display notifications section for more details on how to display your app's notifications in the car screen. See the Start a car app with an intent section for information on how to start your app from a notification action.
Connection API
You can determine whether your app is running on Android Auto or Android Automotive OS by using the CarConnection API to retrieve connection information at runtime.
For example, in your car app's Session , initialize a CarConnection and subscribe to LiveData updates:
In the observer, you can then react to changes in the connection state:
کاتلین
funonConnectionStateUpdated(connectionState:Int){valmessage=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()}
جاوا
privatevoidonConnectionStateUpdated(intconnectionState){Stringmessage;switch(connectionState){caseCarConnection.CONNECTION_TYPE_NOT_CONNECTED:message="Not connected to a head unit";break;caseCarConnection.CONNECTION_TYPE_NATIVE:message="Connected to Android Automotive OS";break;caseCarConnection.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 API
Different cars may allow for a different number of Item instances to be displayed to the user at a time. Use the ConstraintManager to check the content limit at runtime and set the appropriate number of items in your templates.
Start by getting a ConstraintManager from the CarContext :
You can then query the retrieved ConstraintManager object for the relevant content limit. For example, to get the number of items that can be displayed in a grid, call getContentLimit with CONTENT_LIMIT_TYPE_GRID :
If your app offers a signed-in experience for users, you can use templates like the SignInTemplate and LongMessageTemplate with Car App API level 2 and above to handle signing in to your app on the car's head unit.
To create a SignInTemplate , define a SignInMethod . The Car App Library currently supports the following sign-in methods:
QRCodeSignInMethod for QR code sign in, where the user scans a QR code to complete sign-in on their phone. This is available with Car API Level 4 and above.
For example, to implement a template that collects the user's password, start by creating an InputCallback to process and validate user input:
کاتلین
valcallback=object:InputCallback{overridefunonInputSubmitted(text:String){// You will receive this callback when the user presses Enter on the keyboard.}overridefunonInputTextChanged(text:String){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}}
جاوا
InputCallbackcallback=newInputCallback(){@OverridepublicvoidonInputSubmitted(@NonNullStringtext){// You will receive this callback when the user presses Enter on the keyboard.}@OverridepublicvoidonInputTextChanged(@NonNullStringtext){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}};
An InputCallback is required for the InputSignInMethodBuilder .
Finally, use your new InputSignInMethod to create a SignInTemplate .
کاتلین
SignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build()
جاوا
newSignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build();
Use AccountManager
Android Automotive OS apps that have authentication must use AccountManager for the following reasons:
Better UX and ease of account management : Users can easily manage all their accounts from the accounts menu in the system settings, including sign-in and sign-out.
"Guest" experiences : Because cars are shared devices, OEMs can enable guest experiences in the vehicle, where accounts cannot be added.
Add text string variants
Different car screen sizes may show different amounts of text. With Car App API level 2 and above, you can specify multiple variants of a text string to best fit the screen. To see where text variants are accepted, look for templates and components that take a CarText .
Add strings in order from most to least preferred—for example, from longest to shortest. The host picks the appropriate-length string depending on the amount of space available on the car screen.
Add inline CarIcons for rows
You can add icons inline with text to enrich your app's visual appeal using CarIconSpan . See the documentation for CarIconSpan.create for more information on creating these spans. See Spantastic text styling with Spans for an overview of how text styling with spans work.
کاتلین
valrating=SpannableString("Rating: 4.5 stars")rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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)valrow=Row.Builder()....addText(rating).build()
جاوا
SpannableStringrating=newSpannableString("Rating: 4.5 stars");rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsnewCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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);Rowrow=newRow.Builder()....addText(rating).build();
Car Hardware APIs
Starting with Car App API level 3, the Car App Library has APIs that you can use to access vehicle properties and sensors.
الزامات
To use the APIs with Android Auto, start by adding a dependency on androidx.car.app:app-projected to the build.gradle file for your Android Auto module. For Android Automotive OS, add a dependency on androidx.car.app:app-automotive to the build.gradle file for your Android Automotive OS module.
Additionally, in your AndroidManifest.xml file, you need to declare the relevant permissions needed to request the car data you want to use. Note that these permissions must also be granted to you by the user. You can use the same code on both Android Auto and Android Automotive OS, rather than having to create platform-dependent flows. However, the permissions needed are different.
CarInfo
This table describes the properties surfaced by the CarInfo APIs and the permissions you need to request to use them:
Warning: the getOdometerMeters method of the Mileage class is inaccurately named and returns kilometers, not meters.
Odometer distance
com.google.android.gms.permission.CAR_MILEAGE
This data is not available on Android Automotive OS to apps installed from the Play Store.
3
For example, to get the remaining range, instantiate a CarInfo object, then create and register an OnCarDataAvailableListener :
کاتلین
valcarInfo=carContext.getCarService(CarHardwareManager::class.java).carInfovallistener=OnCarDataAvailableListener<EnergyLevel>{data->
if(data.rangeRemainingMeters.status==CarValue.STATUS_SUCCESS){valrangeRemaining=data.rangeRemainingMeters.value}else{// Handle error}}carInfo.addEnergyLevelListener(carContext.mainExecutor,listener)…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener)
جاوا
CarInfocarInfo=getCarContext().getCarService(CarHardwareManager.class).getCarInfo();OnCarDataAvailableListener<EnergyLevel>listener=(data)->{if(data.getRangeRemainingMeters().getStatus()==CarValue.STATUS_SUCCESS){floatrangeRemaining=data.getRangeRemainingMeters().getValue();}else{// Handle error}};carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(),listener);…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener);
Don't assume that the data from the car is available at all times. If you get an error, check the status of the value you requested to better understand why the data you requested could not be retrieved. Refer to the reference documentation for the full CarInfo class definition.
CarSensors
The CarSensors class gives you access to the vehicle's accelerometer, gyroscope, compass, and location data. The availability of these values may depend on the OEM. The format for the data from the accelerometer, gyroscope, and compass is the same as you would get from the SensorManager API . For example, to check the vehicle's heading:
کاتلین
valcarSensors=carContext.getCarService(CarHardwareManager::class.java).carSensorsvallistener=OnCarDataAvailableListener<Compass>{data->
if(data.orientations.status==CarValue.STATUS_SUCCESS){valorientation=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 updatescarSensors.removeCompassListener(listener)
جاوا
CarSensorscarSensors=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 updatescarSensors.removeCompassListener(listener);
To access location data from the car, you also need to declare and request the android.permission.ACCESS_FINE_LOCATION permission.
تست کردن
To simulate sensor data when testing on Android Auto, refer to the Sensors and Sensor configuration sections of the Desktop Head Unit guide. To simulate sensor data when testing on Android Automotive OS, refer to the Emulate hardware state section of the Android Automotive OS emulator guide.
The CarAppService, Session and Screen lifecycles
The Session and Screen classes implement the LifecycleOwner interface. As the user interacts with the app, your Session and Screen objects' lifecycle callbacks are invoked, as described in the following diagrams.
Using your app's CarAppService and the CarAudioRecord API, you can give your app access to the user's car microphone. Users need to give your app permission to access the car microphone. Your app can record and process the user's input within your app.
Permission to record
Before recording any audio, you must first declare the permission to record in your AndroidManifest.xml and request that the user grant it.
You need to request the permission to record at runtime. See the Request permissions section for details on how to request a permission in your car app.
ضبط صدا
After the user gives permission to record, you can record the audio and process the recording.
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)carAudioRecord.startRecording()valdata=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()
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());carAudioRecord.startRecording();byte[]data=newbyte[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();
Audio focus
When recording from the car microphone, first acquire audio focus to ensure that any ongoing media is stopped. If you lose audio focus, stop recording.
Here is an example of how to acquire audio focus:
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)// Take audio focus so that user's media is not recordedvalaudioAttributes=AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build()valaudioFocusRequest=AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener{state:Int->
if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording()}}.build()if(carContext.getSystemService(AudioManager::class.java).requestAudioFocus(audioFocusRequest)!=AudioManager.AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn}carAudioRecord.startRecording()// Process the audio and abandon the AudioFocusRequest when done
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());// Take audio focus so that user's media is not recordedAudioAttributesaudioAttributes=newAudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build();AudioFocusRequestaudioFocusRequest=newAudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener(state->{if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording();}}).build();if(getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)!=AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn;}carAudioRecord.startRecording();// Process the audio and abandon the AudioFocusRequest when done
Testing Library
The Android for Cars Testing Library provides auxiliary classes that you can use to validate your app's behavior in a test environment. For example, the SessionController lets you simulate a connection to the host and verify that the correct Screen and Template are created and returned.
If you find an issue with the library, report it using the Google Issue Tracker . Be sure to fill out all the requested information in the issue template.
Before filing a new issue, please check whether it is listed in the library's release notes or reported in the issues list. You can subscribe and vote for issues by clicking the star for an issue in the tracker. For more information, see Subscribing to an Issue .
The user interface is represented by a graph of model objects that can be arranged together in different ways, as allowed by the template they belong to. Templates are a subset of the models that can act as a root in those graphs. Models include the information to be displayed to the user in the form of text and images as well as attributes to configure aspects of the visual appearance of such information—for example, text colors or image sizes. The host converts the models to views that are designed to meet driver distraction standards and takes care of details like the variety of car screen factors and input modalities.
میزبان
The host is the backend component that implements the functionality offered by the library's APIs so your app can run in the car. The responsibilities of the host range from discovering your app and managing its lifecycle to converting your models into views and notifying your app of user interactions. On mobile devices, this host is implemented by Android Auto. On Android Automotive OS, this host is installed as a system app.
Template restrictions
Different templates enforce restrictions in the content of their models. For example, list templates have limits on the number of items that can be presented to the user. Templates also have restrictions in the way they can be connected to form the flow of a task. For example, the app can only push up to five templates to the screen stack. See Template restrictions for more details.
Screen
Screen is a class provided by the library that apps implement to manage the user interface presented to the user. A Screen has a lifecycle and provides the mechanism for the app to send the template to display when the screen is visible. Screen instances can also be pushed and popped to and from a Screen stack , which ensures they adhere to the template flow restrictions .
CarAppService
CarAppService is an abstract Service class that your app must implement and export to be discovered and managed by the host. Your app's CarAppService is responsible for validating that a host connection can be trusted using createHostValidator and subsequently providing Session instances for each connection using onCreateSession .
Session
Session is an abstract class that your app must implement and return using CarAppService.onCreateSession . It serves as the entry point to display information on the car screen. It has a lifecycle that informs the current state of your app on the car screen, such as when your app is visible or hidden.
When a Session is started, such as when the app is first launched, the host requests for the initial Screen to display using the onCreateScreen method.
Install the Car App Library
See the Jetpack library release page for instructions on how to add the library to your app.
Configure your app's manifest files
Before you can create your car app, configure your app's manifest files as follows.
Declare your CarAppService
The host connects to your app through your CarAppService implementation. You declare this service in your manifest to let the host discover and connect to your app.
You also need to declare your app's category in the <category> element of your app's intent filter. See the list of supported app categories for the values allowed for this element.
The following code snippet shows how to declare a car app service for a point of interest app in your manifest:
Declare your app's category by adding one or more of the following category values in the intent filter when you declare your CarAppService as described in the preceding section :
androidx.car.app.category.NAVIGATION : an app that provides turn-by-turn navigation directions. See Build navigation apps for cars .
androidx.car.app.category.POI : an app that provides functionality relevant to finding points of interest such as parking spots, charging stations, and gas stations. See Build point of interest apps for cars .
androidx.car.app.category.IOT : an app that enables users to take relevant actions on connected devices from within the car. See Build internet of things apps for cars .
androidx.car.app.category.WEATHER : an app that lets users see relevant weather information related to their current location or along their route. See Build weather apps for cars .
See Android app quality for cars for detailed descriptions of each category and criteria for apps to belong to them.
Specify the app name and icon
You need to specify an app name and icon that the host can use to represent your app in the system UI.
You can specify the app name and icon that is used to represent your app using the label and icon attributes of your CarAppService :
The Car App Library defines its own API levels so that you can know which library features are supported by the template host on a vehicle. To retrieve the highest Car App API Level supported by a host, use the getCarAppApiLevel() method.
Declare the minimum Car App API Level supported by your app in your AndroidManifest.xml file:
See the documentation for the RequiresCarApi annotation for details on how to maintain backward compatibility and declare the minimum API level required to use a feature. For a definition of which API level is required to use a certain feature of the Car App Library, check the reference documentation for CarAppApiLevels .
Create your CarAppService and Session
Your app needs to extend the CarAppService class and implement its onCreateSession method, which returns a Session instance corresponding to the current connection to the host:
To handle scenarios where your car app needs to start from a screen that is not the home or landing screen of your app, such as handling deep links, you can pre-seed a back stack of screens using ScreenManager.push before returning from onCreateScreen . Pre-seeding allows users to navigate back to previous screens from the first screen that your app is showing.
Create your start screen
You create the screens displayed by your app by defining classes that extend the Screen class and implementing its onGetTemplate method, which returns the Template instance representing the state of the UI to display in the car screen.
The following snippet shows how to declare a Screen that uses a PaneTemplate template to display a simple “Hello world!” string:
CarContext also offers other functionality, such as letting you load drawable resources using the configuration from the car screen, starting an app in the car using intents, and signaling whether your app should display its map in dark theme .
Implement screen navigation
Apps often present a number of different screens, each possibly using different templates the user can navigate through as they interact with the interface displayed in the screen.
The ScreenManager class provides a screen stack you can use to push screens that can be popped automatically when the user selects a back button in the car screen or uses the hardware back button available in some cars.
The following snippet shows how to add a back action to a message template as well as an action that pushes a new screen when selected by the user:
To help ensure the app is safe to use while driving, the screen stack can have a maximum depth of five screens. See the Template restrictions section for more details.
Refresh the contents of a template
Your app can request the content of a Screen to be invalidated by calling the Screen.invalidate method. The host subsequently calls back into your app's Screen.onGetTemplate method to retrieve the template with the new contents.
When refreshing a Screen , it is important to understand the specific content in the template that can be updated so the host does not count the new template against the template quota. See the Template restrictions section for more details.
We recommended that you structure your screens so there is a one-to-one mapping between a Screen and the type of template it returns through its onGetTemplate implementation.
Draw maps
Navigation, point of interest (POI), and weather apps using the following templates can draw maps by accessing a Surface .
To use the following templates, your app must have one of the corresponding permissions declared in a <uses-permission> element in its AndroidManifest.xml file.
In addition to the permission required for the template that you app is using, your app must declare the androidx.car.app.ACCESS_SURFACE permission in its AndroidManifest.xml file to get access to the surface:
To access the Surface that the host provides, you must implement a SurfaceCallback and provide that implementation to the AppManager car service. The current Surface is passed to your SurfaceCallback in the SurfaceContainer parameter of the onSurfaceAvailable() and onSurfaceDestroyed() callbacks.
The host can draw user interface elements for the templates on top of the map. The host communicates the area of the surface that is guaranteed to be unobstructed and fully visible to the user by calling the SurfaceCallback.onVisibleAreaChanged method. Also, to minimize the number of changes, the host calls the SurfaceCallback.onStableAreaChanged method with the smallest rectangle, which is always visible based on the current template.
For example, when a navigation app uses the NavigationTemplate with an action strip on top, the action strip can hide itself when the user has not interacted with the screen for a while to make more space for the map. In this case, there is a callback to onStableAreaChanged and onVisibleAreaChanged with the same rectangle. When the action strip is hidden, only onVisibleAreaChanged is called with the larger area. If the user interacts with the screen, then again only onVisibleAreaChanged is called with the first rectangle.
Support dark theme
Apps must redraw their map onto the Surface instance with the proper dark colors when the host determines conditions warrant it, as described in Android app quality for cars .
When using the following templates, you can add support for users to interact with the maps you draw, such as letting them see different parts of a map by zooming and panning.
الگو
Interactivity supported since Car App API Level
NavigationTemplate
2
PlaceListNavigationTemplate ( deprecated )
4
RoutePreviewNavigationTemplate ( deprecated )
4
MapTemplate ( deprecated )
5 (introduction of template)
MapWithContentTemplate
7 (introduction of template)
Implement interactivity callbacks
The SurfaceCallback interface has several callback methods you can implement to add interactivity to maps built with the templates in the preceding section:
onScale (with scale factor determined by template host)
2
Rotary nudge in pan mode
onScroll (with distance factor determined by template host)
2
Add a map action strip
These templates can have a map action strip for map-related actions such as zooming in and out, recentering, displaying a compass, and other actions you choose to display. The map action strip can have up to four icon-only buttons that can be refreshed without impacting task depth. It hides during idle state and reappears on active state.
To receive map interactivity callbacks , you must add an Action.PAN button in the map action strip. When the user presses the pan button, the host enters pan mode, as described in the following section.
If your app omits the Action.PAN button in the map action strip, it doesn't receive user input from the SurfaceCallback methods, and the host exits any previously activated pan mode.
On a touchscreen, the pan button is not displayed.
Understand pan mode
In pan mode, the template host translates user input from non-touch input devices, such as rotary controllers and touchpads, into the appropriate SurfaceCallback methods. Respond to the user action to enter or exit pan mode with the setPanModeListener method in the NavigationTemplate.Builder . The host can hide other UI components in the template while the user is in pan mode.
Interact with the user
Your app can interact with the user using patterns similar to a mobile app.
Handle user input
Your app can respond to user input by passing the appropriate listeners to the models that support them. The following snippet shows how to create an Action model that sets an OnClickListener that calls back to a method defined by your app's code:
For more details on how to start apps, including the format of the ACTION_NAVIGATE intent, see the Start a car app with an intent section.
Some actions, such as those that require directing the user to continue the interaction on their mobile devices, are only allowed when the car is parked. You can use the ParkedOnlyOnClickListener to implement those actions. If the car is not parked, the host displays an indication to the user that the action is not allowed in this case. If the car is parked, the code executes normally. The following snippet shows how to use the ParkedOnlyOnClickListener to open a settings screen on the mobile device:
Notifications sent to the mobile device only show up on the car screen if they are extended with a CarAppExtender . Some notification attributes, such as content title, text, icon, and actions, can be set in the CarAppExtender , overriding the notification's attributes when they appear on the car screen.
The following snippet shows how to send a notification to the car screen that displays a different title than the one shown on the mobile device:
Notifications can affect the following parts of the user interface:
A heads-up notification (HUN) may be displayed to the user.
An entry in the notification center may be added, optionally with a badge visible in the rail.
For navigation apps, the notification may be displayed in the rail widget as described in Turn-by-turn notifications .
You can choose how to configure your app's notifications to affect each of those user interface elements by using the notification's priority, as described in the CarAppExtender documentation.
The benefit of using CarContext.requestPermissions() , as opposed to using standard Android APIs , is that you don't need to launch your own Activity to create the permissions dialog. Moreover, you can use the same code on both Android Auto and Android Automotive OS, rather than having to create platform-dependent flows.
Style the permissions dialog on Android Auto
On Android Auto, the permissions dialog for the user will appear on the phone. By default, there will be no background behind the dialog. To set a custom background, declare a car app theme in your AndroidManifest.xml file and set the carPermissionActivityLayout attribute for your car app theme.
The following example shows how to create a notification with an action that opens your app with a screen that shows the details of a parking reservation. You extend the notification instance with a content intent that contains a PendingIntent wrapping an explicit intent to your app's action:
Your app must also declare a BroadcastReceiver that is invoked to process the intent when the user selects the action in the notification interface and invokes CarContext.startCarApp with an intent including the data URI:
Finally, the Session.onNewIntent method in your app handles this intent by pushing the parking reservation screen on the stack, if it's not already on top:
See the Display notifications section for more information on how to handle notifications for the car app.
Template restrictions
The host limits the number of templates to display for a given task to a maximum of five, of which the last template must be one of the following types:
Note that this limit applies to the number of templates and not the number of Screen instances in the stack. For example, if an app sends two templates while in screen A and then pushes screen B, it can now send three more templates. Alternatively, if each screen is structured to send a single template, then the app can push five screen instances onto the ScreenManager stack.
There are special cases to these restrictions: template refreshes and back and reset operations.
Template refreshes
Certain content updates are not counted toward the template limit. In general, if an app pushes a new template that is of the same type and contains the same main content as the previous template, the new template is not counted against the quota. For example, updating the toggle state of a row in a ListTemplate does not count against the quota. See the documentation of individual templates to learn more about what types of content updates can be considered a refresh.
Back operations
To enable sub-flows within a task, the host detects when an app is popping a Screen from the ScreenManager stack and updates the remaining quota based on the number of templates that the app is going backward by.
For example, if the app sends two templates while in screen A, then pushes screen B and sends two more templates, the app has one quota remaining. If the app then pops back to screen A, the host resets the quota to three, because the app has gone backward by two templates.
Note that, when popping back to a screen, an app must send a template that is of the same type as the one last sent by that screen. Sending any other template type causes an error. However, as long as the type remains the same during a back operation, an app can freely modify the contents of the template without affecting the quota.
Reset operations
Certain templates have special semantics that signify the end of a task. For example, the NavigationTemplate is a view that is expected to stay on the screen and be refreshed with new turn-by-turn instructions for the user's consumption. When it reaches one of these templates, the host resets the template quota, treating that template as if it is the first step of a new task. This allows the app to begin a new task. See the documentation of individual templates to see which ones trigger a reset on the host.
If the host receives an intent to start the app from a notification action or from the launcher, the quota is also reset. This mechanism lets an app begin a new task flow from notifications, and it holds true even if an app is already bound and in the foreground.
See the Display notifications section for more details on how to display your app's notifications in the car screen. See the Start a car app with an intent section for information on how to start your app from a notification action.
Connection API
You can determine whether your app is running on Android Auto or Android Automotive OS by using the CarConnection API to retrieve connection information at runtime.
For example, in your car app's Session , initialize a CarConnection and subscribe to LiveData updates:
In the observer, you can then react to changes in the connection state:
کاتلین
funonConnectionStateUpdated(connectionState:Int){valmessage=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()}
جاوا
privatevoidonConnectionStateUpdated(intconnectionState){Stringmessage;switch(connectionState){caseCarConnection.CONNECTION_TYPE_NOT_CONNECTED:message="Not connected to a head unit";break;caseCarConnection.CONNECTION_TYPE_NATIVE:message="Connected to Android Automotive OS";break;caseCarConnection.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 API
Different cars may allow for a different number of Item instances to be displayed to the user at a time. Use the ConstraintManager to check the content limit at runtime and set the appropriate number of items in your templates.
Start by getting a ConstraintManager from the CarContext :
You can then query the retrieved ConstraintManager object for the relevant content limit. For example, to get the number of items that can be displayed in a grid, call getContentLimit with CONTENT_LIMIT_TYPE_GRID :
If your app offers a signed-in experience for users, you can use templates like the SignInTemplate and LongMessageTemplate with Car App API level 2 and above to handle signing in to your app on the car's head unit.
To create a SignInTemplate , define a SignInMethod . The Car App Library currently supports the following sign-in methods:
QRCodeSignInMethod for QR code sign in, where the user scans a QR code to complete sign-in on their phone. This is available with Car API Level 4 and above.
For example, to implement a template that collects the user's password, start by creating an InputCallback to process and validate user input:
کاتلین
valcallback=object:InputCallback{overridefunonInputSubmitted(text:String){// You will receive this callback when the user presses Enter on the keyboard.}overridefunonInputTextChanged(text:String){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}}
جاوا
InputCallbackcallback=newInputCallback(){@OverridepublicvoidonInputSubmitted(@NonNullStringtext){// You will receive this callback when the user presses Enter on the keyboard.}@OverridepublicvoidonInputTextChanged(@NonNullStringtext){// You will receive this callback as the user is typing. The update// frequency is determined by the host.}};
An InputCallback is required for the InputSignInMethodBuilder .
Finally, use your new InputSignInMethod to create a SignInTemplate .
کاتلین
SignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build()
جاوا
newSignInTemplate.Builder(passwordInput).setTitle("Sign in with username and password").setInstructions("Enter your password").setHeaderAction(Action.BACK)....build();
Use AccountManager
Android Automotive OS apps that have authentication must use AccountManager for the following reasons:
Better UX and ease of account management : Users can easily manage all their accounts from the accounts menu in the system settings, including sign-in and sign-out.
"Guest" experiences : Because cars are shared devices, OEMs can enable guest experiences in the vehicle, where accounts cannot be added.
Add text string variants
Different car screen sizes may show different amounts of text. With Car App API level 2 and above, you can specify multiple variants of a text string to best fit the screen. To see where text variants are accepted, look for templates and components that take a CarText .
Add strings in order from most to least preferred—for example, from longest to shortest. The host picks the appropriate-length string depending on the amount of space available on the car screen.
Add inline CarIcons for rows
You can add icons inline with text to enrich your app's visual appeal using CarIconSpan . See the documentation for CarIconSpan.create for more information on creating these spans. See Spantastic text styling with Spans for an overview of how text styling with spans work.
کاتلین
valrating=SpannableString("Rating: 4.5 stars")rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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)valrow=Row.Builder()....addText(rating).build()
جاوا
SpannableStringrating=newSpannableString("Rating: 4.5 stars");rating.setSpan(CarIconSpan.create(// Create a CarIcon with an image of four and a half starsnewCarIcon.Builder(...).build(),// Align the CarIcon to the baseline of the textCarIconSpan.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);Rowrow=newRow.Builder()....addText(rating).build();
Car Hardware APIs
Starting with Car App API level 3, the Car App Library has APIs that you can use to access vehicle properties and sensors.
الزامات
To use the APIs with Android Auto, start by adding a dependency on androidx.car.app:app-projected to the build.gradle file for your Android Auto module. For Android Automotive OS, add a dependency on androidx.car.app:app-automotive to the build.gradle file for your Android Automotive OS module.
Additionally, in your AndroidManifest.xml file, you need to declare the relevant permissions needed to request the car data you want to use. Note that these permissions must also be granted to you by the user. You can use the same code on both Android Auto and Android Automotive OS, rather than having to create platform-dependent flows. However, the permissions needed are different.
CarInfo
This table describes the properties surfaced by the CarInfo APIs and the permissions you need to request to use them:
Warning: the getOdometerMeters method of the Mileage class is inaccurately named and returns kilometers, not meters.
Odometer distance
com.google.android.gms.permission.CAR_MILEAGE
This data is not available on Android Automotive OS to apps installed from the Play Store.
3
For example, to get the remaining range, instantiate a CarInfo object, then create and register an OnCarDataAvailableListener :
کاتلین
valcarInfo=carContext.getCarService(CarHardwareManager::class.java).carInfovallistener=OnCarDataAvailableListener<EnergyLevel>{data->
if(data.rangeRemainingMeters.status==CarValue.STATUS_SUCCESS){valrangeRemaining=data.rangeRemainingMeters.value}else{// Handle error}}carInfo.addEnergyLevelListener(carContext.mainExecutor,listener)…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener)
جاوا
CarInfocarInfo=getCarContext().getCarService(CarHardwareManager.class).getCarInfo();OnCarDataAvailableListener<EnergyLevel>listener=(data)->{if(data.getRangeRemainingMeters().getStatus()==CarValue.STATUS_SUCCESS){floatrangeRemaining=data.getRangeRemainingMeters().getValue();}else{// Handle error}};carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(),listener);…// Unregister the listener when you no longer need updatescarInfo.removeEnergyLevelListener(listener);
Don't assume that the data from the car is available at all times. If you get an error, check the status of the value you requested to better understand why the data you requested could not be retrieved. Refer to the reference documentation for the full CarInfo class definition.
CarSensors
The CarSensors class gives you access to the vehicle's accelerometer, gyroscope, compass, and location data. The availability of these values may depend on the OEM. The format for the data from the accelerometer, gyroscope, and compass is the same as you would get from the SensorManager API . For example, to check the vehicle's heading:
کاتلین
valcarSensors=carContext.getCarService(CarHardwareManager::class.java).carSensorsvallistener=OnCarDataAvailableListener<Compass>{data->
if(data.orientations.status==CarValue.STATUS_SUCCESS){valorientation=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 updatescarSensors.removeCompassListener(listener)
جاوا
CarSensorscarSensors=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 updatescarSensors.removeCompassListener(listener);
To access location data from the car, you also need to declare and request the android.permission.ACCESS_FINE_LOCATION permission.
تست کردن
To simulate sensor data when testing on Android Auto, refer to the Sensors and Sensor configuration sections of the Desktop Head Unit guide. To simulate sensor data when testing on Android Automotive OS, refer to the Emulate hardware state section of the Android Automotive OS emulator guide.
The CarAppService, Session and Screen lifecycles
The Session and Screen classes implement the LifecycleOwner interface. As the user interacts with the app, your Session and Screen objects' lifecycle callbacks are invoked, as described in the following diagrams.
Using your app's CarAppService and the CarAudioRecord API, you can give your app access to the user's car microphone. Users need to give your app permission to access the car microphone. Your app can record and process the user's input within your app.
Permission to record
Before recording any audio, you must first declare the permission to record in your AndroidManifest.xml and request that the user grant it.
You need to request the permission to record at runtime. See the Request permissions section for details on how to request a permission in your car app.
ضبط صدا
After the user gives permission to record, you can record the audio and process the recording.
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)carAudioRecord.startRecording()valdata=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()
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());carAudioRecord.startRecording();byte[]data=newbyte[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();
Audio focus
When recording from the car microphone, first acquire audio focus to ensure that any ongoing media is stopped. If you lose audio focus, stop recording.
Here is an example of how to acquire audio focus:
کاتلین
valcarAudioRecord=CarAudioRecord.create(carContext)// Take audio focus so that user's media is not recordedvalaudioAttributes=AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build()valaudioFocusRequest=AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener{state:Int->
if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording()}}.build()if(carContext.getSystemService(AudioManager::class.java).requestAudioFocus(audioFocusRequest)!=AudioManager.AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn}carAudioRecord.startRecording()// Process the audio and abandon the AudioFocusRequest when done
جاوا
CarAudioRecordcarAudioRecord=CarAudioRecord.create(getCarContext());// Take audio focus so that user's media is not recordedAudioAttributesaudioAttributes=newAudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)// Use the most appropriate usage type for your use case.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).build();AudioFocusRequestaudioFocusRequest=newAudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE).setAudioAttributes(audioAttributes).setOnAudioFocusChangeListener(state->{if(state==AudioManager.AUDIOFOCUS_LOSS){// Stop recording if audio focus is lostcarAudioRecord.stopRecording();}}).build();if(getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)!=AUDIOFOCUS_REQUEST_GRANTED){// Don't record if the focus isn't grantedreturn;}carAudioRecord.startRecording();// Process the audio and abandon the AudioFocusRequest when done
Testing Library
The Android for Cars Testing Library provides auxiliary classes that you can use to validate your app's behavior in a test environment. For example, the SessionController lets you simulate a connection to the host and verify that the correct Screen and Template are created and returned.
If you find an issue with the library, report it using the Google Issue Tracker . Be sure to fill out all the requested information in the issue template.
Before filing a new issue, please check whether it is listed in the library's release notes or reported in the issues list. You can subscribe and vote for issues by clicking the star for an issue in the tracker. For more information, see Subscribing to an Issue .
محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند.
تاریخ آخرین بهروزرسانی 2025-04-29 بهوقت ساعت هماهنگ جهانی.
[[["درک آسان","easyToUnderstand","thumb-up"],["مشکلم را برطرف کرد","solvedMyProblem","thumb-up"],["غیره","otherUp","thumb-up"]],[["اطلاعاتی که نیاز دارم وجود ندارد","missingTheInformationINeed","thumb-down"],["بیشازحد پیچیده/ مراحل بسیار زیاد","tooComplicatedTooManySteps","thumb-down"],["قدیمی","outOfDate","thumb-down"],["مشکل ترجمه","translationIssue","thumb-down"],["مشکل کد / نمونهها","samplesCodeIssue","thumb-down"],["غیره","otherDown","thumb-down"]],["تاریخ آخرین بهروزرسانی 2025-04-29 بهوقت ساعت هماهنگ جهانی."],[],[]]