Przegląd transmisji

Aplikacje na Androida wysyłają i odbierają wiadomości rozgłoszeniowe z systemu Android oraz z innych aplikacji na Androida w sposób podobny do wzorca projektowania publikowanie i subskrybowanie. System i aplikacje zwykle wysyłają transmisje po wystąpieniu określonych zdarzeń. Na przykład system Android wysyła transmisje, gdy występują różne zdarzenia systemowe, takie jak uruchamianie systemu lub ładowanie urządzenia. Aplikacje wysyłają też transmisje niestandardowe, aby na przykład powiadomić inne aplikacje o czymś, co może je zainteresować (np. o nowym pobieraniu danych).

Aplikacje mogą się rejestrować, aby otrzymywać określone transmisje. Gdy wysyłasz transmisję, system automatycznie kieruje ją do aplikacji, które subskrybują ten konkretny typ transmisji.

Ogólnie rzecz biorąc, transmisje mogą służyć jako system przesyłania wiadomości w aplikacjach i poza normalnym przepływem informacji. Musisz jednak uważać, aby nie nadużywać możliwości reagowania na transmisje i wykonywania zadań w tle, ponieważ może to spowolnić działanie systemu.

Komunikaty systemowe

System automatycznie wysyła transmisje podczas różnych zdarzeń systemowych, takich jak włączenie i wyłączenie trybu samolotowego. Wszystkie subskrybowane aplikacje otrzymują te transmisje.

Obiekt Intent otacza wiadomość z rozgłaszaniem. Ciąg tekstowy action wskazuje, które zdarzenie wystąpiło, np. android.intent.action.AIRPLANE_MODE. Intencja może też zawierać dodatkowe informacje w polu dodatkowym. Na przykład działanie trybu samolotowego zawiera dodatkową wartość logiczną, która wskazuje, czy tryb samolotowy jest włączony.

Więcej informacji o czytaniu intencji i pobieraniu ciągu działania z intencji znajdziesz w artykule Intencje i filtry intencji.

Działania związane z komunikatem systemowym

Pełna lista działań systemowych dotyczących transmisji znajdzie się w pliku BROADCAST_ACTIONS.TXTw pakiecie Android SDK. Z każdym działaniem związany jest określony typ pola. Na przykład wartość stałej ACTION_AIRPLANE_MODE_CHANGED to android.intent.action.AIRPLANE_MODE. Dokumentacja dotycząca każdego działania w transmisji jest dostępna w powiązanym z nim polu statycznym.

Zmiany w komunikatach systemowych

Wraz z rozwojem platformy Android okresowo zmienia się sposób działania transmisji systemowych. Aby zapewnić obsługę wszystkich wersji Androida, pamiętaj o następujących zmianach.

Android 14

Gdy aplikacje są w stanie pamięci podręcznej, system optymalizuje dostarczanie transmisji w celu zapewnienia prawidłowego działania systemu. Podczas gdy aplikacja jest w stanie buforowania, system opóźnia mniej ważne transmisje, takie jak ACTION_SCREEN_ON. Gdy aplikacja przejdzie ze stanu buforowania do cyklu życia aktywnego procesu, system dostarczy opóźnione transmisje.

Ważne transmisje ogłoszone w pliku manifestu tymczasowo usuwają aplikacje z pamięci podręcznej na potrzeby ich dostarczenia.

Android 9

Począwszy od Androida 9 (poziom interfejsu API 28) transmisja NETWORK_STATE_CHANGED_ACTION nie otrzymuje informacji o lokalizacji użytkownika ani danych umożliwiających identyfikację osoby.

Jeśli aplikacja jest zainstalowana na urządzeniu z Androidem w wersji 9.0 (poziom interfejsu API 28) lub nowszej, system nie uwzględnia w transmisjach Wi-Fi nazw SSID, nazw BSSID, informacji o połączeniu ani wyników skanowania. Aby uzyskać te informacje, zadzwoń pod numer getConnectionInfo().

Android 8.0

Począwszy od Androida 8.0 (poziom interfejsu API 26) system nakłada dodatkowe ograniczenia na odbiorniki zadeklarowane w pliku manifestu.

