Davranış değişiklikleri: Android 14 veya sonraki sürümleri hedefleyen uygulamalar

Android 14, önceki sürümlerde olduğu gibi uygulamanızı etkileyebilecek davranış değişiklikleri içerir. Aşağıdaki davranış değişiklikleri yalnızca Android 14'ü (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalar için geçerlidir. Uygulamanız Android 14 veya sonraki sürümleri hedefliyorsa geçerli durumlarda bu davranışları düzgün şekilde destekleyecek şekilde değiştirmeniz gerekir.

Uygulamanın targetSdkVersion'sinden bağımsız olarak Android 14'te çalışan tüm uygulamaları etkileyen davranış değişiklikleri listesini de incelemeyi unutmayın.

Temel işlevler

Ön plan hizmeti türleri zorunludur

If your app targets Android 14 (API level 34) or higher, it must specify at least one foreground service type for each foreground service within your app. You should choose a foreground service type that represents your app's use case. The system expects foreground services that have a particular type to satisfy a particular use case.

If a use case in your app isn't associated with any of these types, it's strongly recommended that you migrate your logic to use WorkManager or user-initiated data transfer jobs.

BluetoothAdapter'da BLUETOOTH_CONNECT izninin zorunlu kılınması

Android 14, Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalar için BluetoothAdapter getProfileConnectionState() yöntemi çağrılırken BLUETOOTH_CONNECT iznini zorunlu kılar.

Bu yöntem için BLUETOOTH_CONNECT izni zaten gerekliydi ancak bu şart uygulanmadı. Uygulamanızın, aşağıdaki snippet'te gösterildiği gibi BLUETOOTH_CONNECT öğesini uygulamanızın AndroidManifest.xml dosyasında beyan ettiğinden emin olun ve getProfileConnectionState öğesini çağırmadan önce kullanıcının izin verip vermediğini kontrol edin.

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

OpenJDK 17 güncellemeleri

Android 14, Android'in temel kitaplıklarını en son OpenJDK LTS sürümlerindeki özelliklerle uyumlu hale getirmek için yenileme çalışmalarına devam ediyor. Bu çalışmalara hem kitaplık güncellemeleri hem de uygulama ve platform geliştiricileri için Java 17 dil desteği dahildir.

Bu değişikliklerden bazıları uygulama uyumluluğunu etkileyebilir:

  • Normal ifadelerdeki değişiklikler: OpenJDK'nın anlamını daha yakından takip etmek için geçersiz grup referanslarına artık izin verilmiyor. java.util.regex.Matcher sınıfı tarafından IllegalArgumentException atanmasının olduğu yeni durumlar görebilirsiniz. Bu nedenle, uygulamanızı normal ifadelerin kullanıldığı alanlar açısından test ettiğinizden emin olun. Test sırasında bu değişikliği etkinleştirmek veya devre dışı bırakmak için uyumluluk çerçevesi araçlarını kullanarak DISALLOW_INVALID_GROUP_REFERENCE işaretini açın veya kapatın.
  • UUID işleme: java.util.UUID.fromString() yöntemi artık giriş bağımsız değişkenini doğrularken daha katı kontroller yapıyor. Bu nedenle, seri dışılaştırma sırasında bir IllegalArgumentException görebilirsiniz. Test sırasında bu değişikliği etkinleştirmek veya devre dışı bırakmak için uyumluluk çerçevesi araçlarını kullanarak ENABLE_STRICT_VALIDATION işaretini açın veya kapatın.
  • ProGuard sorunları: Bazı durumlarda, ProGuard'ı kullanarak uygulamanızı küçültmeye, kod karartmaya ve optimize etmeye çalıştığınızda java.lang.ClassValue sınıfının eklenmesi soruna neden olur. Sorun, Class.forName("java.lang.ClassValue")'ün sınıf döndürüp döndürmediğine bağlı olarak çalışma zamanı davranışını değiştiren bir Kotlin kitaplığından kaynaklanıyor. Uygulamanız, java.lang.ClassValue sınıfının bulunmadığı çalışma ortamının eski bir sürümüne göre geliştirildiyse bu optimizasyonlar, java.lang.ClassValue sınıfından türetilen sınıflardan computeValue yöntemini kaldırabilir.

JobScheduler, geri çağırma ve ağ davranışını güçlendirir

