Arabalar için Android Uygulama Kitaplığı'nı kullanma

Android for Cars Uygulama Kitaplığı, navigasyon, ilgi çekici yer (İÇY), nesnelerin interneti (IoT) veya hava durumu uygulamanızı arabaya getirmenize olanak tanır. Bunu, sürücü dikkatini dağıtma standartlarını karşılamak üzere tasarlanmış bir dizi şablon sağlayarak ve araba ekranı faktörlerinin çeşitliliği ile giriş yöntemleri gibi ayrıntıları ele alarak yapar.

Bu kılavuzda, kitaplığın temel özellikleri ve kavramları hakkında genel bilgiler verilmekte ve temel bir uygulama oluşturma süreci adım adım açıklanmaktadır.

Başlamadan önce

  1. Araba Uygulaması Kitaplığı'nı kapsayan Sürüş İçin Tasarım sayfalarını inceleyin.
  2. Aşağıdaki bölümde temel terimleri ve kavramları inceleyin.
  3. Android Auto Sistem Kullanıcı Arayüzü ve Android Automotive OS tasarımı hakkında bilgi edinin.
  4. Sürüm notlarını inceleyin.
  5. Örnekleri inceleyin.

Temel terimler ve kavramlar

Modeller ve Şablonlar
Kullanıcı arayüzü, ait oldukları şablonun izin verdiği şekilde farklı şekillerde düzenlenebilen model nesnelerinin grafiğiyle temsil edilir. Şablonlar, bu grafiklerde kök görevi görebilen modellerin bir alt kümesidir. Modeller, kullanıcılara metin ve resim biçiminde gösterilecek bilgilerin yanı sıra bu bilgilerin görsel görünümünün çeşitli yönlerini (ör. metin renkleri veya resim boyutları) yapılandırmak için kullanılan özellikleri içerir. Ana makine, modelleri sürücünün dikkatini dağıtma standartlarını karşılayacak şekilde tasarlanmış görünümlere dönüştürür ve araba ekranı faktörlerinin çeşitliliği ile giriş yöntemleri gibi ayrıntılarla ilgilenir.
Düzenleyen
Ana makine, kitaplığın API'leri tarafından sunulan işlevleri uygulayan arka uç bileşenidir. Bu sayede uygulamanız arabada çalışabilir. Ana makinenin sorumlulukları, uygulamanızı keşfetmekten ve yaşam döngüsünü yönetmekten modellerinizi görünümlere dönüştürmeye ve uygulamanızı kullanıcı etkileşimleri konusunda bilgilendirmeye kadar uzanır. Mobil cihazlarda bu ana makine, Android Auto tarafından uygulanır. Android Automotive OS'te bu ana makine, sistem uygulaması olarak yüklenir.
Şablon kısıtlamaları
Farklı şablonlar, modellerinin içeriğinde kısıtlamalar uygular. Örneğin, liste şablonlarında kullanıcıya sunulabilecek öğe sayısı sınırlıdır. Şablonların, bir görevin akışını oluşturmak için bağlanma şekliyle ilgili kısıtlamalar da vardır. Örneğin, uygulama ekran yığınına yalnızca beş şablon gönderebilir. Daha fazla bilgi için Şablon kısıtlamaları bölümüne bakın.
Screen
Screen, uygulamaların kullanıcıya sunulan kullanıcı arayüzünü yönetmek için uyguladığı kitaplık tarafından sağlanan bir sınıftır. Screen, yaşam döngüsüne sahiptir ve ekran görünür olduğunda şablonu göndermek için uygulamaya mekanizma sağlar. Screen örnekleri, Screen yığınına da gönderilip yığından çıkarılabilir. Bu sayede, örneklerin şablon akışı kısıtlamalarına uyması sağlanır.
CarAppService
CarAppService, uygulamanızın ana makine tarafından bulunup yönetilebilmesi için uygulaması ve dışa aktarması gereken bir soyut Service sınıfıdır. Uygulamanızın CarAppService, createHostValidator kullanarak bir ana makine bağlantısının güvenilir olup olmadığını doğrulama ve ardından onCreateSession kullanarak her bağlantı için Session örnekleri sağlama sorumluluğundadır.
Session

Session, uygulamanızın CarAppService.onCreateSession kullanarak uygulaması ve döndürmesi gereken soyut bir sınıftır. Araba ekranında bilgileri göstermek için giriş noktası olarak kullanılır. Uygulamanızın araba ekranındaki mevcut durumu (ör. uygulamanızın görünür veya gizli olması) hakkında bilgi veren bir yaşam döngüsüne sahiptir.

Bir Session başlatıldığında (ör. uygulama ilk kez başlatıldığında) ana makine, onCreateScreen yöntemini kullanarak ilk Screen için görüntüleme isteğinde bulunur.

Araba Uygulaması Kitaplığı'nı yükleme

Kitaplığı uygulamanıza nasıl ekleyeceğinizle ilgili talimatlar için Jetpack kitaplığı sürüm sayfasını inceleyin.

Uygulamanızın manifest dosyalarını yapılandırma

Araba uygulamanızı oluşturmadan önce uygulamanızın manifest dosyalarını aşağıdaki gibi yapılandırın.

CarAppService'inizi beyan etme

Barındırıcı, CarAppService uygulamanız üzerinden uygulamanıza bağlanır. Ana makinenin uygulamanızı keşfedip bağlanabilmesi için bu hizmeti manifestinizde beyan edersiniz.

Ayrıca uygulamanızın kategorisini, uygulamanızın intent filtresinin <category> öğesinde de beyan etmeniz gerekir. Bu öğe için izin verilen değerleri desteklenen uygulama kategorileri listesinde görebilirsiniz.

Aşağıdaki kod snippet'inde, manifest dosyanızda bir ilgi alanı uygulaması için araba uygulaması hizmetinin nasıl beyan edileceği gösterilmektedir:

<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService"/>
        <category android:name="androidx.car.app.category.POI"/>
      </intent-filter>
    </service>

    ...
<application>

Desteklenen uygulama kategorileri

CarAppService beyan ederken önceki bölümde açıklandığı gibi intent filtresine aşağıdaki kategori değerlerinden birini veya daha fazlasını ekleyerek uygulamanızın kategorisini beyan edin:

Her kategorinin ayrıntılı açıklamaları ve uygulamaların bu kategorilere ait olma ölçütleri için Arabalar için Android uygulama kalitesi başlıklı makaleyi inceleyin.

Uygulama adını ve simgesini belirtin

Ana makinenin, uygulamanızı sistem kullanıcı arayüzünde temsil etmek için kullanabileceği bir uygulama adı ve simgesi belirtmeniz gerekir.

Uygulamanızı temsil etmek için kullanılan uygulama adını ve simgesini, CarAppService öğenizin label ve icon özelliklerini kullanarak belirtebilirsiniz:

