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

Arabalar için Android Uygulama Kitaplığı, navigasyon, önemli yer (ÖY) ve nesnelerin interneti (IoT) uygulamalarınızı araca getirmenize olanak tanır. Bunu, sürücünün dikkatini dağıtan unsurlar konusundaki standartları karşılamak için tasarlanmış bir dizi şablon sağlayarak ve çeşitli araç ekranı faktörleri ve giriş modları gibi ayrıntıları dikkate alarak yapar.

Bu kılavuzda, kitaplığın temel özelliklerine ve kavramlarına genel bir bakış sunulmakta ve temel bir uygulama oluşturma sürecinde size yol gösterilmektedir.

Başlamadan önce

  1. Araba Uygulaması Kitaplığı'nı kapsayan Sürüş İçin Tasarım sayfalarını inceleyin.
  2. Aşağıdaki bölümde yer alan önemli terimler 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 birlikte düzenlenebilen model nesnelerinin grafiğiyle temsil edilir. Şablonlar, bu grafiklerde kök görevi görebilecek modellerin alt kümesidir. Modeller, kullanıcıya metin ve resim biçiminde gösterilecek bilgilerin yanı sıra bu bilgilerin görsel görünümünün özelliklerini (ör. metin renkleri veya resim boyutları) yapılandırmaya yönelik özellikleri içerir. Barındıran, modelleri sürücü dikkat dağıtma standartlarını karşılayacak şekilde tasarlanmış görünümlere dönüştürür ve araç ekranı faktörlerinin çeşitliliği ve giriş modları gibi ayrıntılarla ilgilenir.
Düzenleyen
Barındırıcı, uygulamanızın araçta çalışabilmesi için kitaplığın API'leri tarafından sunulan işlevleri uygulayan arka uç bileşenidir. Barındırıcının sorumlulukları, uygulamanızı keşfetme ve yaşam döngüsünü yönetmenin yanı sıra modellerinizi görünümlere dönüştürme ve uygulamanızı kullanıcı etkileşimlerinden haberdar etme gibi çeşitli işlemleri kapsar. 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 gösterilebilecek öğe sayısıyla ilgili sınırlamalar vardı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, kitaplık tarafından sağlanan ve uygulamalar tarafından kullanıcıya sunulan kullanıcı arayüzünü yönetmek için uygulanan bir sınıftır. Screen, yaşam döngüsü olan ve uygulamanın ekran görünür olduğunda şablonu göndermesi için mekanizma sağlayan bir öğedir. Screen örnekleri, şablon akışı kısıtlamalarına uymalarını sağlamak için bir Screen yığınına itilebilir ve yığından çıkarılabilir.
CarAppService
CarAppService, barındırıcı tarafından keşfedilip yönetilebilmesi için uygulamanızın uygulamasını ve dışa aktarmasını gerektiren soyut bir Service sınıfıdır. Uygulamanızın CarAppService görevi, bir ana makine bağlantısının createHostValidator kullanılarak güvenilir olduğunu doğrulamaktan ve ardından her bağlantı için onCreateSession kullanarak Session örnekleri sağlamaktan sorumludur.
Session

Session, uygulamanızın CarAppService.onCreateSession kullanarak uygulaması ve döndürmesi gereken soyut bir sınıftır. Araba ekranında bilgi görüntülemek için giriş noktası görevi görür. Uygulamanızın araba ekranındaki mevcut durumunu (ör. uygulamanızın görünür veya gizli olduğu durumlar) bildiren bir yaşam döngüsü vardır.

Session başlatıldığında (ör. uygulamanın ilk kullanıma sunulduğunda), ana makine, onCreateScreen yöntemini kullanarak ilk Screen için görüntülenme isteğinde bulunur.

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

Kitaplığı uygulamanıza eklemeyle ilgili talimatlar için Jetpack kitaplığı sürüm sayfasına bakın.

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 aracılığıyla uygulamanıza bağlanır. Ana makinenin uygulamanızı keşfedip bağlanmasına izin vermek için bu hizmeti manifest dosyanızda beyan edersiniz.