Jeśli Twoja aplikacja jest kierowana na Androida 8.0 lub nowszego, nie możesz użyć pliku manifestu do zadeklarowania odbiornika dla większości niejawnych transmisji (transmisji, które nie są kierowane bezpośrednio na Twoją aplikację). Nadal możesz używać odbiornika zarejestrowanego w kontekście, gdy użytkownik aktywnie korzysta z aplikacji.

Android 7.0

Android 7.0 (poziom interfejsu API 24) i nowsze nie wysyłają tych transmisji systemowych:

Aplikacje kierowane na Androida 7.0 lub nowszego muszą zarejestrować transmisję CONNECTIVITY_ACTION za pomocą registerReceiver(BroadcastReceiver, IntentFilter). Oświadczenie odbiorcy w pliku manifestu nie działa.

Odbieranie transmisji

Aplikacje mogą odbierać transmisje na 2 sposoby: za pomocą odbiorników zarejestrowanych w kontekście lub za pomocą odbiorników zadeklarowanych w pliku manifestu.

Odbiorcom zarejestrowanym w kontekście

Odbiorniki zarejestrowane w kontekście otrzymują transmisje, dopóki ich kontekst rejestracji jest prawidłowy. Zwykle jest to między wywołaniami registerReceiverunregisterReceiver. Kontekst rejestracji staje się nieprawidłowy, gdy system zniszczy odpowiedni kontekst. Jeśli na przykład zarejestrujesz się w kontekście Activity, będziesz otrzymywać transmisje tak długo, jak długo będzie aktywna dana aktywność. Jeśli zarejestrujesz się w kontekście aplikacji, będziesz otrzymywać transmisje przez cały czas działania aplikacji.

Aby zarejestrować odbiornik w kontekście:

  1. W pliku kompilacji na poziomie modułu aplikacji dołącz bibliotekę AndroidX Core w wersji 1.9.0 lub nowszej:

    Groovy

    dependencies {
        def core_version = "1.15.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.0.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-alpha02"
    }

    Kotlin

    dependencies {
        val core_version = "1.15.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.0.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-alpha02")
    }
  2. Utwórz instancję BroadcastReceiver:

    Kotlin

    val myBroadcastReceiver = MyBroadcastReceiver()
    

    Java

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    
  3. Utwórz instancję IntentFilter:

    Kotlin

    val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")
    

    Java

    IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");
    
  4. Wybierz, czy odbiornik strumienia ma być eksportowany i widoczny dla innych aplikacji na urządzeniu. Jeśli ten odbiornik nasłuchuje transmisji wysyłanych z systemu lub z innych aplikacji (nawet innych aplikacji należących do Ciebie), użyj flagi RECEIVER_EXPORTED. Jeśli odbiornik ma słuchać tylko transmisji wysyłanych przez Twoją aplikację, użyj flagi RECEIVER_NOT_EXPORTED.

    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. Zarejestruj odbiorcę, dzwoniąc na numer registerReceiver():

    Kotlin

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

    Java

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);
    
  6. Aby przestać otrzymywać transmisje, zadzwoń pod numer unregisterReceiver(android.content.BroadcastReceiver). Pamiętaj, aby anulować rejestrację odbiornika, gdy nie będzie już potrzebny lub gdy kontekst przestanie być prawidłowy.

Rejestrowanie odbiornika transmisji

Podczas rejestrowania odbiornika transmisji jest on powiązany z kontekstem, w którym został zarejestrowany. Może to spowodować wycieki danych, jeśli zarejestrowany zakres odbiorcy wykracza poza zakres cyklu życia kontekstu. Może się to zdarzyć, gdy zarejestrujesz odbiornik w zakresie aktywności, ale zapomnisz go odrejestrować, gdy system zniszczy aktywność. Dlatego zawsze odrejestruj odbiornik transmisji.

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

Rejestrowanie odbiorników w najmniejszym zakresie

