একটি নেভিগেশন অ্যাপ তৈরি করুন

এই পৃষ্ঠায় কার অ্যাপ লাইব্রেরির বিভিন্ন বৈশিষ্ট্য বিস্তারিতভাবে বর্ণনা করা হয়েছে, যা ব্যবহার করে আপনি আপনার টার্ন-বাই-টার্ন নেভিগেশন অ্যাপের কার্যকারিতা বাস্তবায়ন করতে পারবেন।

আপনার ম্যানিফেস্টে নেভিগেশন সাপোর্ট ঘোষণা করুন।

আপনার নেভিগেশন অ্যাপটিকে তার CarAppService এর ইন্টেন্ট ফিল্টারে androidx.car.app.category.NAVIGATION কার অ্যাপ ক্যাটাগরিটি ঘোষণা করতে হবে:

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

নেভিগেশন অভিপ্রায় সমর্থন করুন

বিভিন্ন ধরনের ইনটেন্ট ফরম্যাট নেভিগেশন অ্যাপগুলোকে অন্যান্য অ্যাপের সাথে, যেমন পয়েন্ট অফ ইন্টারেস্ট অ্যাপ এবং ভয়েস অ্যাসিস্ট্যান্টের সাথে, কাজ করতে সক্ষম করে।

এই ইনটেন্ট ফরম্যাটগুলো সমর্থন করার জন্য, প্রথমে আপনার অ্যাপের ম্যানিফেস্টে ইনটেন্ট ফিল্টার যোগ করে সমর্থন ঘোষণা করুন। এই ইনটেন্ট ফিল্টারগুলোর অবস্থান প্ল্যাটফর্মের উপর নির্ভর করে:

  • অ্যান্ড্রয়েড অটো : যখন কোনো ব্যবহারকারী অ্যান্ড্রয়েড অটো ব্যবহার করছেন না, তখন ইন্টেন্টটি হ্যান্ডেল করার জন্য ব্যবহৃত Activity <activity> ম্যানিফেস্ট এলিমেন্টের মধ্যে।
  • অ্যান্ড্রয়েড অটোমোটিভ ওএস : CarAppActivity এর <activity> ম্যানিফেস্ট এলিমেন্টের মধ্যে।

এরপর, আপনার অ্যাপের Session ইমপ্লিমেন্টেশনে থাকা onCreateScreen() এবং onNewIntent() উভয় কলব্যাকে ইনটেন্টগুলো পড়ুন এবং সেগুলোর ব্যবস্থা নিন।

প্রয়োজনীয় অভিপ্রায় ফর্ম্যাট

NF-6 গুণমানের প্রয়োজনীয়তা পূরণ করতে হলে, আপনার অ্যাপকে অবশ্যই নেভিগেশন ইনটেন্ট পরিচালনা করতে হবে।

ঐচ্ছিক অভিপ্রায় ফর্ম্যাট

আপনার অ্যাপের আন্তঃকার্যক্ষমতা আরও বাড়ানোর জন্য আপনি নিম্নলিখিত ইন্টেন্ট ফরম্যাটগুলোও সমর্থন করতে পারেন:

নেভিগেশন টেমপ্লেটগুলি অ্যাক্সেস করুন

নেভিগেশন অ্যাপগুলো নিম্নলিখিত টেমপ্লেটগুলো অ্যাক্সেস করতে পারে, যেগুলো ব্যাকগ্রাউন্ডে ম্যাপসহ একটি সারফেস প্রদর্শন করে এবং সক্রিয় নেভিগেশনের সময় ধাপে ধাপে দিকনির্দেশনা দেয়।

  • NavigationTemplate : একটি টেমপ্লেট যা সক্রিয় নেভিগেশন চলাকালীন একটি ঐচ্ছিক তথ্যমূলক বার্তা এবং ভ্রমণের আনুমানিক সময় প্রদর্শন করে।
  • MapWithContentTemplate : একটি টেমপ্লেট যা একটি অ্যাপকে কোনো ধরনের কন্টেন্ট (যেমন, একটি তালিকা) সহ ম্যাপ টাইলস রেন্ডার করার সুযোগ দেয়। কন্টেন্টটি সাধারণত ম্যাপ টাইলসের উপরে একটি ওভারলে হিসেবে রেন্ডার করা হয়, যেখানে ম্যাপটি দৃশ্যমান থাকে এবং স্থিতিশীল এলাকাগুলো কন্টেন্টের সাথে সামঞ্জস্যপূর্ণ হয়।

