Android uygulamaları, yayın-abonelik tasarım kalıbına benzer şekilde Android sisteminden ve diğer Android uygulamalarından yayın mesajları gönderip alır. Sistem ve uygulamalar genellikle belirli etkinlikler gerçekleştiğinde yayın gönderir. Örneğin, Android sistemi, sistemin başlatılması veya cihazın şarj edilmesi gibi çeşitli sistem etkinlikleri gerçekleştiğinde yayınlar gönderir. Uygulamalar ayrıca diğer uygulamaları ilgilendirebilecek bir şey (ör. yeni veri indirme) hakkında bilgilendirmek için özel yayınlar da gönderir.
Uygulamalar, belirli yayınları almak için kaydolabilir. Bir yayın gönderildiğinde sistem, yayınları otomatik olarak bu tür yayınları almaya abone olan uygulamalara yönlendirir.
Genel olarak yayınlar, uygulamalar arasında ve normal kullanıcı akışının dışında bir mesajlaşma sistemi olarak kullanılabilir. Ancak yayınlara yanıt verme ve arka planda sistem performansının yavaşlamasına neden olabilecek işleri çalıştırma fırsatını kötüye kullanmamaya dikkat etmeniz gerekir.
Sistem yayınları hakkında
Sistem, çeşitli sistem etkinlikleri gerçekleştiğinde (ör. sistem uçak moduna girip çıktığında) otomatik olarak yayın gönderir. Abone olunan tüm uygulamalar bu yayınları alır.
Intent nesnesi, yayın mesajını sarmalar. action dizesi, android.intent.action.AIRPLANE_MODE gibi gerçekleşen etkinliği tanımlar. Amaç, ek alanına eklenmiş ek bilgiler de içerebilir.
Örneğin, Uçak Modu amacında, Uçak Modu'nun açık olup olmadığını belirten bir Boole değeri bulunur.
Intent'leri okuma ve bir intent'ten işlem dizesini alma hakkında daha fazla bilgi için Intent'ler ve Intent Filtreleri başlıklı makaleyi inceleyin.
Sistem duyurusu işlemleri
Sistem duyurusu işlemlerinin tam listesi için Android SDK'sındaki BROADCAST_ACTIONS.TXT
dosyasına bakın. Her yayın işleminin kendisiyle ilişkili sabit bir alanı vardır. Örneğin, ACTION_AIRPLANE_MODE_CHANGED sabitinin değeri android.intent.action.AIRPLANE_MODE'dır.
Her yayın işlemiyle ilgili dokümanlar, ilişkili sabit alanında mevcuttur.
Sistem yayınlarında yapılan değişiklikler
Android platformu geliştikçe sistem yayınlarının davranış şekli de zaman zaman değişir. Android'in tüm sürümlerini desteklemek için aşağıdaki değişiklikleri göz önünde bulundurun.
Android 16
Android 16'da, farklı işlemler arasında android:priority özelliği veya IntentFilter.setPriority() kullanılarak yapılan yayın dağıtım sırası garanti edilmez. Yayın önceliklerine yalnızca aynı uygulama süreci içinde uyulur, tüm süreçlerde uyulmaz.
Ayrıca yayın öncelikleri otomatik olarak (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1) aralığıyla sınırlandırılır.
Yalnızca sistem bileşenlerinin SYSTEM_LOW_PRIORITY,
SYSTEM_HIGH_PRIORITY değerini yayın önceliği olarak ayarlamasına izin verilir.
Android 14
Uygulamalar önbelleğe alınmış durumdayken sistem, sistem sağlığı için yayın dağıtımını optimize eder. Örneğin, uygulama önbelleğe alınmış durumdayken sistem, ACTION_SCREEN_ON gibi daha az önemli sistem yayınlarını erteler.
Uygulama, önbelleğe alınmış durumdan etkin işlem yaşam döngüsüne geçtiğinde sistem, ertelenen yayınları teslim eder.
Manifest dosyasında belirtilen önemli yayınlar, teslimat için uygulamaları geçici olarak önbelleğe alınmış durumdan kaldırır.
Android 9
Android 9'dan (API düzeyi 28) itibaren NETWORK_STATE_CHANGED_ACTION
yayınında kullanıcının konumu veya kimliği tanımlayabilecek bilgilerle ilgili
bilgiler alınmaz.
Uygulamanız Android 9.0 (API düzeyi 28) veya sonraki bir sürümü çalıştıran bir cihaza yüklendiyse sistem, kablosuz yayınlara SSID'leri, BSSID'leri, bağlantı bilgilerini veya tarama sonuçlarını dahil etmez. Bu bilgileri almak için bunun yerine getConnectionInfo() işlevini çağırın.
Android 8.0
Android 8.0'dan (API düzeyi 26) itibaren sistem, manifest'te belirtilen alıcılar üzerinde ek kısıtlamalar uygular.
Uygulamanız Android 8.0 veya sonraki bir sürümü hedefliyorsa manifesti kullanarak çoğu örtülü yayın için (uygulamanızı özel olarak hedeflemeyen yayınlar) alıcı bildiremezsiniz. Kullanıcı uygulamanızı etkin olarak kullanırken bağlamda kayıtlı bir alıcıyı kullanmaya devam edebilirsiniz.
Android 7.0
Android 7.0 (API düzeyi 24) ve sonraki sürümlerde aşağıdaki sistem yayınları gönderilmez:
Ayrıca Android 7.0 ve sonraki sürümleri hedefleyen uygulamaların, CONNECTIVITY_ACTION yayınını registerReceiver(BroadcastReceiver, IntentFilter) kullanarak kaydetmesi gerekir. Manifestte alıcı bildirmek işe yaramıyor.
Yayın alma
Uygulamalar, yayınları iki şekilde alabilir: bağlamda kayıtlı alıcılar ve manifestte beyan edilen alıcılar aracılığıyla.
Bağlamda kayıtlı alıcılar
Bağlamda kayıtlı alıcılar, kayıtlı bağlamları geçerli olduğu sürece yayınları alır. Bu genellikle registerReceiver ve unregisterReceiver çağrıları arasındadır. Sistemin ilgili bağlamı yok etmesi durumunda kayıt bağlamı da geçersiz hale gelir. Örneğin, Activity bağlamında kaydolursanız etkinlik etkin kaldığı sürece yayın alırsınız. Uygulama bağlamıyla kaydolursanız uygulama çalıştığı sürece yayın alırsınız.
Bir alıcıyı bağlamla kaydetmek için aşağıdaki adımları uygulayın:
Uygulamanızın modül düzeyindeki derleme dosyasına AndroidX Core kitaplığının 1.9.0 veya sonraki bir sürümünü ekleyin:
Groovy
dependencies { def core_version = "1.19.1" // Java language implementation implementation "androidx.core:core:$core_version" // Kotlin implementation "androidx.core:core-ktx:$core_version" // To use RoleManagerCompat implementation "androidx.core:core-role:1.1.0" // To use the Animator APIs implementation "androidx.core:core-animation:1.0.0" // To test the Animator APIs androidTestImplementation "androidx.core:core-animation-testing:1.0.0" // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation "androidx.core:core-performance:1.0.0" // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation "androidx.core:core-google-shortcuts:1.1.0" // Optional - to support backwards compatibility of RemoteViews implementation "androidx.core:core-remoteviews:1.1.0" // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation "androidx.core:core-splashscreen:1.2.0" }
Kotlin
dependencies { val core_version = "1.19.1" // Java language implementation implementation("androidx.core:core:$core_version") // Kotlin implementation("androidx.core:core-ktx:$core_version") // To use RoleManagerCompat implementation("androidx.core:core-role:1.1.0") // To use the Animator APIs implementation("androidx.core:core-animation:1.0.0") // To test the Animator APIs androidTestImplementation("androidx.core:core-animation-testing:1.0.0") // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation("androidx.core:core-performance:1.0.0") // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation("androidx.core:core-google-shortcuts:1.1.0") // Optional - to support backwards compatibility of RemoteViews implementation("androidx.core:core-remoteviews:1.1.0") // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation("androidx.core:core-splashscreen:1.2.0") }
BroadcastReceiverörneği oluşturma:Kotlin
val myBroadcastReceiver = MyBroadcastReceiver()Java
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();IntentFilterörneği oluşturma:Kotlin
val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")Java
IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");Yayın alıcının dışa aktarılıp aktarılmayacağını ve cihazdaki diğer uygulamalar tarafından görünür olup olmayacağını seçin. Bu alıcı, sistemden veya diğer uygulamalardan (sahibi olduğunuz diğer uygulamalar dahil) gönderilen yayınları dinliyorsa
RECEIVER_EXPORTEDişaretini kullanın. Bunun yerine bu alıcı yalnızca uygulamanız tarafından gönderilen yayınları dinliyorsaRECEIVER_NOT_EXPORTEDişaretini kullanın.Kotlin
val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED }Java
boolean listenToBroadcastsFromOtherApps = false; int receiverFlags = listenToBroadcastsFromOtherApps ? ContextCompat.RECEIVER_EXPORTED : ContextCompat.RECEIVER_NOT_EXPORTED;registerReceiver()numaralı telefonu arayarak alıcıyı kaydedin:Kotlin
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)Java
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);Yayın almayı durdurmak için
unregisterReceiver(android.content.BroadcastReceiver)işlevini çağırın. Artık ihtiyacınız olmadığında veya bağlam geçerliliğini yitirdiğinde alıcının kaydını sildiğinizden emin olun.
Yayın alıcınızın kaydını silme
Yayın alıcısı kaydedilirken, kaydedildiği bağlamın referansını tutar. Alıcının kayıtlı kapsamı, bağlam yaşam döngüsü kapsamını aşarsa bu durum sızıntılara neden olabilir. Örneğin, bu durum, bir alıcıyı Etkinlik kapsamında kaydettiğinizde ancak sistem Etkinliği yok ettiğinde kaydını kaldırmayı unuttuğunuzda ortaya çıkabilir. Bu nedenle, yayın alıcınızı her zaman kaydını silin.
Kotlin
class MyActivity : ComponentActivity() {
private val myBroadcastReceiver = MyBroadcastReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags)
setContent { MyApp() }
}
override fun onDestroy() {
super.onDestroy()
// When you forget to unregister your receiver here, you're causing a leak!
this.unregisterReceiver(myBroadcastReceiver)
}
}
Java
class MyActivity extends ComponentActivity {
MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags);
// Set content
}
}
Alıcıları en küçük kapsamda kaydetme
Yayın alıcınız yalnızca sonuçla gerçekten ilgilendiğinizde kaydedilmelidir. Mümkün olan en küçük alıcı kapsamını seçin:
LifecycleResumeEffectveya etkinlikonResume/onPauseyaşam döngüsü yöntemleri: Yayın alıcısı, yalnızca uygulama devam ettirilmiş durumdayken güncellemeleri alır.LifecycleStartEffectveya etkinlikonStart/onStopyaşam döngüsü yöntemleri: Yayın alıcısı, yalnızca uygulama devam ettirilmiş durumdayken güncellemeleri alır.DisposableEffect: Yayın alıcı, yalnızca composable öğe kompozisyon ağacındayken güncellemeleri alır. Bu kapsam, etkinliğin yaşam döngüsü kapsamına eklenmemiş. Alıcıyı uygulama bağlamında kaydetmeyi düşünün. Bunun nedeni, composable'ın teorik olarak etkinlik yaşam döngüsü kapsamından daha uzun süre yaşayabilmesi ve etkinliğin sızmasına neden olabilmesidir.- Etkinlik
onCreate/onDestroy: Yayın alıcısı, etkinlik oluşturulmuş durumdayken güncellemeleri alır.onDestroy()hizmetinde kaydı sildiğinizden emin olun.onSaveInstanceState(Bundle)hizmetinde kaydı silmeyin. Aksi takdirde bu hizmet aranmayabilir. - Özel kapsam: Örneğin,
ViewModelkapsamınızda bir alıcı kaydedebilirsiniz. Böylece, etkinlik yeniden oluşturulduğunda alıcı korunur. Alıcı, etkinlik yaşam döngüsü kapsamından daha uzun süre yaşayabileceğinden ve etkinliğin sızmasına neden olabileceğinden, alıcıyı kaydetmek için uygulama bağlamını kullandığınızdan emin olun.
Durumlu ve durumsuz composable işlevler oluşturma
Compose'da durumlu ve durumsuz composable'lar bulunur. Bir composable içinde yayın alıcısının kaydedilmesi veya kaydının silinmesi, composable'ı durum bilgili yapar. Composable, aynı parametreler iletildiğinde aynı içeriği oluşturacak şekilde tasarlanmış bir işlev değildir. Dahili durum, kayıtlı yayın alıcısına yapılan çağrılara göre değişebilir.
Compose'da en iyi uygulama olarak, composable'larınızı durum bilgili ve durum bilgisiz sürümlere ayırmanızı öneririz. Bu nedenle, yayın alıcının oluşturulmasını Composable'dan çıkararak durumsuz hale getirmenizi öneririz:
@Composable
fun MyStatefulScreen() {
val myBroadcastReceiver = remember { MyBroadcastReceiver() }
val context = LocalContext.current
LifecycleStartEffect(true) {
// ...
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, flags)
onStopOrDispose { context.unregisterReceiver(myBroadcastReceiver) }
}
MyStatelessScreen()
}
@Composable
fun MyStatelessScreen() {
// Implement your screen
}
Manifest'te belirtilen alıcılar
Manifestinizde bir yayın alıcısı tanımlarsanız sistem, yayın gönderildiğinde uygulamanızı başlatır. Uygulama halihazırda çalışmıyorsa sistem uygulamayı başlatır.
Manifest dosyasında yayın alıcısı bildirmek için aşağıdaki adımları uygulayın:
Uygulamanızın manifest dosyasında
<receiver>öğesini belirtin.<!-- If this receiver listens for broadcasts sent from the system or from other apps, even other apps that you own, set android:exported to "true". --> <receiver android:name=".MyBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="com.example.snippets.ACTION_UPDATE_DATA" /> </intent-filter> </receiver>Intent filtreleri, alıcınızın abone olduğu yayın işlemlerini belirtir.
Alt sınıf
BroadcastReceiveroluşturun veonReceive(Context, Intent)'ı uygulayın. Aşağıdaki örnekte yayın alıcısı, yayının içeriğini kaydedip görüntüler:Kotlin
class MyBroadcastReceiver : BroadcastReceiver() { @Inject lateinit var dataRepository: DataRepository override fun onReceive(context: Context, intent: Intent) { if (intent.action == "com.example.snippets.ACTION_UPDATE_DATA") { val data = intent.getStringExtra("com.example.snippets.DATA") ?: "No data" // Do something with the data, for example send it to a data repository: dataRepository.updateData(data) } } }Java
public static class MyBroadcastReceiver extends BroadcastReceiver { @Inject DataRepository dataRepository; @Override public void onReceive(Context context, Intent intent) { if (Objects.equals(intent.getAction(), "com.example.snippets.ACTION_UPDATE_DATA")) { String data = intent.getStringExtra("com.example.snippets.DATA"); // Do something with the data, for example send it to a data repository: if (data != null) { dataRepository.updateData(data); } } } }
Sistem paket yöneticisi, uygulama yüklendiğinde alıcıyı kaydeder. Alıcı, uygulamanıza ayrı bir giriş noktası haline gelir. Bu durumda, uygulama çalışmıyorsa sistem uygulamayı başlatabilir ve yayını iletebilir.
Sistem, aldığı her yayını işlemek için yeni bir BroadcastReceiver bileşen nesnesi oluşturur. Bu nesne yalnızca onReceive(Context, Intent) numarasına yapılan arama süresi boyunca geçerlidir. Kodunuz bu yöntemden döndükten sonra sistem, bileşeni artık etkin olarak değerlendirmez.
İşlem durumu üzerindeki etkiler
BroadcastReceiver cihazınızın çalışıp çalışmaması, içerdiği işlemi etkiler ve bu da sistemin sonlandırılma olasılığını değiştirebilir. Ön plan işlemi, alıcının onReceive() yöntemini yürütür. Sistem, aşırı bellek baskısı altında olmadığı sürece işlemi çalıştırır.
Sistem, BroadcastReceiver özelliğini onReceive() sonra devre dışı bırakır.
Alıcının ana makine sürecinin önemi, uygulama bileşenlerine bağlıdır. Bu işlem yalnızca manifest'te belirtilen bir alıcıyı barındırıyorsa sistem, diğer daha kritik işlemler için kaynakları boşaltmak amacıyla onReceive() sonra işlemi sonlandırabilir. Bu durum, kullanıcının hiç etkileşimde bulunmadığı veya yakın zamanda etkileşimde bulunmadığı uygulamalarda yaygındır.
Bu nedenle, yayın alıcılar uzun süre çalışan arka plan iş parçacıkları başlatmamalıdır.
Sistem, onReceive() işleminden sonra oluşturulan iş parçacığını sonlandırarak belleği geri kazanmak için işlemi istediği zaman durdurabilir. İşlemin devam etmesi için JobScheduler kullanarak alıcıdan bir JobService planlayın. Böylece sistem, işlemin hâlâ devam ettiğini anlar. Daha fazla bilgi için Background Work Overview (Arka Planda Çalışmaya Genel Bakış) başlıklı makaleyi inceleyin.
Yayın gönderme
Android, uygulamaların yayın göndermesi için iki yöntem sunar:
sendOrderedBroadcast(Intent, String)yöntemi, yayınları tek seferde bir alıcıya gönderir. Her alıcı sırayla yürütüldüğünden sonucu bir sonraki alıcıya yayabilir. Ayrıca, yayını tamamen durdurarak diğer alıcılara ulaşmasını da engelleyebilir. Alıcıların aynı uygulama sürecinde çalışacağı sırayı kontrol edebilirsiniz. Bunu yapmak için eşleşen amaç filtresininandroid:priorityözelliğini kullanın. Aynı önceliğe sahip alıcılar rastgele bir sırayla çalıştırılır.sendBroadcast(Intent)yöntemi, yayınları tanımlanmamış bir sırayla tüm alıcılara gönderir. Buna Normal Yayın denir. Bu yöntem daha verimlidir ancak alıcıların diğer alıcılardan gelen sonuçları okuyamayacağı, yayınlardan alınan verileri yaygınlaştıramayacağı veya yayını durduramayacağı anlamına gelir.
Aşağıdaki kod snippet'inde, bir Intent oluşturup sendBroadcast(Intent) işlevini çağırarak yayın gönderme işlemi gösterilmektedir.
Kotlin
val intent = Intent("com.example.snippets.ACTION_UPDATE_DATA").apply {
putExtra("com.example.snippets.DATA", newData)
setPackage("com.example.snippets")
}
context.sendBroadcast(intent)
Java
Intent intent = new Intent("com.example.snippets.ACTION_UPDATE_DATA");
intent.putExtra("com.example.snippets.DATA", newData);
intent.setPackage("com.example.snippets");
context.sendBroadcast(intent);
Yayın mesajı bir Intent nesnesine yerleştirilir. Amacın action dizesi, uygulamanın Java paket adı söz dizimini sağlamalı ve yayın etkinliğini benzersiz şekilde tanımlamalıdır. putExtra(String, Bundle) ile niyetinize ek bilgiler ekleyebilirsiniz. Ayrıca, niyet üzerinde setPackage(String) çağrısı yaparak bir yayını aynı kuruluştaki bir dizi uygulamayla da sınırlayabilirsiniz.
İzinlerle yayınları kısıtlama
İzinler, yayınları belirli izinlere sahip uygulamalarla kısıtlamanıza olanak tanır. Yayın gönderen veya alıcı için kısıtlamalar uygulayabilirsiniz.
İzinlerle yayın gönderme
sendBroadcast(Intent, String) veya sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String,
Bundle) işlevini çağırdığınızda bir izin parametresi belirtebilirsiniz. Yalnızca manifestlerinde <uses-permission> etiketiyle bu izni isteyen alıcılar yayını alabilir. İzin tehlikeli ise alıcının yayını alabilmesi için izni vermeniz gerekir. Örneğin, aşağıdaki kod, izin içeren bir yayın gönderir:
Kotlin
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)
Java
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);
Yayın almak için alıcı uygulamanın izni aşağıdaki gibi istemesi gerekir:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
BLUETOOTH_CONNECT gibi mevcut bir sistem iznini belirtebilir veya <permission> öğesiyle özel bir izin tanımlayabilirsiniz. Genel olarak izinler ve güvenlik hakkında bilgi edinmek için Sistem İzinleri bölümüne bakın.
İzinlerle yayın alma
Bir yayın alıcısını kaydederken izin parametresi belirtirseniz (manifestinizde registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) ile veya <receiver> etiketiyle) yalnızca manifestlerinde <uses-permission> etiketiyle izni isteyen yayıncılar alıcıya bir Amaç gönderebilir. İzin tehlikeliyse yayıncıya da izin verilmelidir.
Örneğin, alıcı uygulamanızın manifestinde aşağıdaki gibi bir alıcı bildirildiğini varsayalım:
<!-- If this receiver listens for broadcasts sent from the system or from
other apps, even other apps that you own, set android:exported to "true". -->
<receiver
android:name=".MyBroadcastReceiverWithPermission"
android:permission="android.permission.ACCESS_COARSE_LOCATION"
android:exported="true">
<intent-filter>
<action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
</intent-filter>
</receiver>
Alternatif olarak, alıcı uygulamanızda aşağıdaki gibi bağlama kayıtlı bir alıcı bulunur:
Kotlin
ContextCompat.registerReceiver(
context, myBroadcastReceiver, filter,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
null, // scheduler that defines thread, null means run on main thread
receiverFlags
)
Java
ContextCompat.registerReceiver(
context, myBroadcastReceiver, filter,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
null, // scheduler that defines thread, null means run on main thread
receiverFlags
);
Ardından, bu alıcılara yayın gönderebilmek için gönderen uygulamanın izni aşağıdaki şekilde istemesi gerekir:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Aynı işlemde yayın yapmaktan kaçının
Yayınlar, farklı uygulamalar arasında veya sistem ile uygulamalar arasında mesaj göndermek için işlemler arası iletişim (IPC) mekanizması olarak tasarlanmıştır. Alıcıların tümünün yayını gönderen işlemle aynı süreçte çalıştığı bir yayın olan kendi kendine yayın göndermek çok verimsizdir, gereksiz sistem yükü oluşturur ve kesinlikle önerilmez.
Uygulamaların kendi kendilerine yayın gönderdiği iki yaygın senaryo şunlardır:
Aynı süreçteki bileşenler arasında iletişim kurma: Örneğin, etkinlikler, parçalar, hizmetler veya arka plan iş parçacıkları arasında etkinlik ya da veri aktarma. Yayın göndermek yerine, gözlemci deseni veya reaktif akışlar gibi standart süreç içi iletişim mekanizmalarını kullanın:
- Kotlin akışları (
SharedFlowveStateFlow): Kotlin'de, uygulamanızdaki eş yordamlar ve bileşenler arasında etkinlik akışları veya durum güncellemeleri yayınlamak ve gözlemlemek için kullanılan modern ve deyimsel bir çözümdür. - Paylaşılan
ViewModel: Aynı etkinlikteki farklı kullanıcı arayüzü bileşenleri (ör. parçalar veya composable'lar) arasında veri ve etkinlik paylaşımını kolaylaştırır. - Geri çağırmalar ve dinleyiciler: Bileşenler arasında doğrudan iletilen veya merkezi bir depoda ya da denetleyicide kaydedilen standart arayüz geri çağırmaları veya işlev referansları.
- Kotlin akışları (
Sistem etkinliklerini, işleri veya alarmları işleme: Örneğin, planlanmış bir iş, alarm veya sistem geri araması alma ve ardından gerçek işi tetiklemek için yayın gönderme. Yayın göndermek yerine, çalışmayı doğrudan bu işin içinde (ör.
JobServiceveya WorkManager çalışanı), alarm işleyicide ya da sistem geri çağırma bileşeninde tamamlayın veya doğrudan uygulamanızın iş mantığı sınıflarına temsilci olarak atayın.
Android 17 QPR2 veya sonraki sürümlerin yüklü olduğu cihazlarda sistem, kendi yayınlarını daha verimli bir şekilde sunar. Bunun için yayınları, ana iş parçacığında kendi alıcılarına ileten gönderme sürecine geri döndürür. Kendi yayınınızı göndermek, işleminizin önemini artırmaz ve önbelleğe alınmış bir işlemin dondurulmasını engellemez. Bu nedenle, uygulamanızın çalışmaya devam etmesini sağlamak veya arka planda çalışmak için kendi yayınlarınıza güvenmeyin. Bu optimizasyonla bile, kendi kendine yayınlar devam eden iletişim mekanizmalarından daha az verimlidir. Bu nedenle, bunun yerine bu alternatifleri kullanın.
Uygulama bileşenleri arasındaki iletişimi tasarlama hakkında daha fazla bilgi için Uygulama mimarisi kılavuzu'na bakın.
Güvenlikle ilgili olarak göz önünde bulundurulması gerekenler
Yayın gönderme ve alma ile ilgili bazı güvenlik hususları:
Birçok uygulama, manifestlerinde aynı yayını alacak şekilde kaydolduysa sistemin çok sayıda uygulama başlatmasına neden olabilir. Bu durum, hem cihaz performansını hem de kullanıcı deneyimini önemli ölçüde etkiler. Bunu önlemek için bildirim beyanı yerine bağlam kaydını kullanmayı tercih edin. Bazen Android sisteminin kendisi, bağlamda kayıtlı alıcıların kullanılmasını zorunlu kılar. Örneğin,
CONNECTIVITY_ACTIONyayını yalnızca bağlamı kaydedilmiş alıcılara teslim edilir.Hassas bilgileri dolaylı intent kullanarak yayınlamayın. Yayın almak için kaydolan tüm uygulamalar bu bilgileri okuyabilir. Yayınlarınızı kimlerin alabileceğini kontrol etmenin üç yolu vardır:
- Yayın gönderirken izin belirtebilirsiniz.
- Android 4.0 (API düzeyi 14) ve sonraki sürümlerde, yayın gönderirken
setPackage(String)ile bir paket belirtebilirsiniz. Sistem, yayını paketle eşleşen uygulamalarla kısıtlar.
Bir alıcı kaydettiğinizde herhangi bir uygulama, uygulamanızın alıcısına kötü amaçlı olabilecek yayınlar gönderebilir. Uygulamanızın aldığı yayınları sınırlamanın birkaç yolu vardır:
- Yayın alıcısını kaydederken bir izin belirtebilirsiniz.
- Manifest'te belirtilen alıcılar için manifest dosyasında android:exported özelliğini "false" olarak ayarlayabilirsiniz. Alıcı, uygulama dışındaki kaynaklardan yayın almaz.
Yayın işlemleri için ad alanı globaldir. İşlem adlarının ve diğer dizelerin, sahibi olduğunuz bir ad alanında yazıldığından emin olun. Aksi takdirde, diğer uygulamalarla istemeden çakışabilirsiniz.
Alıcının
onReceive(Context, Intent)yöntemi ana iş parçacığında çalıştığı için hızlı bir şekilde yürütülmeli ve döndürülmelidir. Uzun süren bir işlem yapmanız gerekiyorsa iş parçacıkları oluşturma veya arka plan hizmetleri başlatma konusunda dikkatli olun. Sistem,onReceive()döndükten sonra tüm işlemi sonlandırabilir. Daha fazla bilgi için İşlem durumu üzerindeki etki başlıklı makaleyi inceleyin. Uzun süren işlemler için şunları yapmanızı öneririz:- Alıcınızın
onReceive()yöntemindegoAsync()yöntemini çağırın veBroadcastReceiver.PendingResultyöntemini arka plan iş parçacığına iletin. Bu sayede,onReceive()'dan döndükten sonra yayın etkin kalır. Ancak bu yaklaşımla bile sistem, yayını çok kısa sürede (10 saniyeden kısa) bitirmenizi bekler. Bu, ana iş parçacığında aksaklık olmasını önlemek için işi başka bir iş parçacığına taşımanıza olanak tanır. JobSchedulerile iş planlama Daha fazla bilgi için Akıllı İş Planlama başlıklı makaleyi inceleyin.
- Alıcınızın
Kullanıcı deneyimi rahatsız edici olduğundan, özellikle birden fazla alıcı varsa yayın alıcılarından etkinlik başlatmayın. Bunun yerine bildirim göstermeyi deneyin.