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

Önceki sürümlerde olduğu gibi Android 14 de 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 bir sürümü hedefliyorsa (geçerli olduğunda) uygulamanızı bu davranışları doğru şekilde destekleyecek şekilde değiştirmeniz gerekir.

Uygulamanın targetSdkVersion özelliğinden bağımsız olarak Android 14 üzerinde çalışan tüm uygulamaları etkileyen davranış değişikliklerinin listesini de incelemeyi unutmayın.

Temel işlevler

Ön plan hizmeti türleri gereklidir

Uygulamanız Android 14 (API düzeyi 34) veya sonraki bir sürümü hedefliyorsa uygulamanızdaki her ön plan hizmeti için en az bir ön plan hizmeti türü belirtmelidir. Uygulamanızın kullanım alanını temsil eden bir ön plan hizmet türü seçmelisiniz. Sistem, belirli bir kullanım alanını karşılaması için belirli bir türe sahip ön plan hizmetlerinin olmasını bekler.

Uygulamanızdaki bir kullanım alanı bu türlerden hiçbiriyle ilişkili değilse mantığınızı WorkManager veya kullanıcı tarafından başlatılan veri aktarımı işlerini kullanacak şekilde taşımanız önemle tavsiye edilir.

BluetoothAdapter'da BLUETOOTH_CONNECT izninin uygulanması

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

Bu yöntem zaten BLUETOOTH_CONNECT izni gerektiriyordu ancak zorunlu kılınmadı. Uygulamanızın AndroidManifest.xml dosyasında aşağıdaki snippet'te gösterildiği gibi BLUETOOTH_CONNECT beyan ettiğinden emin olun ve getProfileConnectionState yöntemini ç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 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致,包括适合应用和平台开发者的库更新和 Java 17 语言支持。

以下变更可能会影响应用兼容性:

  • 对正则表达式的更改:现在,为了更严格地遵循 OpenJDK 的语义,不允许无效的组引用。您可能会看到 java.util.regex.Matcher 类抛出 IllegalArgumentException 的新情况,因此请务必测试应用中使用正则表达式的情形。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换 DISALLOW_INVALID_GROUP_REFERENCE 标志。
  • UUID 处理:现在,验证输入参数时,java.util.UUID.fromString() 方法会执行更严格的检查,因此您可能会在反序列化期间看到 IllegalArgumentException。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换 ENABLE_STRICT_VALIDATION 标志。
  • ProGuard 问题:有时,在您尝试使用 ProGuard 缩减、混淆和优化应用时,添加 java.lang.ClassValue 类会导致问题。问题源自 Kotlin 库,该库会根据 Class.forName("java.lang.ClassValue") 是否会返回类更改运行时行为。如果您的应用是根据没有 java.lang.ClassValue 类的旧版运行时开发的,则这些优化可能会将 computeValue 方法从派生自 java.lang.ClassValue 的类中移除。

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

JobScheduler, kullanıma sunulduğundan beri uygulamanızın birkaç saniye içinde onStartJob veya onStopJob üzerinden geri dönmesini bekliyor. Android 14'ten önce, çok uzun süren işler durdurulur ve sessizce başarısız olur. Uygulamanız Android 14 (API düzeyi 34) veya sonraki sürümleri hedefliyorsa ve ana iş parçacığında izin verilen süreyi aşarsa, uygulama "onStartJob için yanıt yok" veya "onStopJob için yanıt yok" hata mesajıyla bir ANR tetikler. Eşzamansız işleme veya ağır işleri arka plan iş parçacığına taşıma desteği sunan WorkManager'a geçiş yapmayı düşünebilirsiniz.

JobScheduler, setRequiredNetworkType veya setRequiredNetwork kısıtlaması kullanılıyorsa ACCESS_NETWORK_STATE iznini tanımlama zorunluluğu da sunar. Uygulamanız, işi planlarken ACCESS_NETWORK_STATE iznini beyan etmez ve Android 14 veya sonraki sürümleri hedefliyorsa SecurityException sonucunu verir.

Kutular lansman API'si

14 ve sonraki sürümleri hedefleyen uygulamalar için TileService#startActivityAndCollapse(Intent) desteği sonlandırılmıştır ve çağrıldığında artık bir istisna oluşturur. Uygulamanız kartlardan etkinlik başlatıyorsa bunun yerine TileService#startActivityAndCollapse(PendingIntent) işlevini kullanın.

Gizlilik

Fotoğraflara ve videolara kısmi erişim

