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

এই পৃষ্ঠায় বর্ণনা করা হয়েছে কীভাবে ভয়েস ইন্টারঅ্যাকশনের মাধ্যমে কমান্ড পালন করতে হয়।

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

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

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

বাহ্যিক মিডিয়া উৎসের কমান্ডগুলি পরিচালনা করুন

বাহ্যিক মিডিয়া উৎস বলতে সেইসব অ্যান্ড্রয়েড অ্যাপকে বোঝানো হয় যেগুলো MediaSessionCompat এবং MediaBrowseCompat এপিআই সমর্থন করে (এই এপিআইগুলোর ব্যবহার সম্পর্কে বিস্তারিত ব্যাখ্যার জন্য "গাড়ির জন্য মিডিয়া অ্যাপ তৈরি করুন" অংশটি দেখুন)।

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

  1. সিস্টেম-স্বাক্ষরিত হিসেবে ইনস্টল করতে হবে (AAOS এবং নমুনা 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;
}

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

বর্তমানে প্লে হওয়া মিডিয়া সোর্সের সাথে সংযোগ করুন

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

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 পরিষেবাগুলো তাদের তথ্য এবং মিডিয়া কমান্ডগুলো সংগঠিত করার জন্য নির্দিষ্ট নিয়মকানুন ব্যবহার করে।

রেডিও পরিচালনা করুন

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

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

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

  • OEM-দের দিয়ে এগুলোর প্রতিটির জন্য মিডিয়া সার্ভিস বাস্তবায়ন করান। বিস্তারিত জানতে, 'গাড়ির জন্য মিডিয়া অ্যাপ তৈরি করুন' দেখুন।
  • এই MediaBrowseService ইমপ্লিমেন্টেশনগুলোকে General play intents- এ সংজ্ঞায়িত ইন্টেন্ট অ্যাকশনগুলোর মাধ্যমে শনাক্ত করা হবে এবং সেগুলোর প্রতি সাড়া দেওয়া হবে।
  • এই পরিষেবাগুলি 'অন্যান্য উৎসের ধরণ' অংশে বর্ণিত নির্দেশিকা অনুসরণ করে একটি ব্রাউজ ট্রি প্রদর্শন করবে।

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

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

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

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

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

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

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

যানবাহনের নির্দেশাবলী পূরণ করুন

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

জাভা থেকে এই একই কনস্ট্যান্টগুলো অ্যাক্সেস করার জন্য, আপনি VehiclePropertyIds এবং এর সহযোগী ক্লাসগুলো ব্যবহার করতে পারেন। বিভিন্ন প্রপার্টির অ্যাক্সেস নিয়ন্ত্রণের জন্য ভিন্ন ভিন্ন অ্যান্ড্রয়েড পারমিশন থাকে। এই পারমিশনগুলো 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"));
    }

    …
}

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

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

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

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

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

অন্যান্য আদেশ পালন করুন

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

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

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

হেড ইউনিট (HU) ডিজাইনের বাকি অংশের সাথে সামঞ্জস্য ও কাস্টমাইজেশন নিশ্চিত করতে, VIA-দের অধিকাংশ UI এলিমেন্টের জন্য কার UI লাইব্রেরি কম্পোনেন্ট ব্যবহার করা উচিত। বিস্তারিত জানতে, কাস্টমাইজেশন দেখুন।