'कार के लिए Android ऐप्लिकेशन' की लाइब्रेरी का इस्तेमाल करना

Android for Cars ऐप्लिकेशन लाइब्रेरी की मदद से, कार में नेविगेशन, दिलचस्प जगह (पीओआई), इंटरनेट ऑफ़ थिंग्स (आईओटी) या मौसम ऐप्लिकेशन इस्तेमाल किए जा सकते हैं. ऐसा करने के लिए, यह टेंप्लेट का एक सेट उपलब्ध कराता है. ये टेंप्लेट, ड्राइवर के ध्यान भटकाने वाले कॉन्टेंट से जुड़े स्टैंडर्ड के मुताबिक होते हैं. साथ ही, इनमें कार की स्क्रीन के अलग-अलग फ़ैक्टर और इनपुट मोड जैसी जानकारी भी शामिल होती है.

इस गाइड में, लाइब्रेरी की मुख्य सुविधाओं और कॉन्सेप्ट के बारे में खास जानकारी दी गई है. साथ ही, इसमें एक बुनियादी ऐप्लिकेशन सेट अप करने का तरीका भी बताया गया है.

शुरू करने से पहले

  1. कार ऐप्लिकेशन लाइब्रेरी के बारे में बताने वाले ड्राइविंग के लिए डिज़ाइन करें पेजों को देखें
  2. नीचे दिए गए सेक्शन में, मुख्य शब्दों और कॉन्सेप्ट के बारे में जानें.
  3. Android Auto सिस्टम के यूज़र इंटरफ़ेस (यूआई) और Android Automotive OS के डिज़ाइन के बारे में जानें.
  4. प्रॉडक्ट की जानकारी देखें.
  5. सैंपल देखें.

मुख्य शब्द और कॉन्सेप्ट

मॉडल और टेंप्लेट
यूज़र इंटरफ़ेस को मॉडल ऑब्जेक्ट के ग्राफ़ से दिखाया जाता है. इन ऑब्जेक्ट को अलग-अलग तरीकों से व्यवस्थित किया जा सकता है. हालांकि, ऐसा करने के लिए ज़रूरी है कि टेंप्लेट में ऐसा करने की अनुमति हो. टेंप्लेट, उन मॉडल का सबसेट होते हैं जो उन ग्राफ़ में रूट के तौर पर काम कर सकते हैं. मॉडल में, उपयोगकर्ता को टेक्स्ट और इमेज के तौर पर दिखाई जाने वाली जानकारी शामिल होती है. साथ ही, ऐसी जानकारी के विज़ुअल दिखाने के पहलुओं को कॉन्फ़िगर करने के लिए एट्रिब्यूट भी शामिल होते हैं. उदाहरण के लिए, टेक्स्ट के रंग या इमेज के साइज़. होस्ट, मॉडल को ऐसे व्यू में बदलता है जिन्हें ड्राइवर के ध्यान भटकाने से जुड़े मानकों के मुताबिक डिज़ाइन किया गया है. साथ ही, वह कार की स्क्रीन के अलग-अलग फ़ैक्टर और इनपुट मोड जैसे पहलुओं का ध्यान रखता है.
होस्ट
होस्ट, बैकएंड कॉम्पोनेंट होता है. यह लाइब्रेरी के एपीआई की सुविधाओं को लागू करता है, ताकि आपका ऐप्लिकेशन कार में चल सके. होस्ट की ज़िम्मेदारियों में, आपके ऐप्लिकेशन को खोजना और उसका लाइफ़साइकल मैनेज करना शामिल है. साथ ही, आपके मॉडल को व्यू में बदलना और उपयोगकर्ता के इंटरैक्शन की सूचना आपके ऐप्लिकेशन को देना भी होस्ट की ज़िम्मेदारी है. मोबाइल डिवाइसों पर, Android Auto इस होस्ट को लागू करता है. Android Automotive OS पर, यह होस्ट सिस्टम ऐप्लिकेशन के तौर पर इंस्टॉल होता है.
टेंप्लेट से जुड़ी पाबंदियां
अलग-अलग टेंप्लेट, अपने मॉडल के कॉन्टेंट पर पाबंदियां लगाते हैं. उदाहरण के लिए, सूची के टेंप्लेट में उपयोगकर्ता को दिखाए जा सकने वाले आइटम की संख्या सीमित होती है. टेंप्लेट को टास्क के फ़्लो के तौर पर कनेक्ट करने के तरीके पर भी पाबंदियां हैं. उदाहरण के लिए, ऐप्लिकेशन स्क्रीन स्टैक में सिर्फ़ पांच टेंप्लेट पुश कर सकता है. ज़्यादा जानकारी के लिए, टेंप्लेट से जुड़ी पाबंदियां देखें.
Screen
Screen, लाइब्रेरी से मिलने वाली एक क्लास है. ऐप्लिकेशन, उपयोगकर्ता को दिखाए जाने वाले यूज़र इंटरफ़ेस को मैनेज करने के लिए, इसे लागू करते हैं. Screen का एक लाइफ़साइकल होता है. साथ ही, यह ऐप्लिकेशन को स्क्रीन दिखने पर टेंप्लेट दिखाने के लिए, एक तरीका उपलब्ध कराता है. Screen इंस्टेंस को Screen स्टैक में पुश और पॉप भी किया जा सकता है. इससे यह पक्का होता है कि वे टेंप्लेट फ़्लो की पाबंदियों का पालन करते हैं.
CarAppService
CarAppService एक ऐसी Service क्लास है जिसे आपके ऐप्लिकेशन को लागू और एक्सपोर्ट करना होगा, ताकि होस्ट उसे ढूंढ सके और मैनेज कर सके. आपके ऐप्लिकेशन के CarAppService की यह पुष्टि करना ज़िम्मेदारी है कि किसी होस्ट कनेक्शन पर भरोसा किया जा सकता है या नहीं. इसके लिए, createHostValidator का इस्तेमाल किया जाता है. इसके बाद, onCreateSession का इस्तेमाल करके हर कनेक्शन के लिए Session इंस्टेंस उपलब्ध कराए जाते हैं.
Session

Session एक ऐब्स्ट्रैक्ट क्लास है. आपके ऐप्लिकेशन को इसे लागू करना होगा और CarAppService.onCreateSession का इस्तेमाल करके इसे दिखाना होगा. यह कार की स्क्रीन पर जानकारी दिखाने के लिए, एंट्री पॉइंट के तौर पर काम करता है. इसका एक लाइफ़साइकल होता है, जो कार की स्क्रीन पर आपके ऐप्लिकेशन की मौजूदा स्थिति के बारे में बताता है. जैसे, आपका ऐप्लिकेशन कब दिख रहा है या छिपा हुआ है.

जब कोई Session शुरू किया जाता है, जैसे कि ऐप्लिकेशन को पहली बार लॉन्च करने पर, होस्ट onCreateScreen तरीके का इस्तेमाल करके, शुरुआती Screen को दिखाने का अनुरोध करता है.

कार ऐप्लिकेशन लाइब्रेरी इंस्टॉल करना

अपने ऐप्लिकेशन में लाइब्रेरी जोड़ने का तरीका जानने के लिए, Jetpack लाइब्रेरी का रिलीज़ पेज देखें.

अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइलों को कॉन्फ़िगर करना

कार ऐप्लिकेशन बनाने से पहले, अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइलों को इस तरह कॉन्फ़िगर करें.

अपनी CarAppService का एलान करना

होस्ट, आपके ऐप्लिकेशन से CarAppService लागू करने के तरीके से कनेक्ट होता है. होस्ट को आपके ऐप्लिकेशन को खोजने और उससे कनेक्ट करने की अनुमति देने के लिए, आपको अपने मेनिफ़ेस्ट में इस सेवा के बारे में बताना होगा.

आपको अपने ऐप्लिकेशन के इंटेंट फ़िल्टर के <category> एलिमेंट में भी अपने ऐप्लिकेशन की कैटगरी की जानकारी देनी होगी. इस एलिमेंट के लिए इस्तेमाल की जा सकने वाली वैल्यू के बारे में जानने के लिए, काम करने वाली ऐप्लिकेशन कैटगरी की सूची देखें.

यहां दिए गए कोड स्निपेट में, अपने मेनिफ़ेस्ट में दिलचस्पी के किसी ऐप्लिकेशन के लिए, कार ऐप्लिकेशन सेवा का एलान करने का तरीका बताया गया है:

<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService"/>
        <category android:name="androidx.car.app.category.POI"/>
      </intent-filter>
    </service>

    ...
<application>

जिन ऐप्लिकेशन कैटगरी के लिए यह सुविधा उपलब्ध है