Ayrıca, uygulamanızın intent filtresinin <category> öğesinde uygulamanızın kategorisini de belirtmeniz gerekir. Bu öğe için izin verilen değerlere ilişkin desteklenen uygulama kategorilerinin listesine bakın.

Aşağıdaki kod snippet'inde, manifest dosyanızda bir ilgi çekici yer uygulaması için araba uygulaması hizmetinin nasıl tanımlanacağı 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

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

  • androidx.car.app.category.NAVIGATION: Adım adım yol tarifleri sunan bir uygulama. Bu kategoriyle ilgili ek dokümanlar için Arabalar için navigasyon uygulamaları oluşturma başlıklı makaleyi inceleyin.
  • androidx.car.app.category.POI: Park yerleri, şarj istasyonları ve benzin istasyonları gibi önemli noktaları bulmayla ilgili işlevler sunan bir uygulama. Bu kategoriyle ilgili daha fazla doküman için Arabalar için önemli yer uygulamaları oluşturma başlıklı makaleyi inceleyin.
  • androidx.car.app.category.IOT: Kullanıcıların arabadan bağlı cihazlarda alakalı işlemleri yapmasını sağlayan bir uygulama. Bu kategoriyle ilgili ek belgeler için Arabalar için nesne uygulamaları oluşturma sayfasına göz atın.

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, sistem kullanıcı arayüzünde uygulamanızı temsil etmek için kullanabileceği bir uygulama adı ve simgesi belirtmeniz gerekir.

CarAppService öğenizin label ve icon özelliklerini kullanarak uygulamanızı temsil etmek için kullanılan uygulama adını ve simgesini 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 tanımlanmazsa 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 uygulamanızın teması için aşağıdaki özellikleri ayarlamak üzere stil kaynağınızı tanımlayın:

<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 Uygulama Kitaplığı, bir araçtaki şablon ana makinesinin hangi kitaplık özelliklerini desteklediğ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 beyan edin:

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

Geriye dönük uyumluluğu nasıl koruyacağınız ve bir özelliği kullanmak için gereken minimum API düzeyini nasıl beyan edeceğinizle ilgili ayrıntılar için RequiresCarApi ek açıklamalarının dokümanlarına bakın. Araba Uygulama Kitaplığı'nın belirli bir özelliğini kullanmak için hangi API seviyesinin gerekli olduğuna dair bir tanım için CarAppApiLevels referans dokümanlarını inceleyin.

CarAppService ve oturumunuzu oluşturma

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

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 kullanmak üzere 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());
    }
    ...
}

Araba uygulamanızı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) yönetmek için onCreateScreen'ten dönmeden önce ScreenManager.push kullanarak bir arka ekran yığınını önceden ekleyebiliriz. Önceden eklenen veriler, kullanıcıların uygulamanızın gösterdiği ilk ekrandan önceki ekranlara geri dönmelerine olanak tanır.

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

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

Aşağıdaki snippet'te, basit bir "Hello world!" dizesi görüntülemek için PaneTemplate şablonu kullanan bir Screen 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ı, Session ve Screen örneklerinizin erişebildiği bir ContextWrapper alt sınıfıdır. Ekran yığınını yönetmek için ScreenManager, harita çizmek için Surface nesnesine erişme gibi genel uygulama işlevleri için AppManager ve navigasyon meta verilerini ve navigasyonla ilgili diğer etkinlikleri ana makineyle paylaşmak için adım adım navigasyon uygulamaları tarafından kullanılan 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şim bölümüne bakın.

CarContext, araba ekranındaki yapılandırmayı kullanarak çizilebilir kaynakları yüklemenize, intent'leri kullanarak arabanızda bir uygulamayı başlatmanıza ve uygulamanızın haritasını koyu temada göstermesi gerekip gerekmediğini belirtmenize olanak tanır.

Ekran gezinme özelliğini uygulama

Uygulamalar genellikle çeşitli ekranlar sunar. Bu ekranların her biri, kullanıcının ekranda gösterilen arayüzle etkileşime geçerken gezinebileceği farklı şablonlar kullanabilir.

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

