আদেশগুলি পূরণ করুন

এই পৃষ্ঠাটি বর্ণনা করে কিভাবে ভয়েস ইন্টারঅ্যাকশনের মাধ্যমে আদেশগুলি পূরণ করতে হয়।

মিডিয়া কমান্ডগুলি পূরণ করুন

মিডিয়া-সম্পর্কিত কমান্ড তিনটি ভিন্ন গ্রুপে বিভক্ত করা যেতে পারে:

  • বাহ্যিক মিডিয়া উত্স (যেমন AAOS এ ইনস্টল করা Spotify)।
  • ব্যাকএন্ড মিডিয়া সোর্স (যেমন মিউজিক VIA এর মাধ্যমে প্রবাহিত)।
  • স্থানীয় মিডিয়া উত্স (যেমন গাড়ি রেডিও)।

বাহ্যিক মিডিয়া সোর্স কমান্ড পরিচালনা করুন

বাহ্যিক মিডিয়া উত্সগুলিকে Android অ্যাপ হিসাবে সংজ্ঞায়িত করা হয় যেগুলি MediaSessionCompat এবং MediaBrowseCompat APIগুলিকে সমর্থন করে (এই APIগুলির ব্যবহার সম্পর্কে বিশদ ব্যাখ্যার জন্য গাড়ির জন্য মিডিয়া অ্যাপ তৈরি করুন )।

গুরুত্বপূর্ণ: সিস্টেমে ইনস্টল করা সমস্ত মিডিয়া অ্যাপের MediaBrowseService এর সাথে সংযোগ করতে একটি সহকারী অ্যাপের জন্য, এটি অবশ্যই:

  1. সিস্টেম-স্বাক্ষরিত হিসাবে ইনস্টল করুন (এএওএস এবং নমুনা PackageValidator কোডের জন্য মিডিয়া অ্যাপ্লিকেশন ডেভেলপমেন্ট নির্দেশিকা দেখুন)।
  2. android.permission.MEDIA_CONTENT_CONTROL সিস্টেম-প্রিভিলেজড পারমিশন ধরে রাখুন ( সিস্টেম-প্রিভিলেজড পারমিশন দেখুন)।

MediaBrowserCompat এবং MediaControllerCompat ছাড়াও, AAOS নিম্নলিখিতগুলি সরবরাহ করে:

  • CarMediaService বর্তমানে নির্বাচিত মিডিয়া উৎসের কেন্দ্রীভূত তথ্য প্রদান করে। এটি গাড়ি শাটডাউন-রিস্টার্টের পরে পূর্বে চালানো মিডিয়া উত্স পুনরায় চালু করতেও ব্যবহৃত হয়।
  • car-media-common মিডিয়া অ্যাপের তালিকা, সংযোগ এবং ইন্টারঅ্যাক্ট করার সুবিধাজনক পদ্ধতি প্রদান করে।

সাধারণ ভয়েস ইন্টারঅ্যাকশন কমান্ড বাস্তবায়নের জন্য নির্দিষ্ট নির্দেশিকা নিচে দেওয়া আছে।

ইনস্টল করা মিডিয়া উত্সগুলির একটি তালিকা পান

মিডিয়া উত্সগুলি PackageManager ব্যবহার করে সনাক্ত করা যেতে পারে, এবং MediaBrowserService.SERVICE_INTERFACE এর সাথে মেলে এমন পরিষেবাগুলির জন্য ফিল্টারিং। কিছু গাড়িতে কিছু বিশেষ মিডিয়া ব্রাউজার পরিষেবা বাস্তবায়ন হতে পারে, যা বাদ দেওয়া উচিত। এখানে এই যুক্তির একটি উদাহরণ:

private Map<String, MediaSource> getAvailableMediaSources() {
    List<String> customMediaServices =
        Arrays.asList(mContext.getResources()
            .getStringArray(R.array.custom_media_packages));
    List<ResolveInfo> mediaServices = mPackageManager.queryIntentServices(
            new Intent(MediaBrowserService.SERVICE_INTERFACE),
            PackageManager.GET_RESOLVED_FILTER);
    Map<String, MediaSource> result = new HashMap<>();
    for (ResolveInfo info : mediaServices) {
        String packageName = info.serviceInfo.packageName;
        if (customMediaServices.contains(packageName)) {
            // Custom media sources should be ignored, as they might have a
            // specialized handling (e.g., radio).
            continue;
        }
        String className = info.serviceInfo.name;
        ComponentName componentName = new ComponentName(packageName,
            className);
        MediaSource source = MediaSource.create(mContext, componentName);
        result.put(source.getDisplayName().toString().toLowerCase(),
            source);
    }
    return result;
}