पिछले सेक्शन में बताए गए तरीके से CarAppService का एलान करते समय, इंटेंट फ़िल्टर में कैटगरी की इनमें से एक या उससे ज़्यादा वैल्यू जोड़कर, अपने ऐप्लिकेशन की कैटगरी का एलान करें:

हर कैटगरी के बारे में ज़्यादा जानकारी और ऐप्लिकेशन को उस कैटगरी में शामिल करने की ज़रूरी शर्तों के लिए, कार के लिए Android ऐप्लिकेशन की क्वालिटी देखें.

ऐप्लिकेशन का नाम और आइकॉन डालना

आपको ऐप्लिकेशन का नाम और आइकॉन बताना होगा, ताकि होस्ट आपके ऐप्लिकेशन को सिस्टम के यूज़र इंटरफ़ेस (यूआई) में दिखा सके.

CarAppService के label और icon एट्रिब्यूट का इस्तेमाल करके, ऐप्लिकेशन का नाम और आइकॉन बताया जा सकता है. इनका इस्तेमाल, ऐप्लिकेशन को दिखाने के लिए किया जाता है:

...
<service
   android:name=".MyCarAppService"
   android:exported="true"
   android:label="@string/my_app_name"
   android:icon="@drawable/my_app_icon">
   ...
</service>
...

अगर लेबल या आइकॉन को <service> एलिमेंट में एलान नहीं किया गया है, तो होस्ट <application> एलिमेंट के लिए बताई गई वैल्यू का इस्तेमाल करता है.

पसंद के मुताबिक थीम सेट करना

अपने कार ऐप्लिकेशन के लिए कस्टम थीम सेट करने के लिए, अपनी मेनिफ़ेस्ट फ़ाइल में <meta-data> एलिमेंट जोड़ें. इसके लिए, यह तरीका अपनाएं:

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

इसके बाद, अपनी पसंद के मुताबिक कार ऐप्लिकेशन की थीम के लिए ये एट्रिब्यूट सेट करने के लिए, स्टाइल रिसोर्स का एलान करें:

<resources>
  <style name="MyCarAppTheme">
    <item name="carColorPrimary">@layout/my_primary_car_color</item>
    <item name="carColorPrimaryDark">@layout/my_primary_dark_car_color</item>
    <item name="carColorSecondary">@layout/my_secondary_car_color</item>
    <item name="carColorSecondaryDark">@layout/my_secondary_dark_car_color</item>
    <item name="carPermissionActivityLayout">@layout/my_custom_background</item>
  </style>
</resources>

कार ऐप्लिकेशन का एपीआई लेवल

कार ऐप्लिकेशन लाइब्रेरी, अपने एपीआई लेवल तय करती है, ताकि आपको यह पता चल सके कि किसी गाड़ी पर टेंप्लेट होस्ट, लाइब्रेरी की कौनसी सुविधाएं इस्तेमाल कर सकता है. होस्ट के साथ काम करने वाले Car App API का सबसे ज़्यादा लेवल पाने के लिए, getCarAppApiLevel() वाला तरीका अपनाएं.

अपनी AndroidManifest.xml फ़ाइल में, अपने ऐप्लिकेशन के साथ काम करने वाले Car App API के कम से कम लेवल की जानकारी दें:

<manifest ...>
    <application ...>
        <meta-data
            android:name="androidx.car.app.minCarApiLevel"
            android:value="1"/>
    </application>
</manifest>

किसी सुविधा का इस्तेमाल करने के लिए ज़रूरी एपीआई लेवल का एलान करने और पुराने वर्शन के साथ काम करने की सुविधा को बनाए रखने के तरीके के बारे में जानने के लिए, RequiresCarApi एनोटेशन के दस्तावेज़ देखें. कार ऐप्लिकेशन लाइब्रेरी की किसी सुविधा का इस्तेमाल करने के लिए, किस एपीआई लेवल की ज़रूरत है, यह जानने के लिए CarAppApiLevels के लिए रेफ़रंस दस्तावेज़ देखें.

CarAppService और सेशन बनाना

आपके ऐप्लिकेशन को CarAppService क्लास को एक्सटेंड करना होगा और उसका onCreateSession तरीका लागू करना होगा. यह तरीका, होस्ट के मौजूदा कनेक्शन से जुड़ा Session इंस्टेंस दिखाता है:

KotlinJava
class HelloWorldService : CarAppService() {
    ...
    override fun onCreateSession(): Session {
        return HelloWorldSession()
    }
    ...
}
public final class HelloWorldService extends CarAppService {
    ...
    @Override
    @NonNull
    public Session onCreateSession() {
        return new HelloWorldSession();
    }
    ...
}

Session इंस्टेंस, ऐप्लिकेशन को पहली बार शुरू करने के लिए, Screen इंस्टेंस को वापस लाने के लिए ज़िम्मेदार होता है:

KotlinJava
class HelloWorldSession : Session() {
    ...
    override fun onCreateScreen(intent: Intent): Screen {
        return HelloWorldScreen(carContext)
    }
    ...
}
public final class HelloWorldSession extends Session {
    ...
    @Override
    @NonNull
    public Screen onCreateScreen(@NonNull Intent intent) {
        return new HelloWorldScreen(getCarContext());
    }
    ...
}

डीप लिंक को मैनेज करने जैसी स्थितियों में, कार ऐप्लिकेशन को ऐसी स्क्रीन से शुरू करना पड़ सकता है जो आपके ऐप्लिकेशन की होम या लैंडिंग स्क्रीन न हो. ऐसे में, onCreateScreen से वापस आने से पहले, ScreenManager.push का इस्तेमाल करके, स्क्रीन के बैक स्टैक को पहले से सेट किया जा सकता है. डेटा पहले से सेव होने की सुविधा की मदद से, उपयोगकर्ता आपके ऐप्लिकेशन की पहली स्क्रीन से पिछली स्क्रीन पर वापस जा सकते हैं.

स्टार्ट स्क्रीन बनाना

अपने ऐप्लिकेशन में दिखने वाली स्क्रीन बनाने के लिए, ऐसी क्लास तय करें जो Screen क्लास को एक्सटेंड करती हों. साथ ही, onGetTemplate का तरीका लागू करें. यह तरीका, Template इंस्टेंस दिखाता है, जो कार की स्क्रीन पर दिखाए जाने वाले यूज़र इंटरफ़ेस (यूआई) की स्थिति दिखाता है.

नीचे दिए गए स्निपेट में, PaneTemplate टेंप्लेट का इस्तेमाल करके, “Hello world!” स्ट्रिंग दिखाने वाले Screen को डिक्लेर करने का तरीका बताया गया है:

KotlinJava
class HelloWorldScreen(carContext: CarContext) : Screen(carContext) {
    override fun onGetTemplate(): Template {
        val row = Row.Builder().setTitle("Hello world!").build()
        val pane = Pane.Builder().addRow(row).build()
        return PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build()
    }
}
public class HelloWorldScreen extends Screen {
    @NonNull
    @Override
    public Template onGetTemplate() {
        Row row = new Row.Builder().setTitle("Hello world!").build();
        Pane pane = new Pane.Builder().addRow(row).build();
        return new PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build();
    }
}

CarContext क्लास

CarContext क्लास, ContextWrapper सबक्लास है. इसे आपके Session और Screen इंस्टेंस ऐक्सेस कर सकते हैं. यह कार की सेवाओं का ऐक्सेस देता है. जैसे, स्क्रीन स्टैक को मैनेज करने के लिए ScreenManager; ऐप्लिकेशन से जुड़ी सामान्य सुविधाओं के लिए AppManager, जैसे कि मैप बनाने के लिए Surface ऑब्जेक्ट को ऐक्सेस करना; और NavigationManager, जिसका इस्तेमाल टर्न-बाय-टर्न नेविगेशन ऐप्लिकेशन करते हैं. इससे वे नेविगेशन के मेटाडेटा और होस्ट के साथ नेविगेशन से जुड़े अन्य इवेंट की जानकारी शेयर करते हैं.

नेविगेशन ऐप्लिकेशन के लिए उपलब्ध लाइब्रेरी फ़ंक्शन की पूरी सूची देखने के लिए, नेविगेशन टेंप्लेट ऐक्सेस करना लेख पढ़ें.

CarContext में अन्य सुविधाएं भी उपलब्ध हैं. जैसे, कार की स्क्रीन से कॉन्फ़िगरेशन का इस्तेमाल करके, ड्रॉ किए जा सकने वाले रिसॉर्स लोड करने की सुविधा, इंटेंट का इस्तेमाल करके कार में ऐप्लिकेशन शुरू करने की सुविधा, और यह सिग्नल देने की सुविधा कि आपके ऐप्लिकेशन को अपना मैप डार्क थीम में दिखाना चाहिए या नहीं.

स्क्रीन पर नेविगेशन लागू करना

