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

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

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

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

  1. कार के लिए ऐप्लिकेशन लाइब्रेरी के बारे में जानकारी देने वाले डिज़ाइन फ़ॉर ड्राइविंग पेज देखें
  2. यहां दिए गए सेक्शन में, अहम शब्दों और कॉन्सेप्ट के बारे में जानें.
  3. Android Auto System UI और 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 दिखाने का अनुरोध करता है.

Car App Library इंस्टॉल करना

अपनी लाइब्रेरी को अपने ऐप्लिकेशन में जोड़ने का तरीका जानने के लिए, 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 ऐप्लिकेशन की क्वालिटी देखें.

इस कैटगरी का इस्तेमाल, उपयोगकर्ताओं को Play Store में उनके काम के ऐप्लिकेशन खोजने में मदद करने के लिए किया जाता है.

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

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

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 लेवल

Car App Library, अपने एपीआई लेवल तय करती है. इससे आपको यह पता चल सकता है कि किसी वाहन पर टेंप्लेट होस्ट करने वाले ऐप्लिकेशन के साथ, लाइब्रेरी की कौनसी सुविधाएं काम करती हैं. होस्ट के साथ काम करने वाले सबसे नए 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 एनोटेशन से जुड़ा दस्तावेज़ देखें. Car App Library की किसी सुविधा का इस्तेमाल करने के लिए, किस एपीआई लेवल की ज़रूरत होती है, इसकी परिभाषा जानने के लिए CarAppApiLevels का रेफ़रंस दस्तावेज़ देखें.

CarAppService और Session बनाएं

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

Kotlin

class HelloWorldService : CarAppService() {
    ...
    override fun onCreateSession(): Session {
        return HelloWorldSession()
    }
    ...
}

Java

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

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

Kotlin

class HelloWorldSession : Session() {
    ...
    override fun onCreateScreen(intent: Intent): Screen {
        return HelloWorldScreen(carContext)
    }
    ...
}

Java

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

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

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

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

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

Kotlin

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

Java

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

CarContext क्लास

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

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

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

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

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

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

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

Kotlin

val template = MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener { screenManager.push(NextScreen(carContext)) }
            .build())
    .build()

Java

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

Action.BACK ऑब्जेक्ट, एक स्टैंडर्ड Action है, जो ScreenManager.pop को अपने-आप चालू करता है. इस व्यवहार को बदलने के लिए, 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 (deprecated) androidx.car.app.NAVIGATION_TEMPLATES एक हिस्से से दूसरे हिस्से पर जाना
PlaceListNavigationTemplate (deprecated) androidx.car.app.NAVIGATION_TEMPLATES एक हिस्से से दूसरे हिस्से पर जाना
RoutePreviewNavigationTemplate (deprecated) androidx.car.app.NAVIGATION_TEMPLATES एक हिस्से से दूसरे हिस्से पर जाना

सरफ़ेस की अनुमति का एलान करना

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

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

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

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

Kotlin

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

Java

carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

कॉन्टेंट रेंडर करने के लिए वर्चुअल डिसप्ले का इस्तेमाल करना

Canvas एपीआई का इस्तेमाल करके, सीधे Surface में रेंडर करने के अलावा, VirtualDisplay और Presentation एपीआई का इस्तेमाल करके भी, Surface में व्यू रेंडर किए जा सकते हैं. इस उदाहरण में दिखाया गया है:

class HelloWorldSurfaceCallback(context: Context) : SurfaceCallback {
  lateinit var virtualDisplay: VirtualDisplay
  lateinit var presentation: Presentation

  override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
      virtualDisplay = context
          .getSystemService(DisplayManager::class.java)
          .createVirtualDisplay(
              VIRTUAL_DISPLAY_NAME ,
              surfaceContainer.width,
              surfaceContainer.height,
              surfaceContainer.dpi,
              surfaceContainer.surface,
              0
          )

      presentation = Presentation(context, virtualDisplay.display)

      // Instantiate the view to be used as the content view
      val view = ...

      presentation.setContentView(view)
      presentation.show()
  }

  override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
    presentation.dismiss()
    // This handles releasing the Surface provided when creating the VirtualDisplay
    virtualDisplay.release()
  }
}

वर्चुअल डिसप्ले पर रेंडर करने के लिए, कंपोज़ का इस्तेमाल करना

Presentation के कॉन्टेंट व्यू के तौर पर, ComposeView का इस्तेमाल किया जा सकता है. ComposeView का इस्तेमाल किसी गतिविधि से बाहर किया जाता है. इसलिए, आपको यह पक्का करना होगा कि यह या कोई पैरंट व्यू, LifecycleOwner और SavedStateRegistryOwner को आगे बढ़ाता हो. इसके लिए, setViewTreeLifecycleOwner और setViewTreeSavedStateRegistryOwner का इस्तेमाल करें.

Session पहले से ही LifecycleOwner लागू करता है. साथ ही, आपका लागू किया गया कोड, दोनों भूमिकाओं को पूरा करने के लिए SavedStateRegistryOwner को भी लागू कर सकता है.

class HelloWorldSession() : Session(), SavedStateRegistryOwner { ... }

class HelloWorldSurfaceCallback(session: HelloWorldSession) : SurfaceCallback {
  ...

  override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
    ...
    val view = ComposeView(session.carContext)
    view.setViewTreeLifecycleOwner(session)
    view.setViewTreeSavedStateRegistryOwner(session)
    view.setContent {
      // Composable content
    }