...
<service
   android:name=".MyCarAppService"
   android:exported="true"
   android:label="@string/my_app_name"
   android:icon="@drawable/my_app_icon">
   ...
</service>
...

Etiket veya simge <service> öğesinde bildirilmemişse ana makine, <application> öğesi için belirtilen değerlere geri döner.

Özel tema ayarlama

Araba uygulamanız için özel bir tema ayarlamak üzere manifest dosyanıza aşağıdaki gibi bir <meta-data> öğesi ekleyin:

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

Ardından, özel araba uygulaması temanız için aşağıdaki özellikleri ayarlamak üzere stil kaynağınızı bildirin:

<resources>
  <style name="MyCarAppTheme">
    <item name="carColorPrimary">@layout/my_primary_car_color</item>
    <item name="carColorPrimaryDark">@layout/my_primary_dark_car_color</item>
    <item name="carColorSecondary">@layout/my_secondary_car_color</item>
    <item name="carColorSecondaryDark">@layout/my_secondary_dark_car_color</item>
    <item name="carPermissionActivityLayout">@layout/my_custom_background</item>
  </style>
</resources>

Araba uygulaması API düzeyi

Araba Uygulaması Kitaplığı, hangi kitaplık özelliklerinin araçtaki şablon ana makinesi tarafından desteklendiğini bilmeniz için kendi API düzeylerini tanımlar. Bir ana makine tarafından desteklenen en yüksek Car App API düzeyini almak için getCarAppApiLevel() yöntemini kullanın.

Uygulamanızın desteklediği minimum Car App API düzeyini AndroidManifest.xml dosyanızda bildirin:

<manifest ...>
    <application ...>
        <meta-data
            android:name="androidx.car.app.minCarApiLevel"
            android:value="1"/>
    </application>
</manifest>

Geriye dönük uyumluluğu koruma ve bir özelliği kullanmak için gereken minimum API düzeyini bildirme hakkında ayrıntılı bilgi için RequiresCarApi ek açıklamasının dokümanlarına bakın. Araba Uygulaması Kitaplığı'nın belirli bir özelliğini kullanmak için hangi API düzeyinin gerekli olduğunu öğrenmek istiyorsanız CarAppApiLevels ile ilgili referans belgelerine göz atın.

CarAppService ve Oturumunuzu oluşturma

Uygulamanızın CarAppService sınıfını genişletmesi ve ana makineyle mevcut bağlantıya karşılık gelen bir Session örneği döndüren onCreateSession yöntemini uygulaması gerekir:

Kotlin

class HelloWorldService : CarAppService() {
    ...
    override fun onCreateSession(): Session {
        return HelloWorldSession()
    }
    ...
}

Java

public final class HelloWorldService extends CarAppService {
    ...
    @Override
    @NonNull
    public Session onCreateSession() {
        return new HelloWorldSession();
    }
    ...
}

Session örneği, uygulama ilk kez başlatıldığında kullanılacak Screen örneğini döndürmekten sorumludur:

Kotlin

class HelloWorldSession : Session() {
    ...
    override fun onCreateScreen(intent: Intent): Screen {
        return HelloWorldScreen(carContext)
    }
    ...
}

Java

public final class HelloWorldSession extends Session {
    ...
    @Override
    @NonNull
    public Screen onCreateScreen(@NonNull Intent intent) {
        return new HelloWorldScreen(getCarContext());
    }
    ...
}

Aracınızın uygulamasının, uygulamanızın ana ekranı veya açılış ekranı olmayan bir ekrandan başlatılması gereken senaryoları (ör. derin bağlantıları işleme) ele almak için ScreenManager.push kullanarak ekranların geri yığınını önceden doldurabilirsiniz. Bu işlemi, onCreateScreen'dan dönmeden önce yapın. Önceden doldurma, kullanıcıların uygulamanızın gösterdiği ilk ekrandan önceki ekranlara geri dönmesine olanak tanır.

Başlangıç ekranınızı oluşturma

Uygulamanızın gösterdiği ekranları, Screen sınıfını genişleten sınıfları tanımlayarak ve onGetTemplate yöntemini uygulayarak oluşturursunuz. Bu yöntem, kullanıcı arayüzünün durumunu temsil eden Template örneğini döndürür. Bu örnek, araç ekranında gösterilecek kullanıcı arayüzünün durumunu temsil eder.

Aşağıdaki snippet'te, basit bir "Merhaba dünya!" dizesini görüntülemek için PaneTemplate şablonunu kullanan bir Screen öğesinin nasıl bildirileceği gösterilmektedir:

Kotlin

class HelloWorldScreen(carContext: CarContext) : Screen(carContext) {
    override fun onGetTemplate(): Template {
        val row = Row.Builder().setTitle("Hello world!").build()
        val pane = Pane.Builder().addRow(row).build()
        return PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build()
    }
}

Java

public class HelloWorldScreen extends Screen {
    @NonNull
    @Override
    public Template onGetTemplate() {
        Row row = new Row.Builder().setTitle("Hello world!").build();
        Pane pane = new Pane.Builder().addRow(row).build();
        return new PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build();
    }
}

CarContext sınıfı

CarContext sınıfı, ContextWrapper alt sınıfıdır ve Session ile Screen örneklerinizde kullanılabilir. Ekran yığınını yönetmek için kullanılan ScreenManager, Surface nesnesine erişerek harita çizme gibi genel uygulamayla ilgili işlevler için kullanılan AppManager ve adım adım navigasyon uygulamalarının navigasyon meta verilerini ve diğer navigasyonla ilgili etkinlikleri ana makineyle iletmek için kullandığı NavigationManager gibi araç hizmetlerine erişim sağlar.

Gezinme uygulamalarında kullanılabilen kitaplık işlevlerinin kapsamlı bir listesi için Gezinme şablonlarına erişme başlıklı makaleyi inceleyin.

CarContext ayrıca, araba ekranındaki yapılandırmayı kullanarak çizilebilir kaynakları yüklemenize, amaçları kullanarak arabada bir uygulamayı başlatmanıza ve uygulamanızın haritasını koyu temada gösterip göstermemesi gerektiğine dair sinyal vermenize olanak tanıyan başka işlevler de sunar.

Ekran gezinmesini uygulama

Uygulamalar genellikle farklı ekranlar sunar. Bu ekranların her birinde, kullanıcının ekranda gösterilen arayüzle etkileşim kurarken gezinebileceği farklı şablonlar kullanılabilir.

ScreenManager sınıfı, kullanıcının araba ekranında geri düğmesini seçtiğinde veya bazı arabalarda bulunan donanım geri düğmesini kullandığında otomatik olarak açılabilen ekranları göndermek için kullanabileceğiniz bir ekran yığını sağlar.