ऐप्लिकेशन में अक्सर कई अलग-अलग स्क्रीन होती हैं. हर स्क्रीन में अलग-अलग टेंप्लेट का इस्तेमाल किया जा सकता है. उपयोगकर्ता, स्क्रीन पर दिखाए गए इंटरफ़ेस से इंटरैक्ट करते समय, इन टेंप्लेट पर जा सकता है.

ScreenManager क्लास, स्क्रीन स्टैक उपलब्ध कराती है. इसका इस्तेमाल करके, ऐसी स्क्रीन को पुश किया जा सकता है जो उपयोगकर्ता के कार की स्क्रीन पर मौजूद 'वापस जाएं' बटन को चुनने या कुछ कारों में मौजूद 'वापस जाएं' बटन का इस्तेमाल करने पर, अपने-आप पॉप अप हो सकती हैं.

नीचे दिए गए स्निपेट में, मैसेज टेंप्लेट में 'वापस जाएं' कार्रवाई जोड़ने का तरीका बताया गया है. साथ ही, यह भी बताया गया है कि उपयोगकर्ता के चुने जाने पर, नई स्क्रीन पर ले जाने वाली कार्रवाई कैसे जोड़ें:

KotlinJava
val template = MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener { screenManager.push(NextScreen(carContext)) }
            .build())
    .build()
MessageTemplate template = new MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        new Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener(
                () -> getScreenManager().push(new NextScreen(getCarContext())))
            .build())
    .build();

Action.BACK ऑब्जेक्ट एक स्टैंडर्ड Action है, जो ScreenManager.pop को अपने-आप ट्रिगर करता है. इस व्यवहार को बदला जा सकता है. इसके लिए, CarContext में उपलब्ध OnBackPressedDispatcher इंस्टेंस का इस्तेमाल करें.

यह पक्का करने के लिए कि गाड़ी चलाते समय ऐप्लिकेशन का इस्तेमाल करना सुरक्षित है, स्क्रीन स्टैक में ज़्यादा से ज़्यादा पांच स्क्रीन हो सकती हैं. ज़्यादा जानकारी के लिए, टेंप्लेट से जुड़ी पाबंदियां सेक्शन देखें.

टेंप्लेट का कॉन्टेंट रीफ़्रेश करना

आपका ऐप्लिकेशन, Screen.invalidate तरीके को कॉल करके, किसी Screen के कॉन्टेंट को अमान्य करने का अनुरोध कर सकता है. इसके बाद, होस्ट आपके ऐप्लिकेशन के Screen.onGetTemplate तरीके का इस्तेमाल करके, नए कॉन्टेंट के साथ टेंप्लेट को वापस पाता है.

Screen को रीफ़्रेश करते समय, यह समझना ज़रूरी है कि टेंप्लेट में कौनसा कॉन्टेंट अपडेट किया जा सकता है, ताकि होस्ट नए टेंप्लेट को टेंप्लेट कोटा में न गिने. ज़्यादा जानकारी के लिए, टेंप्लेट से जुड़ी पाबंदियां सेक्शन देखें.

हमारा सुझाव है कि आप अपनी स्क्रीन को इस तरह से व्यवस्थित करें कि Screen और onGetTemplate लागू करने के बाद दिखने वाले टेंप्लेट के बीच एक-एक मैपिंग हो.

मैप बनाना

नेविगेशन, लोकप्रिय जगह की जानकारी (पीओआई), और मौसम की जानकारी दिखाने वाले ऐप्लिकेशन, यहां दिए गए टेंप्लेट का इस्तेमाल करके, Surface को ऐक्सेस करके मैप बना सकते हैं.

यहां दिए गए टेंप्लेट का इस्तेमाल करने के लिए, आपके ऐप्लिकेशन में AndroidManifest.xml फ़ाइल के <uses-permission> एलिमेंट में, इनमें से कोई एक अनुमति होनी चाहिए.

टेंप्लेट टेंप्लेट की अनुमति कैटगरी के लिए दिशा-निर्देश
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES एक हिस्से से दूसरे हिस्से पर जाना
MapWithContentTemplate androidx.car.app.NAVIGATION_TEMPLATES या
androidx.car.app.MAP_TEMPLATES
नेविगेशन, पीओआई, मौसम
MapTemplate (अब काम नहीं करता) androidx.car.app.NAVIGATION_TEMPLATES एक हिस्से से दूसरे हिस्से पर जाना
PlaceListNavigationTemplate (अब काम नहीं करता) androidx.car.app.NAVIGATION_TEMPLATES एक हिस्से से दूसरे हिस्से पर जाना
RoutePreviewNavigationTemplate (अब काम नहीं करता) androidx.car.app.NAVIGATION_TEMPLATES एक हिस्से से दूसरे हिस्से पर जाना

प्लैटफ़ॉर्म की अनुमति का एलान करना

आपके ऐप्लिकेशन के इस्तेमाल किए जा रहे टेंप्लेट के लिए ज़रूरी अनुमति के अलावा, आपके ऐप्लिकेशन को प्लैटफ़ॉर्म का ऐक्सेस पाने के लिए, अपनी AndroidManifest.xml फ़ाइल में androidx.car.app.ACCESS_SURFACE अनुमति का एलान करना होगा:

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
  ...
</manifest>

प्लैटफ़ॉर्म ऐक्सेस करना

होस्ट की ओर से उपलब्ध कराए गए Surface को ऐक्सेस करने के लिए, आपको SurfaceCallback को लागू करना होगा. साथ ही, AppManager कार सेवा को लागू करने की जानकारी देनी होगी. मौजूदा Surface को onSurfaceAvailable() और onSurfaceDestroyed() कॉलबैक के SurfaceContainer पैरामीटर में, आपके SurfaceCallback पर पास किया जाता है.

KotlinJava
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

सतह के दिखने वाले हिस्से को समझना

होस्ट, मैप के ऊपर टेंप्लेट के लिए यूज़र इंटरफ़ेस एलिमेंट बना सकता है. होस्ट, स्क्रीन के उस हिस्से के बारे में बताता है जो उपयोगकर्ता को पूरी तरह से दिखता है और जिसमें कोई रुकावट नहीं होती. इसके लिए, वह SurfaceCallback.onVisibleAreaChanged तरीका इस्तेमाल करता है. साथ ही, बदलावों की संख्या कम करने के लिए, होस्ट सबसे छोटे रेक्टैंगल के साथ SurfaceCallback.onStableAreaChanged तरीका इस्तेमाल करता है. यह तरीका, मौजूदा टेंप्लेट के आधार पर हमेशा दिखता है.

उदाहरण के लिए, जब कोई नेविगेशन ऐप्लिकेशन, सबसे ऊपर ऐक्शन स्ट्रिप के साथ NavigationTemplate का इस्तेमाल करता है, तो मैप के लिए ज़्यादा जगह बनाने के लिए, ऐक्शन स्ट्रिप कुछ समय के लिए अपने-आप छिप सकती है. ऐसा तब होता है, जब उपयोगकर्ता ने कुछ समय तक स्क्रीन से इंटरैक्ट न किया हो. इस मामले में, एक ही रेक्टैंगल में onStableAreaChanged और onVisibleAreaChanged के लिए कॉलबैक है. जब ऐक्शन स्ट्रिप छिपी होती है, तो सिर्फ़ onVisibleAreaChanged को बड़े एरिया के साथ कॉल किया जाता है. अगर उपयोगकर्ता स्क्रीन के साथ इंटरैक्ट करता है, तो फिर से सिर्फ़ onVisibleAreaChanged को पहले रेक्टैंगल के साथ कॉल किया जाता है.

गहरे रंग वाली थीम काम करती है

जब होस्ट यह तय करता है कि ज़रूरत पड़ने पर Surface इंस्टेंस पर ऐप्लिकेशन के मैप को सही डार्क रंगों में फिर से दिखाना है, तो ऐप्लिकेशन को ऐसा करना होगा. इस बारे में कारों के लिए Android ऐप्लिकेशन की क्वालिटी में बताया गया है.

यह तय करने के लिए कि आपको डार्क मैप बनाना है या नहीं, CarContext.isDarkMode वाला तरीका अपनाएं. गहरे रंग वाली थीम का स्टेटस बदलने पर, आपको Session.onCarConfigurationChanged पर कॉल मिलता है.

उपयोगकर्ताओं को आपके मैप के साथ इंटरैक्ट करने की सुविधा देना

यहां दिए गए टेंप्लेट का इस्तेमाल करते समय, उपयोगकर्ताओं को आपके बनाए गए मैप के साथ इंटरैक्ट करने की सुविधा जोड़ी जा सकती है. जैसे, ज़ूम इन और पैन करके, उन्हें मैप के अलग-अलग हिस्से दिखाना.