Android 14'te, kullanıcıların belirli bir türdeki tüm medyalara erişim izni vermek yerine, kitaplıklarındaki belirli resim ve videolara erişim izni verebilmelerini sağlayan Seçili Fotoğraflar Erişimi kullanıma sunuldu.

Bu değişiklik yalnızca uygulamanız Android 14 (API düzeyi 34) veya sonraki sürümleri hedefliyorsa etkin olur. Fotoğraf seçiciyi henüz kullanmıyorsanız herhangi bir depolama izni istemek zorunda kalmadan kullanıcı gizliliğini iyileştiren resim ve video seçerken tutarlı bir deneyim sunmak için uygulamanızda bu özelliği uygulamanızı öneririz.

Depolama izinlerini kullanarak kendi galeri seçicinizi kullanıyorsanız ve uygulamanız üzerinde tam kontrol sahibi olmanız gerekiyorsa yeni READ_MEDIA_VISUAL_USER_SELECTED iznini kullanmak için uygulamanızı uyarlayın. Uygulamanız yeni izni kullanmıyorsa sistem, uygulamanızı uyumluluk modunda çalıştırır.

Kullanıcı deneyimi

Güvenli tam ekran Intent bildirimleri

Android 11 (API düzeyi 30) ile tüm uygulamalar, telefon kilitliyken tam ekran ayarlar göndermek için Notification.Builder.setFullScreenIntent kullanılabiliyordu. AndroidManifest'te USE_FULL_SCREEN_INTENT iznini beyan ederek uygulama yükleme işleminde bu izni 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ılan çalar saat ayarları) için tasarlanmıştır. Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalar için bu izni kullanmasına izin verilen uygulamalar, yalnızca arama ve alarm sağlayan uygulamalarla sınırlıdır. Google Play Store, bu profile uymayan uygulamalar için varsayılan USE_FULL_SCREEN_INTENT izinlerini iptal eder. Bu politika değişiklikleri için son tarih 31 Mayıs 2024'tür.

Bu izin, kullanıcı Android 14'e güncellemeden önce telefonda yüklü uygulamalar için etkin kalır. Kullanıcılar bu izni etkinleştirip devre dışı bırakabilir.

Uygulamanızın izne sahip olup olmadığını kontrol etmek için yeni NotificationManager.canUseFullScreenIntent API'sini kullanabilirsiniz. İzniniz yoksa uygulamanız, kullanıcıların izin verebileceği ayarlar sayfasını başlatmak için yeni intent'i ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT kullanabilir.

Güvenlik

Dolaylı ve beklemedeki niyetlerle 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 aşağıdaki şekillerde örtülü amaçlar göndermesini kısıtlar:

  • Dolaylı amaçlar yalnızca dışa aktarılan bileşenlere yayınlanır. Uygulamalar, dışa aktarılmayan bileşenleri yayınlamak için açık bir intent kullanmalı veya bileşeni dışa aktarılmış olarak işaretlemelidir.
  • Bir uygulama, bileşen veya paket belirtmeyen bir amaçla değişken bir beklemedeki intent oluşturursa sistem bir istisna uygular.

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

Örneğin, uygulamanızın manifest dosyasında bildirilebilecek bir niyet filtresi şöyledir:

<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ışırsa istisna oluşur:

Kotlin

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

Java

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

Uygulamanız, dışa aktarılmayan etkinliği başlatmak için bunun yerine açık bir intent kullanmalıdır:

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ına kayıtlı yayın alıcıları dışa aktarma davranışını belirtmelidir

Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen ve bağlama kayıtlı alıcıları kullanan uygulama ve hizmetlerin, alıcının cihazdaki diğer tüm uygulamalara (sırasıyla RECEIVER_EXPORTED veya RECEIVER_NOT_EXPORTED) dışa aktarılıp aktarılmayacağını belirten bir işaret belirtmesi gerekir. Bu şart, Android 13'te kullanıma sunulan bu alıcılar için özelliklerden yararlanarak uygulamaların güvenlik açıklarına karşı korunmasına yardımcı olur.

Yalnızca sistem yayınlarını alan alıcılar için istisna

Uygulamanız Context#registerReceiver() gibi Context#registerReceiver yöntemleriyle yalnızca sistem yayınları için alıcı kaydediyorsa alıcıyı kaydederken bir bayrak belirtmemelidir.

Daha güvenli dinamik kod yükleme

Uygulamanız Android 14 (API düzeyi 34) veya sonraki sürümleri hedefliyorsa ve Dinamik Kod Yükleme (DCL) kullanıyorsa dinamik olarak yüklenen tüm dosyaların salt okunur olarak işaretlenmesi gerekir. Aksi takdirde, sistem bir istisna oluşturur. Uygulamaların mümkün olduğunda kodu dinamik olarak yüklemekten kaçınmasını öneririz. Aksi takdirde, kod yerleştirme veya kodda değişiklik yaparak uygulama güvenliğinin ihlal edilmesi riskini önemli ölçüde artırabilirsiniz.