এই টেমপ্লেটগুলো ব্যবহার করে কীভাবে আপনার নেভিগেশন অ্যাপের ইউজার ইন্টারফেস ডিজাইন করবেন সে সম্পর্কে আরও বিস্তারিত জানতে, নেভিগেশন অ্যাপস দেখুন।

ন্যাভিগেশন টেমপ্লেটগুলো অ্যাক্সেস করার জন্য, আপনার অ্যাপকে তার AndroidManifest.xml ফাইলে androidx.car.app.NAVIGATION_TEMPLATES পারমিশনটি ডিক্লেয়ার করতে হবে:

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

মানচিত্র আঁকতে অতিরিক্ত অনুমতির প্রয়োজন হয়।

MapWithContentTemplate-এ স্থানান্তরিত করুন

কার অ্যাপ এপিআই লেভেল ৭ থেকে MapTemplate , PlaceListNavigationTemplate এবং RoutePreviewNavigationTemplate টেমপ্লেটগুলো অপ্রচলিত (deprecated) বলে গণ্য করা হচ্ছে। অপ্রচলিত টেমপ্লেটগুলোর সাপোর্ট অব্যাহত থাকবে, তবে MapWithContentTemplate এ স্থানান্তরিত হওয়ার জন্য দৃঢ়ভাবে সুপারিশ করা হচ্ছে।

এই টেমপ্লেটগুলো দ্বারা প্রদত্ত কার্যকারিতা MapWithContentTemplate ব্যবহার করে প্রয়োগ করা যেতে পারে। উদাহরণস্বরূপ নিম্নলিখিত কোড স্নিপেটগুলো দেখুন:

মানচিত্র টেমপ্লেট

// MapTemplate (deprecated)
val templateDeprecated = MapTemplate.Builder()
    .setPane(paneBuilder.build())
    .setActionStrip(actionStrip)
    .setHeader(header)
    .setMapController(mapController)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        PaneTemplate.Builder(paneBuilder.build())
            .setHeader(header)
            .build()
    )
    .setActionStrip(actionStrip)
    .setMapController(mapController)
    .build()

স্থানতালিকা নেভিগেশন টেমপ্লেট

// PlaceListNavigationTemplate (deprecated)
val templateDeprecated = PlaceListNavigationTemplate.Builder()
    .setItemList(itemListBuilder.build())
    .setHeader(header)
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(itemListBuilder.build())
            .setHeader(header)
            .build()
    )
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build()
    )
    .build()

রুটপ্রিভিউ নেভিগেশন টেমপ্লেট

// RoutePreviewNavigationTemplate (deprecated)
val templateDeprecated = RoutePreviewNavigationTemplate.Builder()
    .setItemList(
        ItemList.Builder()
            .addItem(
                Row.Builder()
                    .setTitle(title)
                    .build()
            )
            .build()
    )
    .setHeader(header)
    .setNavigateAction(
        Action.Builder()
            .setTitle(actionTitle)
            .setOnClickListener { /* onClick */ }
            .build()
    )
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(
                ItemList.Builder()
                    .addItem(
                        Row.Builder()
                            .setTitle(title)
                            .addAction(
                                Action.Builder()
                                    .setTitle(actionTitle)
                                    .setOnClickListener { /* onClick */ }
                                    .build()
                            )
                            .build()
                    )
                    .build()
            )
            .setHeader(header)
            .build()
    )
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build()
    )
    .build()

নেভিগেশন অ্যাপগুলোকে অবশ্যই হোস্টের সাথে অতিরিক্ত নেভিগেশন মেটাডেটা আদান-প্রদান করতে হয়। হোস্ট এই তথ্য ব্যবহার করে গাড়ির হেড ইউনিটকে তথ্য সরবরাহ করে এবং শেয়ার করা রিসোর্স নিয়ে নেভিগেশন অ্যাপ্লিকেশনগুলোর মধ্যে সংঘর্ষ প্রতিরোধ করে।

নেভিগেশন মেটাডেটা CarContext থেকে অ্যাক্সেসযোগ্য NavigationManager কার সার্ভিসের মাধ্যমে প্রদান করা হয়:

val navigationManager = carContext.getCarService(NavigationManager::class.java)

নেভিগেশন শুরু, শেষ এবং বন্ধ করুন

একাধিক নেভিগেশন অ্যাপ, রাউটিং নোটিফিকেশন এবং যানবাহন ক্লাস্টার ডেটা পরিচালনা করার জন্য হোস্টকে নেভিগেশনের বর্তমান অবস্থা সম্পর্কে অবগত থাকতে হয়। যখন কোনো ব্যবহারকারী নেভিগেশন শুরু করেন, তখন NavigationManager.navigationStarted কল করুন। একইভাবে, যখন নেভিগেশন শেষ হয় — উদাহরণস্বরূপ, যখন ব্যবহারকারী তার গন্তব্যে পৌঁছান বা নেভিগেশন বাতিল করেন — তখন NavigationManager.navigationEnded কল করুন।

ব্যবহারকারী নেভিগেট করা শেষ করলেই কেবল NavigationManager.navigationEnded কল করুন। উদাহরণস্বরূপ, যদি ভ্রমণের মাঝপথে আপনার রুট পুনরায় গণনা করার প্রয়োজন হয়, তাহলে এর পরিবর্তে Trip.Builder.setLoading(true) ব্যবহার করুন।

মাঝে মাঝে, হোস্টের কোনো অ্যাপকে নেভিগেশন বন্ধ করার প্রয়োজন হয় এবং এর জন্য NavigationManager.setNavigationManagerCallback এর মাধ্যমে আপনার অ্যাপ দ্বারা সরবরাহকৃত একটি NavigationManagerCallback অবজেক্টে onStopNavigation কল করে। এরপর অ্যাপটিকে অবশ্যই ক্লাস্টার ডিসপ্লেতে পরবর্তী মোড়ের তথ্য, নেভিগেশন নোটিফিকেশন এবং ভয়েস গাইডেন্স প্রদান বন্ধ করতে হবে।

ভ্রমণের তথ্য আপডেট করুন

সক্রিয় নেভিগেশন চলাকালীন, NavigationManager.updateTrip কল করুন। এই কলে প্রদত্ত তথ্য গাড়ির ক্লাস্টার এবং হেডস-আপ ডিসপ্লে ব্যবহার করতে পারে। চালিত নির্দিষ্ট গাড়ির উপর নির্ভর করে, সমস্ত তথ্য ব্যবহারকারীকে দেখানো হয় না। উদাহরণস্বরূপ, ডেস্কটপ হেড ইউনিট (DHU) Trip যুক্ত হওয়া Step দেখায়, কিন্তু Destination তথ্য দেখায় না।

ক্লাস্টার ডিসপ্লেতে অঙ্কন

ব্যবহারকারীকে সবচেয়ে আকর্ষণীয় অভিজ্ঞতা দেওয়ার জন্য, আপনি গাড়ির ক্লাস্টার ডিসপ্লেতে শুধু সাধারণ মেটাডেটা দেখানোর বাইরেও যেতে চাইতে পারেন। কার অ্যাপ এপিআই লেভেল ৬ থেকে শুরু করে, নেভিগেশন অ্যাপগুলোর কাছে ক্লাস্টার ডিসপ্লেতে সরাসরি তাদের নিজস্ব কন্টেন্ট রেন্ডার করার বিকল্প রয়েছে (সমর্থিত যানবাহনগুলোতে), তবে নিম্নলিখিত সীমাবদ্ধতাগুলো প্রযোজ্য:

  • ক্লাস্টার ডিসপ্লে এপিআই ইনপুট নিয়ন্ত্রণ সমর্থন করে না।
  • গাড়ির অ্যাপের গুণমান নির্দেশিকা NF-9 : ক্লাস্টার ডিসপ্লেতে শুধুমাত্র ম্যাপ টাইলস দেখানো উচিত। এই টাইলসগুলিতে ঐচ্ছিকভাবে একটি সক্রিয় নেভিগেশন রুট প্রদর্শন করা যেতে পারে।
  • ক্লাস্টার ডিসপ্লে এপিআই শুধুমাত্র NavigationTemplate ব্যবহার সমর্থন করে।
    • মূল ডিসপ্লের বিপরীতে, ক্লাস্টার ডিসপ্লেতে পর্যায়ক্রমে নির্দেশনা, ETA কার্ড এবং অ্যাকশনের মতো NavigationTemplate সমস্ত UI উপাদান ধারাবাহিকভাবে নাও দেখানো হতে পারে। ম্যাপ টাইলস হলো একমাত্র UI উপাদান যা ধারাবাহিকভাবে প্রদর্শিত হয়।