टेंप्लेट इंटरैक्टिविटी की सुविधा, Car App API लेवल से काम करती है
NavigationTemplate 2
PlaceListNavigationTemplate (अब काम नहीं करता) 4
RoutePreviewNavigationTemplate (अब काम नहीं करता) 4
MapTemplate (अब काम नहीं करता) 5 (टेंप्लेट का परिचय)
MapWithContentTemplate 7 (टेंप्लेट का परिचय)

इंटरैक्टिव कॉलबैक लागू करना

SurfaceCallback इंटरफ़ेस में, कई कॉलबैक तरीके होते हैं. इनका इस्तेमाल करके, पिछले सेक्शन में दिए गए टेंप्लेट से बनाए गए मैप में इंटरैक्टिविटी जोड़ी जा सकती है:

इंटरैक्शन SurfaceCallback तरीका Car App API लेवल के बाद से काम करता है
टैप करें onClick 5
ज़ूम करने के लिए पिंच करें onScale 2
एक-टच से खींचें और छोड़ें onScroll 2
एक-टच फ़्लिंग onFling 2
दो बार टैप करें onScale (टेंप्लेट होस्ट के हिसाब से तय किए गए स्केल फ़ैक्टर के साथ) 2
पैन मोड में रोटरी नॉब का इस्तेमाल करके आइटम को थोड़ा सा आगे या पीछे ले जाना onScroll (टेंप्लेट होस्ट के हिसाब से तय की गई दूरी के फ़ैक्टर के साथ) 2

मैप ऐक्शन स्ट्रिप जोड़ना

इन टेंप्लेट में, मैप से जुड़ी कार्रवाइयों के लिए मैप ऐक्शन स्ट्रिप हो सकती है. जैसे, ज़ूम इन और ज़ूम आउट करना, फिर से केंद्र में ले जाना, कंपास दिखाना, और ऐसी अन्य कार्रवाइयां जिन्हें दिखाने का विकल्प चुना जाता है. मैप ऐक्शन स्ट्रिप में, सिर्फ़ आइकॉन वाले चार बटन हो सकते हैं. इन्हें टास्क के लेवल पर असर डाले बिना रीफ़्रेश किया जा सकता है. यह आइकॉन, डिवाइस के इस्तेमाल में न होने पर छिप जाता है और इस्तेमाल में होने पर फिर से दिखने लगता है.

मैप पर इंटरैक्टिविटी कॉलबैक पाने के लिए, आपको मैप ऐक्शन स्ट्रिप में Action.PAN बटन जोड़ना ज़रूरी है. जब उपयोगकर्ता, पैन बटन दबाता है, तो होस्ट पैन मोड में चला जाता है. इस मोड के बारे में यहां बताया गया है.

अगर आपका ऐप्लिकेशन, मैप ऐक्शन स्ट्रिप में Action.PAN button को शामिल नहीं करता है, तो उसे SurfaceCallback तरीकों से उपयोगकर्ता का इनपुट नहीं मिलता. साथ ही, होस्ट पहले से चालू किए गए पैन मोड से बाहर निकल जाता है.

टचस्क्रीन पर, पैन बटन नहीं दिखता.

पैन मोड के बारे में जानकारी

पैन मोड में, टेंप्लेट होस्ट, उपयोगकर्ता के इनपुट को टच इनपुट डिवाइसों से, सही SurfaceCallback तरीकों में बदल देता है. जैसे, रोटरी कंट्रोलर और टचपैड. NavigationTemplate.Builder में setPanModeListener वाले तरीके का इस्तेमाल करके, पैन मोड में जाने या उससे बाहर निकलने के लिए उपयोगकर्ता की कार्रवाई का जवाब दें. जब उपयोगकर्ता पैन मोड में हो, तब होस्ट टेंप्लेट में मौजूद अन्य यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट छिपा सकता है.

उपयोगकर्ता से इंटरैक्ट करना

आपका ऐप्लिकेशन, मोबाइल ऐप्लिकेशन जैसे पैटर्न का इस्तेमाल करके उपयोगकर्ता के साथ इंटरैक्ट कर सकता है.

उपयोगकर्ता के इनपुट को मैनेज करना

आपका ऐप्लिकेशन, उपयोगकर्ता के इनपुट का जवाब दे सकता है. इसके लिए, वह उन मॉडल को सही लिसनर भेजता है जिनमें इनपुट के जवाब देने की सुविधा होती है. यहां दिए गए स्निपेट में, ऐसा Action मॉडल बनाने का तरीका बताया गया है जो OnClickListener सेट करता है. यह OnClickListener, आपके ऐप्लिकेशन के कोड से तय किए गए तरीके को वापस कॉल करता है:

KotlinJava
val action = Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(::onClickNavigate)
    .build()
Action action = new Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(this::onClickNavigate)
    .build();

इसके बाद, onClickNavigate तरीका, CarContext.startCarApp तरीके का इस्तेमाल करके, डिफ़ॉल्ट नेविगेशन कार ऐप्लिकेशन को शुरू कर सकता है:

KotlinJava
private fun onClickNavigate() {
    val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address))
    carContext.startCarApp(intent)
}
private void onClickNavigate() {
    Intent intent = new Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address));
    getCarContext().startCarApp(intent);
}

ऐप्लिकेशन शुरू करने के तरीके के बारे में ज़्यादा जानकारी के लिए, इंटेंट की मदद से कार ऐप्लिकेशन शुरू करना सेक्शन देखें. इसमें ACTION_NAVIGATE इंटेंट का फ़ॉर्मैट भी शामिल है.

कुछ कार्रवाइयों को सिर्फ़ तब अनुमति दी जाती है, जब कार पार्क की गई हो. जैसे, उपयोगकर्ता को मोबाइल डिवाइसों पर इंटरैक्शन जारी रखने के लिए निर्देश देना. इन कार्रवाइयों को लागू करने के लिए, ParkedOnlyOnClickListener का इस्तेमाल किया जा सकता है. अगर कार पार्क नहीं की गई है, तो होस्ट उपयोगकर्ता को यह जानकारी दिखाता है कि इस मामले में कार्रवाई करने की अनुमति नहीं है. अगर कार पार्क की गई है, तो कोड सामान्य तरीके से काम करता है. यहां दिए गए स्निपेट में, मोबाइल डिवाइस पर सेटिंग स्क्रीन खोलने के लिए, ParkedOnlyOnClickListener का इस्तेमाल करने का तरीका बताया गया है:

KotlinJava
val row = Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(::openSettingsOnPhone))
    .build()
Row row = new Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(this::openSettingsOnPhone))
    .build();

सूचनाएं दिखाना

मोबाइल डिवाइस पर भेजी गई सूचनाएं, कार की स्क्रीन पर सिर्फ़ तब दिखती हैं, जब उन्हें CarAppExtender के साथ एक्सटेंड किया गया हो. सूचना के कुछ एट्रिब्यूट, जैसे कि कॉन्टेंट का टाइटल, टेक्स्ट, आइकॉन, और कार्रवाइयां, CarAppExtender में सेट की जा सकती हैं. इससे, कार की स्क्रीन पर सूचना के एट्रिब्यूट दिखने पर, उन्हें बदल दिया जाता है.

यहां दिए गए स्निपेट में, कार की स्क्रीन पर सूचना भेजने का तरीका बताया गया है. यह सूचना, मोबाइल डिवाइस पर दिखाई गई सूचना से अलग टाइटल दिखाती है:

KotlinJava
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build()
Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build();

सूचनाओं से यूज़र इंटरफ़ेस के इन हिस्सों पर असर पड़ सकता है:

  • उपयोगकर्ता को हेड्स-अप सूचना (एचयूएन) दिखाई जा सकती है.
  • सूचना केंद्र में एक एंट्री जोड़ी जा सकती है. इसके अलावा, रेल में दिखने वाला बैज भी जोड़ा जा सकता है.
  • नेविगेशन ऐप्लिकेशन के लिए, सूचना रेल विजेट में दिख सकती है, जैसा कि रास्ते के बारे में जानकारी देने वाली सूचनाएं में बताया गया है.

आपके पास यह चुनने का विकल्प होता है कि आपके ऐप्लिकेशन की सूचनाओं को कैसे कॉन्फ़िगर किया जाए, ताकि उन सभी यूज़र इंटरफ़ेस एलिमेंट पर असर पड़े. इसके लिए, सूचना की प्राथमिकता का इस्तेमाल करें. इस बारे में CarAppExtender दस्तावेज़ में बताया गया है.

अगर NotificationCompat.Builder.setOnlyAlertOnce को true की वैल्यू के साथ कॉल किया जाता है, तो सबसे ज़्यादा प्राथमिकता वाली सूचना, सिर्फ़ एक बार 'ज़्यादा सूचनाएं' के तौर पर दिखती है.