Since its introduction, JobScheduler expects your app to return from onStartJob or onStopJob within a few seconds. Prior to Android 14, if a job runs too long, the job is stopped and fails silently. If your app targets Android 14 (API level 34) or higher and exceeds the granted time on the main thread, the app triggers an ANR with the error message "No response to onStartJob" or "No response to onStopJob".

This ANR may be a result of 2 scenarios: 1. There is work blocking the main thread, preventing the callbacks onStartJob or onStopJob from executing and completing within the expected time limit. 2. The developer is running blocking work within the JobScheduler callback onStartJob or onStopJob, preventing the callback from completing within the expected time limit.

To address #1, you will need to further debug what is blocking the main thread when the ANR occurs, you can do this using ApplicationExitInfo#getTraceInputStream() to get the tombstone trace when the ANR occurs. If you're able to manually reproduce the ANR, you can record a system trace and inspect the trace using either Android Studio or Perfetto to better understand what is running on the main thread when the ANR occurs. Note that this can happen when using JobScheduler API directly or using the androidx library WorkManager.

To address #2, consider migrating to WorkManager, which provides support for wrapping any processing in onStartJob or onStopJob in an asynchronous thread.

JobScheduler also introduces a requirement to declare the ACCESS_NETWORK_STATE permission if using setRequiredNetworkType or setRequiredNetwork constraint. If your app does not declare the ACCESS_NETWORK_STATE permission when scheduling the job and is targeting Android 14 or higher, it will result in a SecurityException.

Tiles launch API

For apps targeting 14 and higher, TileService#startActivityAndCollapse(Intent) is deprecated and now throws an exception when called. If your app launches activities from tiles, use TileService#startActivityAndCollapse(PendingIntent) instead.

Gizlilik

Fotoğraflara ve videolara kısmi erişim

Android 14 introduces Selected Photos Access, which allows users to grant apps access to specific images and videos in their library, rather than granting access to all media of a given type.

This change is only enabled if your app targets Android 14 (API level 34) or higher. If you don't use the photo picker yet, we recommend implementing it in your app to provide a consistent experience for selecting images and videos that also enhances user privacy without having to request any storage permissions.

If you maintain your own gallery picker using storage permissions and need to maintain full control over your implementation, adapt your implementation to use the new READ_MEDIA_VISUAL_USER_SELECTED permission. If your app doesn't use the new permission, the system runs your app in a compatibility mode.

Kullanıcı deneyimi

Güvenli tam ekran intent bildirimleri

Android 11 (API düzeyi 30) ile birlikte, telefon kilitliyken tam ekran intent'ler göndermek için tüm uygulamaların Notification.Builder.setFullScreenIntent kullanması mümkündü. AndroidManifest dosyasında USE_FULL_SCREEN_INTENT iznini belirterek bu izni uygulama yüklenirken otomatik olarak verebilirsiniz.

Tam ekran intent bildirimleri, kullanıcının hemen ilgilenmesini gerektiren son derece yüksek öncelikli bildirimler (ör. gelen telefon araması veya kullanıcı tarafından yapılandırılmış alarm saati ayarları) için tasarlanmıştır. Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalarda bu iznin kullanılmasına izin verilen uygulamalar yalnızca arama ve alarm sağlayan uygulamalarla sınırlıdır. Google Play Store, bu profile uymayan uygulamaların varsayılan USE_FULL_SCREEN_INTENT izinlerini iptal eder. Bu politika değişikliklerinin son tarihi 31 Mayıs 2024'tür.

Bu izin, kullanıcı Android 14'e güncellemeden önce telefona yüklenen uygulamalarda etkin kalır. Kullanıcılar bu izni etkinleştirip devre dışı bırakabilir.

Uygulamanızın izin alıp almadığını kontrol etmek için yeni API'yi NotificationManager.canUseFullScreenIntent kullanabilirsiniz. İzin yoksa uygulamanız, kullanıcıların izni verebileceği ayarlar sayfasını başlatmak için yeni intent'i ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT kullanabilir.

Güvenlik

Örtülü ve bekleyen amaçlarla ilgili kısıtlamalar