Aşağıdaki snippet'te, bir mesaj şablonuna geri düğmesi ve kullanıcı tarafından seçildiğinde yeni bir ekran gösteren bir işlem ekleme 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'ı otomatik olarak çağıran standart bir Action'tir. Bu davranış, CarContext'da bulunan OnBackPressedDispatcher örneği kullanılarak geçersiz kılınabilir.

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

Şablon içeriğini yenileme

Uygulamanız, Screen.invalidate yöntemini çağırarak bir Screen içeriğinin geçersiz kılınmasını isteyebilir. Ardından barındırıcı, yeni içeriklerin bulunduğu şablonu almak için uygulamanızın Screen.onGetTemplate yöntemini tekrar çağırır.

Bir Screen öğesini yenilerken ana makinenin yeni şablonu şablon kotasına dahil etmemesi için şablonda güncellenebilecek belirli içeriği anlamak önemlidir. Daha fazla ayrıntı 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 navigasyon ve önemli yer (ÖY) uygulamaları, Surface'a erişerek harita çizebilir:

Ş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, ÖY
MapTemplate (desteklenmiyor) androidx.car.app.NAVIGATION_TEMPLATES Gezinme
PlaceListNavigationTemplate (desteklenmiyor) androidx.car.app.NAVIGATION_TEMPLATES Gezinme
RoutePreviewNavigationTemplate (desteklenmiyor) androidx.car.app.NAVIGATION_TEMPLATES Gezinme

Yüzey izni beyanı

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

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

Yüzeylere erişme

Ana makinenin sağladığı Surface öğesine erişmek için bir SurfaceCallback uygulamanız ve bu uygulamayı AppManager araba hizmetine sağlamanız gerekir. Mevcut Surface, onSurfaceAvailable() ve onSurfaceDestroyed() geri çağırmalarının SurfaceContainer parametresinde SurfaceCallback'inize 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

Ana makine, haritanın üst kısmındaki şablonlara ilişkin kullanıcı arayüzü öğelerini çizebilir. Barındırıcı, SurfaceCallback.onVisibleAreaChanged yöntemini çağırarak yüzeyin engelsiz ve kullanıcı tarafından tamamen görülebileceğini garanti eden alanı iletir. Ayrıca ana makine, değişiklik sayısını en aza indirmek için SurfaceCallback.onStableAreaChanged yöntemini en küçük dikdörtgenle çağırır. Bu dikdörtgen, geçerli şablona göre her zaman görünür olur.

Örneğin, bir navigasyon uygulamasında üstte işlem çubuğu bulunan NavigationTemplate kullanılıyorsa kullanıcı ekranla bir süre etkileşimde bulunmadığında haritaya daha fazla yer açmak için işlem çubuğu gizlenebilir. Bu durumda, aynı dikdörtgenle onStableAreaChanged ve onVisibleAreaChanged için geri çağırma işlevi vardır. İşlem çubuğu gizliyken yalnızca onVisibleAreaChanged çağrılır ve daha büyük alan gösterilir. Kullanıcı ekranla etkileşimde bulunursa tekrar ilk dikdörtgenle yalnızca onVisibleAreaChanged çağrılır.

Koyu temayı destekleyin

Ana makine, koşulların gerektirdiğini belirlediğinde uygulamalar, arabalar için Android uygulama kalitesi bölümünde açıklandığı üzere haritalarını uygun koyu renklerle Surface örneğine yeniden çizmelidir.

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

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 geçmesi için destek ekleyebilirsiniz. Örneğin, yakınlaştırıp uzaklaştırarak haritanın farklı bölümlerini görmelerine olanak tanıyabilirsiniz.

Şablon Araba Uygulaması API düzeyi 21'den beri desteklenen etkileşim
NavigationTemplate 2
PlaceListNavigationTemplate (desteklenmiyor) 4
RoutePreviewNavigationTemplate (kullanımdan kaldırıldı) 4
MapTemplate (desteklenmiyor) 5 (introduction of template)
MapWithContentTemplate 7 (şablonun tanıtımı)

Etkileşimli geri çağırma işlevlerini uygulama

SurfaceCallback arayüzünde, önceki bölümdeki şablonlarla oluşturulan haritalara etkileşim eklemek için uygulayabileceğiniz birkaç geri çağırma yöntemi vardır:

Etkileşim SurfaceCallback yöntem 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 fırlatma onFling 2
İki kez dokunun onScale (şablon ana makinesine göre belirlenen ölçeklendirme faktörü ile) 2
Kaydırma modunda dönen kaydırma onScroll (mesafe faktörü şablon ana makinesi tarafından belirlenir) 2

Haritaya ilişkin işlem şeridi ekle

Bu şablonlarda, yakınlaştırma ve uzaklaştırma, yeniden merkezleme, pusula gösterme gibi haritalarla ilgili işlemler ve göstermeyi seçtiğiniz diğer işlemler için bir harita işlem şeridinin bulunabileceği Haritada işlem şeridinde, görev derinliğini etkilemeden yenilenebilen en fazla dört yalnızca simge düğmesi bulunabilir. Boştayken gizlenir ve etkin durumda yeniden görünür.

Harita etkileşim geri çağırmaları 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 ev sahibi kaydırma moduna girer.

Uygulamanız, harita işlem şeridindeki Action.PAN düğmesini atlarsa SurfaceCallback yöntemlerinden kullanıcı girişi almaz ve ev sahibi daha önce etkinleştirilmiş tüm kaydırma modlarından çıkar.

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

Kaydırma modunu anlama

Kaydırma modunda şablon ana makinesi, dokunmatik olmayan giriş cihazlarından (ör. döner kontrolörler ve dokunmatik yüzeyler) gelen kullanıcı girişlerini uygun SurfaceCallback yöntemlerine dönüştürür. Kaydırma moduna girmek veya moddan çıkmak için NavigationTemplate.Builder'teki setPanModeListener yöntemini kullanarak kullanıcı işlemine yanıt verin. Kullanıcı kaydırma modundayken ev sahibi, şablondaki diğer kullanıcı arayüzü bileşenlerini gizleyebilir.

Kullanıcıyla etkileşim kurma

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

Kullanıcı girişini işleme

Uygulamanız, uygun dinleyicileri 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 niyetinin biçimi de dahil olmak üzere uygulamaları nasıl başlatacağınızla ilgili daha fazla bilgi için Amaç ile araba uygulaması başlatma bölümüne bakın.

Kullanıcıyı mobil cihazlarında etkileşimi devam ettirmeye yönlendirmeyi gerektiren işlemler gibi bazı işlemlere yalnızca araç park edildiğinde izin verilir. Bu işlemleri uygulamak için ParkedOnlyOnClickListener simgesini kullanabilirsiniz. Araba park edilmemişse ana makine, kullanıcıya bu durumda işleme izin verilmediğine dair bir uyarı görüntüler. Araba park halindeyse kod normal şekilde yürütülür. Aşağıdaki snippet'te, mobil cihazda bir ayarlar ekranı 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üle

Mobil cihaza gönderilen bildirimler yalnızca CarAppExtender ile genişletildiklerinde araç ekranında gösterilir. İçerik başlığı, metin, simge ve işlemler gibi bazı bildirim özellikleri CarAppExtender'te ayarlanabilir. Bu sayede, araba ekranında görünen bildirimin özellikleri geçersiz kılınabilir.

Aşağıdaki snippet'te, araba ekranına mobil cihazda gösterilenden farklı bir başlığın 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 bir uyarı bildirimi (HUN) gösterilebilir.
  • Bildirim merkezine bir giriş eklenebilir. İsteğe bağlı olarak çubuğunda bir rozet gösterilebilir.
  • Navigasyon uygulamaları için bildirim, Adım adım yol tarifi bildirimleri bölümünde açıklandığı gibi çubuklu widget'ta gösterilebilir.

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

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'ın Sürüş İçin Tasarım kılavuzuna bakın.

Kısa iletileri gösterme

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 isteme

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

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

Android Auto'daki izin iletişim kutusunu biçimlendirme

Android Auto'da, kullanıcıya ait izinler iletişim kutusu telefonda görünür. Varsayılan olarak iletişim kutusunun arkasında arka plan yoktur. Özel bir arka plan ayarlamak için AndroidManifest.xml dosyanızda bir araç uygulaması teması tanımlayın ve araç 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>