कार के ऐप्लिकेशन की सूचनाओं को डिज़ाइन करने के तरीके के बारे में ज़्यादा जानने के लिए, सूचनाओं के बारे में, ड्राइविंग के लिए Google डिज़ाइन की गाइड देखें.

टोस्ट दिखाना

आपका ऐप्लिकेशन, इस स्निपेट में दिखाए गए तरीके से CarToast का इस्तेमाल करके, टॉस्ट दिखा सकता है:

KotlinJava
CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()
CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();

अनुमतियों का अनुरोध करना

अगर आपके ऐप्लिकेशन को पाबंदी वाले डेटा या कार्रवाइयों का ऐक्सेस चाहिए, जैसे कि जगह की जानकारी, तो Android अनुमतियों के स्टैंडर्ड नियम लागू होंगे. अनुमति का अनुरोध करने के लिए, CarContext.requestPermissions() तरीका अपनाएं.

स्टैंडर्ड Android API का इस्तेमाल करने के बजाय, CarContext.requestPermissions() का इस्तेमाल करने का फ़ायदा यह है कि अनुमतियों का डायलॉग बॉक्स बनाने के लिए, आपको अपना Activity लॉन्च करने की ज़रूरत नहीं होती. इसके अलावा, प्लैटफ़ॉर्म के हिसाब से फ़्लो बनाने के बजाय, एक ही कोड का इस्तेमाल Android Auto और Android Automotive OS, दोनों पर किया जा सकता है.

Android Auto पर अनुमतियों के डायलॉग बॉक्स को स्टाइल करना

Android Auto पर, उपयोगकर्ता के लिए अनुमतियों का डायलॉग बॉक्स फ़ोन पर दिखेगा. डिफ़ॉल्ट रूप से, डायलॉग के पीछे कोई बैकग्राउंड नहीं होगा. पसंद के मुताबिक बैकग्राउंड सेट करने के लिए, अपनी AndroidManifest.xml फ़ाइल में कार ऐप्लिकेशन की थीम तय करें. साथ ही, कार ऐप्लिकेशन की थीम के लिए carPermissionActivityLayout एट्रिब्यूट सेट करें.

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

इसके बाद, अपनी कार के ऐप्लिकेशन की थीम के लिए carPermissionActivityLayout एट्रिब्यूट सेट करें:

<resources>
  <style name="MyCarAppTheme">
    <item name="carPermissionActivityLayout">@layout/my_custom_background</item>
  </style>
</resources>

इंटेंट की मदद से कार ऐप्लिकेशन शुरू करना

इनमें से कोई एक कार्रवाई करने के लिए, CarContext.startCarApp तरीका कॉल किया जा सकता है:

यहां दिए गए उदाहरण में, ऐसी सूचना बनाने का तरीका बताया गया है जिससे आपका ऐप्लिकेशन, पार्किंग बुकिंग की जानकारी दिखाने वाली स्क्रीन पर खुले. आपने सूचना के इंस्टेंस को कॉन्टेंट इंटेंट के साथ बढ़ाया है. इसमें आपके ऐप्लिकेशन की कार्रवाई के लिए, साफ़ तौर पर PendingIntent इंटेंट को रैप किया गया है:

KotlinJava
val notification = notificationBuilder
    ...
    .extend(
        CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(ComponentName(context, MyNotificationReceiver::class.java)),
                    0))
            .build())
Notification notification = notificationBuilder
    ...
    .extend(
        new CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    new Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(new ComponentName(context, MyNotificationReceiver.class)),
                    0))
            .build());

आपके ऐप्लिकेशन को एक BroadcastReceiver भी एलान करना होगा. जब उपयोगकर्ता सूचना इंटरफ़ेस में कार्रवाई चुनता है, तो इंटेंट को प्रोसेस करने के लिए इसका इस्तेमाल किया जाता है. साथ ही, डेटा यूआरआई वाले इंटेंट के साथ CarContext.startCarApp को भी इस्तेमाल किया जाता है:

KotlinJava
class MyNotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val intentAction = intent.action
        if (ACTION_VIEW_PARKING_RESERVATION == intentAction) {
            CarContext.startCarApp(
                intent,
                Intent(Intent.ACTION_VIEW)
                    .setComponent(ComponentName(context, MyCarAppService::class.java))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)))
        }
    }
}
public class MyNotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        if (ACTION_VIEW_PARKING_RESERVATION.equals(intentAction)) {
            CarContext.startCarApp(
                intent,
                new Intent(Intent.ACTION_VIEW)
                    .setComponent(new ComponentName(context, MyCarAppService.class))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)));
        }
    }
}

आखिर में, आपके ऐप्लिकेशन में मौजूद Session.onNewIntent तरीका, पार्किंग बुक करने की स्क्रीन को स्टैक पर डालकर इस इंटेंट को मैनेज करता है. ऐसा तब किया जाता है, जब यह स्क्रीन पहले से सबसे ऊपर न हो:

KotlinJava
override fun onNewIntent(intent: Intent) {
    val screenManager = carContext.getCarService(ScreenManager::class.java)
    val uri = intent.data
    if (uri != null
        && MY_URI_SCHEME == uri.scheme
        && MY_URI_HOST == uri.schemeSpecificPart
        && ACTION_VIEW_PARKING_RESERVATION == uri.fragment
    ) {
        val top = screenManager.top
        if (top !is ParkingReservationScreen) {
            screenManager.push(ParkingReservationScreen(carContext))
        }
    }
}
@Override
public void onNewIntent(@NonNull Intent intent) {
    ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
    Uri uri = intent.getData();
    if (uri != null
        && MY_URI_SCHEME.equals(uri.getScheme())
        && MY_URI_HOST.equals(uri.getSchemeSpecificPart())
        && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment())
    ) {
        Screen top = screenManager.getTop();
        if (!(top instanceof ParkingReservationScreen)) {
            screenManager.push(new ParkingReservationScreen(getCarContext()));
        }
    }
}

कार ऐप्लिकेशन की सूचनाओं को मैनेज करने के तरीके के बारे में ज़्यादा जानकारी के लिए, सूचनाएं दिखाएं सेक्शन देखें.

टेंप्लेट से जुड़ी पाबंदियां

होस्ट, किसी टास्क के लिए ज़्यादा से ज़्यादा पांच टेंप्लेट दिखा सकता है. इनमें से आखिरी टेंप्लेट इनमें से किसी एक तरह का होना चाहिए:

ध्यान दें कि यह सीमा, स्टैक में मौजूद टेम्प्लेट की संख्या पर लागू होती है, न कि Screen इंस्टेंस की संख्या पर. उदाहरण के लिए, अगर कोई ऐप्लिकेशन स्क्रीन A पर दो टेंप्लेट भेजता है और फिर स्क्रीन B पर पुश करता है, तो वह अब तीन और टेंप्लेट भेज सकता है. इसके अलावा, अगर हर स्क्रीन को एक टेंप्लेट भेजने के लिए व्यवस्थित किया गया है, तो ऐप्लिकेशन ScreenManager स्टैक पर पांच स्क्रीन इंस्टेंस को पुश कर सकता है.

इन पाबंदियों के कुछ खास मामले हैं: टेंप्लेट रीफ़्रेश करना और वापस जाना और रीसेट करना.

टेंप्लेट रीफ़्रेश होना

कॉन्टेंट के कुछ अपडेट, टेंप्लेट की सीमा में नहीं गिने जाते. आम तौर पर, अगर कोई ऐप्लिकेशन एक ही तरह का नया टेंप्लेट पॉश करता है और उसमें पिछले टेंप्लेट जैसा ही मुख्य कॉन्टेंट होता है, तो नए टेंप्लेट को कोटे में शामिल नहीं किया जाता. उदाहरण के लिए, ListTemplate में किसी पंक्ति के टॉगल स्टेटस को अपडेट करने पर, उसे कोटे में शामिल नहीं किया जाता. अलग-अलग टेंप्लेट के दस्तावेज़ देखें और जानें कि किस तरह के कॉन्टेंट अपडेट को रीफ़्रेश माना जा सकता है.

बैक ऑपरेशंस

किसी टास्क में सब-फ़्लो चालू करने के लिए, होस्ट यह पता लगाता है कि कोई ऐप्लिकेशन ScreenManager स्टैक से Screen कब पॉप कर रहा है. साथ ही, ऐप्लिकेशन के पीछे की ओर जाने वाले टेंप्लेट की संख्या के आधार पर, बचे हुए कोटा को अपडेट करता है.

उदाहरण के लिए, अगर ऐप्लिकेशन स्क्रीन A पर दो टेंप्लेट भेजता है, फिर स्क्रीन B पर पुश करता है और दो और टेंप्लेट भेजता है, तो ऐप्लिकेशन के पास एक कोटा बचता है. अगर ऐप्लिकेशन फिर से स्क्रीन A पर पॉप अप होता है, तो होस्ट कोटा को तीन पर रीसेट कर देता है, क्योंकि ऐप्लिकेशन दो टेंप्लेट पीछे चला गया है.

