Sesli asistan Dokunarak Oku

Android Automotive, sesin sürüş güvenliği etkileşimleri için çok önemli bir bileşen olduğunu ve kullanıcıların sürüş sırasında Android Automotive işletim sistemiyle etkileşim kurmasının en güvenli yollarından biri olduğunu düşünüyor. Sonuç olarak, sesli asistanların kullanıcılar için sürüş sırasında gerçekleştirilmesi zor olabilecek görevleri yerine getirmesini sağlamak amacıyla Android sesli asistan API'lerini ( VoiceInteractionSession dahil) genişlettik.

Dokunarak Oku, kullanıcı mesaj bildirimleriyle etkileşimde bulunduğunda sesli asistanların kullanıcı adına metin mesajlarını okumasına ve yanıtlamasına olanak tanır. Bu işlevselliği sağlamak için bir sesli asistanı CarVoiceInteractionSession entegre edebilirsiniz.

Otomotiv'de, INBOX veya INBOX_IN_GROUP olarak tanımlanan Bildirim Merkezi'ne gönderilen bildirimler (örneğin, SMS mesajları) bir Oynat düğmesi içerir. Kullanıcı, seçilen sesli asistanın bildirimi yüksek sesle okuması ve isteğe bağlı olarak sesle yanıt vermesi için Oynat'a tıklayabilir.

Okumak için dokunarak bildirim

Şekil 1. Oynat düğmesiyle Dokunarak Oku bildirimi.

CarVoiceInteractionSession ile entegrasyon

Sonraki bölümlerde sesli asistanın CarVoiceInteractionSession ile nasıl entegre edileceği açıklanmaktadır.

Sesli etkileşimleri destekleyin

Araba sesli etkileşim hizmetleri sağlayan uygulamaların mevcut Android sesli etkileşimleriyle entegre olması gerekir . Daha fazla bilgi edinmek için Android için Google Asistan'a bakın ( VoiceInteractionSession hariç). Tüm sesli etkileşim API öğeleri mobil cihazlarda uygulananlarla aynı kalsa da, CarVoiceInteractionSession ( CarVoiceInteractionSession'ı Uygulama bölümünde açıklanmıştır) VoiceInteractionSession yerini almıştır. Daha fazla bilgi için şu sayfalara bakın:

CarVoiceInteractionSession'ı uygulayın

CarVoiceInteractionSession sesli asistanların metin mesajlarını yüksek sesle okumasını ve ardından bu mesajlara kullanıcı adına yanıt vermesini sağlamak için kullanabileceğiniz API'leri kullanıma sunar.

CarVoiceInteractionSession ve VoiceInteractionSession sınıfları arasındaki temel fark, CarVoiceInteractionSession eylemi onShow geçirmesidir, böylece sesli yardımcı, CarVoiceInteractionSession bir oturum başlatır başlatmaz kullanıcının isteğinin içeriğini algılayabilir. Her sınıf için onShow parametreleri aşağıdaki tabloda listelenmiştir:

ArabaSesEtkileşimOturumu Sesli Etkileşim Oturumu
onShow şu üç parametreyi alır:
  • args
  • showFlags
  • actions
onShow şu iki parametreyi alır:
  • args
  • showFlags

Android 10'daki değişiklikler

Android 10'dan başlayarak platform, hangi eylemlerin desteklendiğini tespit etmek için VoiceInteractionService.onGetSupportedVoiceActions çağırır. Sesli yardımcı, aşağıdaki örnekte gösterildiği gibi VoiceInteractionService.onGetSupportedVoiceActions geçersiz kılar ve uygular:

public class MyInteractionService extends VoiceInteractionService {
    private static final List SUPPORTED_VOICE_ACTIONS = Arrays.asList(
        CarVoiceInteractionSession.VOICE_ACTION_READ_NOTIFICATION);

    @Override
    public Set onGetSupportedVoiceActions(@NonNull Set voiceActions) {
       Set result = new HashSet<>(voiceActions);
       result.retainAll(SUPPORTED_VOICE_ACTIONS);
       return result;
   }
}

Geçerli eylemler aşağıdaki tabloda açıklanmıştır. Her eylemle ilgili ayrıntılar için bkz. Sıra diyagramları .

Aksiyon Beklenen yük Beklenen sesli etkileşim eylemi
VOICE_ACTION_READ_NOTIFICATION Mesajları kullanıcıya yüksek sesle okuyun ve ardından mesajlar başarıyla okunduğunda Okundu olarak işaretle seçeneğini beklemede olarak etkinleştirin. İsteğe bağlı olarak kullanıcıdan yanıt vermesini isteyin.
VOICE_ACTION_REPLY_NOTIFICATION Anahtarla parçalanabilir.
StatusBarNotification ile eşleşen KEY_NOTIFICATION .
android.permission.BIND_NOTIFICATION_LISTENER_SERVICE gerektirir.
Kullanıcıdan yanıt mesajını belirtmesini isteyin, yanıt mesajını bekleyen niyetin RemoteInputReply girin ve ardından bekleyen niyeti tetikleyin.
VOICE_ACTION_HANDLE_EXCEPTION Anahtarlı dize.
ExceptionValue ile eşleşen KEY_EXCEPTION ( Exception değerleri bölümünde açıklanmıştır).
Bir Boole değeriyle eşleşen KEY_FALLBACK_ASSISTANT_ENABLED . Değer true ise kullanıcının isteğini yerine getirebilecek geri dönüş yardımcısı devre dışı bırakılmıştır.
İstisna için yapılması beklenen eylem, istisnanın belgelerinde tanımlanır.