সচেতন থাকুন যে মিডিয়া সোর্স যে কোনো সময় ইনস্টল বা আনইনস্টল হতে পারে। একটি সঠিক তালিকা বজায় রাখার জন্য, অভিপ্রায় ক্রিয়াগুলির জন্য একটি BroadcastReceiver উদাহরণ প্রয়োগ করার সুপারিশ করা হয় ACTION_PACKAGE_ADDED , ACTION_PACKAGE_CHANGED , ACTION_PACKAGE_REPLACED , এবং ACTION_PACKAGE_REMOVED

বর্তমানে বাজানো মিডিয়া উৎসের সাথে সংযোগ করুন

CarMediaService বর্তমানে নির্বাচিত মিডিয়া সোর্স এবং যখন এই মিডিয়া সোর্স পরিবর্তিত হয় তা পাওয়ার পদ্ধতি প্রদান করে৷ এই পরিবর্তনগুলি ঘটতে পারে কারণ ব্যবহারকারী সরাসরি UI এর সাথে ইন্টারঅ্যাক্ট করেছেন, বা গাড়িতে হার্ডওয়্যার বোতাম ব্যবহারের কারণে। অন্যদিকে, কার-মিডিয়া-সাধারণ লাইব্রেরি একটি প্রদত্ত মিডিয়া উত্সের সাথে সংযোগ করার সুবিধাজনক উপায় সরবরাহ করে। বর্তমানে নির্বাচিত মিডিয়া অ্যাপের সাথে কীভাবে সংযোগ করবেন তার একটি সরলীকৃত স্নিপেট এখানে রয়েছে:

public class MediaActuator implements
        MediaBrowserConnector.onConnectedBrowserChanged {
    private final Car mCar;
    private CarMediaManager mCarMediaManager;
    private MediaBrowserConnector mBrowserConnector;

    …

    public void initialize(Context context) {
        mCar = Car.createCar(context);
        mBrowserConnector = new MediaBrowserConnector(context, this);
        mCarMediaManager = (CarMediaManager)
            mCar.getCarManager(Car.CAR_MEDIA_SERVICE);
        mBrowserConnector.connectTo(mCarMediaManager.getMediaSource());
        …
    }

    @Override
    public void onConnectedBrowserChanged(
            @Nullable MediaBrowserCompat browser) {
        // TODO: Handle connected/disconnected browser
    }

    …
}

বর্তমানে মিডিয়া সোর্সের প্লেব্যাক নিয়ন্ত্রণ করুন

একটি সংযুক্ত MediaBrowserCompat এর মাধ্যমে টার্গেট অ্যাপে পরিবহন নিয়ন্ত্রণ কমান্ড পাঠানো সহজ। এখানে একটি সরলীকৃত উদাহরণ:

public class MediaActuator …  {
    …
    private MediaControllerCompat mMediaController;

    @Override
    public void onConnectedBrowserChanged(
            @Nullable MediaBrowserCompat browser) {
        if (browser != null && browser.isConnected()) {
            mMediaController = new MediaControllerCompat(mContext,
                browser.getSessionToken());
        } else {
            mMediaController = null;
        }
    }

    private boolean playSongOnCurrentSource(String song) {
        if (mMediaController == null) {
            // No source selected.
            return false;
        }
        MediaControllerCompat.TransportControls controls =
            mMediaController.getTransportControls();
        PlaybackStateCompat state = controller.getPlaybackState();
        if (state == null || ((state.getActions() &
                PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH) == 0)) {
            // Source can't play from search
            return false;
        }
        controls.playFromSearch(query, null);
        return true;
    }

    …
}

স্থানীয় মিডিয়া সোর্স কমান্ডগুলি পরিচালনা করুন (রেডিও, সিডি প্লেয়ার, ব্লুটুথ, ইউএসবি)

