Yayınlara genel bakış

Android uygulamaları, yayınlama-abone olma tasarım desenine 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 hakkında (ö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, bu tür yayınları almayı kabul eden uygulamalara otomatik olarak 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 iş çalıştırma fırsatını kötüye kullanmamaya dikkat etmeniz gerekir. Bu işlemler, sistem performansının yavaşlamasına neden olabilir.

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 edinmek 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'dir. 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 düzenli olarak 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, android:priority özelliği veya farklı işlemler arasında IntentFilter.setPriority() kullanılarak yayın teslim sırası garanti edilmez. Yayın önceliklerine yalnızca aynı uygulama süreci içinde uyulur, tüm süreçlerde değil.

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 yayın önceliği ayarlamasına izin verilir.

Android 14

Uygulamalar önbelleğe alınmış durumdayken sistem, yayın dağıtımını sistem sağlığı için optimize eder. Örneğin, uygulama önbelleğe alınmış durumdayken sistem, ACTION_SCREEN_ON gibi daha az önemli olan 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.

Manifestte 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 kişisel olarak tanımlanabilir verilerle 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 (API düzeyi 26) sürümünden 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 manifest dosyasını kullanarak çoğu dolaylı yayın için (uygulamanızı özellikle hedeflemeyen yayınlar) alıcı bildiremezsiniz. Kullanıcı uygulamanızı etkin olarak kullanırken bağlamda kayıtlı 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. Manifest'te alıcı bildirmek işe yaramaz.

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ıt bağlamları geçerli olduğu sürece yayınları alır. Bu genellikle registerReceiver ve unregisterReceiver çağrıları arasındadır. Sistem, ilgili bağlamı yok ettiğinde 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.18.0"
    
        // 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.18.0"
    
        // 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ı kayıtlıyken, onu kaydettirdiğiniz 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, bir alıcıyı Etkinlik kapsamında kaydettikten sonra sistem Etkinliği yok ettiğinde kaydını silmeyi unutursanız bu durum oluşabilir. 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 ettirilen 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 ettirilen durumdayken güncellemeleri alır.
  • DisposableEffect: Yayın alıcı, yalnızca composable öğe kompozisyon ağacındayken güncelleme alır. Bu kapsam, etkinlik yaşam döngüsü kapsamına eklenmedi. Alıcıyı uygulama bağlamında kaydetmeyi deneyin. 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. onSaveInstanceState(Bundle) yerine onDestroy() adresinden kaydınızı sildiğinizden emin olun. Aksi takdirde bu işlem ç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 bilgili ve durum bilgisiz birleştirilebilir işlevler oluşturma

Compose'da durum bilgili ve durum bilgisiz composable'lar bulunur. Bir composable içinde yayın alıcısı kaydetmek veya kaydını silmek, composable'ı durumlu hale getirir. 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ı durumlu ve durumsuz 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

Manifest dosyanızda bir yayın alıcısı tanımlarsanız sistem, duyuru gönderildiğinde uygulamanızı başlatır. Uygulama halihazırda çalışmıyorsa sistem uygulamayı başlatır.

Manifestte bir yayın alıcısı tanımlamak 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)'ı uygulayın. Aşağıdaki örnekteki yayın alıcısı, yayının içeriğini kaydeder ve 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ız için 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üğünde 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. Bir ö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şime girmediği veya yakın zamanda etkileşime girmediği 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 herhangi bir anda işlemi durdurarak oluşturulan iş parçacığını sonlandırabilir ve belleği geri alabilir. Sürecin devam etmesi için alıcıdan JobScheduler kullanarak bir JobService planlayın. Böylece sistem, sürecin hâlâ devam ettiğini anlar. Daha fazla bilgi için 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ıştırılma 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, 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 sarılır. 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) işlevini çağırarak bir yayını aynı kuruluştaki bir dizi uygulamayla 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ısı için kısıtlamalar uygulayabilirsiniz.

İzinlerle yayın gönderme

sendBroadcast(Intent, String) veya sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)'ı aradığı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 ö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ı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 izni belirtebilir veya <permission> öğesiyle özel bir izin tanımlayabilirsiniz. Genel olarak izinler ve güvenlik hakkında bilgi edinmek için Sistem İzinleri başlıklı makaleye göz atı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ı vardır:

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" />

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 kaydedilmişse sistemin çok sayıda uygulama başlatmasına neden olabilir. Bu durum, hem cihaz performansı hem de kullanıcı deneyimi üzerinde önemli bir etkiye yol açar. Bunu önlemek için bildirim beyanı yerine bağlam kaydını kullanın. 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 gönderilir.

  • 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 izin belirtebilirsiniz.
    • Manifest'te bildirilen alıcılar için manifest'te android:exported özelliğini "false" olarak ayarlayabilirsiniz. Alıcı, uygulama dışındaki kaynaklardan yayın almaz.
  • Yayın işlemleri için 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ığından 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 etkisi bölümünü inceleyin. Uzun süren işlemler için şunları yapmanızı öneririz:

    • Alıcınızın onReceive() yönteminde goAsync()'ı çağırma ve BroadcastReceiver.PendingResult'ı arka plan iş parçacığına aktarma. Bu işlem, onReceive()'dan döndükten sonra yayının etkin kalmasını sağlar. 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ı makaleye bakı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 deneyebilirsiniz.