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 powiadomić inne aplikacje o czymś, co może je zainteresować (np. o pobieraniu nowych 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 odpowiadania 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 transmisją. 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 dotyczącym transmisji jest powiązane stałe pole. Na przykład wartość stałej ACTION_AIRPLANE_MODE_CHANGED to android.intent.action.AIRPLANE_MODE. Dokumentacja dotycząca każdego działania przesyłania jest dostępna w powiązanym z nim polu stałych.

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 16

Androidzie 16 kolejność przesyłania transmisji za pomocą atrybutu android:priority lub IntentFilter.setPriority() w różnych procesach nie będzie gwarantowana. Priorytety transmisji są uwzględniane tylko w ramach tego samego procesu aplikacji, a nie wszystkich procesów.

Priorytety transmisji są automatycznie ograniczane do zakresu (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1). Ustawienie priorytetu transmisji SYSTEM_LOW_PRIORITY lub SYSTEM_HIGH_PRIORITY może być ustawiane tylko przez komponenty systemowe.

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 pamięci podręcznej, 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 zadeklarowane 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ę.

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 o 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 tak długo, jak długo ich kontekst rejestracji jest ważny. 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.16.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-beta02"
    }

    Kotlin

    dependencies {
        val core_version = "1.16.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-beta02")
    }
  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 transmisji 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 rejestracji odbiornik transmisji zawiera odwołanie do kontekstu, w którym został zarejestrowany. Może to spowodować wycieki, 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
    }
}

Rejestruj odbiorniki w najmniejszym zakresie.

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

  • 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 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 wyodrębnienie 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 .

    
     android:name=".MyBroadcastReceiver" android:exported="false">
        
             android:name="com.example.snippets.ACTION_UPDATE_DATA" />
        
    
    

    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 rejestruje 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 w tle 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 odbiorcy 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 odbiorniki są wykonywane w ramach tego samego procesu aplikacji. Aby to zrobić, użyj atrybutu android:priority filtra intencji dopasowania. 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 normalną transmisją. Jest to bardziej wydajne, ale oznacza, że odbiorniki 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 zapakowana 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 uprawnienie za pomocą tagu w pliku manifestu. Jeśli uprawnienia są niebezpieczne, musisz je przyznać, zanim odbiorca będzie mógł odbierać 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:

 android:name="android.permission.ACCESS_COARSE_LOCATION" />

Możesz określić istniejące uprawnienie systemowe, takie jak BLUETOOTH_CONNECT, lub zdefiniować uprawnienie niestandardowe za pomocą elementu . 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 w pliku manifestu), tylko nadawcy, którzy poprosili o uprawnienia za pomocą tagu 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 odbiornik określony w manifeście w ten sposób:


    android:name=".MyBroadcastReceiverWithPermission"
    android:permission="android.permission.ACCESS_COARSE_LOCATION"
    android:exported="true">
    
         android:name="com.example.snippets.ACTION_UPDATE_DATA" />
    

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:

 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 zarejestrowanych w manifeście chce odbierać tę samą transmisję, system może uruchomić wiele 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 egzekwuje 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. Istnieje kilka sposobów ograniczania transmisji, które otrzymuje Twoja aplikacja:

    • 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 działań transmisji 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 jest wykonywana na głównym wątku, więc powinna być szybko wykonywana i zwracana. 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ć zadanie długotrwałe, 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.