স্থানীয় মিডিয়া উত্সগুলি উপরে বর্ণিত একই MediaSession এবং MediaBrowse APIগুলি ব্যবহার করে সিস্টেমে তাদের কার্যকারিতা প্রকাশ করে৷ প্রতিটি ধরণের হার্ডওয়্যারের বৈশিষ্ট্যগুলিকে মিটমাট করার জন্য, এই MediaBrowse পরিষেবাগুলি তাদের তথ্য এবং মিডিয়া কমান্ডগুলি সংগঠিত করার জন্য নির্দিষ্ট কনভেনশনগুলি ব্যবহার করে৷

রেডিও হ্যান্ডেল

Radio MediaBrowseService ACTION_PLAY_BROADCASTRADIO অভিপ্রায় ফিল্টার দ্বারা চিহ্নিত করা যেতে পারে। তারা ইমপ্লিমেন্ট রেডিওতে বর্ণিত প্লেব্যাক নিয়ন্ত্রণ এবং মিডিয়া ব্রাউজ কাঠামো অনুসরণ করবে বলে আশা করা হচ্ছে। AAOS car-broadcastradio-support লাইব্রেরি অফার করে যার মধ্যে ধ্রুবক এবং পদ্ধতি রয়েছে যাতে OEM-কে তাদের নিজস্ব রেডিও পরিষেবাগুলির জন্য MediaBrowseService বাস্তবায়ন তৈরি করতে সাহায্য করে যা সংজ্ঞায়িত প্রোটোকল অনুসরণ করে এবং তাদের ব্রাউজ ট্রি (উদাহরণস্বরূপ, VIAs) ব্যবহার করা অ্যাপগুলির জন্য সমর্থন প্রদান করে।

অক্জিলিয়ারী ইনপুট, সিডি অডিও এবং ইউএসবি মিডিয়া পরিচালনা করুন

AOSP-এর অংশ হিসাবে এই মিডিয়া উত্সগুলির কোনও ডিফল্ট বাস্তবায়ন নেই। প্রস্তাবিত পদ্ধতি হল:

ব্লুটুথ পরিচালনা করুন

ব্লুটুথ মিডিয়া বিষয়বস্তু AVRCP ব্লুটুথ প্রোফাইলের মাধ্যমে প্রকাশ করা হয়। এই কার্যকারিতা অ্যাক্সেস সহজতর করার জন্য, AAOS একটি MediaBrowserService এবং MediaSession বাস্তবায়ন অন্তর্ভুক্ত করে যা যোগাযোগের বিশদ বিবরণকে বিমূর্ত করে ( প্যাকেজ/অ্যাপস/ব্লুটুথ দেখুন)।

সংশ্লিষ্ট মিডিয়া ব্রাউজার ট্রি স্ট্রাকচার BrowseTree ক্লাসে সংজ্ঞায়িত করা হয়েছে। প্লেব্যাক কন্ট্রোল কমান্ড অন্য যেকোন অ্যাপে একইভাবে বিতরণ করা যেতে পারে, এর MediaSession বাস্তবায়ন ব্যবহার করে।

স্ট্রিমিং মিডিয়া কমান্ডগুলি পরিচালনা করুন

সার্ভার সাইড মিডিয়া স্ট্রিমিং বাস্তবায়নের জন্য, VIA-কে অবশ্যই মিডিয়া সোর্স হতে হবে, MediaBrowse এবং MediaSession API প্রয়োগ করে। গাড়ির জন্য মিডিয়া অ্যাপ তৈরি করুন দেখুন। এই APIগুলি বাস্তবায়ন করে, একটি ভয়েস কন্ট্রোল অ্যাপ সক্ষম হবে (অন্যান্য জিনিসগুলির মধ্যে):

  • মিডিয়া উৎস নির্বাচনে নির্বিঘ্নে অংশগ্রহণ করুন
  • গাড়ি পুনরায় চালু করার পরে স্বয়ংক্রিয়ভাবে পুনরায় চালু হবে
  • মিডিয়া সেন্টার UI ব্যবহার করে প্লেব্যাক এবং ব্রাউজিং নিয়ন্ত্রণ প্রদান করুন
  • স্ট্যান্ডার্ড হার্ডওয়্যার মিডিয়া বোতাম ইভেন্টগুলি গ্রহণ করুন

