Yayınlara genel bakış

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, diğer uygulamaları ilgilerini çekebilecek bir konuda (ör. yeni veri indirme) 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 anonslar, uygulamalar arasında ve normal kullanıcı işlemleri akışının dışında bir mesajlaşma sistemi olarak kullanılabilir. Ancak yayınlara yanıt verme fırsatını kötüye kullanmamaya ve arka planda sistem performansını yavaşlatabilecek işler çalıştırmamaya dikkat etmeniz gerekir.

Sistem duyuruları 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 olan 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. Intent, ek alanında paketlenmiş 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 bir sabit 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 duyuruları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ğini veya IntentFilter.setPriority() yöntemini kullanan yayın teslim 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ırlıdır. Yalnızca sistem bileşenlerinin yayın önceliği olarak SYSTEM_LOW_PRIORITY, SYSTEM_HIGH_PRIORITY değerini 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 sistem, uygulama önbelleğe alınmış durumdayken ACTION_SCREEN_ON gibi daha az önemli sistem duyurularını erteler. Uygulama, önbelleğe alınmış durumdan etkin işlem yaşam döngüsüne geçtiğinde sistem, ertelenen yayınları yayınlar.

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 (API düzeyi 28) ile başlayarak NETWORK_STATE_CHANGED_ACTION yayını, kullanıcının konumu veya kimliği tanımlayabilecek veriler hakkında bilgi almaz.

Uygulamanız Android 9.0 (API düzeyi 28) veya sonraki bir sürümün yüklü olduğu bir cihaza yüklenirse sistem, kablosuz yayınlara SSID'leri, BSSID'leri, bağlantı bilgilerini veya tarama sonuçlarını dahil etmez. Bu bilgileri almak için getConnectionInfo() işlevini çağırın.

Android 8.0

Android 8.0 (API düzeyi 26) sürümünden itibaren sistem, manifest dosyasında tanımlanan alıcılara ek kısıtlamalar getirir.

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 bir şekilde kullanırken bağlama kayıtlı alıcı 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. Manifest dosyasında alıcı tanımlamak işe yaramaz.

Anons 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ğlam kayıtlı alıcılar, kayıt 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ınları alırsınız.

Bir alıcıyı bağlamla kaydetmek için aşağıdaki adımları uygulayın:

  1. 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")
    }
  2. BroadcastReceiver örneği oluşturun:

    Kotlin

    val myBroadcastReceiver = MyBroadcastReceiver()
    

    Java

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    
  3. 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");
    
  4. Yayın alıcısının dışa aktarılıp aktarılmayacağını ve cihazdaki diğer uygulamalar tarafından görülüp görülmeyeceğini seçin. Bu alıcı, sistemden veya diğer uygulamalardan (sahip olduğunuz diğer uygulamalar dahil) gönderilen yayınları dinliyorsa RECEIVER_EXPORTED işaretini kullanın. Bu alıcı yalnızca uygulamanız tarafından gönderilen yayınları dinliyorsa RECEIVER_NOT_EXPORTED iş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;
    
  5. registerReceiver() numaralı telefonu arayarak alıcıyı kaydedin:

    Kotlin

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)
    

    Java

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);
    
  6. Yayınları 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ı iptal etme

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:

  • LifecycleResumeEffect veya etkinlik onResume/onPause yaşam döngüsü yöntemleri: Yayın alıcısı, yalnızca uygulama devam ettirildiğinde güncelleme alır.
  • LifecycleStartEffect veya etkinlik onStart/onStop yaşam döngüsü yöntemleri: Yayın alıcısı, yalnızca uygulama devam ettirildiğinde güncelleme 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 dayanabilmesi ve etkinliği sızdırabilmesidir.
  • Etkinlik onCreate/onDestroy: Yayın alıcısı, etkinlik oluşturulduktan sonra güncellemeleri alır. Kaydı onSaveInstanceState(Bundle) yerine onDestroy() içinde iptal ettiğinizden emin olun. Aksi takdirde bu çağrılmayabilir.
  • Ö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.

Durum bilgisi olan ve olmayan composable oluşturma

Compose'da durum bilgisi olan ve olmayan composable'lar bulunur. Bir composable içinde yayın alıcıyı kaydetmek veya kaydını iptal etmek, onu durum bilgisi olan bir hale getirir. Oluşturulabilir öğe, aynı parametreler iletildiğinde aynı içeriği oluşturan deterministik 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
}

Manifestte tanımlanan 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:

  1. 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.

  2. BroadcastReceiver alt sınıfını oluşturun ve onReceive(Context, Intent) yöntemini 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) çağrısı süresince 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ı olmadığı sürece işlemi çalıştırır.