ध्यान दें कि किसी स्क्रीन पर वापस पॉप होने पर, ऐप्लिकेशन को एक ऐसा टेंप्लेट भेजना चाहिए जो उस स्क्रीन से आखिरी बार भेजे गए टेंप्लेट जैसा हो. किसी दूसरे तरह का टेंप्लेट भेजने पर गड़बड़ी होती है. हालांकि, जब तक बैक ऑपरेशन के दौरान टाइप एक जैसा रहता है, तब तक ऐप्लिकेशन कोटा पर असर डाले बिना टेंप्लेट के कॉन्टेंट में आसानी से बदलाव कर सकता है.

कार्रवाइयां रीसेट करना

कुछ टेंप्लेट में खास सेमेटिक्स होते हैं, जो किसी टास्क के खत्म होने का संकेत देते हैं. उदाहरण के लिए, NavigationTemplate एक ऐसा व्यू है जो स्क्रीन पर बना रहता है और उपयोगकर्ता के इस्तेमाल के लिए, हर बार नए निर्देशों के साथ रीफ़्रेश होता रहता है. जब यह इनमें से किसी टेंप्लेट पर पहुंच जाता है, तो होस्ट टेंप्लेट कोटा को रीसेट कर देता है. साथ ही, उस टेंप्लेट को नए टास्क के पहले चरण के तौर पर इस्तेमाल करता है. इससे ऐप्लिकेशन को नया टास्क शुरू करने में मदद मिलती है. अलग-अलग टेंप्लेट के दस्तावेज़ देखें और जानें कि कौनसे टेंप्लेट, होस्ट पर रीसेट को ट्रिगर करते हैं.

अगर होस्ट को सूचना कार्रवाई या लॉन्चर से ऐप्लिकेशन शुरू करने का इंटेंट मिलता है, तो कोटा भी रीसेट हो जाता है. इस तरीके से, ऐप्लिकेशन को सूचनाओं से नया टास्क फ़्लो शुरू करने में मदद मिलती है. भले ही, ऐप्लिकेशन पहले से ही बाउंड हो और फ़ोरग्राउंड में हो.

कार की स्क्रीन पर अपने ऐप्लिकेशन की सूचनाएं दिखाने के तरीके के बारे में ज़्यादा जानकारी के लिए, सूचनाएं दिखाएं सेक्शन देखें. सूचना से जुड़ी कार्रवाई से अपना ऐप्लिकेशन शुरू करने का तरीका जानने के लिए, इंटेंट की मदद से कार ऐप्लिकेशन शुरू करना सेक्शन देखें.

Connection API

रनटाइम के दौरान कनेक्शन की जानकारी पाने के लिए, CarConnection API का इस्तेमाल करके यह पता लगाया जा सकता है कि आपका ऐप्लिकेशन Android Auto पर चल रहा है या Android Automotive OS पर.

उदाहरण के लिए, अपनी कार के ऐप्लिकेशन के Session में, CarConnection शुरू करें और LiveData अपडेट की सदस्यता लें:

KotlinJava
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);

इसके बाद, ऑब्ज़र्वर में कनेक्शन की स्थिति में हुए बदलावों पर प्रतिक्रिया दी जा सकती है:

KotlinJava
fun onConnectionStateUpdated(connectionState: Int) {
  val message = when(connectionState) {
    CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit"
    CarConnection.CONNECTION_TYPE_NATIVE -> "Connected to Android Automotive OS"
    CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto"
    else -> "Unknown car connection type"
  }
  CarToast.makeText(carContext, message, CarToast.LENGTH_SHORT).show()
}
private void onConnectionStateUpdated(int connectionState) {
  String message;
  switch(connectionState) {
    case CarConnection.CONNECTION_TYPE_NOT_CONNECTED:
      message = "Not connected to a head unit";
      break;
    case CarConnection.CONNECTION_TYPE_NATIVE:
      message = "Connected to Android Automotive OS";
      break;
    case CarConnection.CONNECTION_TYPE_PROJECTION:
      message = "Connected to Android Auto";
      break;
    default:
      message = "Unknown car connection type";
      break;
  }
  CarToast.makeText(getCarContext(), message, CarToast.LENGTH_SHORT).show();
}

Constraints API

अलग-अलग कारों के लिए, उपयोगकर्ता को एक बार में अलग-अलग संख्या में Item इंस्टेंस दिखाए जा सकते हैं. रनटाइम के दौरान कॉन्टेंट की सीमा देखने के लिए, ConstraintManager का इस्तेमाल करें. साथ ही, अपने टेंप्लेट में आइटम की सही संख्या सेट करें.

CarContext से ConstraintManager पाकर शुरू करें:

KotlinJava
val manager = carContext.getCarService(ConstraintManager::class.java)
ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);

इसके बाद, कॉन्टेंट की सीमा के बारे में जानने के लिए, वापस लाए गए ConstraintManager ऑब्जेक्ट से क्वेरी की जा सकती है. उदाहरण के लिए, ग्रिड में दिखाए जा सकने वाले आइटम की संख्या जानने के लिए, CONTENT_LIMIT_TYPE_GRID के साथ getContentLimit को कॉल करें:

KotlinJava
val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)
int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);

साइन-इन फ़्लो जोड़ना

अगर आपका ऐप्लिकेशन, उपयोगकर्ताओं को साइन इन करने की सुविधा देता है, तो कार की हेड यूनिट पर अपने ऐप्लिकेशन में साइन इन करने की सुविधा को मैनेज करने के लिए, Car App API के लेवल 2 और उसके बाद के वर्शन के साथ SignInTemplate और LongMessageTemplate जैसे टेंप्लेट का इस्तेमाल किया जा सकता है.

SignInTemplate बनाने के लिए, SignInMethod तय करें. फ़िलहाल, कार ऐप्लिकेशन लाइब्रेरी में साइन इन करने के ये तरीके इस्तेमाल किए जा सकते हैं:

  • उपयोगकर्ता नाम/पासवर्ड से साइन इन करने के लिए, InputSignInMethod का इस्तेमाल करें.
  • PinSignInMethod पिन से साइन इन करने के लिए, जहां उपयोगकर्ता हेड यूनिट पर दिखाए गए पिन का इस्तेमाल करके, अपने फ़ोन से खाता लिंक करता है.
  • ProviderSignInMethod सेवा देने वाली कंपनी के साइन इन के लिए, जैसे कि Google साइन इन और One Tap.
  • QRCodeSignInMethod क्यूआर कोड से साइन इन करने के लिए, जहां उपयोगकर्ता अपने फ़ोन पर साइन इन करने के लिए क्यूआर कोड स्कैन करता है. यह सुविधा, Car API लेवल 4 और उसके बाद के वर्शन के साथ उपलब्ध है.

उदाहरण के लिए, उपयोगकर्ता का पासवर्ड इकट्ठा करने वाला टेंप्लेट लागू करने के लिए, उपयोगकर्ता के इनपुट को प्रोसेस और पुष्टि करने के लिए, InputCallback बनाएं:

KotlinJava
val callback = object : InputCallback {
    override fun onInputSubmitted(text: String) {
        // You will receive this callback when the user presses Enter on the keyboard.
    }

    override fun onInputTextChanged(text: String) {
        // You will receive this callback as the user is typing. The update
        // frequency is determined by the host.
    }
}
InputCallback callback = new InputCallback() {
    @Override
    public void onInputSubmitted(@NonNull String text) {
        // You will receive this callback when the user presses Enter on the keyboard.
    }

    @Override
    public void onInputTextChanged(@NonNull String text) {
        // You will receive this callback as the user is typing. The update
        // frequency is determined by the host.
    }
};

InputSignInMethod Builder के लिए InputCallback की ज़रूरत है.

KotlinJava
val passwordInput = InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build()
InputSignInMethod passwordInput = new InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build();

आखिर में, SignInTemplate बनाने के लिए अपने नए InputSignInMethod का इस्तेमाल करें.

KotlinJava
SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build()
new SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build();

AccountManager का इस्तेमाल करना

पुष्टि करने की सुविधा वाले Android Automotive OS ऐप्लिकेशन को इन वजहों से, AccountManager का इस्तेमाल करना होगा:

  • बेहतर यूज़र एक्सपीरियंस और खाता मैनेज करने में आसानी: उपयोगकर्ता, सिस्टम सेटिंग में मौजूद खातों के मेन्यू से अपने सभी खातों को आसानी से मैनेज कर सकते हैं. इसमें साइन-इन और साइन-आउट करना भी शामिल है.
  • "मेहमान" के लिए अनुभव: कारें शेयर किए जाने वाले डिवाइस होते हैं. इसलिए, OEM, वाहन में मेहमान के लिए अनुभव चालू कर सकते हैं. इसमें खाते नहीं जोड़े जा सकते.