Aşağıdaki snippet'te, bir mesaj şablonuna geri gitme eyleminin ve kullanıcı tarafından seçildiğinde yeni bir ekranı gönderen eylemin nasıl ekleneceği gösterilmektedir:

Kotlin

val template = MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener { screenManager.push(NextScreen(carContext)) }
            .build())
    .build()

Java

MessageTemplate template = new MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        new Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener(
                () -> getScreenManager().push(new NextScreen(getCarContext())))
            .build())
    .build();

Action.BACK nesnesi, ScreenManager.pop işlevini otomatik olarak çağıran standart bir Action'tır. Bu davranış, CarContext öğesinden kullanılabilen OnBackPressedDispatcher örneği kullanılarak geçersiz kılınabilir.

Uygulamanın sürüş sırasında güvenli bir şekilde kullanılabilmesini sağlamak için ekran yığınında en fazla beş ekran olabilir. Daha fazla bilgi için Şablon kısıtlamaları bölümüne bakın.

Şablonun içeriğini yenileme

Uygulamanız, Screen.invalidate yöntemini çağırarak Screen içeriğinin geçersiz kılınmasını isteyebilir. Ardından, yeni içeriklerle şablonu almak için ana makine, uygulamanızın Screen.onGetTemplate yöntemini tekrar çağırır.

Screen yenilenirken, yeni şablonun şablon kotasına dahil edilmemesi için şablondaki hangi içeriğin güncellenebileceğini anlamak önemlidir. Daha fazla bilgi için Şablon kısıtlamaları bölümüne bakın.

Ekranlarınızı, Screen ile onGetTemplate uygulaması aracılığıyla döndürdüğü şablon türü arasında bire bir eşleme olacak şekilde yapılandırmanızı öneririz.

Harita çizme

Aşağıdaki şablonları kullanan gezinme, önemli yer (POI) ve hava durumu uygulamaları, Surface erişerek harita çizebilir.

Aşağıdaki şablonları kullanmak için uygulamanızın <uses-permission> öğesinde, AndroidManifest.xml dosyasında beyan edilmiş ilgili izinlerden birine sahip olması gerekir.

Şablon Şablon izni Kategori rehberliği
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Gezinme
MapWithContentTemplate androidx.car.app.NAVIGATION_TEMPLATES VEYA
androidx.car.app.MAP_TEMPLATES
Gezinme, Öİ, Hava durumu
MapTemplate (kullanımdan kaldırıldı) androidx.car.app.NAVIGATION_TEMPLATES Gezinme
PlaceListNavigationTemplate (kullanımdan kaldırıldı) androidx.car.app.NAVIGATION_TEMPLATES Gezinme
RoutePreviewNavigationTemplate (kullanımdan kaldırıldı) androidx.car.app.NAVIGATION_TEMPLATES Gezinme

Yüzey iznini beyan etme

Uygulamanızın kullandığı şablon için gereken izne ek olarak, yüzeye erişmek için uygulamanızın androidx.car.app.ACCESS_SURFACE dosyasında AndroidManifest.xml iznini beyan etmesi gerekir:

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
  ...
</manifest>

Platforma erişme

Barındırıcının sağladığı Surface hizmetine erişmek için SurfaceCallback hizmetini uygulamanız ve bu uygulamayı AppManager araç hizmetine sağlamanız gerekir. Mevcut Surface, onSurfaceAvailable() ve onSurfaceDestroyed() geri çağırmalarının SurfaceContainer parametresinde SurfaceCallback öğenize iletilir.

Kotlin

carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)

Java

carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

Yüzeyin görünür alanını anlama

Düzenleyen, şablonlar için kullanıcı arayüzü öğelerini haritanın üzerine çizebilir. Ana makine, SurfaceCallback.onVisibleAreaChanged yöntemini çağırarak yüzeyin engellenmemiş ve kullanıcıya tamamen görünür olacağı alanı bildirir. Ayrıca, değişiklik sayısını en aza indirmek için ana makine, SurfaceCallback.onStableAreaChanged yöntemini geçerli şablona göre her zaman görünür olan en küçük dikdörtgenle çağırır.

Örneğin, bir gezinme uygulaması üstte işlem şeridi ile birlikte NavigationTemplate kullandığında, kullanıcı bir süredir ekranla etkileşimde bulunmadığında işlem şeridi harita için daha fazla alan açmak üzere kendini gizleyebilir. Bu durumda, aynı dikdörtgenle onStableAreaChanged ve onVisibleAreaChanged için geri arama vardır. İşlem şeridi gizlendiğinde, daha büyük alanla yalnızca onVisibleAreaChanged çağrılır. Kullanıcı ekranla etkileşimde bulunursa yine yalnızca onVisibleAreaChanged, ilk dikdörtgenle birlikte çağrılır.

Koyu tema desteği

Uygulamalar, ana makine koşulların bunu gerektirdiğini belirlediğinde haritalarını Surface örneğine uygun koyu renklerle yeniden çizmelidir. Bu işlem, Android'de arabalar için uygulama kalitesi bölümünde açıklanmıştır.

Koyu renkli bir harita çizip çizmeyeceğinize karar vermek için CarContext.isDarkMode yöntemini kullanabilirsiniz. Koyu tema durumu her değiştiğinde Session.onCarConfigurationChanged numarasına bir çağrı alırsınız.

Küme ekranında harita çizme

Navigasyon uygulamaları, ana ekranda harita çizmenin yanı sıra direksiyonun arkasındaki gösterge ekranında da harita çizmeyi destekleyebilir. Daha fazla yardım için Küme ekranına çizme başlıklı makaleyi inceleyin.

Kullanıcıların haritanızla etkileşim kurmasına izin verme

Aşağıdaki şablonları kullanırken, kullanıcıların çizdiğiniz haritalarla etkileşime girmesini sağlayabilirsiniz. Örneğin, yakınlaştırma ve kaydırma yaparak haritanın farklı bölümlerini görmelerine izin verebilirsiniz.

Şablon Car App API düzeyinden itibaren etkileşim desteklenir.
NavigationTemplate 2
PlaceListNavigationTemplate (kullanımdan kaldırıldı) 4
RoutePreviewNavigationTemplate (kullanımdan kaldırıldı) 4
MapTemplate (kullanımdan kaldırıldı) 5 (şablonun tanıtımı)
MapWithContentTemplate 7 (şablonun tanıtımı)

Etkileşim geri çağırmalarını uygulama

SurfaceCallback arayüzünde, önceki bölümde yer alan şablonlarla oluşturulan haritalara etkileşim eklemek için uygulayabileceğiniz çeşitli geri çağırma yöntemleri bulunur:

Etkileşim SurfaceCallback yöntemi Car App API düzeyinden itibaren desteklenir.
Dokunun onClick 5
Yakınlaştırmak için sıkıştırın onScale 2
Tek dokunuşla sürükleme onScroll 2
Tek dokunuşla kaydırma onFling 2
İki kez dokunun onScale (ölçeklendirme faktörü şablon ana makinesi tarafından belirlenir) 2
Kaydırma modunda döner sürükleme onScroll (uzaklık faktörü, şablon ana makinesi tarafından belirlenir) 2

Harita işlem şeridi ekleme

Bu şablonlarda, haritayla ilgili işlemler (ör. yakınlaştırma ve uzaklaştırma, yeniden ortalama, pusula gösterme) ve göstermeyi seçtiğiniz diğer işlemler için bir harita işlem şeridi olabilir. Harita işlem şeridinde, görev derinliğini etkilemeden yenilenebilen en fazla dört simge içeren düğme olabilir. Boşta kalma durumunda gizlenir ve etkin durumda yeniden görünür.

Harita etkileşim geri aramaları almak için harita işlem şeridine bir Action.PAN düğmesi eklemeniz gerekir. Kullanıcı kaydırma düğmesine bastığında, aşağıdaki bölümde açıklandığı gibi sunucu kaydırma moduna girer.

Uygulamanız harita işlem şeridinde Action.PAN düğmesini atlıyorsa SurfaceCallback yöntemlerinden kullanıcı girişi almaz ve ana makine, daha önce etkinleştirilmiş olan tüm kaydırma modlarından çıkar.

Dokunmatik ekranda kaydırma düğmesi gösterilmez.

Kaydırma modunu anlama

Kaydırma modunda, şablon ana makinesi, çevirmeli kontrol cihazları ve dokunmatik yüzeyler gibi dokunmatik olmayan giriş cihazlarından gelen kullanıcı girişini uygun SurfaceCallback yöntemlerine çevirir. Kullanıcının kaydırma moduna girme veya kaydırma modundan çıkma işlemine NavigationTemplate.Builder içindeki setPanModeListener yöntemiyle yanıt verin. Düzenleyen, kullanıcı kaydırma modundayken şablondaki diğer kullanıcı arayüzü bileşenlerini gizleyebilir.

Kullanıcıyla etkileşim kurma

Uygulamanız, mobil uygulamalara benzer kalıplar kullanarak kullanıcıyla etkileşim kurabilir.

Kullanıcı girişini işleme

Uygulamanız, uygun dinleyicileri bunları destekleyen modellere ileterek kullanıcı girişine yanıt verebilir. Aşağıdaki snippet'te, uygulamanızın kodu tarafından tanımlanan bir yöntemi geri çağıran bir OnClickListener ayarlayan bir Action modelinin nasıl oluşturulacağı gösterilmektedir:

Kotlin

val action = Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(::onClickNavigate)
    .build()

Java

Action action = new Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(this::onClickNavigate)
    .build();

onClickNavigate yöntemi, CarContext.startCarApp yöntemini kullanarak varsayılan navigasyon araba uygulamasını başlatabilir:

Kotlin

private fun onClickNavigate() {
    val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address))
    carContext.startCarApp(intent)
}

Java

private void onClickNavigate() {
    Intent intent = new Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address));
    getCarContext().startCarApp(intent);
}

ACTION_NAVIGATE amacının biçimi de dahil olmak üzere uygulamaları başlatma hakkında daha fazla bilgi için Bir amaca sahip araba uygulaması başlatma bölümüne bakın.

Kullanıcının etkileşime mobil cihazında devam etmesini gerektirenler gibi bazı işlemler yalnızca araba park hâlindeyken yapılabilir. Bu işlemleri uygulamak için ParkedOnlyOnClickListener simgesini kullanabilirsiniz. Araba park edilmemişse ana makine, kullanıcının bu durumda işleme izin verilmediği konusunda bilgilendirir. Araba park hâlindeyken kod normal şekilde yürütülür. Aşağıdaki snippet'te, mobil cihazda ayarlar ekranını açmak için ParkedOnlyOnClickListener öğesinin nasıl kullanılacağı gösterilmektedir:

Kotlin

val row = Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(::openSettingsOnPhone))
    .build()

Java

Row row = new Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(this::openSettingsOnPhone))
    .build();

Bildirimleri görüntüleme

Mobil cihaza gönderilen bildirimler, yalnızca CarAppExtender ile genişletilmişse araç ekranında gösterilir. İçerik başlığı, metin, simge ve işlemler gibi bazı bildirim özellikleri CarAppExtender içinde ayarlanabilir. Bu durumda, araba ekranında göründüklerinde bildirimin özelliklerinin üzerine yazılır.

Aşağıdaki kod snippet'inde, mobil cihazda gösterilenden farklı bir başlık görüntüleyen bir bildirimin araba ekranına nasıl gönderileceği gösterilmektedir:

Kotlin

val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build()

Java

Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build();

Bildirimler, kullanıcı arayüzünün aşağıdaki bölümlerini etkileyebilir:

  • Kullanıcıya uyarı bildirimi (HUN) gösterilebilir.
  • Bildirim merkezine bir giriş eklenebilir. İsteğe bağlı olarak, kanalda görünen bir rozet de eklenebilir.
  • Navigasyon uygulamalarında bildirim, Dönüş dönüş bildirimleri bölümünde açıklandığı gibi ray widget'ında gösterilebilir.

CarAppExtender dokümanında açıklandığı gibi, uygulamanızın bildirimlerini, bildirim önceliğini kullanarak bu kullanıcı arayüzü öğelerinin her birini etkileyecek şekilde yapılandırabilirsiniz.

NotificationCompat.Builder.setOnlyAlertOnce true değeriyle çağrılırsa yüksek öncelikli bildirim yalnızca bir kez HUN olarak gösterilir.

Araba uygulamanızın bildirimlerini tasarlama hakkında daha fazla bilgi için Bildirimler ile ilgili Google Design for Driving kılavuzuna bakın.

Kısa iletileri göster

Uygulamanız, bu snippet'te gösterildiği gibi CarToast kullanarak bir durum mesajı gösterebilir:

Kotlin

CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()

Java

CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();

İzin isteğinde bulunma

Uygulamanızın kısıtlanmış verilere veya işlemlere (ör. konum) erişmesi gerekiyorsa Android izinleriyle ilgili standart kurallar geçerlidir. İzin istemek için CarContext.requestPermissions() yöntemini kullanabilirsiniz.

Standart Android API'leri kullanmak yerine CarContext.requestPermissions() kullanmanın avantajı, izin iletişim kutusunu oluşturmak için kendi Activity'nizi başlatmanız gerekmemesidir. Ayrıca, platforma bağlı akışlar oluşturmak zorunda kalmak yerine hem Android Auto hem de Android Automotive OS'de aynı kodu kullanabilirsiniz.