Android, Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalar için uygulamaların dahili uygulama bileşenlerine örtülü niyet göndermesini aşağıdaki şekillerde kısıtlar:

  • Örtük intent'ler yalnızca dışa aktarılan bileşenlere gönderilir. Uygulamalar, dışa aktarılmayan bileşenlere yayın yapmak için açık bir intent kullanmalı veya bileşeni dışa aktarıldı olarak işaretlemelidir.
  • Bir uygulama, bileşen veya paket belirtmeyen bir intent ile değişken bekleyen intent oluşturursa sistem bir istisna oluşturur.

Bu değişiklikler, kötü amaçlı uygulamaların, uygulamanın dahili bileşenleri tarafından kullanılması amaçlanan örtülü niyetlere müdahale etmesini önler.

Örneğin burada, uygulamanızın manifest dosyasında bildirilebilecek bir amaç filtresi verilmiştir:

<activity
    android:name=".AppActivity"
    android:exported="false">
    <intent-filter>
        <action android:name="com.example.action.APP_ACTION" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Uygulamanız bu etkinliği dolaylı intent kullanarak başlatmaya çalıştıysa ActivityNotFoundException istisnası atılır:

Kotlin

// Throws an ActivityNotFoundException exception when targeting Android 14.
context.startActivity(Intent("com.example.action.APP_ACTION"))

Java

// Throws an ActivityNotFoundException exception when targeting Android 14.
context.startActivity(new Intent("com.example.action.APP_ACTION"));

Dışa aktarılmayan etkinliği başlatmak için uygulamanızın bunun yerine açık bir intent kullanması gerekir:

Kotlin

// This makes the intent explicit.
val explicitIntent =
        Intent("com.example.action.APP_ACTION")
explicitIntent.apply {
    package = context.packageName
}
context.startActivity(explicitIntent)

Java

// This makes the intent explicit.
Intent explicitIntent =
        new Intent("com.example.action.APP_ACTION")
explicitIntent.setPackage(context.getPackageName());
context.startActivity(explicitIntent);

Çalışma zamanında kaydedilen yayın alıcılar, dışa aktarma davranışını belirtmelidir

Apps and services that target Android 14 (API level 34) or higher and use context-registered receivers are required to specify a flag to indicate whether or not the receiver should be exported to all other apps on the device: either RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED, respectively. This requirement helps protect apps from security vulnerabilities by leveraging the features for these receivers introduced in Android 13.

Exception for receivers that receive only system broadcasts

If your app is registering a receiver only for system broadcasts through Context#registerReceiver methods, such as Context#registerReceiver(), then it shouldn't specify a flag when registering the receiver.

Daha güvenli dinamik kod yükleme

Uygulamanız Android 14 (API düzeyi 34) veya sonraki sürümleri hedefliyorsa ve Dinamik Kod kullanıyorsa Yükleniyor (DCL) durumunda, dinamik olarak yüklenen tüm dosyalar salt okunur olarak işaretlenmelidir. Aksi takdirde, sistem bir istisna uygular. Uygulamalardan Kodu dinamik olarak yükleme Çünkü böyle yapmak, uygulamanızın tekrar gözden geçirilmesi riskini veya başkasının eline geçer.

Kodu dinamik olarak yüklemeniz gerekiyorsa dinamik olarak yüklenen dosyayı (ör. DEX, JAR veya APK dosyası) açıldıktan hemen sonra ve herhangi bir içerik yazılmadan önce salt okunur olarak ayarlamak için aşağıdaki yaklaşımı kullanın:

Kotlin

val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
    // Set the file to read-only first to prevent race conditions
    jar.setReadOnly()
    // Then write the actual file content
}
val cl = PathClassLoader(jar, parentClassLoader)

Java

File jar = new File("DYNAMICALLY_LOADED_FILE.jar");
try (FileOutputStream os = new FileOutputStream(jar)) {
    // Set the file to read-only first to prevent race conditions
    jar.setReadOnly();
    // Then write the actual file content
} catch (IOException e) { ... }
PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);

Mevcut olan ve dinamik olarak yüklenmiş dosyaları işleyin