टेक्स्ट स्ट्रिंग के वैरिएंट जोड़ना

कार की अलग-अलग स्क्रीन साइज़ पर, अलग-अलग टेक्स्ट दिख सकता है. Car App API के लेवल 2 और उसके बाद के वर्शन में, स्क्रीन पर सबसे सही तरीके से फ़िट करने के लिए, टेक्स्ट स्ट्रिंग के कई वैरिएंट तय किए जा सकते हैं. यह देखने के लिए कि टेक्स्ट वैरिएंट कहां स्वीकार किए जाते हैं, ऐसे टेंप्लेट और कॉम्पोनेंट ढूंढें जिनमें CarText का इस्तेमाल किया जाता है.

CarText.Builder.addVariant() के तरीके का इस्तेमाल करके, CarText में टेक्स्ट स्ट्रिंग के वैरिएंट जोड़े जा सकते हैं:

KotlinJava
val itemTitle = CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build()
CarText itemTitle = new CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build();

इसके बाद, इस CarText का इस्तेमाल किया जा सकता है. उदाहरण के लिए, GridItem के मुख्य टेक्स्ट के तौर पर.

KotlinJava
GridItem.Builder()
    .addTitle(itemTitle)
    ...
    .build()
new GridItem.Builder()
    .addTitle(itemTitle)
    ...
    build();

सबसे ज़्यादा से लेकर सबसे कम पसंदीदा क्रम में स्ट्रिंग जोड़ें. उदाहरण के लिए, सबसे लंबी से लेकर सबसे छोटी तक. होस्ट, कार की स्क्रीन पर उपलब्ध जगह के हिसाब से, सही लंबाई वाली स्ट्रिंग चुनता है.

लाइनों के लिए इनलाइन कार आइकॉन जोड़ना

CarIconSpan का इस्तेमाल करके, अपने ऐप्लिकेशन के विज़ुअल को बेहतर बनाने के लिए, टेक्स्ट के साथ इनलाइन आइकॉन जोड़े जा सकते हैं. इन स्पैन को बनाने के बारे में ज़्यादा जानने के लिए, CarIconSpan.create के दस्तावेज़ देखें. स्पैन की मदद से टेक्स्ट स्टाइल करने की सुविधा के काम करने के तरीके के बारे में खास जानकारी पाने के लिए, Spantastic के साथ टेक्स्ट स्टाइल करना लेख पढ़ें.

KotlinJava
  
val rating = SpannableString("Rating: 4.5 stars")
rating.setSpan(
    CarIconSpan.create(
        // Create a CarIcon with an image of four and a half stars
        CarIcon.Builder(...).build(),
        // Align the CarIcon to the baseline of the text
        CarIconSpan.ALIGN_BASELINE
    ),
    // The start index of the span (index of the character '4')
    8,
    // The end index of the span (index of the last 's' in "stars")
    16,
    Spanned.SPAN_INCLUSIVE_INCLUSIVE
)

val row = Row.Builder()
    ...
    .addText(rating)
    .build()
  
  
  
SpannableString rating = new SpannableString("Rating: 4.5 stars");
rating.setSpan(
        CarIconSpan.create(
                // Create a CarIcon with an image of four and a half stars
                new CarIcon.Builder(...).build(),
                // Align the CarIcon to the baseline of the text
                CarIconSpan.ALIGN_BASELINE
        ),
        // The start index of the span (index of the character '4')
        8,
        // The end index of the span (index of the last 's' in "stars")
        16,
        Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
Row row = new Row.Builder()
        ...
        .addText(rating)
        .build();
  
  

कार हार्डवेयर एपीआई

कार ऐप्लिकेशन एपीआई लेवल 3 से शुरू होकर, कार ऐप्लिकेशन लाइब्रेरी में ऐसे एपीआई हैं जिनका इस्तेमाल, वाहन की प्रॉपर्टी और सेंसर को ऐक्सेस करने के लिए किया जा सकता है.

ज़रूरी शर्तें

Android Auto के साथ एपीआई का इस्तेमाल करने के लिए, अपने Android Auto मॉड्यूल की build.gradle फ़ाइल में androidx.car.app:app-projected पर डिपेंडेंसी जोड़ें. Android Automotive OS के लिए, अपने Android Automotive OS मॉड्यूल की build.gradle फ़ाइल में androidx.car.app:app-automotive पर डिपेंडेंसी जोड़ें.

इसके अलावा, आपको अपनी AndroidManifest.xml फ़ाइल में, कार के उस डेटा का अनुरोध करने के लिए, ज़रूरी अनुमतियों का एलान करना होगा जिसका इस्तेमाल करना है. ध्यान दें कि उपयोगकर्ता को ये अनुमतियां भी आपको देनी होंगी. प्लैटफ़ॉर्म के हिसाब से फ़्लो बनाने के बजाय, Android Auto और Android Automotive OS, दोनों पर एक ही कोड का इस्तेमाल किया जा सकता है. हालांकि, इसके लिए ज़रूरी अनुमतियां अलग-अलग होती हैं.

CarInfo

इस टेबल में, CarInfo एपीआई से मिलने वाली प्रॉपर्टी और उनका इस्तेमाल करने के लिए, आपको जिन अनुमतियों का अनुरोध करना होगा उनके बारे में बताया गया है:

माटिंग में इस्तेमाल हुए तरीके प्रॉपर्टी Android Auto की अनुमतियां Android Automotive OS की अनुमतियां Car App API लेवल के बाद से काम करता है
fetchModel ब्रैंड, मॉडल, साल android.car.permission.CAR_INFO 3
fetchEnergyProfile ईवी कनेक्टर के टाइप, ईंधन के टाइप com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_INFO 3
fetchExteriorDimensions

यह डेटा, सिर्फ़ Android Automotive OS वाले उन वाहनों पर उपलब्ध है जिनमें एपीआई 30 या उसके बाद का वर्शन काम करता है

एक्सटीरियर डाइमेंशन लागू नहीं android.car.permission.CAR_INFO 7
addTollListener
removeTollListener
टोल कार्ड का स्टेटस, टोल कार्ड का टाइप 3
addEnergyLevelListener
removeEnergyLevelListener
बैटरी लेवल, ईंधन का लेवल, ईंधन का लेवल कम है, और बाकी बची रेंज com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_ENERGY,
android.car.permission.CAR_ENERGY_PORTS,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addSpeedListener
removeSpeedListener
रफ़्तार, डिसप्ले स्पीड (कार के क्लस्टर डिसप्ले पर दिखती है) com.google.android.gms.permission.CAR_SPEED android.car.permission.CAR_SPEED,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addMileageListener
removeMileageListener

चेतावनी: Mileage क्लास के getOdometerMeters मेथड का नाम गलत है और यह मीटर के बजाय, किलोमीटर दिखाता है.

ओडोमीटर की दूरी com.google.android.gms.permission.CAR_MILEAGE यह डेटा, Android Automotive OS पर Play Store से इंस्टॉल किए गए ऐप्लिकेशन के लिए उपलब्ध नहीं है. 3

उदाहरण के लिए, बाकी रेंज पाने के लिए, CarInfo ऑब्जेक्ट का इंस्टेंस बनाएं. इसके बाद, OnCarDataAvailableListener बनाएं और रजिस्टर करें:

KotlinJava
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo

val listener = OnCarDataAvailableListener<EnergyLevel> { data ->
    if (data.rangeRemainingMeters.status == CarValue.STATUS_SUCCESS) {
      val rangeRemaining = data.rangeRemainingMeters.value
    } else {
      // Handle error
    }
  }

carInfo.addEnergyLevelListener(carContext.mainExecutor, listener)

// Unregister the listener when you no longer need updates
carInfo.removeEnergyLevelListener(listener)
CarInfo carInfo = getCarContext().getCarService(CarHardwareManager.class).getCarInfo();

OnCarDataAvailableListener<EnergyLevel> listener = (data) -> {
  if(data.getRangeRemainingMeters().getStatus() == CarValue.STATUS_SUCCESS) {
    float rangeRemaining = data.getRangeRemainingMeters().getValue();
  } else {
    // Handle error
  }
};

carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(), listener);

// Unregister the listener when you no longer need updates
carInfo.removeEnergyLevelListener(listener);

यह मत सोचें कि कार का डेटा हमेशा उपलब्ध होता है. अगर आपको कोई गड़बड़ी दिखती है, तो जिस वैल्यू का अनुरोध किया गया है उसकी स्थिति देखें. इससे आपको यह समझने में मदद मिलेगी कि आपके अनुरोध किए गए डेटा को क्यों नहीं वापस पाया जा सका. CarInfo क्लास की पूरी परिभाषा जानने के लिए, रेफ़रंस दस्तावेज़ देखें.