Android Auto'da izin iletişim kutusunu stilize etme

Android Auto'da, kullanıcının izin iletişim kutusu telefonda görünür. Varsayılan olarak iletişim kutusunun arkasında arka plan olmaz. Özel bir arka plan ayarlamak için AndroidManifest.xml dosyanızda bir araba uygulaması teması tanımlayın ve araba uygulaması temanız için carPermissionActivityLayout özelliğini ayarlayın.

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

Ardından, araba uygulaması temanız için carPermissionActivityLayout özelliğini ayarlayın:

<resources>
  <style name="MyCarAppTheme">
    <item name="carPermissionActivityLayout">@layout/my_custom_background</item>
  </style>
</resources>

Bir amaçla araba uygulaması başlatma

Aşağıdaki işlemlerden birini gerçekleştirmek için CarContext.startCarApp yöntemini çağırabilirsiniz:

  • Telefon görüşmesi yapmak için numara çeviriciyi açın.
  • Varsayılan navigasyon aracı uygulaması ile bir konuma adım adım navigasyonu başlatın.
  • Bir amaç belirleyerek kendi uygulamanızı oluşturun.

Aşağıdaki örnekte, park yeri rezervasyonu ayrıntılarını gösteren bir ekranla uygulamanızı açan bir işlem içeren bildirimin nasıl oluşturulacağı gösterilmektedir. Bildirim örneğini, uygulamanızın işlemine yönelik açık bir niyet içeren bir PendingIntent ile sarmalanmış bir içerik niyetiyle genişletiyorsunuz:

Kotlin

val notification = notificationBuilder
    ...
    .extend(
        CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(ComponentName(context, MyNotificationReceiver::class.java)),
                    0))
            .build())

Java

Notification notification = notificationBuilder
    ...
    .extend(
        new CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    new Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(new ComponentName(context, MyNotificationReceiver.class)),
                    0))
            .build());

Uygulamanız ayrıca, kullanıcı bildirim arayüzünde işlemi seçtiğinde amaç işlenmek üzere çağrılan ve veri URI'si içeren bir amaçla CarContext.startCarApp'ı çağıran bir BroadcastReceiver beyan etmelidir:

Kotlin

class MyNotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val intentAction = intent.action
        if (ACTION_VIEW_PARKING_RESERVATION == intentAction) {
            CarContext.startCarApp(
                intent,
                Intent(Intent.ACTION_VIEW)
                    .setComponent(ComponentName(context, MyCarAppService::class.java))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)))
        }
    }
}

Java

public class MyNotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        if (ACTION_VIEW_PARKING_RESERVATION.equals(intentAction)) {
            CarContext.startCarApp(
                intent,
                new Intent(Intent.ACTION_VIEW)
                    .setComponent(new ComponentName(context, MyCarAppService.class))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)));
        }
    }
}

Son olarak, uygulamanızdaki Session.onNewIntent yöntemi, park yeri rezervasyonu ekranı henüz en üstte değilse yığına göndererek bu amaca yönelik işlemi gerçekleştirir:

Kotlin

override fun onNewIntent(intent: Intent) {
    val screenManager = carContext.getCarService(ScreenManager::class.java)
    val uri = intent.data
    if (uri != null
        && MY_URI_SCHEME == uri.scheme
        && MY_URI_HOST == uri.schemeSpecificPart
        && ACTION_VIEW_PARKING_RESERVATION == uri.fragment
    ) {
        val top = screenManager.top
        if (top !is ParkingReservationScreen) {
            screenManager.push(ParkingReservationScreen(carContext))
        }
    }
}

Java

@Override
public void onNewIntent(@NonNull Intent intent) {
    ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
    Uri uri = intent.getData();
    if (uri != null
        && MY_URI_SCHEME.equals(uri.getScheme())
        && MY_URI_HOST.equals(uri.getSchemeSpecificPart())
        && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment())
    ) {
        Screen top = screenManager.getTop();
        if (!(top instanceof ParkingReservationScreen)) {
            screenManager.push(new ParkingReservationScreen(getCarContext()));
        }
    }
}

Araba uygulaması bildirimlerini yönetme hakkında daha fazla bilgi için Bildirimleri görüntüleme bölümüne bakın.

Şablon kısıtlamaları

Düzenleyen, belirli bir görev için gösterilecek şablon sayısını en fazla beşle sınırlar. Bu şablonlardan sonuncusu aşağıdaki türlerden biri olmalıdır:

Bu sınırın, yığındaki Screen örneklerinin sayısına değil, şablon sayısına uygulandığını unutmayın. Örneğin, bir uygulama A ekranındayken iki şablon gönderip B ekranını gönderirse artık üç şablon daha gönderebilir. Alternatif olarak, her ekran tek bir şablon gönderecek şekilde yapılandırılmışsa uygulama, ScreenManager yığınına beş ekran örneği gönderebilir.

Bu kısıtlamalarla ilgili özel durumlar vardır: şablon yenileme, geri alma ve sıfırlama işlemleri.

Şablon yenilemeleri

Belirli içerik güncellemeleri, şablon sınırına dahil edilmez. Genel olarak, bir uygulama aynı türde olan ve önceki şablonla aynı ana içeriği içeren yeni bir şablon gönderirse yeni şablon, kotaya dahil edilmez. Örneğin, ListTemplate içindeki bir satırın açma/kapatma durumunu güncellemek kotaya dahil edilmez. Ne tür içerik güncellemelerinin yenileme olarak kabul edilebileceği hakkında daha fazla bilgi edinmek için tek tek şablonların dokümanlarına bakın.

Geri işlemleri

Bir görevde alt akışları etkinleştirmek için ana makine, bir uygulama ScreenManager yığınından Screen çıkardığında bunu algılar ve uygulamanın geri gittiği şablon sayısına göre kalan kotayı günceller.

Örneğin, uygulama A ekranındayken iki şablon gönderir, ardından B ekranını gönderir ve iki şablon daha gönderirse uygulamanın bir kotası kalır. Uygulama daha sonra A ekranına geri dönerse ana makine, uygulama iki şablon geriye gittiği için kotayı üçe sıfırlar.

Bir ekrana geri döndüğünde uygulamanın, bu ekran tarafından en son gönderilen şablonla aynı türde bir şablon göndermesi gerektiğini unutmayın. Diğer şablon türlerinin gönderilmesi hataya neden olur. Ancak, geri gitme işlemi sırasında tür aynı kaldığı sürece bir uygulama, kotayı etkilemeden şablonun içeriğini serbestçe değiştirebilir.

Sıfırlama işlemleri

