आदेश पूरा करें

यह पृष्ठ बताता है कि वॉयस इंटरेक्शन के साथ कमांड को कैसे पूरा किया जाए।

मीडिया आदेश पूरा करें

मीडिया-संबंधित कमांड को तीन अलग-अलग समूहों में विभाजित किया जा सकता है:

  • बाहरी मीडिया स्रोत (जैसे AAOS में स्थापित Spotify)।
  • बैकएंड मीडिया स्रोत (जैसे वीआईए के माध्यम से स्ट्रीम किया गया संगीत)।
  • स्थानीय मीडिया स्रोत (जैसे कार रेडियो)।

बाहरी मीडिया स्रोत आदेशों को संभालें

बाहरी मीडिया स्रोतों को एंड्रॉइड ऐप्स के रूप में परिभाषित किया गया है जो MediaSessionCompat और MediaBrowseCompat 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;
}

ध्यान रखें कि मीडिया स्रोत किसी भी समय इंस्टॉल या अनइंस्टॉल किए जा सकते हैं। एक सटीक सूची बनाए रखने के लिए, आशय क्रियाओं ACTION_PACKAGE_ADDED , ACTION_PACKAGE_CHANGED , ACTION_PACKAGE_REPLACED , और ACTION_PACKAGE_REMOVED के लिए BroadcastReceiver इंस्टेंस को लागू करने की अनुशंसा की जाती है।

वर्तमान में चल रहे मीडिया स्रोत से कनेक्ट करें

CarMediaService वर्तमान में चयनित मीडिया स्रोत प्राप्त करने के तरीके प्रदान करता है, और जब यह मीडिया स्रोत बदलता है। ये परिवर्तन उपयोगकर्ता द्वारा सीधे यूआई के साथ इंटरैक्ट करने या कार में हार्डवेयर बटन के उपयोग के कारण हो सकते हैं। दूसरी ओर, कार-मीडिया-कॉमन लाइब्रेरी किसी दिए गए मीडिया स्रोत से जुड़ने के सुविधाजनक तरीके प्रदान करती है। वर्तमान में चयनित मीडिया ऐप से कैसे जुड़ें, इसका एक सरल स्निपेट यहां दिया गया है:

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 सेवाएँ अपनी जानकारी और मीडिया कमांड को व्यवस्थित करने के लिए विशिष्ट सम्मेलनों का उपयोग करती हैं।

रेडियो संभालें

रेडियो MediaBrowseService को ACTION_PLAY_BROADCASTRADIO इंटेंट फ़िल्टर द्वारा पहचाना जा सकता है। उनसे अपेक्षा की जाती है कि वे इम्प्लीमेंट रेडियो में वर्णित प्लेबैक नियंत्रण और मीडिया ब्राउज़ संरचना का पालन करें। AAOS car-broadcastradio-support लाइब्रेरी प्रदान करता है जिसमें ओईएम को अपनी स्वयं की रेडियो सेवाओं के लिए MediaBrowseService कार्यान्वयन बनाने में मदद करने के लिए स्थिरांक और तरीके शामिल हैं जो परिभाषित प्रोटोकॉल का पालन करते हैं, और अपने ब्राउज़ ट्री (उदाहरण के लिए, VIA) का उपभोग करने वाले ऐप्स के लिए समर्थन प्रदान करता है।

सहायक इनपुट, सीडी ऑडियो और यूएसबी मीडिया को संभालें

AOSP के भाग के रूप में इन मीडिया स्रोतों का कोई डिफ़ॉल्ट कार्यान्वयन नहीं है। सुझाया गया दृष्टिकोण यह है:

ब्लूटूथ संभालें

ब्लूटूथ मीडिया सामग्री AVRCP ब्लूटूथ प्रोफ़ाइल के माध्यम से उजागर होती है। इस कार्यक्षमता तक पहुंच को सुविधाजनक बनाने के लिए, AAOS में एक MediaBrowserService और MediaSession कार्यान्वयन शामिल है जो संचार विवरणों को सारगर्भित करता है ( पैकेज/ऐप्स/ब्लूटूथ देखें)।

संबंधित मीडिया ब्राउज़र ट्री संरचना को ब्राउजट्री क्लास में परिभाषित किया गया है। इसके MediaSession कार्यान्वयन का उपयोग करके प्लेबैक नियंत्रण कमांड किसी अन्य ऐप की तरह ही वितरित किए जा सकते हैं।

स्ट्रीमिंग मीडिया कमांड को संभालें

सर्वर साइड मीडिया स्ट्रीमिंग को लागू करने के लिए, VIA को MediaBrowse और MediaSession API को लागू करते हुए स्वयं एक मीडिया स्रोत बनना होगा। कारों के लिए मीडिया ऐप्स बनाएं का संदर्भ लें। इन एपीआई को कार्यान्वित करके, एक ध्वनि नियंत्रण ऐप (अन्य बातों के अलावा) सक्षम होगा:

  • मीडिया स्रोत चयन में निर्बाध रूप से भाग लें
  • कार पुनरारंभ होने के बाद स्वचालित रूप से फिर से शुरू हो जाए
  • मीडिया सेंटर यूआई का उपयोग करके प्लेबैक और ब्राउज़िंग नियंत्रण प्रदान करें
  • मानक हार्डवेयर मीडिया बटन ईवेंट प्राप्त करें