ক্লাস্টার সমর্থন ঘোষণা করুন

আপনার অ্যাপ যে ক্লাস্টার ডিসপ্লেতে রেন্ডারিং সমর্থন করে, তা হোস্ট অ্যাপ্লিকেশনকে জানানোর জন্য, আপনাকে অবশ্যই আপনার CarAppService এর <intent-filter> এ একটি androidx.car.app.category.FEATURE_CLUSTER <category> এলিমেন্ট যোগ করতে হবে, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:

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

জীবনচক্র এবং অবস্থা ব্যবস্থাপনা

এপিআই লেভেল ৬ থেকে শুরু করে, কার অ্যাপের লাইফসাইকেল ফ্লো একই থাকে, কিন্তু এখন CarAppService::onCreateSession SessionInfo টাইপের একটি প্যারামিটার গ্রহণ করে, যা তৈরি হতে থাকা Session সম্পর্কে অতিরিক্ত তথ্য প্রদান করে (যেমন, ডিসপ্লে টাইপ এবং সমর্থিত টেমপ্লেটগুলোর সেট)।

অ্যাপগুলোর কাছে দুটি বিকল্প রয়েছে: হয় ক্লাস্টার এবং মূল ডিসপ্লে উভয়কে পরিচালনা করার জন্য একই Session ক্লাস ব্যবহার করা, অথবা প্রতিটি ডিসপ্লের আচরণ কাস্টমাইজ করার জন্য ডিসপ্লে-নির্দিষ্ট Sessions তৈরি করা (যেমনটি নিচের কোড স্নিপেটে দেখানো হয়েছে)।

override fun onCreateSession(sessionInfo: SessionInfo): Session {
    return if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) {
        ClusterSession()
    } else {
        MainDisplaySession()
    }
}

ক্লাস্টার ডিসপ্লে কখন বা আদৌ প্রদান করা হবে কিনা, সে বিষয়ে কোনো নিশ্চয়তা নেই, এবং এমনও হতে পারে যে ক্লাস্টার Session একমাত্র Session (উদাহরণস্বরূপ, আপনার অ্যাপ সক্রিয়ভাবে নেভিগেট করার সময় ব্যবহারকারী মূল ডিসপ্লেটি অন্য কোনো অ্যাপে পরিবর্তন করে নিলেন)। "প্রমিত" নিয়মটি হলো, NavigationManager::navigationStarted কল করার পরেই অ্যাপটি ক্লাস্টার ডিসপ্লের নিয়ন্ত্রণ লাভ করে। তবে, এমনও হতে পারে যে কোনো সক্রিয় নেভিগেশন না থাকা সত্ত্বেও অ্যাপটি ক্লাস্টার ডিসপ্লে পেয়ে গেল, অথবা কখনোই ক্লাস্টার ডিসপ্লে পেল না। ম্যাপ টাইলগুলোর নিষ্ক্রিয় অবস্থা রেন্ডার করার মাধ্যমে এই পরিস্থিতিগুলো সামাল দেওয়ার দায়িত্ব আপনার অ্যাপেরই।

হোস্ট প্রতিটি Session জন্য আলাদা বাইন্ডার এবং CarContext ইনস্ট্যান্স তৈরি করে। এর মানে হলো, যখন ScreenManager::push বা Screen::invalidate মতো মেথড ব্যবহার করা হয়, তখন শুধুমাত্র সেই Session প্রভাবিত হয় যেখান থেকে সেগুলোকে কল করা হয়। যদি একাধিক Session মধ্যে যোগাযোগের প্রয়োজন হয়, তবে অ্যাপগুলোর উচিত এই ইনস্ট্যান্সগুলোর মধ্যে নিজস্ব যোগাযোগ চ্যানেল তৈরি করা (উদাহরণস্বরূপ, ব্রডকাস্ট , একটি শেয়ার্ড সিঙ্গেলটন বা অন্য কিছু ব্যবহার করে)।