Araç uygulamasını intent ile başlatma

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

  • Telefon araması yapmak için numara çeviriciyi açın.
  • Varsayılan navigasyon aracı uygulaması ile bir konuma adım adım yol tarifi almaya başlayın.
  • Kendi uygulamanızı bir amaç doğrultusunda başlatın.

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

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, kullanıcı bildirim arayüzünde işlemi seçtiğinde ve CarContext.startCarApp'i veri URI'sini içeren bir intent ile çağırdığında intent'i işlemek için çağrılan bir BroadcastReceiver de bildirmelidir:

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 rezervasyonu ekranını en üstte değilse park rezervasyonu ekranını yığına iterek bu amacı yerine getirir.

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

Araç uygulamasının 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ı

Ana makine, belirli bir görev için görüntülenecek şablon sayısını en fazla beşle sınırlandırır. Bu sayılardan sonuncu şablon aşağıdaki türlerden biri olmalıdır:

Bu sınırın, yığıntaki Screen örneğinin sayısı için değil, şablon sayısı için geçerli olduğunu unutmayın. Örneğin, bir uygulama A ekranındayken iki şablon gönderir ve ardından B ekranına geçerse 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ıtlamalar için özel durumlar vardır: şablon yenileme ve 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 önceki şablonla aynı türde yeni bir şablon aktarırsa yeni şablon kotaya dahil edilmez. Örneğin, ListTemplate içindeki bir satırın açma/kapatma durumunun güncellenmesi kotaya dahil edilmez. Ne tür içerik güncellemelerinin yenileme olarak değerlendirilebileceği hakkında daha fazla bilgi edinmek için şablonların dokümanlarına bakın.

Geri işlemleri

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

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

Bir uygulamanın, bir ekrana geri dönerken o ekran tarafından en son gönderilenle aynı türde bir şablon göndermesi gerektiğini unutmayın. Diğer şablon türleri gönderildiğinde hata meydana gelir. Ancak, geri alma işlemi sırasında tür aynı kaldığı sürece uygulama, kotayı etkilemeden şablonun içeriğini özgürce değiştirebilir.

Sıfırlama işlemleri

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

Düzenleyen, bildirim işleminden veya başlatıcıdan uygulamayı başlatma amacı 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 nasıl görüntüleyeceğiniz hakkında daha fazla bilgi için Bildirimleri görüntüleme bölümüne bakın. Uygulamanızı bildirim işleminden nasıl başlatacağınız hakkında bilgi edinmek için Bir araba uygulamasını intent ile 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 CarConnection API'yi kullanarak çalışma zamanında bağlantı bilgilerini alabilirsiniz.

Örneğin, araba uygulamanızın Session bölümünde bir 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);

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ıya tek seferde farklı sayıda Item örneği gösterilmesine izin verebilir. Çalışma zamanında içerik sınırını kontrol etmek ve şablonlarınızda uygun sayıda öğe ayarlamak için ConstraintManager kodunu 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 ilgili içerik sınırı için sorgulayabilirsiniz. Örneğin, bir ızgarada gösterilebilecek öğelerin sayısını almak için CONTENT_LIMIT_TYPE_GRID ile getContentLimit çağrısı yapı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ılara oturum açmış bir deneyim sunuyorsa arabanın ana ünitesinde uygulamanızda oturum açmayı yönetmek için Car App API 2 ve sonraki sürümlerde SignInTemplate ve LongMessageTemplate gibi şablonları kullanabilirsiniz.

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

Örneğin, kullanıcının şifresini toplayan bir şablon uygulamak için kullanıcı girişini işlemek ve 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'inizi kullanarak bir 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();

Hesap Yöneticisi'ni kullanma

Kimlik doğrulaması olan Android Automotive OS uygulamaları aşağıdaki nedenlerle AccountManager'ı kullanmalıdır:

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

Metin dizesi varyantları ekleme

Farklı araba ekran boyutları farklı miktarlarda metin gösterebilir. Car App API 2. düzey ve üzeri sürümlerde, ekrana en uygun metin dizesinin birden fazla varyantını belirtebilirsiniz. Metin varyantlarının nerede kabul edildiğini görmek için CarText alan şablonları ve bileşenleri arayın.

