Komutları yerine getir

Bu sayfada komutların sesli etkileşimle nasıl yerine getirileceği açıklanmaktadır.

Medya komutlarını yerine getirin

Medyayla ilgili komut üç farklı gruba ayrılabilir:

  • Harici medya kaynakları (AAOS'ta yüklü Spotify gibi).
  • Arka uç medya kaynakları (VIA aracılığıyla aktarılan müzik gibi).
  • Yerel medya kaynakları (araba radyosu gibi).

Harici medya kaynağı komutlarını yönetin

Harici medya kaynakları, MediaSessionCompat ve MediaBrowseCompat API'lerini destekleyen Android uygulamaları olarak tanımlanır (bu API'lerin kullanımına ilişkin ayrıntılı açıklama için Arabalar için medya uygulamaları oluşturma bölümüne bakın).

Önemli: Bir yardımcı uygulamanın sistemdeki tüm yüklü medya uygulamalarının MediaBrowseService bağlanabilmesi için:

  1. Sistem imzalı olarak kurulmalıdır (AAOS için Medya Uygulaması Geliştirme yönergelerine ve örnek PackageValidator koduna bakın).
  2. android.permission.MEDIA_CONTENT_CONTROL sistem ayrıcalıklı iznine sahip olun (bkz . Sistem ayrıcalıklı izinleri verme ).

AAOS, MediaBrowserCompat ve MediaControllerCompat ek olarak aşağıdakileri sağlar:

  • CarMediaService mevcut seçili medya kaynağı hakkında merkezi bilgi sağlar. Bu aynı zamanda araç kapatılıp yeniden başlatıldıktan sonra önceden oynatılan bir medya kaynağını sürdürmek için de kullanılır.
  • car-media-common medya uygulamalarını listelemek, bağlanmak ve bunlarla etkileşimde bulunmak için kullanışlı yöntemler sağlar.

Aşağıda, yaygın sesli etkileşim komutlarının uygulanmasına özel yönergeler verilmektedir.

Yüklü medya kaynaklarının listesini alın

Medya kaynakları, PackageManager kullanılarak ve MediaBrowserService.SERVICE_INTERFACE ile eşleşen hizmetler için filtreleme yapılarak tespit edilebilir. Bazı araçlarda, hariç tutulması gereken bazı özel medya tarayıcı hizmeti uygulamaları bulunabilir. İşte bu mantığın bir örneği:

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

Medya kaynaklarının herhangi bir zamanda kurulabileceğini veya kaldırılabileceğini unutmayın. Doğru bir liste sağlamak amacıyla ACTION_PACKAGE_ADDED , ACTION_PACKAGE_CHANGED , ACTION_PACKAGE_REPLACED ve ACTION_PACKAGE_REMOVED niyet eylemleri için bir BroadcastReceiver örneğinin uygulanması önerilir.

Şu anda oynatılan medya kaynağına bağlanın

CarMediaService seçili olan medya kaynağını ve bu medya kaynağı değiştiğinde almak için yöntemler sağlar. Bu değişiklikler, kullanıcının kullanıcı arayüzüyle doğrudan etkileşime girmesi veya araçtaki donanım düğmelerinin kullanılması nedeniyle meydana gelebilir. Öte yandan, car-media-ortak kütüphanesi belirli bir medya kaynağına bağlanmak için uygun yollar sunar. Şu anda seçili olan medya uygulamasına nasıl bağlanılacağına ilişkin basitleştirilmiş bir pasajı burada bulabilirsiniz:

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
    }

    …
}

Şu anda oynatılan medya kaynağının oynatılmasını kontrol etme

Bağlı bir MediaBrowserCompat ile aktarım kontrolü komutlarını hedef uygulamaya göndermek kolaydır. İşte basitleştirilmiş bir örnek:

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

    …
}

Yerel medya kaynağı komutlarını yönetin (radyo, CD çalar, Bluetooth, USB)

Yerel medya kaynakları, yukarıda ayrıntıları verilen aynı MediaSession ve MediaBrowse API'lerini kullanarak işlevlerini sisteme sunar. Her donanım türünün özelliklerine uyum sağlamak amacıyla bu MediaBrowse hizmetleri, bilgilerini ve ortam komutlarını düzenlemek için belirli kurallar kullanır.

Radyo kolu

Radio MediaBrowseService, ACTION_PLAY_BROADCASTRADIO amaç filtresiyle tanımlanabilir. Radyonun Uygulanması bölümünde açıklanan oynatma kontrollerini ve medyaya göz atma yapısını takip etmeleri bekleniyor. AAOS, OEM'lerin, tanımlanan protokolü takip eden kendi radyo hizmetleri için MediaBrowseService uygulamaları oluşturmalarına yardımcı olacak sabitler ve yöntemler içeren car-broadcastradio-support kitaplığı sunar ve göz atma ağaçlarını tüketen uygulamalar (örneğin, VIA'lar) için destek sağlar.

Yardımcı girişi, CD sesini ve USB ortamını yönetin

AOSP'nin bir parçası olarak bu medya kaynaklarının varsayılan uygulaması yoktur. Önerilen yaklaşım şudur:

Bluetooth'u yönetin

Bluetooth medya içeriği AVRCP Bluetooth profili aracılığıyla gösterilir. Bu işlevselliğe erişimi kolaylaştırmak için AAOS, iletişim ayrıntılarını özetleyen bir MediaBrowserService ve MediaSession uygulaması içerir (bkz. paketler/uygulamalar/Bluetooth ).