सभी नेविगेशन ऐप्स के साथ इंटरैक्ट करने का कोई मानकीकृत तरीका नहीं है। Google मानचित्र के साथ एकीकरण के लिए, Android ऑटोमोटिव इरादों के लिए Google मानचित्र देखें। अन्य ऐप्स के साथ एकीकरण के लिए, सीधे ऐप डेवलपर्स से संपर्क करें। किसी भी ऐप (Google मैप्स सहित) के लिए एक इरादा लॉन्च करने से पहले, सत्यापित करें कि इरादे को हल किया जा सकता है ( इरादा अनुरोध देखें)। इससे लक्ष्य ऐप उपलब्ध न होने की स्थिति में उपयोगकर्ता को सूचित करने का अवसर मिलता है।

वाहन आदेश पूरा करें

पढ़ने और लिखने दोनों के लिए वाहन संपत्तियों तक पहुंच CarPropertyManager के माध्यम से प्रदान की जाती है। वाहन संपत्तियों के प्रकार, इसके कार्यान्वयन और अन्य विवरण संपत्ति कॉन्फ़िगरेशन में बताए गए हैं। एंड्रॉइड द्वारा समर्थित गुणों के सटीक विवरण के लिए, सीधे hardware/interfaces/automotive/vehicle/2.0/types.hal को संदर्भित करना सबसे अच्छा है। वहां परिभाषित वाहनप्रॉपर्टी एनम में मानक और विक्रेता विशिष्ट गुण, डेटा प्रकार, परिवर्तन मोड, इकाइयां और पढ़ने/लिखने की पहुंच परिभाषा दोनों शामिल हैं।

जावा से इन्हीं स्थिरांकों तक पहुँचने के लिए, आप व्हीकलप्रॉपर्टीआईड्स और उसके सहयोगी वर्गों का उपयोग कर सकते हैं। अलग-अलग संपत्तियों की पहुंच को नियंत्रित करने वाली अलग-अलग एंड्रॉइड अनुमतियां होती हैं। इन अनुमतियों को CarService मेनिफ़ेस्ट में घोषित किया गया है, और संपत्तियों और अनुमतियों के बीच मैपिंग का वर्णन VehiclePropertyIds Javadoc में किया गया है और PropertiesHalServiceIds में लागू किया गया है।

वाहन संपत्ति पढ़ें

निम्नलिखित एक उदाहरण है जो दर्शाता है कि वाहन की गति को कैसे पढ़ा जाए:

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"));
    }

    …
}

संचार आदेश पूरा करें

मैसेजिंग कमांड संभालें

वीआईए को वॉयस असिस्टेंट टैप-टू-रीड में वर्णित "टैप-टू-रीड " प्रवाह के बाद आने वाले संदेशों को संभालना होगा, जो वैकल्पिक रूप से आने वाले संदेश प्रेषक को उत्तर भेजने का काम संभाल सकता है। इसके अतिरिक्त, वीआईए सीधे कार से या ब्लूटूथ पर एसएमएस संदेश लिखने और भेजने के लिए SmsManager ( android.telephony पैकेज का हिस्सा) का उपयोग कर सकते हैं।

कॉल आदेश संभालें

इसी तरह, VIA फ़ोन कॉल करने और उपयोगकर्ता के वॉयस मेल नंबर पर कॉल करने के लिए TelephonyManager उपयोग कर सकता है। इन मामलों में, VIA सीधे टेलीफोनी स्टैक या कार डायलर ऐप के साथ इंटरैक्ट करेगा। किसी भी स्थिति में, कार डायलर ऐप उपयोगकर्ता को वॉयस-कॉल से संबंधित यूआई प्रदर्शित करने वाला होना चाहिए।

अन्य आदेशों को पूरा करें

वीआईए और सिस्टम के बीच एकीकरण के अन्य संभावित बिंदुओं की सूची के लिए, प्रसिद्ध एंड्रॉइड इरादों की सूची देखें। कई उपयोगकर्ता आदेशों को सर्वर-साइड हल किया जा सकता है (उदाहरण के लिए, उपयोगकर्ताओं के ईमेल और कैलेंडर ईवेंट पढ़ना) और वॉयस इंटरैक्शन के अलावा सिस्टम के साथ किसी भी इंटरैक्शन की आवश्यकता नहीं होती है।

इमर्सिव क्रियाएँ (दृश्य सामग्री प्रदर्शित करें)

जहां यह उपयोगकर्ता के कार्यों या समझ को बढ़ाता है, वहीं वीआईए कार स्क्रीन पर पूरक दृश्य सामग्री प्रदान कर सकता है। ड्राइवर का ध्यान भटकाने को कम करने के लिए ऐसी सामग्री को सरल, संक्षिप्त और कार्रवाई योग्य रखें। इमर्सिव क्रियाओं पर यूआई/यूएक्स दिशानिर्देशों के विवरण के लिए, प्रीलोडेड असिस्टेंट्स: यूएक्स गाइडेंस देखें।

शेष हेड यूनिट (एचयू) डिज़ाइन के साथ अनुकूलन और स्थिरता को सक्षम करने के लिए, वीआईए को अधिकांश यूआई तत्वों के लिए कार यूआई लाइब्रेरी घटकों का उपयोग करना चाहिए। विवरण के लिए, अनुकूलन देखें।