CarSensors

CarSensors क्लास की मदद से, आपको वाहन के एक्सलरोमीटर, जाइरोस्कोप, कंपास, और जगह की जानकारी के डेटा का ऐक्सेस मिलता है. इन वैल्यू की उपलब्धता, OEM पर निर्भर हो सकती है. एक्सलरोमीटर, जाइरोस्कोप, और कंपास से मिले डेटा का फ़ॉर्मैट, वही है जो आपको SensorManager API से मिलेगा. उदाहरण के लिए, वाहन की हेडिंग देखने के लिए:

KotlinJava
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors

val listener = OnCarDataAvailableListener<Compass> { data ->
    if (data.orientations.status == CarValue.STATUS_SUCCESS) {
      val orientation = data.orientations.value
    } else {
      // Data not available, handle error
    }
  }

carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, carContext.mainExecutor, listener)

// Unregister the listener when you no longer need updates
carSensors.removeCompassListener(listener)
CarSensors carSensors = getCarContext().getCarService(CarHardwareManager.class).getCarSensors();

OnCarDataAvailableListener<Compass> listener = (data) -> {
  if (data.getOrientations().getStatus() == CarValue.STATUS_SUCCESS) {
    List<Float> orientations = data.getOrientations().getValue();
  } else {
    // Data not available, handle error
  }
};

carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, getCarContext().getMainExecutor(),
    listener);

// Unregister the listener when you no longer need updates
carSensors.removeCompassListener(listener);

कार से जगह की जानकारी का डेटा ऐक्सेस करने के लिए, आपको android.permission.ACCESS_FINE_LOCATION से अनुमति का अनुरोध करना होगा और इसकी जानकारी देनी होगी.

टेस्ट करना

Android Auto पर जांच करते समय सेंसर डेटा को सिम्युलेट करने के लिए, डेस्कटॉप हेड यूनिट की गाइड के सेंसर और सेंसर कॉन्फ़िगरेशन सेक्शन देखें. Android Automotive OS पर जांच करते समय सेंसर डेटा को सिम्युलेट करने के लिए, Android Automotive OS एमुलेटर गाइड का हार्डवेयर की स्थिति को एमुलेट करें सेक्शन देखें.

CarAppService, सेशन, और स्क्रीन के लाइफ़साइकल

Session और Screen क्लास, LifecycleOwner इंटरफ़ेस को लागू करती हैं. जब उपयोगकर्ता ऐप्लिकेशन के साथ इंटरैक्ट करता है, तो आपके Session और Screen ऑब्जेक्ट के लाइफ़साइकल कॉलबैक ट्रिगर होते हैं. इस बारे में यहां दिए गए डायग्राम में बताया गया है.

CarAppService और सेशन की लाइफ़साइकल

पहली इमेज. Session लाइफ़साइकल.

पूरी जानकारी के लिए, Session.getLifecycle के तरीके के दस्तावेज़ देखें.

स्क्रीन का लाइफ़साइकल

दूसरी इमेज. Screen लाइफ़साइकल.

पूरी जानकारी के लिए, Screen.getLifecycle तरीके के दस्तावेज़ देखें.

कार के माइक्रोफ़ोन से रिकॉर्ड करना

अपने ऐप्लिकेशन के CarAppService और CarAudioRecord एपीआई का इस्तेमाल करके, अपने ऐप्लिकेशन को उपयोगकर्ता की कार के माइक्रोफ़ोन का ऐक्सेस दिया जा सकता है. उपयोगकर्ताओं को कार के माइक्रोफ़ोन को ऐक्सेस करने के लिए, आपके ऐप्लिकेशन को अनुमति देनी होगी. आपका ऐप्लिकेशन, उपयोगकर्ता के इनपुट को रिकॉर्ड और प्रोसेस कर सकता है.

रिकॉर्ड करने की अनुमति

कोई ऑडियो रिकॉर्ड करने से पहले, आपको अपने AndroidManifest.xml में रिकॉर्ड करने की अनुमति का एलान करना होगा. साथ ही, उपयोगकर्ता से अनुमति देने का अनुरोध करना होगा.

<manifest ...>
   ...
   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   ...
</manifest>

आपको रनटाइम के दौरान रिकॉर्ड करने की अनुमति का अनुरोध करना होगा. अपने कार ऐप्लिकेशन में अनुमति का अनुरोध करने के तरीके के बारे में जानने के लिए, अनुमतियों का अनुरोध करें सेक्शन देखें.

ऑडियो रिकॉर्ड करने की अनुमति दें

उपयोगकर्ता से रिकॉर्ड करने की अनुमति मिलने के बाद, ऑडियो रिकॉर्ड किया जा सकता है और रिकॉर्डिंग को प्रोसेस किया जा सकता है.

KotlinJava
val carAudioRecord = CarAudioRecord.create(carContext)
        carAudioRecord.startRecording()

        val data = ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE)
        while(carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording()
 
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        carAudioRecord.startRecording();

        byte[] data = new byte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE];
        while (carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording();
 

ऑडियो फ़ोकस

कार के माइक्रोफ़ोन से रिकॉर्डिंग करते समय, पहले ऑडियो फ़ोकस सेट करें, ताकि यह पक्का किया जा सके कि चल रहा कोई भी मीडिया बंद हो गया है. अगर ऑडियो फ़ोकस नहीं मिलता है, तो रिकॉर्डिंग बंद करें.

ऑडियो फ़ोकस पाने का तरीका यहां बताया गया है:

KotlinJava
 
val carAudioRecord = CarAudioRecord.create(carContext)
        
        // Take audio focus so that user's media is not recorded
        val audioAttributes = AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            // Use the most appropriate usage type for your use case
            .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
            .build()
        
        val audioFocusRequest =
            AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                .setAudioAttributes(audioAttributes)
                .setOnAudioFocusChangeListener { state: Int ->
                    if (state == AudioManager.AUDIOFOCUS_LOSS) {
                        // Stop recording if audio focus is lost
                        carAudioRecord.stopRecording()
                    }
                }
                .build()
        
        if (carContext.getSystemService(AudioManager::class.java)
                .requestAudioFocus(audioFocusRequest)
            != AudioManager.AUDIOFOCUS_REQUEST_GRANTED
        ) {
            // Don't record if the focus isn't granted
            return
        }
        
        carAudioRecord.startRecording()
        // Process the audio and abandon the AudioFocusRequest when done
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        // Take audio focus so that user's media is not recorded
        AudioAttributes audioAttributes =
                new AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                        // Use the most appropriate usage type for your use case
                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
                        .build();

        AudioFocusRequest audioFocusRequest =
                new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                        .setAudioAttributes(audioAttributes)
                        .setOnAudioFocusChangeListener(state -> {
                            if (state == AudioManager.AUDIOFOCUS_LOSS) {
                                // Stop recording if audio focus is lost
                                carAudioRecord.stopRecording();
                            }
                        })
                        .build();

        if (getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)
                != AUDIOFOCUS_REQUEST_GRANTED) {
            // Don't record if the focus isn't granted
            return;
        }

        carAudioRecord.startRecording();
        // Process the audio and abandon the AudioFocusRequest when done
 

Testing Library

Android for Cars टेस्टिंग लाइब्रेरी, सहायक कक्षाएं उपलब्ध कराती है. इनका इस्तेमाल करके, टेस्टिंग एनवायरमेंट में अपने ऐप्लिकेशन के व्यवहार की पुष्टि की जा सकती है. उदाहरण के लिए, SessionController की मदद से, होस्ट से कनेक्शन को सिम्युलेट किया जा सकता है. साथ ही, यह पुष्टि की जा सकती है कि सही Screen और Template बनाए गए हैं और दिखाए गए हैं.

इस्तेमाल के उदाहरणों के लिए, सैंपल देखें.

'कार के लिए Android ऐप्लिकेशन' की लाइब्रेरी से जुड़ी समस्या की शिकायत करना

अगर आपको लाइब्रेरी में कोई समस्या मिलती है, तो Google समस्या ट्रैकर का इस्तेमाल करके उसकी शिकायत करें. समस्या के टेंप्लेट में, मांगी गई सभी जानकारी ज़रूर भरें.

नई समस्या बनाना

कोई नई समस्या दर्ज करने से पहले, कृपया देखें कि वह लाइब्रेरी के रिलीज़ नोट में दी गई सूची में शामिल है या समस्याओं की सूची में शामिल है. ट्रैकर में किसी समस्या के लिए स्टार पर क्लिक करके, उस पर सदस्यता ली जा सकती है और उस पर वोट किया जा सकता है. ज़्यादा जानकारी के लिए, किसी समस्या की सदस्यता लेना लेख पढ़ें.