টেস্টিং ক্লাস্টার সাপোর্ট

আপনি আপনার ইমপ্লিমেন্টেশনটি অ্যান্ড্রয়েড অটো এবং অ্যান্ড্রয়েড অটোমোটিভ ওএস উভয়টিতেই পরীক্ষা করতে পারেন। অ্যান্ড্রয়েড অটোর ক্ষেত্রে, ডেস্কটপ হেড ইউনিটকে একটি সেকেন্ডারি ক্লাস্টার ডিসপ্লে অনুকরণ করার জন্য কনফিগার করতে হয়। অ্যান্ড্রয়েড অটোমোটিভ ওএস-এর জন্য, এপিআই লেভেল ৩০ এবং তার উপরের জেনেরিক সিস্টেম ইমেজগুলো একটি ক্লাস্টার ডিসপ্লে অনুকরণ করে।

টেক্সট বা আইকন দিয়ে TravelEstimate কাস্টমাইজ করুন

টেক্সট, আইকন বা উভয়টি দিয়ে ভ্রমণের আনুমানিক সময় কাস্টমাইজ করতে, TravelEstimate.Builder ক্লাসের setTripIcon বা setTripText মেথডগুলো ব্যবহার করুন। NavigationTemplate , আনুমানিক পৌঁছানোর সময়, অবশিষ্ট সময় এবং অবশিষ্ট দূরত্বের পাশাপাশি বা সেগুলোর পরিবর্তে ঐচ্ছিকভাবে টেক্সট ও আইকন সেট করার জন্য TravelEstimate ব্যবহার করে।

চিত্র ১. নিজস্ব আইকন ও লেখা সহ ভ্রমণের আনুমানিক হিসাব।

নিম্নলিখিত কোড স্নিপেটটি ভ্রমণের আনুমানিক খরচ কাস্টমাইজ করতে setTripIcon এবং setTripText ব্যবহার করে:

TravelEstimate.Builder(
    Distance.create(350.0, Distance.UNIT_METERS),
    arrivalTimeAtDestination
)
    .setTripIcon(
        CarIcon.Builder(
            IconCompat.createWithResource(carContext, R.drawable.ic_garage)
        ).build()
    )
    .setTripText(CarText.create("Custom Text"))
    .build()

ধাপে ধাপে বিজ্ঞপ্তি প্রদান করুন

নিয়মিত আপডেট হওয়া একটি নেভিগেশন নোটিফিকেশন ব্যবহার করে ধাপে ধাপে (TBT) নেভিগেশন নির্দেশনা প্রদান করুন। গাড়ির স্ক্রিনে একটি নেভিগেশন নোটিফিকেশন হিসেবে বিবেচিত হওয়ার জন্য, আপনার নোটিফিকেশনের নির্মাতাকে অবশ্যই নিম্নলিখিত কাজগুলো করতে হবে:

  1. NotificationCompat.Builder.setOngoing মেথড ব্যবহার করে নোটিফিকেশনটিকে চলমান হিসেবে চিহ্নিত করুন।
  2. নোটিফিকেশনের ক্যাটাগরি Notification.CATEGORY_NAVIGATION এ সেট করুন।
  3. CarAppExtender ব্যবহার করে নোটিফিকেশনটির পরিধি বাড়ান।

গাড়ির স্ক্রিনের নীচে রেল উইজেটে একটি ন্যাভিগেশন নোটিফিকেশন প্রদর্শিত হয়। যদি নোটিফিকেশনটির গুরুত্বের স্তর IMPORTANCE_HIGH এ সেট করা থাকে, তবে এটি একটি হেডস-আপ নোটিফিকেশন (HUN) হিসেবেও প্রদর্শিত হয়। যদি CarAppExtender.Builder.setImportance মেথড ব্যবহার করে গুরুত্ব সেট করা না হয়, তবে নোটিফিকেশন চ্যানেলের গুরুত্ব ব্যবহার করা হয়।

অ্যাপটি CarAppExtender এ একটি PendingIntent সেট করতে পারে, যা ব্যবহারকারী HUN বা রেল উইজেটে ট্যাপ করলে অ্যাপে পাঠানো হয়।