Dinamik olarak yüklenen mevcut dosyalara yönelik istisnaların atılmasını önlemek için dinamik olarak denemeden önce dosyaları silip yeniden oluşturmanızı öneririz. bunları uygulamanıza tekrar yükleyebilirsiniz. Dosyaları yeniden oluştururken önceki yazma zamanında dosyaları salt okunur olarak işaretleme ile ilgili yol gösterici bilgiler içerir. Alternatif olarak mevcut dosyaları salt okunur olarak yeniden etiketleyin. Ancak bu örnekte, önce dosyaların bütünlüğünü doğrulamanızı öneririz (örneğin, uygulamanızın korunmasına yardımcı olmak için dosyanın imzasını güvenilir bir değerle karşılaştırarak kötü amaçlı işlemlerden korur.

Arka planda etkinlik başlatmayla ilgili ek kısıtlamalar

For apps targeting Android 14 (API level 34) or higher, the system further restricts when apps are allowed to start activities from the background:

These changes expand the existing set of restrictions to protect users by preventing malicious apps from abusing APIs to start disruptive activities from the background.

Zip path traversal

Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalarda Android, ZIP Yol Geçiş Güvenlik Açığını aşağıdaki şekilde önler: ZipFile(String) ve ZipInputStream.getNextEntry(), ZIP dosyası giriş adları ".." içeriyorsa veya "/" ile başlıyorsa ZipException hatası oluşturur.

Uygulamalar, dalvik.system.ZipPathValidator.clearCallback() çağrısı yaparak bu doğrulamayı devre dışı bırakabilir.

Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalarda, aşağıdaki senaryolardan birinde MediaProjection#createVirtualDisplay tarafından bir SecurityException atılır:

Uygulamanız, her yakalama oturumundan önce kullanıcıdan izin almalıdır. Tek bir yakalama oturumu, MediaProjection#createVirtualDisplay üzerinde tek bir çağrıdır ve her MediaProjection örneği yalnızca bir kez kullanılmalıdır.

Yapılandırma değişikliklerini işleme

Uygulamanızın yapılandırma değişikliklerini (ör. ekran yönü veya ekran boyutu değişikliği) işlemek için MediaProjection#createVirtualDisplay'ü çağırması gerekiyorsa mevcut MediaProjection örneği için VirtualDisplay'ı güncellemek üzere aşağıdaki adımları uygulayabilirsiniz:

  1. Yeni genişlik ve yükseklikle VirtualDisplay#resize işlevini çağırın.
  2. VirtualDisplay#setSurface için yeni genişlik ve yükseklik içeren yeni bir Surface sağlayın.

Geri arama kaydı

Uygulamanız, kullanıcının yakalama oturumuna devam etmek için izin vermediği durumları işlemek üzere bir geri çağırma işlevi kaydetmelidir. Bunu yapmak için Callback#onStop'u uygulayın ve uygulamanızın ilgili tüm kaynakları (ör. VirtualDisplay ve Surface) yayınlamasını sağlayın.

Uygulamanız bu geri çağırma işlevini kaydetmezse MediaProjection#createVirtualDisplay, uygulamanız işlevi çağırdığında IllegalStateException hatası verir.

SDK olmayan arayüzlerle ilgili güncellenen kısıtlamalar

Android 14, Android geliştiricilerle işbirliği ve en son dahili testlere dayalı olarak kısıtlanmış SDK dışı arayüzlerin güncellenmiş listelerini içerir. Mümkün olduğunda, SDK olmayan arayüzleri kısıtlamadan önce herkese açık alternatiflerin kullanılabilir olmasını sağlarız.

Uygulamanız Android 14'ü hedeflemiyorsa bu değişikliklerin bazıları sizi hemen etkilemeyebilir. Ancak şu anda bazı SDK dışı arayüzleri (uygulamanızın hedef API düzeyine bağlı olarak) kullanabilseniz de herhangi bir SDK dışı yöntemi veya alanı kullanmak uygulamanızın bozulma riskini her zaman yüksek tutar.

Uygulamanızın SDK dışı arayüzler kullanıp kullanmadığından emin değilseniz öğrenmek için uygulamanızı test edebilirsiniz. Uygulamanız SDK dışı arayüzleri kullanıyorsa SDK alternatiflerine geçişi planlamaya başlamanız gerekir. Bununla birlikte, bazı uygulamaların SDK dışı arayüzleri kullanmak için geçerli kullanım alanları olduğunu anlıyoruz. Uygulamanızdaki bir özellik için SDK dışı arayüz kullanmaya alternatif bulamıyorsanız yeni bir herkese açık API isteğinde bulunmalısınız.

To learn more about the changes in this release of Android, see Updates to non-SDK interface restrictions in Android 14. To learn more about non-SDK interfaces generally, see Restrictions on non-SDK interfaces.