Odbiornik transmisji powinien być zarejestrowany tylko wtedy, gdy rzeczywiście interesuje Cię wynik. Wybierz jak najmniejszy możliwy zakres odbiorczy:

  • LifecycleResumeEffect lub metody cyklu życia aktywności onResume/onPause: odbiornik transmisji otrzymuje aktualizacje tylko wtedy, gdy aplikacja jest wznowiona.
  • LifecycleStartEffect lub metody cyklu życia aktywności onStart/onStop: odbiornik transmisji otrzymuje aktualizacje tylko wtedy, gdy aplikacja jest wznowiona.
  • DisposableEffect: odbiornik transmisji otrzymuje aktualizacje tylko wtedy, gdy kompozyt znajduje się w drzewie kompozycji. Ten zakres nie jest powiązany z zakresem cyklu życia aktywności. Rozważ zarejestrowanie odbiornika w kontekście aplikacji. Dzieje się tak, ponieważ komponent może teoretycznie przetrwać okres życia aktywności i wyciekać z niej.
  • Aktywność onCreate/onDestroy: odbiornik transmisji otrzymuje aktualizacje, gdy aktywność jest w stanie utworzona. Pamiętaj, aby wyrejestrować się w funkcji onDestroy(), a nie onSaveInstanceState(Bundle), ponieważ ta druga może nie zostać wywołana.
  • zakres niestandardowy: możesz na przykład zarejestrować odbiornik w zakresie ViewModel, aby przetrwał on odtworzenie aktywności; Pamiętaj, aby używać kontekstu aplikacji do rejestrowania odbiornika, ponieważ odbiornik może przetrwać poza zakresem cyklu życia aktywności i wyciekać aktywność.

Tworzenie komponentów stanowych i bezstanowych

Składanka może zawierać komponenty stanowe i bezstanowe. Rejestrowanie lub anulowanie rejestracji odbiornika w ramach usługi kompozytowej powoduje, że usługa staje się zależna od stanu. Funkcja typu „composable” nie jest funkcją deterministyczną, która renderuje ten sam materiał, gdy zostaną przekazane te same parametry. Stan wewnętrzny może się zmieniać w zależności od wywołań zarejestrowanego odbiornika transmisji.

Zgodnie ze sprawdzoną metodą w komponowaniu zalecamy podzielenie komponentów na wersje ze stanem i bez stanu. Dlatego zalecamy przeniesienie funkcji tworzenia odbiornika transmisji z komponowalnego, aby uczynić ją stanową:

@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
}

Odbiorcy zadeklarowani w pliku manifestu

Jeśli w manifeście zadeklarujesz odbiornik transmisji, system uruchomi Twoją aplikację, gdy zostanie wysłana transmisja. Jeśli aplikacja nie jest jeszcze uruchomiona, system ją uruchamia.

Aby zadeklarować odbiornik transmisji w pliku manifestu, wykonaj te czynności:

  1. W pliku manifestu aplikacji określ element <receiver>.

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

    Filtry intencji określają działania przesyłania, do których subskrybuje odbiorca.

  2. Utwórz podklasę BroadcastReceiver i zaimplementuj onReceive(Context, Intent). W tym przykładzie odbiornik transmisji zapisuje i wyświetla zawartość transmisji:

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

Menedżer pakietów systemowych rejestruje odbiornik po zainstalowaniu aplikacji. Odbiornik staje się wtedy osobnym punktem wejścia do aplikacji, co oznacza, że system może uruchomić aplikację i przekazać transmisję, nawet jeśli aplikacja nie jest uruchomiona.

System tworzy nowy obiekt komponentu BroadcastReceiver, aby obsługiwać każdą otrzymaną transmisję. Ten obiekt jest ważny tylko przez czas trwania połączenia z onReceive(Context, Intent). Gdy kod zwróci wartość z tego metody, system uzna, że komponent nie jest już aktywny.

Wpływ na stan procesu

To, czy BroadcastReceiver działa, wpływa na zawarty w nim proces, co może zmienić prawdopodobieństwo uszkodzenia systemu. Proces na pierwszym planie wykonuje metodę onReceive() odbiorcy. System uruchamia proces, z wyjątkiem sytuacji, gdy dochodzi do ekstremalnego obciążenia pamięci.