যদি NotificationCompat.Builder.setOnlyAlertOnce true মান দিয়ে কল করা হয়, তাহলে একটি উচ্চ-গুরুত্বপূর্ণ নোটিফিকেশন HUN-এ শুধুমাত্র একবার অ্যালার্ট করে।

নিচের কোড স্নিপেটটিতে দেখানো হয়েছে কীভাবে একটি ন্যাভিগেশন নোটিফিকেশন তৈরি করতে হয়:

NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    Intent(ACTION_OPEN_APP).setComponent(
                        ComponentName(context, MyNotificationReceiver::class.java)
                    ),
                    PendingIntent.FLAG_IMMUTABLE
                )
            )
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build()
    )
    .build()

দূরত্বের পরিবর্তনের জন্য নিয়মিত TBT নোটিফিকেশন আপডেট করুন, যা রেল উইজেট আপডেট করে, এবং শুধুমাত্র নোটিফিকেশনটি একটি HUN হিসাবে দেখান। আপনি CarAppExtender.Builder.setImportance ব্যবহার করে নোটিফিকেশনের গুরুত্ব নির্ধারণ করে HUN-এর আচরণ নিয়ন্ত্রণ করতে পারেন। গুরুত্ব IMPORTANCE_HIGH এ সেট করলে একটি HUN দেখানো হয়। এটিকে অন্য কোনো মানে সেট করলে শুধুমাত্র রেল উইজেট আপডেট হয়।

PlaceListNavigationTemplate-এর বিষয়বস্তু রিফ্রেশ করুন

PlaceListNavigationTemplate দিয়ে তৈরি করা স্থানের তালিকা ব্রাউজ করার সময়, আপনি ড্রাইভারদের একটি বোতামে ট্যাপ করে কন্টেন্ট রিফ্রেশ করার সুযোগ দিতে পারেন। তালিকা রিফ্রেশ সক্ষম করতে, OnContentRefreshListener ইন্টারফেসের onContentRefreshRequested মেথডটি ইমপ্লিমেন্ট করুন এবং টেমপ্লেটে লিসেনার সেট করার জন্য PlaceListNavigationTemplate.Builder.setOnContentRefreshListener ব্যবহার করুন।

নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে টেমপ্লেটে লিসেনার সেট করতে হয়:

PlaceListNavigationTemplate.Builder()
    .setOnContentRefreshListener {
        // Execute any desired logic
        // Then call invalidate() so onGetTemplate() is called again
        screen.invalidate()
    }
    .build()

PlaceListNavigationTemplate এর হেডারে রিফ্রেশ বাটনটি শুধুমাত্র তখনই দেখানো হয়, যখন লিসেনারটির কোনো ভ্যালু থাকে।

যখন ব্যবহারকারী রিফ্রেশ বোতামে ক্লিক করেন, তখন আপনার OnContentRefreshListener ইমপ্লিমেন্টেশনের onContentRefreshRequested মেথডটি কল করা হয়। onContentRefreshRequested এর ভেতরে, Screen.invalidate মেথডটি কল করুন। এরপর হোস্ট আপনার অ্যাপের Screen.onGetTemplate মেথডকে কলব্যাক করে রিফ্রেশ করা কন্টেন্টসহ টেমপ্লেটটি পুনরুদ্ধার করে। টেমপ্লেট রিফ্রেশ করার বিষয়ে আরও তথ্যের জন্য “Refresh the contents of a template” দেখুন। যতক্ষণ পর্যন্ত onGetTemplate দ্বারা ফেরত আসা পরবর্তী টেমপ্লেটটি একই ধরনের হয়, ততক্ষণ পর্যন্ত এটিকে একটি রিফ্রেশ হিসেবে গণ্য করা হয় এবং এটি টেমপ্লেট কোটার মধ্যে গণনা করা হয় না।

অডিও নির্দেশনা প্রদান করুন

গাড়ির স্পিকারের মাধ্যমে নেভিগেশন নির্দেশনা চালানোর জন্য, আপনার অ্যাপকে অবশ্যই অডিও ফোকাসের জন্য অনুরোধ করতে হবে। আপনার AudioFocusRequest এর অংশ হিসেবে, এর ব্যবহার AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE হিসেবে সেট করুন। এছাড়াও, ফোকাস গেইন AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK হিসেবে সেট করুন।