Sistem, onReceive() sonra BroadcastReceiver özelliğini devre dışı bırakır. Alıcının ana makine işleminin önemi, uygulama bileşenlerine bağlıdır. Bu işlem yalnızca manifestte tanımlanmış bir alıcı barındırıyorsa sistem, diğer daha kritik işlemler için kaynakları serbest bırakmak amacıyla onReceive() sonra işlemi sonlandırabilir. Bu durum genellikle kullanıcının hiç etkileşimde bulunmadığı veya yakın zamanda etkileşimde bulunmadığı uygulamalarda görülür.

Bu nedenle, yayın alıcıları uzun süre çalışan arka plan iş parçacıkları başlatmamalıdır. Sistem, belleği geri almak için onReceive() tarihinden sonra işlemi istediği zaman durdurabilir ve oluşturulan iş parçacığını sonlandırabilir. Süreci canlı tutmak için JobScheduler kullanarak alıcıdan bir JobService planlayın. Böylece sistem, sürecin hâlâ çalıştığını bilir. Arka plan çalışmasına genel bakış bölümünde daha fazla bilgi bulabilirsiniz.

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 işlemi içinde çalışma sırasını kontrol edebilirsiniz. Bunu yapmak için eşleşen amaç filtresinin android: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, tüm alıcılara belirsiz bir sırada yayın gönderir. Buna normal anons denir. Bu daha verimli bir yöntemdir ancak alıcılar diğer alıcılardan gelen sonuçları okuyamaz, yayından alınan verileri yayamaz veya yayını iptal edemez.

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. Intent'in 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 intent'e ek bilgi ekleyebilirsiniz. Ayrıca, intent üzerinde setPackage(String) yöntemini çağırarak yayını aynı kuruluştaki bir dizi uygulamayla sınırlayabilirsiniz.

Yayınları izinlerle kısıtlama

İzinler, yayınları belirli izinlere sahip uygulama grubuyla 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) yöntemini çağırırken bir izin parametresi belirtebilirsiniz. Yalnızca manifestlerinde <uses-permission> etiketiyle bu izni isteyen alıcılar yayını alabilir. İzin tehlikeliyse alıcının yayını alabilmesi için önce 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ınları almak için alıcı uygulamanın aşağıdaki gibi izin istemesi gerekir:

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

BLUETOOTH_CONNECT gibi mevcut bir sistem izni 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ı kaydederken izin parametresi belirtirseniz (registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) ile veya manifest dosyanızdaki <receiver> etiketinde) yalnızca manifest dosyasında <uses-permission> etiketiyle izin isteyen yayıncılar alıcıya Intent gönderebilir. İzin tehlikeliyse yayıncıya da izin verilmelidir.

Örneğin, alıcı uygulamanızın manifest dosyasında aşağıdaki gibi bir alıcı tanımlandığını 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>

Alıcı uygulamanızda aşağıdaki gibi bağlama kayıtlı bir alıcı varsa:

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şlem içinde 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 kalıbı veya reaktif akışlar gibi standart işlem içi iletişim mekanizmalarını kullanın:

    • Kotlin Akışları (SharedFlow ve StateFlow): Uygulamanızdaki eş yordamlar ve bileşenler arasında etkinlik akışları veya durum güncellemeleri yayınlamak ve gözlemlemek için Kotlin'de modern ve deyimsel bir çözüm.
    • 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: Doğrudan bileşenler arasında iletilen veya merkez veri deposuna ya da denetleyiciye kaydedilen standart arayüz geri çağırmaları veya işlev referansları.
  • 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. JobService veya 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. Bunun yerine, Arka plan görevlerine genel bakış bölümünde açıklandığı gibi göreviniz için uygun API'yi seçin. Bu optimizasyona rağmen, kendi kendine yayınlar, işlem içi 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

Anons gönderme ve alma ile ilgili bazı güvenlik konuları şunlardır:

  • Birçok uygulama, manifest dosyasında aynı yayını almak için kaydolduysa sistemin çok sayıda uygulama başlatmasına neden olabilir. Bu da hem cihaz performansını hem de kullanıcı deneyimini önemli ölçüde etkiler. Bunu önlemek için manifest 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_ACTION yayını yalnızca bağlama kayıtlı alıcılara yayınlanır.

  • Hassas bilgileri dolaylı intent kullanarak yayınlamayın. Yayınları 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.
    • Manifestte tanımlanan alıcılar için manifestte android:exported özelliğini "false" olarak ayarlayabilirsiniz. Alıcı, uygulama dışındaki kaynaklardan yayın almaz.
  • Yayın işlemlerinin ad alanı geneldir. İş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ülüp 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önteminde goAsync() yöntemini çağırıp BroadcastReceiver.PendingResult öğesini bir arka plan iş parçacığına iletme. Bu sayede, onReceive() uygulamasından 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. Ana iş parçacığında aksaklık yaşanmaması için işi başka bir iş parçacığına taşımanıza olanak tanır.
    • JobScheduler ile iş planlama Daha fazla bilgi için Akıllı İş Planlama başlıklı makaleyi inceleyin.
  • 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.