Kodu dinamik olarak yüklemeniz gerekiyorsa, dinamik olarak yüklenen dosyayı (DEX, JAR veya APK dosyası gibi) dosya açılır açılmaz 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);

Halihazırda mevcut olan dinamik olarak yüklenen dosyaları işleyin

Dinamik olarak yüklenen mevcut dosyaların istisnalarının oluşmasını önlemek için uygulamanızda dinamik olarak tekrar yüklemeyi denemeden önce dosyaları silip yeniden oluşturmanızı öneririz. Dosyaları yeniden oluştururken, yazma zamanında dosyaları salt okunur olarak işaretlemek için yukarıdaki yönergeleri uygulayın. Alternatif olarak, mevcut dosyaları salt okunur olarak yeniden etiketleyebilirsiniz ancak bu durumda, uygulamanızın kötü amaçlı işlemlerden korunmasına yardımcı olmak için öncelikle dosyaların bütünlüğünü doğrulamanızı (örneğin, dosyanın imzasını güvenilir bir değerle kontrol ederek) doğrulamanızı önemle tavsiye ederiz.

Etkinliklerin arka planda başlatılmasıyla ilgili ek kısıtlamalar

对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,系统会进一步限制允许应用何时从后台启动 activity:

这些变更扩展了一组现有限制,以防止恶意应用滥用 API 以在后台启动干扰性活动,从而保护用户。

Sıkıştırılmış yol geçişi

Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalarda Zip Yolu Geçiş Güvenlik Açığını şu şekilde engeller: ZipFile(String) ve ZipInputStream.getNextEntry(); zip dosyası giriş adları ".." içeriyorsa veya "/" ile başlıyorsa ZipException hatası verir.

Uygulamalar dalvik.system.ZipPathValidator.clearCallback() çağrısı yaparak bu doğrulamanın kapsamı dışında kalmayı seçebilir.

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

Uygulamanız, her yakalama oturumundan önce kullanıcıdan izin vermesini istemelidir. Tek bir yakalama oturumu, MediaProjection#createVirtualDisplay üzerindeki 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 (ekran yönünün veya ekran boyutunun değiştirilmesi gibi) işlemek için MediaProjection#createVirtualDisplay yöntemini çağırması gerekiyorsa mevcut MediaProjection örneği için VirtualDisplay öğesini güncellemek üzere aşağıdaki adımları uygulayabilirsiniz:

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

Geri çağırmayı kaydet

Uygulamanız, kullanıcının yakalama oturumuna devam etmesine izin vermediği durumları ele almak için bir geri çağırma kaydetmelidir. Bunu yapmak için Callback#onStop aracını 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ğırmayı kaydetmezse MediaProjection#createVirtualDisplay tarafından çağrıldığında bir IllegalStateException döndürülür.

SDK dışı kısıtlamalar güncellendi

Android 14, Android geliştiricileriyle yapılan ortak çalışmalara ve en son dahili testlere göre 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şikliklerden bazıları sizi hemen etkilemeyebilir. Bununla birlikte, şu anda bazı SDK dışı arayüzleri (uygulamanızın hedef API düzeyine bağlı olarak) kullanabilseniz de herhangi bir SDK olmayan yöntemi veya alanı kullanmak her zaman uygulamanızın bozulma riskini artırır.

Uygulamanızın SDK olmayan arayüzler kullanıp kullanmadığından emin değilseniz öğrenmek için uygulamanızı test edebilirsiniz. Uygulamanız SDK olmayan arayüzlere dayanıyorsa SDK alternatiflerine geçiş planlamaya başlamanız gerekir. Yine de, bazı uygulamaların SDK dışı arayüz kullanımıyla ilgili geçerli kullanım alanları olduğunun farkındayız. Uygulamanızdaki bir özellik için SDK olmayan arayüz kullanmaya alternatif bulamıyorsanız yeni bir herkese açık API isteğinde bulunmanız gerekir.

Android'in bu sürümündeki değişiklikler hakkında daha fazla bilgi edinmek için Android 14'te SDK dışı arayüz kısıtlamalarıyla ilgili güncellemeler bölümüne göz atın. Genel olarak SDK olmayan arayüzler hakkında daha fazla bilgi edinmek için SDK olmayan arayüzlerle ilgili kısıtlamalar bölümüne bakın.