সমস্ত নেভিগেশন অ্যাপের সাথে ইন্টারঅ্যাক্ট করার কোন প্রমিত উপায় নেই। Google Maps-এর সাথে ইন্টিগ্রেশনের জন্য, Android Automotive Intents-এর জন্য Google Maps দেখুন। অন্যান্য অ্যাপের সাথে ইন্টিগ্রেশনের জন্য, অ্যাপ ডেভেলপারদের সাথে সরাসরি যোগাযোগ করুন। যেকোন অ্যাপে (Google Maps সহ) একটি অভিপ্রায় চালু করার আগে, অভিপ্রায়টি সমাধান করা যেতে পারে তা যাচাই করুন ( ইন্টেন্ট অনুরোধগুলি দেখুন)। টার্গেট অ্যাপটি উপলব্ধ না হলে এটি ব্যবহারকারীকে জানানোর সুযোগ তৈরি করে।

গাড়ির আদেশগুলি পূরণ করুন

CarPropertyManager-এর মাধ্যমে পড়া এবং লিখতে উভয়ের জন্য গাড়ির বৈশিষ্ট্যগুলিতে অ্যাক্সেস সরবরাহ করা হয়। যানবাহনের বৈশিষ্ট্যের ধরন, এর বাস্তবায়ন এবং অন্যান্য বিবরণ সম্পত্তি কনফিগারেশনে ব্যাখ্যা করা হয়েছে। অ্যান্ড্রয়েড দ্বারা সমর্থিত বৈশিষ্ট্যগুলির সঠিক বিবরণের জন্য, সরাসরি hardware/interfaces/automotive/vehicle/2.0/types.hal এ উল্লেখ করা ভাল। সেখানে সংজ্ঞায়িত VehicleProperty enum-এ স্ট্যান্ডার্ড এবং ভেন্ডর নির্দিষ্ট বৈশিষ্ট্য, ডেটা প্রকার, পরিবর্তন মোড, ইউনিট এবং রিড/রাইট অ্যাক্সেস সংজ্ঞা উভয়ই রয়েছে।

জাভা থেকে এই একই ধ্রুবকগুলি অ্যাক্সেস করতে, আপনি VehiclePropertyIds এবং এর সহযোগী ক্লাসগুলি ব্যবহার করতে পারেন। বিভিন্ন বৈশিষ্ট্যে তাদের অ্যাক্সেস নিয়ন্ত্রণ করার জন্য বিভিন্ন Android অনুমতি রয়েছে। এই অনুমতিগুলি CarService ম্যানিফেস্টে ঘোষণা করা হয়, এবং VehiclePropertyIds Javadoc-এ বর্ণিত বৈশিষ্ট্য এবং অনুমতিগুলির মধ্যে ম্যাপিং এবং PropertyHalServiceIds- এ প্রয়োগ করা হয়।

একটি যানবাহন সম্পত্তি পড়ুন

গাড়ির গতি কীভাবে পড়তে হয় তা দেখানোর একটি উদাহরণ নিচে দেওয়া হল:

public class CarActuator ... {
    private final Car mCar;
    private final CarPropertyManager mCarPropertyManager;
    private final TextToSpeech mTTS;

    /** Global VHAL area id */
    public static final int GLOBAL_AREA_ID = 0;

    public CarActuator(Context context, TextToSpeech tts) {
        mCar = Car.createCar(context);
        mCarPropertyManager = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
        mTTS = tts;
        ...
    }

    @Nullable
    private void getSpeedInMetersPerSecond() {
        if (!mCarPropertyManager.isPropertyAvailable(VehiclePropertyIds.PERF_VEHICLE_SPEED,
                GLOBAL_AREA_ID)) {
            mTTS.speak("I'm sorry, but I can't read the speed of this vehicle");
            return;
        }
        // Data type and unit can be found in
        // automotive/vehicle/2.0/types.hal
        float speedInMps = mCarPropertyManager.getFloatProperty(
                VehiclePropertyIds.PERF_VEHICLE_SPEED, GLOBAL_AREA_ID);
        int speedInMph = (int)(speedInMetersPerSecond * 2.23694f);
        mTTS.speak(String.format("Sure. Your current speed is %d miles "
                + "per hour", speedInUserUnit);
    }

    ...
}

একটি যানবাহন সম্পত্তি সেট করুন

সামনের এসি কীভাবে চালু এবং বন্ধ করতে হয় তা দেখানোর একটি উদাহরণ নিচে দেওয়া হল।

public class CarActuator … {
    …