    presentation.setContentView(view)
    presentation.show()
  }

  ...
}

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

होस्ट, मैप के ऊपर टेंप्लेट के लिए यूज़र इंटरफ़ेस एलिमेंट बना सकता है. होस्ट, 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 (introduction of template)

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

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

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

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

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

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

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

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

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

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

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

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

उपयोगकर्ता के इनपुट को हैंडल करना

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

Kotlin

val action = Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(::onClickNavigate)
    .build()

Java

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

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

Kotlin

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

Java

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

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

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

Kotlin

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

Java

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

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

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

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

Kotlin

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

Java

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

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

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

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

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

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

टोस्ट दिखाएं

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

Kotlin

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

Java

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

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

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

स्टैंडर्ड 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 शामिल है:

Kotlin

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

Java

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

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

Kotlin

class MyNotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val intentAction = intent.action
        if (ACTION_VIEW_PARKING_RESERVATION == intentAction) {
            CarContext.startCarApp(
                intent,
                Intent(Intent.ACTION_VIEW)
                    .setComponent(ComponentName(context, MyCarAppService::class.java))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)))
        }
    }
}

Java

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

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

Kotlin

override fun onNewIntent(intent: Intent) {
    val screenManager = carContext.getCarService(ScreenManager::class.java)
    val uri = intent.data
    if (uri != null
        && MY_URI_SCHEME == uri.scheme
        && MY_URI_HOST == uri.schemeSpecificPart
        && ACTION_VIEW_PARKING_RESERVATION == uri.fragment
    ) {
        val top = screenManager.top
        if (top !is ParkingReservationScreen) {
            screenManager.push(ParkingReservationScreen(carContext))
        }
    }
}

Java

@Override
public void onNewIntent(@NonNull Intent intent) {
    ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
    Uri uri = intent.getData();
    if (uri != null
        && MY_URI_SCHEME.equals(uri.getScheme())
        && MY_URI_HOST.equals(uri.getSchemeSpecificPart())
        && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment())
    ) {
        Screen top = screenManager.getTop();
        if (!(top instanceof ParkingReservationScreen)) {
            screenManager.push(new ParkingReservationScreen(getCarContext()));
        }
    }
}

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

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

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

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

चलाने के बाद, logcat आउटपुट में चरणों की मौजूदा संख्या देखी जा सकती है.

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

टेंप्लेट रीफ़्रेश होते हैं

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

बैक ऑपरेशन

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

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

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

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

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

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

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

Connection API

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

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

Kotlin

CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)

Java

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

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

Kotlin

fun onConnectionStateUpdated(connectionState: Int) {
  val message = when(connectionState) {
    CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit"
    CarConnection.CONNECTION_TYPE_NATIVE -> "Connected to Android Automotive OS"
    CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto"
    else -> "Unknown car connection type"
  }
  CarToast.makeText(carContext, message, CarToast.LENGTH_SHORT).show()
}

Java

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

Constraints API

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

सबसे पहले, CarContext से ConstraintManager पाएं:

Kotlin

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

Java

ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);

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

Kotlin

val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)

Java

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

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

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

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

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

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

Kotlin

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

    override fun onInputTextChanged(text: String) {
        // You will receive this callback as the user is typing. The update
        // frequency is determined by the host.
    }
}

Java

InputCallback callback = new InputCallback() {
    @Override
    public void onInputSubmitted(@NonNull String text) {
        // You will receive this callback when the user presses Enter on the keyboard.
    }

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

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

Kotlin

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

Java

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

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

Kotlin

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

Java

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

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

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

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

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

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

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

Kotlin

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

Java

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

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

Kotlin

GridItem.Builder()
    .addTitle(itemTitle)
    ...
    .build()

Java

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

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

पंक्तियों के लिए इनलाइन CarIcon जोड़ना

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

Kotlin

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

val row = Row.Builder()
    ...
    .addText(rating)
    .build()
  
  

Java

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

कार के हार्डवेयर से जुड़े एपीआई

Car App API लेवल 3 से, Car App Library में ऐसे एपीआई उपलब्ध हैं जिनका इस्तेमाल करके, वाहन की प्रॉपर्टी और सेंसर ऐक्सेस किए जा सकते हैं.

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

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 बनाएं और रजिस्टर करें:

Kotlin

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

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

carInfo.addEnergyLevelListener(carContext.mainExecutor, listener)

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

Java

CarInfo carInfo = getCarContext().getCarService(CarHardwareManager.class).getCarInfo();

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

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

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

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

CarSensors

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

Kotlin

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

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

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

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

Java

CarSensors carSensors = getCarContext().getCarService(CarHardwareManager.class).getCarSensors();

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

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

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

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

टेस्ट करना

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

CarAppService, Session, और Screen की लाइफ़साइकल

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>

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

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

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

Kotlin

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

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

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        carAudioRecord.startRecording();

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

ऑडियो फ़ोकस

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

ऑडियो फ़ोकस पाने का एक उदाहरण यहां दिया गया है:

Kotlin

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

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        // Take audio focus so that user's media is not recorded
        AudioAttributes audioAttributes =
                new AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                        // Use the most appropriate usage type for your use case
                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
                        .build();

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

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

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

Testing Library

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

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

Android for Cars App Library से जुड़ी किसी समस्या की शिकायत करना

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

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

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