CarText.Builder.addVariant() yöntemini kullanarak bir 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();

Ardından bu CarText öğesini, örneğin bir GridItem öğesinin birincil metni olarak kullanabilirsiniz.

Kotlin

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

Java

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

Dilerseniz dizelerinizi en çok tercih edilenden en az tercih edilene göre (ör. en uzundan en kısaya) sıralayın. Barındıran, araç ekranındaki boşluğa göre uygun uzunluktaki dizeyi 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 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 Spantastik metin stilleri ve Spans'lar bölümünü 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

Araç Uygulaması API'si 3. düzeyden itibaren Araç Uygulaması Kitaplığı'nda, araç özelliklerine ve sensörlere erişmek için kullanabileceğiniz API'ler bulunur.

Şartlar

API'leri Android Auto ile kullanmak için Android Auto modülünüzün build.gradle dosyasına androidx.car.app:app-projected bağımlılık 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ığı ekleyin.

Ayrıca, AndroidManifest.xml dosyanızda, kullanmak istediğiniz araç verilerini istemek için gereken ilgili izinleri belirtmeniz gerekir. Bu izinlerin kullanıcı tarafından size verilmesi gerektiğini unutmayın. Platforma bağımlı akışlar oluşturmak yerine, hem Android Auto hem de Android Automotive OS'te 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 beri desteklenir
fetchModel Marka, model, yıl android.car.permission.CAR_INFO 3
fetchEnergyProfile Elektrikli araç 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çlarında 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, yakıt seviyesi düşük, 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örüntüleme hızı (arabadaki 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
Kilometre sayacı mesafesi com.google.android.gms.permission.CAR_MILEAGE Bu veriler, Android Automotive OS'te Play Store'dan yüklenen uygulamalar tarafından 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);

Arabadan gelen verilerin her zaman kullanılabileceğini varsaymayın. Hata alırsanız istediğiniz verilerin neden alınamadığını daha iyi anlamak için istediğiniz değerin durumunu kontrol edin. CarInfo sınıfı tanımının tamamı 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 gelen verilerin biçimi, SensorManager API'den alacağınız verilerle 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);

Araçtaki konum verilerine erişmek için android.permission.ACCESS_FINE_LOCATION iznini de belirtmeniz ve istemeniz gerekir.

Test

Android Auto'da test yaparken sensör verilerini simüle etmek için masaüstü ana birim kılavuzunun 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 emülatör kılavuzunun Donanım durumu emülasyonu bölümüne bakın.

CarAppService, Oturum ve Ekran yaşam döngüleri

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

CarAppService ve oturumların yaşam döngüleri

Şekil 1. Session yaşam döngüsü.

Tüm ayrıntılar için Session.getLifecycle yöntemiyle ilgili belgelere göz atın.

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

Şekil 2. Screen yaşam döngüsü.

Tüm ayrıntılar için Screen.getLifecycle yöntemiyle ilgili belgelere bakın.

Araç mikrofonundan kayıt yapma

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

Kayıt izni

Herhangi bir sesi kaydetmeden önce, AndroidManifest.xml içinde kayıt yapma iznini beyan etmeniz ve kullanıcıdan bu izni vermesini istemeniz gerekir.

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

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

Ses kaydet

Kullanıcı kayıt izni verdikten sonra sesi kaydedebilir ve 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ğı

Araç mikrofonundan kayıt yaparken, devam eden medya içeriğinin durdurulduğundan emin olmak için önce ses odağı özelliğini kullanın. Ses odağını kaybederseniz kaydı durdurun.

Burada, ses odağının nasıl elde edileceğine ilişkin 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
 

Test Kitaplığı

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 makineyle bağlantıyı simüle etmenize ve doğru Screen ile Template öğelerinin 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ığıyla ilgili sorunları bildirme

Kitaplıkla ilgili bir sorunla karşılaşırsanız Google Sorun Takip Aracı'nı kullanarak sorunu bildirin. Sorun şablonunda istenen tüm bilgileri doldurduğunuzdan emin olun.

Yeni sorun oluşturma

Yeni bir sorun göndermeden önce lütfen sorunun 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 bölümüne bakın.