Bazı şablonlar, bir görevin sonunu belirten özel semantiğe sahiptir. Örneğin, NavigationTemplate, ekranda kalması ve kullanıcının tüketimi için adım adım yeni talimatlarla yenilenmesi beklenen bir görünümdür. Bu şablonlardan birine ulaştığında, ana makine şablon kotasını sıfırlar ve bu şablonu yeni bir görevin ilk adımıymış gibi ele alır. Bu, uygulamanın yeni bir göreve başlamasına olanak tanır. Hangi şablonların ana makinede sıfırlamayı tetiklediğini görmek için tek tek şablonların dokümanlarına bakın.

Düzenleyen, uygulamayı başlatma isteğini bir bildirim işleminden veya başlatıcıdan alırsa kota da sıfırlanır. Bu mekanizma, bir uygulamanın bildirimlerden yeni bir görev akışı başlatmasına olanak tanır. Bu durum, uygulama zaten bağlı ve ön planda olsa bile geçerlidir.

Uygulamanızın bildirimlerini araç ekranında gösterme hakkında daha fazla bilgi için Bildirimleri görüntüleme bölümüne bakın. Uygulamanızı bir bildirim işleminden nasıl başlatacağınızla ilgili bilgi için Bir amaçla araba uygulaması başlatma bölümüne bakın.

Connection API

Uygulamanızın Android Auto'da mı yoksa Android Automotive OS'te mi çalıştığını belirlemek için çalışma zamanında bağlantı bilgilerini almak üzere CarConnection API'sini kullanabilirsiniz.

Örneğin, araba uygulamanızın Session bölümünde CarConnection başlatın ve LiveData güncellemelerine abone olun:

Kotlin

CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)

Java

new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);

Ardından, gözlemcide bağlantı durumundaki değişikliklere tepki verebilirsiniz:

Kotlin

fun onConnectionStateUpdated(connectionState: Int) {
  val message = when(connectionState) {
    CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit"
    CarConnection.CONNECTION_TYPE_NATIVE -> "Connected to Android Automotive OS"
    CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto"
    else -> "Unknown car connection type"
  }
  CarToast.makeText(carContext, message, CarToast.LENGTH_SHORT).show()
}

Java

private void onConnectionStateUpdated(int connectionState) {
  String message;
  switch(connectionState) {
    case CarConnection.CONNECTION_TYPE_NOT_CONNECTED:
      message = "Not connected to a head unit";
      break;
    case CarConnection.CONNECTION_TYPE_NATIVE:
      message = "Connected to Android Automotive OS";
      break;
    case CarConnection.CONNECTION_TYPE_PROJECTION:
      message = "Connected to Android Auto";
      break;
    default:
      message = "Unknown car connection type";
      break;
  }
  CarToast.makeText(getCarContext(), message, CarToast.LENGTH_SHORT).show();
}

Constraints API

Farklı arabalar, kullanıcılara aynı anda farklı sayıda Item örneğinin gösterilmesine izin verebilir. Çalışma zamanında içerik sınırını kontrol etmek ve şablonlarınızda uygun öğe sayısını ayarlamak için ConstraintManager kullanın.

CarContext'dan ConstraintManager alarak başlayın:

Kotlin

val manager = carContext.getCarService(ConstraintManager::class.java)

Java

ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);

Ardından, alınan ConstraintManager nesnesini sorgulayarak ilgili içerik sınırını öğrenebilirsiniz. Örneğin, bir ızgarada gösterilebilecek öğe sayısını almak için getContentLimit işlevini CONTENT_LIMIT_TYPE_GRID ile birlikte çağırın:

Kotlin

val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)

Java

int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);

Oturum açma akışı ekleme

Uygulamanız kullanıcılar için oturum açma deneyimi sunuyorsa arabanın baş ünitesinde uygulamanızda oturum açma işlemini gerçekleştirmek için Car App API düzeyi 2 ve üzeri sürümlerde SignInTemplate ve LongMessageTemplate gibi şablonları kullanabilirsiniz.

SignInTemplate oluşturmak için SignInMethod tanımlayın. Araba uygulaması kitaplığı şu anda aşağıdaki oturum açma yöntemlerini desteklemektedir:

  • Kullanıcı adı/şifre ile oturum açma için InputSignInMethod.
  • PinSignInMethod Kullanıcının, telefonundan hesaplarını bağladığı PIN ile oturum açma için baş ünitesinde gösterilen bir PIN kullanılır.
  • ProviderSignInMethod Google ile oturum açma ve One Tap gibi sağlayıcı oturum açma işlemleri için.
  • QRCodeSignInMethod Kullanıcının telefonunda oturum açma işlemini tamamlamak için QR kodu taradığı QR koduyla oturum açma işlemi. Bu özellik, Car API düzeyi 4 ve sonraki sürümlerde kullanılabilir.

Örneğin, kullanıcının şifresini toplayan bir şablon uygulamak için öncelikle kullanıcı girişini işleyip doğrulamak üzere bir InputCallback oluşturarak başlayın:

Kotlin

val callback = object : InputCallback {
    override fun onInputSubmitted(text: String) {
        // You will receive this callback when the user presses Enter on the keyboard.
    }

    override fun onInputTextChanged(text: String) {
        // You will receive this callback as the user is typing. The update
        // frequency is determined by the host.
    }
}

Java

InputCallback callback = new InputCallback() {
    @Override
    public void onInputSubmitted(@NonNull String text) {
        // You will receive this callback when the user presses Enter on the keyboard.
    }

    @Override
    public void onInputTextChanged(@NonNull String text) {
        // You will receive this callback as the user is typing. The update
        // frequency is determined by the host.
    }
};

InputSignInMethod Builder için InputCallback gereklidir.

Kotlin

val passwordInput = InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build()

Java

InputSignInMethod passwordInput = new InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build();

Son olarak, yeni InputSignInMethod ile SignInTemplate oluşturun.

Kotlin

SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build()

Java

new SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build();

AccountManager'ı kullanma

Kimlik doğrulama içeren Android Automotive OS uygulamaları, aşağıdaki nedenlerden dolayı AccountManager'ı kullanmalıdır:

  • Daha iyi kullanıcı deneyimi ve kolay hesap yönetimi: Kullanıcılar, oturum açma ve kapatma dahil olmak üzere tüm hesaplarını sistem ayarlarındaki hesaplar menüsünden kolayca yönetebilir.
  • "Misafir" deneyimleri: Arabalar paylaşılan cihazlar olduğundan OEM'ler, araçta hesap eklenemeyen misafir deneyimlerini etkinleştirebilir.

Metin dizesi varyantları ekleme

Farklı araç ekranı boyutlarında farklı miktarlarda metin gösterilebilir. Car App API'nin 2. ve sonraki sürümlerinde, metin dizisinin ekrana en iyi şekilde uyması için birden fazla varyant belirtebilirsiniz. Metin varyantlarının kabul edildiği yerleri görmek için CarText alan şablonları ve bileşenleri bulun.

