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

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

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

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

  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 और बाद में Session उपलब्ध करा रहा है का इस्तेमाल करके हर कनेक्शन के लिए इंस्टेंस onCreateSession.
Session

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

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

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

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

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

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

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

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

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

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

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

    ...
<application>

इस्तेमाल किए जा सकने वाले ऐप्लिकेशन की कैटगरी

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

इनके लिए, कार के लिए 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 ऐप्लिकेशन एपीआई लेवल वापस पाने के लिए, getCarAppApiLevel() तरीका.

अपनी AndroidManifest.xml फ़ाइल:

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

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

अपना CarAppService और सेशन बनाएं

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

Kotlin

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

Java

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

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

Kotlin

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

Java

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

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

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

आप Screen क्लास और इसे लागू करना onGetTemplate तरीका, जो नतीजे के तौर पर Template इंस्टेंस, कार की स्क्रीन में दिखने वाली यूज़र इंटरफ़ेस (यूआई) की स्थिति.

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

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 को इस नंबर पर कॉल करके अमान्य किया जाएगा Screen.invalidate तरीका. इसके बाद, होस्ट आपके ऐप्लिकेशन के Screen.onGetTemplate तरीके का इस्तेमाल करके, नए कॉन्टेंट के साथ टेंप्लेट को वापस पाता है.

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

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

मैप बनाएं

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

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

प्लैटफ़ॉर्म को अनुमति दें

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

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

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

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

Kotlin

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

Java

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

सतह के दिखने वाले हिस्से के बारे में जानकारी

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

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

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

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

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

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

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

टेंप्लेट इंटरैक्टिविटी की सुविधा, 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, सेव नहीं किया जाता है बटन दिखाई देता है, तो इसे इससे उपयोगकर्ता इनपुट नहीं मिलता SurfaceCallback तरीके और होस्ट, पहले से चालू किसी भी तरीके को बंद कर देता है पैन मोड.

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

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

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

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

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

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

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

Kotlin

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

Java

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

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

Kotlin

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

Java

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

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

कुछ कार्रवाइयां, जैसे कि वे कार्रवाइयां जिन्हें जारी रखने के लिए उपयोगकर्ता को निर्देश देना ज़रूरी होता है मोबाइल डिवाइस पर इंटरैक्शन, सिर्फ़ कार पार्क होने पर ही किए जा सकते हैं. इन कार्रवाइयों को लागू करने के लिए, 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 की वैल्यू के साथ कॉल किया जाता है, तो सबसे ज़्यादा प्राथमिकता वाली सूचना, सिर्फ़ एक बार 'ज़्यादा सूचनाएं' के तौर पर दिखती है.

कार के ऐप्लिकेशन की सूचनाओं को डिज़ाइन करने के तरीके के बारे में ज़्यादा जानने के लिए, सूचनाओं के बारे में, ड्राइविंग के लिए 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 को शुरू किया जाता है:

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 स्टैक.

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

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

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

बैक ऑपरेशन

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

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

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

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

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

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

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

Connection API

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

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

Kotlin

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

Java

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

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

Kotlin

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

Java

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

कंस्ट्रेंट एपीआई

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

CarContext से ConstraintManager लें:

Kotlin

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

Java

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

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

Kotlin

val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)

Java

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

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

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

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

  • InputSignInMethod का इस्तेमाल करें.
  • PinSignInMethod पिन से साइन-इन करने के लिए, जहां उपयोगकर्ता अपने फ़ोन से अपने खाते को लिंक करता है मुख्य यूनिट पर दिखने वाले पिन का इस्तेमाल करके.
  • ProviderSignInMethod प्रोवाइडर साइन इन के लिए, जैसे कि Google साइन इन और One Tap.
  • QRCodeSignInMethod क्यूआर कोड साइन इन के लिए, जहां उपयोगकर्ता साइन-इन पूरा करने के लिए क्यूआर कोड स्कैन करता है उसका फ़ोन. यह सुविधा, Car API लेवल 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();

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

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 वाले ऐप्लिकेशन का इस्तेमाल करना ज़रूरी है Account Manager की ये वजहें हो सकती हैं:

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

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

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

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

Kotlin

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

Java

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

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

Kotlin

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

Java

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

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

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

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

Kotlin

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

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

Java

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

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

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

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

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

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

कार की जानकारी

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

माटिंग में इस्तेमाल हुए तरीके प्रॉपर्टी Android Auto की अनुमतियां Android Automotive OS की अनुमतियां यह सुविधा, कार ऐप्लिकेशन एपीआई लेवल पर काम करती है
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
ओडोमीटर की दूरी 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 क्लास की मदद से, आपको वाहन के एक्सलरोमीटर, जाइरोस्कोप, कंपास, और जगह की जानकारी के डेटा का ऐक्सेस मिलता है. इन वैल्यू की उपलब्धता, इन बातों पर निर्भर कर सकती है: ओईएम. एक्सलरोमीटर, जाइरोस्कोप, और कंपास से मिले डेटा का फ़ॉर्मैट, वही है जो आपको 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 क्लास, 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
 

टेस्टिंग लाइब्रेरी

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

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

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

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

नई समस्या जोड़ें

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