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 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:

  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şturma:

    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ı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_EXPORTED işaretini kullanın. Bunun yerine 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ı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:

  • LifecycleResumeEffect veya etkinlik onResume/onPause yaşam döngüsü yöntemleri: Yayın alıcısı, yalnızca uygulama devam ettirilmiş durumdayken güncellemeleri alır.
  • LifecycleStartEffect veya etkinlik onStart/onStop yaş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:

  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. Alt sınıf BroadcastReceiver oluşturun ve onReceive(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ç 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, 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ı (SharedFlow ve StateFlow): 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ı.
  • 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. 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_ACTION yayı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önteminde goAsync() yöntemini çağırın ve BroadcastReceiver.PendingResult yö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.
    • 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.