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

Önceki sürümlerde olduğu gibi Android 14'te de uygulamanızı etkileyebilecek davranış değişiklikleri yer alıyor. 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 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

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ö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 AndroidManifest.xml dosyasında aşağıdaki snippet'te gösterildiği gibi BLUETOOTH_CONNECT beyan ettiğinden emin olun ve getProfileConnectionState işlevini çağırmadan önce kullanıcıya iznin verildiğini kontrol edin.

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

OpenJDK 17 güncellemeleri

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

Bu değişikliklerden birkaçı uygulama uyumluluğunu etkileyebilir:

  • Normal ifadelerde yapılan değişiklikler: Geçersiz grup referanslarının, OpenJDK'nin anlamını daha yakından takip etmesine artık izin verilmemektedir. java.util.regex.Matcher sınıfının IllegalArgumentException değerini attığı yeni durumlar görebilirsiniz. Bu nedenle uygulamanızı normal ifadelerin kullanıldığı alanlar için 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 değiştirin.
  • UUID işleme: java.util.UUID.fromString() yöntemi artık giriş bağımsız değişkenini doğrularken daha sıkı kontroller gerçekleştirir. Bu nedenle serileştirme 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 etkinleştirin.
  • ProGuard sorunları: Bazı durumlarda, ProGuard'ı kullanarak uygulamanızı küçültmeye, gizlemeye ve optimize etmeye çalışırsanız java.lang.ClassValue sınıfının eklenmesi soruna neden olur. Sorun, Class.forName("java.lang.ClassValue") ürününün bir 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ır. Uygulamanız, çalışma zamanının java.lang.ClassValue sınıfının bulunmadığı eski bir sürüme göre geliştirildiyse bu optimizasyonlar, computeValue yöntemini java.lang.ClassValue öğesinden türetilen sınıflardan kaldırabilir.

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

Job Scheduler, kullanıma sunulduğu andan itibaren uygulamanızın Birkaç saniye içinde onStartJob veya onStopJob. Android 14'ten önce bir iş çok uzun süre çalışırsa iş 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şıyorsa "onStartJob için yanıt yok" veya "onStopJob için yanıt yok" hata mesajıyla bir ANR tetikler.

Bu ANR, 2 senaryoya bağlı olabilir: 1. Ana iş parçacığını engelleyen ve geri çağırmaları engelleyen bir iş var (onStartJob) veya onStopJob beklenen süre sınırı içinde yürütülmesini ve tamamlanmasını engeller. 2. Geliştirici, JobScheduler içinde engelleme çalışmasını çalıştırıyor onStartJob veya onStopJob geri çağırması, geri çağırmanın önüne geçer. beklenen süre aşılmadan tamamlanmasıdır.

1. sorunu gidermek için ANR oluştuğunda ana iş parçacığının ne tarafından engellendiğini daha ayrıntılı bir şekilde hata ayıklamanız gerekir. ANR oluştuğunda tombstone izlemeyi almak için ApplicationExitInfo#getTraceInputStream()'i kullanarak bunu yapabilirsiniz. ANR'yi manuel olarak yeniden oluşturabiliyorsanız sistem izleme kaydedebilir ve Android Studio veya Perfetto ile hangi uygulamaların yüklü olduğunu daha iyi anlayın ANR gerçekleştiğinde ana iş parçacığı. Bunun doğrudan JobScheduler API'yi kullanırken olabileceğini unutmayın veya androidx kitaplığını kullanabilirsiniz.

2. sorunu gidermek için onStartJob veya onStopJob'deki tüm işlemleri asenkron bir iş parçacığında sarmalama desteği sunan WorkManager'a geçiş yapabilirsiniz.

JobScheduler, setRequiredNetworkType veya setRequiredNetwork kısıtlaması kullanılıyorsa ACCESS_NETWORK_STATE iznini beyan etme şartını da getirir. Uygulamanız İşi planlarken ACCESS_NETWORK_STATE izni Android 14 veya sonraki sürümlerde SecurityException oluşur.

Tiles launch API

14 ve sonraki sürümleri hedefleyen uygulamalar için TileService#startActivityAndCollapse(Intent) desteği sonlandırıldı ve artık çalışıyor çağrıldığında bir istisna oluşturur. Uygulamanız kartlardan etkinlik başlatıyorsa bunun yerine TileService#startActivityAndCollapse(PendingIntent) değerini 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 ö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

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 salt okunur olarak işaretlenmelidir. 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, uygulamanın kod ekleme veya kodla oynama yoluyla güvenliğinin ihlal edilme riski büyük ölçüde artar.

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

Zaten mevcut olan dinamik olarak yüklenen dosyaları işleme

Mevcut dinamik olarak yüklenen dosyalar için istisnaların atılmasını önlemek amacıyla, dosyaları uygulamanızda tekrar dinamik olarak yüklemeyi denemeden önce dosyaları silip yeniden oluşturmanızı öneririz. Dosyaları yeniden oluştururken, yazma sırasında dosyaları salt okunur olarak işaretlemeyle ilgili önceki talimatları uygulayın. Alternatif olarak, mevcut dosyaları salt okunur olarak yeniden etiketleyebilirsiniz. Ancak bu durumda, uygulamanızı kötü amaçlı işlemlere karşı korumak için önce dosyaların bütünlüğünü doğrulamanızı (örneğin, dosyanın imzasını güvenilir bir değerle karşılaştırarak) önemle tavsiye ederiz.

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

Sistem, Android 14 (API düzeyi 34) veya sonraki sürümleri hedefleyen uygulamalar için uygulamaların arka planda etkinlik başlatmasına izin verilen zamanı kısıtlar:

  • Bir uygulama şunu kullanarak PendingIntent gönderdiğinde: PendingIntent#send() veya benzer yöntemler varsa uygulamanın etkinleştirilmesi gerekir. başlatmak için kendi arka plan etkinliği başlatma ayrıcalıklarını beklemeye gerek yoktur. Etkinleştirmek için uygulamanın setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED) ile bir ActivityOptionspaketi iletmesi gerekir.
  • Görünür bir uygulama, arka plandaki başka bir uygulamanın hizmetini bağladığında bindService() yöntemi kullanıldığında, görünür uygulama artık Android'e kendi arka plan etkinliği başlatma ayrıcalıklarını bağlı hizmet. Etkinleştirmek için uygulama, bindService() yöntemini çağırırken BIND_ALLOW_ACTIVITY_STARTS işaretini içermelidir.

Bu değişiklikler, kötü amaçlı uygulamaların arka planda rahatsız edici etkinlikler başlatmak için API'leri kötüye kullanmasını engelleyerek kullanıcıları korumak amacıyla mevcut kısıtlama grubunu genişletir.

Zip yolu 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ştiricilerle yapılan ortak çalışmalara ve en son şirket içi 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ılabildiğinden emin oluruz.

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

Uygulamanızda SDK dışı arayüzlerin kullanılıp kullanılmadığını öğrenmek için uygulamanızı test edebilirsiniz. Uygulamanız SDK dışı arayüzleri kullanıyorsa SDK alternatiflerine geçiş planlamaya başlamanız gerekir. Bununla birlikte, bazı uygulamaların SDK dışı arayüzler için geçerli kullanım alanları olduğunun farkındayız. Uygulamanızdaki bir özellik için SDK dışı arayüz kullanmanın alternatifini 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.