    private void changeFrontAC(boolean turnOn) {
        List<CarPropertyConfig> configs = mCarPropertyManager
                .getPropertyList(new ArraySet<>(Arrays.asList(
                    VehiclePropertyIds.HVAC_AC_ON)));
        if (configs == null || configs.size() != 1) {
            mTTS.speak("I'm sorry, but I can't control the AC of your vehicle");
            return;
        }

        // Find the front area Ids for the AC property.
        int[] areaIds = configs.get(0).getAreaIds();
        List<Integer> areasToChange = new ArrayList<>();
        for (int areaId : areaIds) {
            if ((areaId & (VehicleAreaSeat.SEAT_ROW_1_CENTER
                        | VehicleAreaSeat.SEAT_ROW_1_LEFT
                        | VehicleAreaSeat.SEAT_ROW_1_RIGHT)) == 0) {
                continue;
            }
            boolean isACInAreaAlreadyOn = mCarPropertyManager
                    .getBooleanProperty(VehiclePropertyIds.HVAC_AC_ON, areaId);
            if ((!isACInAreaAlreadyOn && turnOn) || (isACInAreaAlreadyOn && !turnOn)) {
                areasToChange.add(areaId);
            }
        }
        if (areasToChange.isEmpty()) {
            mTTS.speak(String.format("The AC is already %s", turnOn ? "on" : "off"));
            return;
        }

        for (int areaId : areasToChange) {
            mCarPropertyManager.setBooleanProperty(
                VehiclePropertyIds.HVAC_AC_ON, areaId, turnOn);
        }
        mTTS.speak(String.format("Okay, I'm turning your front AC %s",
            turnOn ? "on" : "off"));
    }

    …
}

যোগাযোগের আদেশগুলি পূরণ করুন

মেসেজিং কমান্ড পরিচালনা করুন

VIAs অবশ্যই ভয়েস সহকারী ট্যাপ-টু-রিডে বর্ণিত "ট্যাপ-টু-রিড " ফ্লো অনুসরণ করে আগত বার্তাগুলি পরিচালনা করতে হবে, যা ঐচ্ছিকভাবে আগত বার্তা প্রেরকের কাছে উত্তর পাঠানোর ব্যবস্থা করতে পারে৷ উপরন্তু, VIAs গাড়ি থেকে বা ব্লুটুথের মাধ্যমে সরাসরি এসএমএস বার্তা রচনা ও পাঠাতে SmsManager ( android.telephony প্যাকেজের অংশ) ব্যবহার করতে পারে।

কল কমান্ড পরিচালনা করুন

একইভাবে, VIAs ফোন কল করতে এবং ব্যবহারকারীর ভয়েস মেল নম্বরে কল করতে TelephonyManager ব্যবহার করতে পারে। এই ক্ষেত্রে, VIAs সরাসরি টেলিফোনি স্ট্যাকের সাথে বা কার ডায়লার অ্যাপের সাথে যোগাযোগ করবে। যাই হোক না কেন, গাড়ি ডায়ালার অ্যাপটি ব্যবহারকারীর কাছে ভয়েস-কল সম্পর্কিত UI প্রদর্শন করা উচিত।

অন্যান্য আদেশগুলি পূরণ করুন

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

ইমারসিভ অ্যাকশন (ভিজ্যুয়াল কন্টেন্ট প্রদর্শন)

যেখানে এটি ব্যবহারকারীর ক্রিয়াকলাপ বা বোঝার উন্নতি করে, সেখানে একটি VIA গাড়ির স্ক্রিনে সম্পূরক ভিজ্যুয়াল সামগ্রী সরবরাহ করতে পারে। ড্রাইভারের বিভ্রান্তি কমাতে, এই ধরনের বিষয়বস্তু সহজ, সংক্ষিপ্ত এবং কার্যকরী রাখুন। নিমজ্জিত ক্রিয়া সম্পর্কে UI/UX নির্দেশিকা সম্পর্কে বিশদ বিবরণের জন্য, প্রিলোড করা সহকারী: UX গাইডেন্স দেখুন।

হেড ইউনিট (HU) ডিজাইনের বাকি অংশের সাথে কাস্টমাইজেশন এবং সামঞ্জস্যতা সক্ষম করতে, ভিআইএগুলিকে বেশিরভাগ UI উপাদানগুলির জন্য কার UI লাইব্রেরির উপাদানগুলি ব্যবহার করা উচিত৷ বিস্তারিত জানার জন্য, কাস্টমাইজেশন দেখুন।