নেভিগেশন অনুকরণ করুন

গুগল প্লে স্টোরে আপনার অ্যাপ জমা দেওয়ার সময় এর নেভিগেশন কার্যকারিতা যাচাই করার জন্য, আপনার অ্যাপকে অবশ্যই NavigationManagerCallback.onAutoDriveEnabled কলব্যাকটি ইমপ্লিমেন্ট করতে হবে। যখন এই কলব্যাকটি কল করা হয়, ব্যবহারকারী নেভিগেশন শুরু করলে আপনার অ্যাপকে অবশ্যই নির্বাচিত গন্তব্যে নেভিগেশন সিমুলেট করতে হবে। বর্তমান Session লাইফসাইকেল যখনই Lifecycle.Event.ON_DESTROY স্টেটে পৌঁছাবে, তখনই আপনার অ্যাপ এই মোড থেকে বেরিয়ে আসতে পারবে।

আপনার onAutoDriveEnabled এর ইমপ্লিমেন্টেশনটি কল করা হচ্ছে কিনা, তা কমান্ড লাইন থেকে নিম্নলিখিতটি এক্সিকিউট করে পরীক্ষা করতে পারেন:

adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE

নিম্নলিখিত উদাহরণে এটি দেখানো হয়েছে:

adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE

ডিফল্ট নেভিগেশন কার অ্যাপ

অ্যান্ড্রয়েড অটোতে, ব্যবহারকারীর চালু করা সর্বশেষ নেভিগেশন অ্যাপটিই ডিফল্ট নেভিগেশন কার অ্যাপ হিসেবে কাজ করে। যখন ব্যবহারকারী অ্যাসিস্ট্যান্টের মাধ্যমে নেভিগেশন কমান্ড দেন অথবা অন্য কোনো অ্যাপ নেভিগেশন শুরু করার জন্য ইন্টেন্ট পাঠায়, তখন ডিফল্ট অ্যাপটি নেভিগেশন ইন্টেন্ট গ্রহণ করে

প্রাসঙ্গিক নেভিগেশন সতর্কতা প্রদর্শন করুন

Alert নেভিগেশন স্ক্রিনের প্রেক্ষাপট থেকে বের না হয়েই চালককে গুরুত্বপূর্ণ তথ্য এবং ঐচ্ছিক পদক্ষেপ প্রদর্শন করে। চালককে সর্বোত্তম অভিজ্ঞতা দেওয়ার জন্য, Alert NavigationTemplate মধ্যে কাজ করে, যাতে নেভিগেশন রুট বাধাগ্রস্ত না হয় এবং চালকের মনোযোগের বিচ্যুতি ন্যূনতম রাখা যায়।

Alert শুধুমাত্র NavigationTemplate মধ্যেই উপলব্ধ। NavigationTemplate বাইরে ব্যবহারকারীকে অবহিত করতে, ' নোটিফিকেশন প্রদর্শন' অংশে ব্যাখ্যা করা অনুযায়ী হেডস-আপ নোটিফিকেশন (HUN) ব্যবহার করার কথা বিবেচনা করুন।

উদাহরণস্বরূপ, Alert ব্যবহার করুন:

  • বর্তমান নেভিগেশন সম্পর্কিত কোনো আপডেট, যেমন ট্র্যাফিক অবস্থার পরিবর্তন, সম্পর্কে ড্রাইভারকে অবহিত করুন।
  • ড্রাইভারের কাছে বর্তমান নেভিগেশন সম্পর্কিত কোনো আপডেট, যেমন কোনো স্পিড ট্র্যাপ আছে কিনা, তা জিজ্ঞাসা করুন।
  • আসন্ন কোনো কাজের প্রস্তাব দিন এবং চালক তা গ্রহণ করবেন কিনা জিজ্ঞাসা করুন, যেমন তিনি যাওয়ার পথে কাউকে তুলে নিতে ইচ্ছুক কিনা।

এর মৌলিক রূপে, একটি Alert একটি শিরোনাম এবং Alert সময়কাল থাকে। সময়কালটি একটি প্রোগ্রেস বারের মাধ্যমে দেখানো হয়। ঐচ্ছিকভাবে, আপনি একটি উপ-শিরোনাম, একটি আইকন এবং সর্বোচ্চ দুটি Action অবজেক্ট যোগ করতে পারেন।