System dezaktywuje BroadcastReceiver po onReceive(). Znaczenie procesu hosta odbiorcy zależy od komponentów aplikacji. Jeśli proces hostuje tylko odbiornik zadeklarowany w pliku manifestu, system może go zakończyć po onReceive(), aby zwolnić zasoby dla innych, ważniejszych procesów. Jest to typowe w przypadku aplikacji, z których użytkownik nigdy nie korzystał lub z których nie korzystał od dłuższego czasu.

Dlatego odbiorniki transmisji nie powinny inicjować długotrwałych wątków w tle. System może przerwać proces w dowolnym momencie po onReceive(), aby odzyskać pamięć, i w ten sposób zakończyć utworzony wątek. Aby proces nie został przerwany, zaplanuj JobService z urządzenia odbiorczego za pomocą polecenia JobScheduler, aby system wiedział, że proces jest nadal aktywny. Więcej informacji znajdziesz w omówieniu pracy w tle.

Wysyłanie transmisji

Aplikacje na Androida mogą wysyłać transmisje na 2 sposoby:

  • Metoda sendOrderedBroadcast(Intent, String) wysyła transmisje do jednego odbiorcy naraz. Każdy odbiorca wykonuje kod kolejno, przekazując wynik do następnego odbiorcy. Może też całkowicie przerwać transmisję, aby nie dotarła do innych odbiorników. Możesz kontrolować kolejność, w jakiej odbiorcy są wywoływani. Aby to zrobić, użyj atrybutu android:priority filtra intencji dopasowującego. Odbiorcy o tym samym priorytecie są wywoływane w dowolnej kolejności.
  • Metoda sendBroadcast(Intent) wysyła transmisje do wszystkich odbiorców w niezdefiniowanej kolejności. Taki rodzaj transmisji nazywamy transmisją normalną. Jest to bardziej wydajne, ale oznacza, że odbiorcy nie mogą odczytać wyników z innych odbiorników, rozpowszechniać danych otrzymanych z transmisji ani przerywać transmisji.

Ten fragment kodu pokazuje, jak wysłać transmisję, tworząc intencję i wywołując sendBroadcast(Intent).

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

Wiadomość rozgłoszeniowa jest ujęta w obiekt Intent. Ciąg znaków action w intencji musi zawierać składnię nazwy pakietu aplikacji w języku Java oraz jednoznacznie identyfikować zdarzenie transmisji. Możesz dołączyć dodatkowe informacje do intencjonalnego korzystania z putExtra(String, Bundle). Możesz też ograniczyć transmisję do zbioru aplikacji w tej samej organizacji, wywołując setPackage(String) w intencji.

Ograniczanie transmisji za pomocą uprawnień

Uprawnienia umożliwiają ograniczenie transmisji do zestawu aplikacji, które mają określone uprawnienia. Możesz narzucić ograniczenia nadawcy lub odbiorcy transmisji.

Wysyłanie transmisji z uprawnieniami

Gdy wywołujesz metodę sendBroadcast(Intent, String) lub sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle), możesz określić parametr uprawnień. Transmisję mogą odbierać tylko odbiorcy, którzy poprosili o to oznaczenie w pliku manifestu za pomocą tagu <uses-permission>. Jeśli uprawnienia są niebezpieczne, musisz je przyznać, zanim odbiorca będzie mógł odebrać transmisję. Na przykład ten kod wysyła transmisję z uprawnieniem:

Kotlin

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)

Java

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);

Aby odbierać transmisje, aplikacja odbiorcza musi poprosić o uprawnienia w ten sposób:

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

Możesz określić istniejące uprawnienie systemowe, np. BLUETOOTH_CONNECT, lub zdefiniować uprawnienie niestandardowe za pomocą elementu <permission>. Informacje o uprawnieniach i zabezpieczeniach znajdziesz w artykule Uprawnienia systemowe.

Odbieranie transmisji z uprawnieniami