İlgili medya tarayıcısı ağaç yapısı, BrowseTree sınıfında tanımlanır. Oynatma kontrolü komutları, MediaSession uygulaması kullanılarak diğer uygulamalara benzer şekilde iletilebilir.

Akışlı ortam komutlarını işleme

Sunucu tarafı medya akışını uygulamak için VIA'nın kendisi de MediaBrowse ve MediaSession API'yi uygulayan bir medya kaynağı haline gelmelidir. Arabalar için medya uygulamaları oluşturma konusuna bakın. Bu API'leri uygulayarak bir ses kontrolü uygulaması şunları yapabilecektir (diğer şeylerin yanı sıra):

  • Medya kaynağı seçimine sorunsuz bir şekilde katılın
  • Araba yeniden başlatıldıktan sonra otomatik olarak devam ettirilecek
  • Media Center kullanıcı arayüzünü kullanarak oynatma ve göz atma kontrolü sağlayın
  • Standart donanım medya düğmesi olaylarını alın

Tüm navigasyon uygulamalarıyla etkileşim kurmanın standartlaştırılmış bir yolu yoktur. Google Haritalar ile entegrasyonlar için Android Automotive Intents için Google Haritalar'a bakın. Diğer uygulamalarla entegrasyonlar için doğrudan uygulama geliştiricileriyle iletişime geçin. Herhangi bir uygulamaya (Google Haritalar dahil) yönelik bir amaç başlatmadan önce, amacın çözülebildiğini doğrulayın (bkz. Niyet istekleri ). Bu, hedef uygulamanın mevcut olmaması durumunda kullanıcıyı bilgilendirme fırsatı yaratır.

Araç komutlarını yerine getirin

Hem okuma hem de yazma için araç özelliklerine erişim CarPropertyManager aracılığıyla sağlanır. Araç özellikleri türleri, uygulanması ve diğer ayrıntılar Özellik konfigürasyonlarında açıklanmaktadır. Android tarafından desteklenen özelliklerin doğru bir açıklaması için doğrudan hardware/interfaces/automotive/vehicle/2.0/types.hal adresine başvurmak en iyisidir. Burada tanımlanan Araç Özelliği numaralandırması hem standart hem de satıcıya özel özellikleri, veri türlerini, değişiklik modunu, birimleri ve okuma/yazma erişim tanımını içerir.

Aynı sabitlere Java'dan erişmek için, AraçPropertyIds'i ve ona eşlik eden sınıfları kullanabilirsiniz. Farklı mülklerin, erişimlerini kontrol eden farklı Android izinleri vardır. Bu izinler CarService bildiriminde bildirilir ve özellikler ile izinler arasındaki eşleme, AraçPropertyIds Javadoc'unda açıklanır ve PropertyHalServiceIds'de uygulanır.

Bir araç özelliğini okuyun

Aşağıda araç hızının nasıl okunacağını gösteren bir örnek verilmiştir:

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

    ...
}

Araç özelliği ayarlama

Aşağıda ön klimanın nasıl açılıp kapatılacağını gösteren bir örnek bulunmaktadır.

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

    …
}

İletişim komutlarını yerine getirin

Mesajlaşma komutlarını yönetin

VIA'ların gelen mesajları , Sesli asistan Dokunarak Oku'da açıklanan "okumak için dokun" akışını takip ederek işlemesi gerekir; bu akış, isteğe bağlı olarak gelen mesaj göndericisine yanıtların gönderilmesini yönetebilir. Ayrıca VIA'lar, doğrudan araçtan veya Bluetooth üzerinden SMS mesajları oluşturmak ve göndermek için SmsManager ( android.telephony paketinin bir parçası) kullanabilir.

Çağrı komutlarını yönetin

Benzer şekilde, VIA'lar telefon aramaları yapmak ve kullanıcının sesli posta numarasını aramak için TelephonyManager kullanabilir. Bu durumlarda VIA'lar doğrudan telefon hattıyla veya Araç Çevirici uygulamasıyla etkileşime girecek. Her durumda, Araç Çevirici uygulaması, kullanıcıya sesli aramayla ilgili kullanıcı arayüzünü görüntüleyen uygulama olmalıdır.

Diğer komutları yerine getirin

VIA ile sistem arasındaki diğer olası entegrasyon noktalarının bir listesi için iyi bilinen Android amaçları listesine bakın. Birçok kullanıcı komutu sunucu tarafında çözülebilir (örneğin, kullanıcıların e-postalarını ve takvim etkinliklerini okumak) ve sistemle sesli etkileşimin kendisi dışında herhangi bir etkileşim gerektirmez.

Sürükleyici eylemler (görsel içeriği görüntüleyin)

Kullanıcı eylemlerini veya anlayışını iyileştirdiği durumlarda VIA, araç ekranında tamamlayıcı görsel içerik sağlayabilir. Sürücünün dikkatinin dağılmasını en aza indirmek için bu tür içerikleri basit, kısa ve uygulanabilir tutun. Sürükleyici eylemlere ilişkin UI/UX yönergeleri hakkında ayrıntılar için bkz . Önceden Yüklenmiş Yardımcılar: UX Rehberi .

Ana ünite (HU) tasarımının geri kalanıyla özelleştirme ve tutarlılık sağlamak amacıyla VIA'lar, çoğu kullanıcı arayüzü öğesi için Araç Kullanıcı Arayüzü Kitaplığı bileşenlerini kullanmalıdır. Ayrıntılar için bkz. Özelleştirme .