চিত্র ২. প্রাসঙ্গিক নেভিগেশন সতর্কতা।

একবার কোনো Alert দেখানো হলে, ড্রাইভারের কার্যকলাপের ফলে NavigationTemplate থেকে বেরিয়ে গেলেও সেটি অন্য কোনো টেমপ্লেটে স্থানান্তরিত হয় না। Alert সময়সীমা শেষ না হওয়া পর্যন্ত, ব্যবহারকারী কোনো পদক্ষেপ না নেওয়া পর্যন্ত, অথবা অ্যাপটি Alert বাতিল না করা পর্যন্ত এটি মূল NavigationTemplate থেকে যায়।

একটি সতর্কতা তৈরি করুন

Alert.Builder ব্যবহার করে Alert ইনস্ট্যান্স তৈরি করুন:

Alert.Builder(
    1, // alertId
    CarText.create("Hello"), // title
    5000 // durationMillis
)
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create("Subtitle"))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(alertCallback)
    .build()

আপনি যদি Alert বাতিল বা খারিজ হওয়ার বিষয়টি শুনতে চান, তাহলে AlertCallback ইন্টারফেসের একটি ইমপ্লিমেন্টেশন তৈরি করুন। AlertCallback কল পাথগুলো হলো:

  • যদি Alert সময়সীমা শেষ হয়ে যায়, তাহলে হোস্ট AlertCallback.onCancel মানটি দিয়ে AlertCallback.REASON_TIMEOUT মেথডটি কল করে। এরপর এটি AlertCallback.onDismiss মেথডটি কল করে।

  • যদি ড্রাইভার অ্যাকশন বাটনগুলোর কোনো একটিতে ক্লিক করে, তাহলে হোস্ট Action.OnClickListener কল করে এবং তারপর AlertCallback.onDismiss কল করে।

  • যদি Alert সমর্থিত না হয়, তাহলে হোস্ট AlertCallback.onCancel AlertCallback.REASON_NOT_SUPPORTED করে। হোস্ট AlertCallback.onDismiss কল করে না, কারণ Alert দেখানো হয়নি।

সতর্কতার সময়কাল কনফিগার করুন

আপনার অ্যাপের প্রয়োজন অনুযায়ী একটি Alert সময়কাল বেছে নিন। একটি নেভিগেশন Alert জন্য প্রস্তাবিত সময়কাল হলো ১০ সেকেন্ড। আরও তথ্যের জন্য নেভিগেশন অ্যালার্ট দেখুন।

একটি সতর্কতা দেখান

একটি Alert দেখানোর জন্য, আপনার অ্যাপের CarContext এর মাধ্যমে উপলব্ধ AppManager.showAlert মেথডটি কল করুন।

carContext.getCarService(AppManager::class.java).showAlert(alert)

  • এমন একটি Alert দিয়ে showAlert কল করলে, যার alertId ইতিমধ্যে প্রদর্শিত Alert ID-এর সমান, তাহলে কিছুই হয় না। Alert আপডেট হয় না। একটি Alert আপডেট করতে হলে, আপনাকে অবশ্যই একটি নতুন alertId দিয়ে এটি পুনরায় তৈরি করতে হবে।
  • ইতিমধ্যে প্রদর্শিত Alert থেকে ভিন্ন alertId সহ একটি Alert দিয়ে showAlert কল করলে, প্রদর্শিত Alert টি বাতিল হয়ে যায়।

একটি সতর্কতা খারিজ করুন

যদিও টাইমআউট বা ড্রাইভারের হস্তক্ষেপের কারণে একটি Alert স্বয়ংক্রিয়ভাবে বাতিল হয়ে যায়, আপনি ম্যানুয়ালিও একটি Alert বাতিল করতে পারেন, যেমন যদি এর তথ্য পুরোনো হয়ে যায়। একটি Alert বাতিল করতে, Alert alertId সহ dismissAlert মেথডটি কল করুন।

carContext.getCarService(AppManager::class.java).dismissAlert(alert.id)

ইতিমধ্যে প্রদর্শিত Alert এর সাথে মেলে না এমন একটি alertId দিয়ে dismissAlert কল করলে কিছুই হয় না। এটি কোনো এক্সেপশনও থ্রো করে না।