Jeśli podczas rejestrowania odbiornika transmisji użyjesz parametru uprawnień (w tagu registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) lub <receiver> w pliku manifestu), tylko nadawcy, którzy poprosili o uprawnienia za pomocą tagu <uses-permission> w pliku manifestu, mogą wysyłać intencje do odbiornika. Jeśli uprawnienia są niebezpieczne, nadawca musi je również uzyskać.

Załóżmy na przykład, że aplikacja odbiorcza ma w deklaracji w manifeście odbiornik o takim wyglądzie:

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

Aplikacja odbiorcza może też mieć odbiornik rejestrowany w kontekście w ten sposób:

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

Aby móc wysyłać transmisje do tych odbiorców, aplikacja wysyłająca musi poprosić o dostęp w ten sposób:

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

Zagadnienia związane z bezpieczeństwem

Oto kilka kwestii związanych z bezpieczeństwem przesyłania i odbierania transmisji:

  • Jeśli wiele aplikacji w swoim pliku manifestu zarejestrowało się do odbioru tej samej transmisji, może to spowodować uruchomienie przez system wielu aplikacji, co może mieć znaczący wpływ zarówno na wydajność urządzenia, jak i wrażenia użytkownika. Aby tego uniknąć, użyj rejestracji kontekstu zamiast deklaracji w pliku manifestu. Czasami system Androida sam wymusza używanie odbiorników zarejestrowanych w kontekście. Na przykład transmisja CONNECTIVITY_ACTION jest dostarczana tylko do odbiorników zarejestrowanych w kontekście.

  • Nie przekazuj informacji poufnych za pomocą niejawnych intencji. Każda aplikacja może odczytać te informacje, jeśli zarejestruje się do odbioru transmisji. Możesz kontrolować, kto może odbierać Twoje transmisje na 3 sposoby:

    • Podczas wysyłania transmisji możesz określić uprawnienia.
    • W Androidzie 4.0 (poziom interfejsu API 14) i nowszych podczas wysyłania transmisji możesz określić pakiet za pomocą setPackage(String). System ogranicza transmisję do zestawu aplikacji dopasowanych do pakietu.
  • Gdy zarejestrujesz odbiornik, każda aplikacja może wysyłać do niego potencjalnie szkodliwe transmisje. Możesz ograniczyć liczbę transmisji, które otrzymuje Twoja aplikacja, na kilka sposobów:

    • Podczas rejestrowania odbiornika transmisji możesz określić uprawnienia.
    • W przypadku odbiorników zadeklarowanych w pliku manifestu możesz ustawić w nim atrybut android:exported na „false”. Odbiornik nie odbiera transmisji ze źródeł spoza aplikacji.
  • Przestrzeń nazw akcji przesyłania jest globalna. Upewnij się, że nazwy działań i inne ciągi znaków są zapisane w Twojej przestrzeni nazw. W przeciwnym razie możesz przypadkowo zakłócić działanie innych aplikacji.

  • Metoda onReceive(Context, Intent) odbiornika działa na głównym wątku, więc powinna się szybko wykonać i zwrócić. Jeśli musisz wykonać długotrwałe zadanie, uważaj na tworzenie wątków lub uruchamianie usług w tle, ponieważ system może zakończyć cały proces po zwróceniu wartości przez funkcję onReceive(). Więcej informacji znajdziesz w sekcji Wpływ na stan procesu. Aby wykonać długotrwałe zadanie, zalecamy:

    • Wywoływanie metody goAsync() w metodzie onReceive() odbiorcy i przekazywanie parametru BroadcastReceiver.PendingResult do wątku w tle. Dzięki temu transmisja będzie aktywna po powrocie z onReceive(). Jednak nawet w tym przypadku system wymaga, aby zakończyć transmisję bardzo szybko (w mniej niż 10 sekund). Umożliwia to przeniesienie pracy do innego wątku, aby uniknąć błędów w głównym wątku.
    • planowania zadania za pomocą JobScheduler; Więcej informacji znajdziesz w artykule Inteligentne planowanie zadań.
  • Nie uruchamiaj działań z odbiorników transmisji, ponieważ może to zakłócić działanie aplikacji, zwłaszcza jeśli jest więcej niż 1 odbiornik. Zamiast tego możesz wyświetlić powiadomienie.