İstisna değerleri

EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING , sesli asistana Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE izninin eksik olduğunu ve bu iznin kullanıcıdan alınması gerektiğini belirtir.

Bildirim dinleyicisi izni iste

Varsayılan sesli asistanın bildirim dinleyicisi izni yoksa platformun FallbackAssistant (otomobil üreticisi tarafından etkinleştirildiyse), sesli asistanın izin istemesi konusunda bilgilendirilmeden önce mesajı yüksek sesle okuyabilir. FallbackAssistant etkin olup olmadığını ve mesajı okuyup okumadığını belirlemek için sesli asistanın veri yükündeki KEY_FALLBACK_ASSISTANT_ENABLED Boolean değerini kontrol etmesi gerekir.

Platform, sesli asistanın bu iznin istenme sayısı kadar hız sınırlama mantığı eklemesini önerir. Bunu yapmak, sesli asistana bu izni vermek istemeyen ve FallbackAssistant metin mesajlarını yüksek sesle okumasını tercih eden kullanıcıya saygı gösterir. Kullanıcının bir mesaj bildiriminde Oynat'a her basışında kullanıcıdan izin istemek, olumsuz bir kullanıcı deneyimi olabilir. Platform, sesli asistan adına hız sınırı koymuyor.

Bildirim dinleyicisi izni istenirken sesli asistan, kullanıcının park halinde mi yoksa araba mı sürdüğünü belirlemek için CarUxRestrictionsManager kullanmalıdır. Kullanıcı araba kullanıyorsa sesli asistan, iznin nasıl verileceğiyle ilgili talimatlar sağlayan bir bildirim görüntüler. Bunu yapmak, kullanıcının daha güvenli olduğunda izin vermesine yardımcı olur (ve hatırlatır).

StatusBarNotification'la çalışın

Oku ve Yanıtla sesli eylemleriyle iletilen StatusBarNotification Kullanıcılara mesaj bildirme bölümünde açıklandığı gibi her zaman araçla uyumlu bir mesajlaşma bildiriminde bulunur. Bazı bildirimler Yanıt Bekleniyor amacına sahip olmasa da hepsinde Okundu Olarak İşaretleme bekleyen amaçları vardır.

Bildirimlerle etkileşimleri kolaylaştırmak için, bildirimden mesajları ayıklamak ve yanıt mesajlarını bildirimin uygun bekleyen amacına yazmak için yöntemler sağlayan NotificationPayloadHandler kullanın. Sesli yardımcı mesajı okuduktan sonra sesli asistanın Okundu Olarak İşaretle amacını tetiklemesi gerekir .

Dokunarak Okuma ön koşullarını karşılayın

Kullanıcı mesajları okumak ve yanıtlamak için sesli eylemi tetiklediğinde yalnızca varsayılan sesli asistanın VoiceInteractionSession bilgilendirilir. Yukarıda belirtildiği gibi, bu varsayılan sesli asistanın aynı zamanda bildirim dinleyicisi iznine de sahip olması gerekir.

Sıra diyagramları

Bu şekiller CarVoiceInteractionSession actions mantıksal akışlarını gösterir:

VOICE_ACTION_READ_NOTIFICATION

Şekil 2. VOICE_ACTION_READ_NOTIFICATION için sıra diyagramı.

Şekil 3'te izin isteklerine oran sınırlarının uygulanması önerilir:

VOICE_ACTION_REPLY_NOTIFICATION

Şekil 3. VOICE_ACTION_REPLY_NOTIFICATION için sıra diyagramı.

VOICE_ACTION_HANDLE_EXCEPTION

Şekil 4. VOICE_ACTION_HANDLE_EXCEPTION için sıra diyagramı.

Uygulamanın adını oku

Sesli yardımcınızın, mesajın okunması sırasında mesajlaşma uygulamasının adını yüksek sesle okumasını istiyorsanız (örneğin, "Hangouts'tan Sam şunu söyledi..."), asistanın mesajı okuduğundan emin olmak için aşağıdaki kod örneğinde gösterilene benzer bir işlev oluşturun. doğru isim:

@Nullable
String getMessageApplicationName(Context context, StatusBarNotification statusBarNotification) {
    ApplicationInfo info = getApplicationInfo(context, statusBarNotification.getPackageName());
    if (info == null) return null;

    Notification notification = statusBarNotification.getNotification();

    // Sometimes system packages will post on behalf of other apps, so check this
    // field for a system app notification.
    if (isSystemApp(info)
            && notification.extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) {
        return notification.extras.getString(Notification.EXTRA_SUBSTITUTE_APP_NAME);
    } else {
        PackageManager pm = context.getPackageManager();
        return String.valueOf(pm.getApplicationLabel(info));
    }
}

@Nullable
ApplicationInfo getApplicationInfo(Context context, String packageName) {
    final PackageManager pm = context.getPackageManager();
    ApplicationInfo info;
    try {
        info = pm.getApplicationInfo(packageName, 0);
    } catch (PackageManager.NameNotFoundException e) {
        return null;
    }
    return info;
}

boolean isSystemApp(ApplicationInfo info) {
    return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}