CarText.Builder.addVariant() yöntemiyle CarText öğesine metin dizesi varyantları ekleyebilirsiniz:

Kotlin

val itemTitle = CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build()

Java

CarText itemTitle = new CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build();

Daha sonra bu CarText öğesini kullanabilirsiniz. Örneğin, GridItem öğesinin birincil metni olarak kullanabilirsiniz.

Kotlin

GridItem.Builder()
    .addTitle(itemTitle)
    ...
    .build()

Java

new GridItem.Builder()
    .addTitle(itemTitle)
    ...
    build();

Dizeleri en çok tercih edilenden en az tercih edilene doğru (ör. en uzundan en kısaya) ekleyin. Ana makine, araba ekranında bulunan alan miktarına bağlı olarak uygun uzunlukta bir dize seçer.

Satırlar için satır içi CarIcon'lar ekleme

CarIconSpan kullanarak uygulamanızın görsel çekiciliğini artırmak için metinle birlikte satır içi simgeler ekleyebilirsiniz. Bu aralıkları oluşturma hakkında daha fazla bilgi için CarIconSpan.create dokümanlarına bakın. Aralıklarla metin stilinin nasıl çalıştığına dair genel bir bakış için Aralıklarla metin stilini kullanma başlıklı makaleyi inceleyin.

Kotlin

  
val rating = SpannableString("Rating: 4.5 stars")
rating.setSpan(
    CarIconSpan.create(
        // Create a CarIcon with an image of four and a half stars
        CarIcon.Builder(...).build(),
        // Align the CarIcon to the baseline of the text
        CarIconSpan.ALIGN_BASELINE
    ),
    // The start index of the span (index of the character '4')
    8,
    // The end index of the span (index of the last 's' in "stars")
    16,
    Spanned.SPAN_INCLUSIVE_INCLUSIVE
)

val row = Row.Builder()
    ...
    .addText(rating)
    .build()
  
  

Java

  
SpannableString rating = new SpannableString("Rating: 4.5 stars");
rating.setSpan(
        CarIconSpan.create(
                // Create a CarIcon with an image of four and a half stars
                new CarIcon.Builder(...).build(),
                // Align the CarIcon to the baseline of the text
                CarIconSpan.ALIGN_BASELINE
        ),
        // The start index of the span (index of the character '4')
        8,
        // The end index of the span (index of the last 's' in "stars")
        16,
        Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
Row row = new Row.Builder()
        ...
        .addText(rating)
        .build();
  
  

Araba Donanımı API'leri

Car App API düzeyi 3'ten itibaren Car App Library'de araç özelliklerine ve sensörlerine erişmek için kullanabileceğiniz API'ler bulunur.

Şartlar

API'leri Android Auto ile kullanmak için öncelikle Android Auto modülünüzün build.gradle dosyasına androidx.car.app:app-projected bağımlılığı ekleyin. Android Automotive OS için Android Automotive OS modülünüzün build.gradle dosyasına androidx.car.app:app-automotive bağımlılığını ekleyin.

Ayrıca, AndroidManifest.xml dosyanızda, kullanmak istediğiniz araç verilerini istemek için gereken ilgili izinleri beyan etmeniz gerekir. Bu izinlerin kullanıcı tarafından size verilmesi gerektiğini unutmayın. Platforma bağlı akışlar oluşturmak yerine hem Android Auto hem de Android Automotive OS'de aynı kodu kullanabilirsiniz. Ancak, gereken izinler farklıdır.

CarInfo

Bu tabloda, CarInfo API'leri tarafından sunulan özellikler ve bunları kullanmak için istemeniz gereken izinler açıklanmaktadır:

Yöntemler Özellikler Android Auto İzinleri Android Automotive OS İzinleri Car App API düzeyinden itibaren desteklenir.
fetchModel Marka, model, yıl android.car.permission.CAR_INFO 3
fetchEnergyProfile EV konnektör türleri, yakıt türleri com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_INFO 3
fetchExteriorDimensions

Bu veriler yalnızca API 30 veya sonraki sürümleri çalıştıran bazı Android Automotive OS araçlarda kullanılabilir.

Dış boyutlar Yok android.car.permission.CAR_INFO 7
addTollListener
removeTollListener
Ücret kartı durumu, ücret kartı türü 3
addEnergyLevelListener
removeEnergyLevelListener
Pil seviyesi, yakıt seviyesi, düşük yakıt seviyesi, kalan mesafe com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_ENERGY,
android.car.permission.CAR_ENERGY_PORTS,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addSpeedListener
removeSpeedListener
Ham hız, gösterge hızı (aracın gösterge ekranında gösterilir) com.google.android.gms.permission.CAR_SPEED android.car.permission.CAR_SPEED,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addMileageListener
removeMileageListener

Uyarı: getOdometerMeters yöntemi, Mileage sınıfında yanlış adlandırılmış ve metre değil kilometre döndürüyor.

Kilometre sayacı mesafesi com.google.android.gms.permission.CAR_MILEAGE Bu veriler, Play Store'dan yüklenen uygulamalar için Android Automotive OS'te kullanılamaz. 3

Örneğin, kalan aralığı almak için bir CarInfo nesnesi oluşturun, ardından bir OnCarDataAvailableListener oluşturup kaydedin:

Kotlin

val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo

val listener = OnCarDataAvailableListener<EnergyLevel> { data ->
    if (data.rangeRemainingMeters.status == CarValue.STATUS_SUCCESS) {
      val rangeRemaining = data.rangeRemainingMeters.value
    } else {
      // Handle error
    }
  }

carInfo.addEnergyLevelListener(carContext.mainExecutor, listener)

// Unregister the listener when you no longer need updates
carInfo.removeEnergyLevelListener(listener)

Java

CarInfo carInfo = getCarContext().getCarService(CarHardwareManager.class).getCarInfo();

OnCarDataAvailableListener<EnergyLevel> listener = (data) -> {
  if(data.getRangeRemainingMeters().getStatus() == CarValue.STATUS_SUCCESS) {
    float rangeRemaining = data.getRangeRemainingMeters().getValue();
  } else {
    // Handle error
  }
};

carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(), listener);

// Unregister the listener when you no longer need updates
carInfo.removeEnergyLevelListener(listener);

Aracın verilerinin her zaman kullanılabileceğini varsaymayın. Hata alırsanız istenen verilerin neden alınamadığını daha iyi anlamak için istediğiniz değerin durumunu kontrol edin. Tam CarInfo sınıf tanımı için referans belgelerine bakın.

CarSensors

CarSensors sınıfı, aracın ivme ölçer, jiroskop, pusula ve konum verilerine erişmenizi sağlar. Bu değerlerin kullanılabilirliği OEM'ye bağlı olabilir. İvme ölçer, jiroskop ve pusuladan alınan verilerin biçimi, SensorManager API'den aldığınız biçimle aynıdır. Örneğin, aracın yönünü kontrol etmek için:

Kotlin

val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors

val listener = OnCarDataAvailableListener<Compass> { data ->
    if (data.orientations.status == CarValue.STATUS_SUCCESS) {
      val orientation = data.orientations.value
    } else {
      // Data not available, handle error
    }
  }

carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, carContext.mainExecutor, listener)

// Unregister the listener when you no longer need updates
carSensors.removeCompassListener(listener)

Java

CarSensors carSensors = getCarContext().getCarService(CarHardwareManager.class).getCarSensors();

OnCarDataAvailableListener<Compass> listener = (data) -> {
  if (data.getOrientations().getStatus() == CarValue.STATUS_SUCCESS) {
    List<Float> orientations = data.getOrientations().getValue();
  } else {
    // Data not available, handle error
  }
};

carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, getCarContext().getMainExecutor(),
    listener);

// Unregister the listener when you no longer need updates
carSensors.removeCompassListener(listener);

Aracın konum verilerine erişmek için android.permission.ACCESS_FINE_LOCATION iznini de bildirmeniz ve istemeniz gerekir.

Test

Android Auto'da test yaparken sensör verilerini simüle etmek için Masaüstü Ana Birim Kılavuzu'nun Sensörler ve Sensör yapılandırması bölümlerine bakın. Android Automotive OS'te test yaparken sensör verilerini simüle etmek için Android Automotive OS Emulator Guide'ın Emulate hardware state (Donanım durumunu taklit etme) bölümüne bakın.

CarAppService, Session ve Screen yaşam döngüleri

Session ve Screen sınıfları, LifecycleOwner arayüzünü uygular. Kullanıcı uygulamayla etkileşimde bulundukça Session ve Screen nesnelerinizin yaşam döngüsü geri çağırma işlevleri aşağıdaki diyagramlarda açıklandığı gibi çağrılır.

CarAppService ve oturumun yaşam döngüleri

1. Şekil. SessionYaşam döngüsü

Tüm ayrıntılar için Session.getLifecycle yönteminin belgelerine bakın.

Ekranın yaşam döngüsü

Şekil 2. ScreenYaşam döngüsü

Tüm ayrıntılar için Screen.getLifecycle yönteminin belgelerine bakın.

Aracın mikrofonundan kayıt yapma

Uygulamanızın CarAppService ve CarAudioRecord API'sini kullanarak uygulamanıza kullanıcının araba mikrofonuna erişim izni verebilirsiniz. Kullanıcıların, uygulamanızın araba mikrofonuna erişmesine izin vermesi gerekir. Uygulamanız, kullanıcının uygulamanızdaki girişini kaydedip işleyebilir.

Kaydetme izni

Herhangi bir ses kaydetmeden önce, AndroidManifest.xml uygulamanızda kayıt iznini beyan etmeniz ve kullanıcının bu izni vermesini istemeniz gerekir.

<manifest ...>
   ...
   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   ...
</manifest>

Çalışma zamanında kayıt izni istemeniz gerekir. Araba uygulamanızda izin isteme hakkında ayrıntılı bilgi için İzin iste bölümüne bakın.

Ses kaydet

Kullanıcı kaydetme izni verdikten sonra sesi kaydedebilir ve kaydı işleyebilirsiniz.

Kotlin

val carAudioRecord = CarAudioRecord.create(carContext)
        carAudioRecord.startRecording()

        val data = ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE)
        while(carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording()
 

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        carAudioRecord.startRecording();

        byte[] data = new byte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE];
        while (carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording();
 

Ses odağı

Aracın mikrofonundan kayıt yaparken devam eden tüm medyanın durdurulması için önce ses odaklaması elde edin. Ses odağını kaybederseniz kaydı durdurun.

Aşağıda, ses odağının nasıl elde edileceğine dair bir örnek verilmiştir:

Kotlin

 
val carAudioRecord = CarAudioRecord.create(carContext)
        
        // Take audio focus so that user's media is not recorded
        val audioAttributes = AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            // Use the most appropriate usage type for your use case
            .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
            .build()
        
        val audioFocusRequest =
            AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                .setAudioAttributes(audioAttributes)
                .setOnAudioFocusChangeListener { state: Int ->
                    if (state == AudioManager.AUDIOFOCUS_LOSS) {
                        // Stop recording if audio focus is lost
                        carAudioRecord.stopRecording()
                    }
                }
                .build()
        
        if (carContext.getSystemService(AudioManager::class.java)
                .requestAudioFocus(audioFocusRequest)
            != AudioManager.AUDIOFOCUS_REQUEST_GRANTED
        ) {
            // Don't record if the focus isn't granted
            return
        }
        
        carAudioRecord.startRecording()
        // Process the audio and abandon the AudioFocusRequest when done

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        // Take audio focus so that user's media is not recorded
        AudioAttributes audioAttributes =
                new AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                        // Use the most appropriate usage type for your use case
                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
                        .build();

        AudioFocusRequest audioFocusRequest =
                new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                        .setAudioAttributes(audioAttributes)
                        .setOnAudioFocusChangeListener(state -> {
                            if (state == AudioManager.AUDIOFOCUS_LOSS) {
                                // Stop recording if audio focus is lost
                                carAudioRecord.stopRecording();
                            }
                        })
                        .build();

        if (getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)
                != AUDIOFOCUS_REQUEST_GRANTED) {
            // Don't record if the focus isn't granted
            return;
        }

        carAudioRecord.startRecording();
        // Process the audio and abandon the AudioFocusRequest when done
 

Testing Library

Android for Cars Test Kitaplığı, uygulamanızın test ortamındaki davranışını doğrulamak için kullanabileceğiniz yardımcı sınıflar sağlar. Örneğin, SessionController, ana makineye bağlantıyı simüle etmenize ve doğru Screen ile Template değerlerinin oluşturulup döndürüldüğünü doğrulamanıza olanak tanır.

Kullanım örnekleri için Örnekler bölümüne bakın.

Arabalar için Android uygulama kitaplığı ile ilgili sorun bildirme

Kitaplıkla ilgili bir sorun bulursanız Google Sorun İzleyici'yi kullanarak sorunu bildirin. Sorun şablonunda istenen tüm bilgileri doldurduğunuzdan emin olun.

Yeni sorun oluşturma

Yeni bir sorun kaydetmeden önce lütfen kitaplığın sürüm notlarında listelenip listelenmediğini veya sorun listesinde bildirilip bildirilmediğini kontrol edin. Takipçideki bir sorunun yıldızını tıklayarak sorunlara abone olabilir ve oy verebilirsiniz. Daha fazla bilgi için Bir soruna abone olma başlıklı makaleyi inceleyin.