Odbiorniki emisji na platformie Xamarin.Android
W tej sekcji omówiono sposób używania odbiornika emisji.
Omówienie odbiornika emisji
Odbiornik emisji jest składnikiem systemu Android, który umożliwia aplikacji odpowiadanie na komunikaty (Android ), które są emitowane przez system operacyjny Android Intent
lub przez aplikację. Emisje są zgodne z modelem publikowania-subskrybowania — zdarzenie powoduje opublikowanie i odebranie emisji przez te składniki, które są zainteresowane zdarzeniem.
System Android identyfikuje dwa typy emisji:
- Jawna emisja — te typy emisji dotyczą określonej aplikacji. Najczęstszym zastosowaniem jawnej emisji jest uruchomienie działania. Przykład jawnej emisji, gdy aplikacja musi wybrać numer telefonu; wyśle intencję docelową aplikacji Telefon w systemie Android i przekaże numer telefonu, który ma zostać wybrany. Następnie system Android będzie kierować intencję do aplikacji Telefon.
- Niejawna emisja — te emisje są wysyłane do wszystkich aplikacji na urządzeniu. Przykładem niejawnej emisji jest intencja
ACTION_POWER_CONNECTED
. Ta intencja jest publikowana za każdym razem, gdy system Android wykryje, że bateria na urządzeniu jest ładowana. System Android będzie kierować tę intencję do wszystkich aplikacji zarejestrowanych na potrzeby tego zdarzenia.
Odbiornik emisji jest podklasą BroadcastReceiver
typu i musi zastąpić metodę OnReceive
. System Android zostanie wykonany OnReceive
w głównym wątku, więc ta metoda powinna zostać zaprojektowana do szybkiego wykonania. Należy zachować ostrożność podczas tworzenia wątków OnReceive
, ponieważ system Android może zakończyć proces po zakończeniu działania metody. Jeśli odbiornik emisji musi wykonywać długotrwałą pracę, zaleca się zaplanowanie zadania przy użyciu JobScheduler
dyspozytora zadań programu Firebase. Planowanie pracy z zadaniem zostanie omówione w osobnym przewodniku.
Filtr intencji służy do rejestrowania odbiornika emisji, aby system Android mógł prawidłowo kierować komunikaty. Filtr intencji można określić w czasie wykonywania (jest to czasami określane jako odbiornik zarejestrowany kontekstowo lub jako rejestracja dynamiczna) lub może być statycznie zdefiniowane w manifeście systemu Android ( odbiornik zarejestrowany w manifeście). Platforma Xamarin.Android udostępnia atrybut języka C#, IntentFilterAttribute
który statycznie zarejestruje filtr intencji (zostanie on omówiony bardziej szczegółowo w dalszej części tego przewodnika). Począwszy od systemu Android 8.0, nie można statycznie zarejestrować aplikacji na potrzeby niejawnej emisji.
Podstawową różnicą między odbiornikiem zarejestrowanym w manifeście a odbiornikiem zarejestrowanym kontekstowo jest to, że odbiornik zarejestrowany w kontekście będzie reagować tylko na emisje, gdy aplikacja jest uruchomiona, podczas gdy odbiornik zarejestrowany w manifeście może reagować na emisje, mimo że aplikacja może nie działać.
Istnieją dwa zestawy interfejsów API do zarządzania odbiornikiem emisji i wysyłania emisji:
Context
— KlasaAndroid.Content.Context
może służyć do rejestrowania odbiornika emisji, który będzie reagować na zdarzenia całego systemu. SłużyContext
również do publikowania emisji w całym systemie.LocalBroadcastManager
— Jest to interfejs API dostępny za pośrednictwem pakietu NuGet biblioteki pomocy technicznej platformy Xamarin w wersji 4. Ta klasa służy do przechowywania emisji i odbiorników emisji izolowanych w kontekście aplikacji, która ich używa. Ta klasa może być przydatna w celu uniemożliwienia innym aplikacjom odpowiadania na emisje tylko przez aplikację lub wysyłanie komunikatów do prywatnych odbiorników.
Odbiornik emisji może nie wyświetlać okien dialogowych i zdecydowanie odradza się uruchamianie działania z poziomu odbiornika emisji. Jeśli odbiornik emisji musi powiadomić użytkownika, powinien opublikować powiadomienie.
Nie można powiązać ani uruchomić usługi z poziomu odbiornika emisji.
W tym przewodniku opisano sposób tworzenia odbiornika emisji i rejestrowania go w taki sposób, aby mógł odbierać emisje.
Tworzenie odbiornika emisji
Aby utworzyć odbiornik emisji na platformie Xamarin.Android, aplikacja powinna podklasować BroadcastReceiver
klasę , a BroadcastReceiverAttribute
następnie zastąpić metodę OnReceive
:
[BroadcastReceiver(Enabled = true, Exported = false)]
public class SampleReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here.
String value = intent.GetStringExtra("key");
}
}
Po skompilowaniu klasy Xamarin.Android zaktualizuje również narzędzie AndroidManifest przy użyciu niezbędnych metadanych w celu zarejestrowania odbiornika. W przypadku statycznie zarejestrowanego odbiornika Enabled
emisji należy odpowiednio ustawić wartość true
, w przeciwnym razie system Android nie będzie mógł utworzyć wystąpienia odbiornika.
Właściwość Exported
określa, czy odbiornik emisji może odbierać komunikaty spoza aplikacji. Jeśli właściwość nie jest jawnie ustawiona, wartość domyślna właściwości jest określana przez system Android na podstawie tego, czy istnieją jakiekolwiek filtry intencji skojarzone z odbiornikiem emisji. Jeśli dla odbiornika emisji istnieje co najmniej jeden filtr intencji, system Android przyjmie, że Exported
właściwość to true
. Jeśli nie ma żadnych filtrów intencji skojarzonych z odbiornikiem emisji, system Android przyjmie, że wartość to false
.
Metoda OnReceive
odbiera odwołanie do Intent
wysłanego do odbiornika emisji. Dzięki temu nadawca intencji może przekazać wartości do odbiornika emisji.
Statyczne rejestrowanie odbiornika emisji za pomocą filtru intencji
Gdy element BroadcastReceiver
zostanie ozdobiony elementem , platforma Xamarin.Android doda element niezbędny <intent-filter>
do manifestu IntentFilterAttribute
systemu Android w czasie kompilacji. Poniższy fragment kodu jest przykładem odbiornika emisji, który będzie uruchamiany po zakończeniu rozruchu urządzenia (jeśli odpowiednie uprawnienia systemu Android zostały przyznane przez użytkownika):
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class MyBootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Work that should be done when the device boots.
}
}
Uwaga
W systemie Android 8.0 (interfejs API 26 i nowszych) firma Google wprowadziła ograniczenia dotyczące tego, co aplikacje mogą robić, gdy użytkownicy nie wchodzą z nimi bezpośrednio w interakcje. Te ograniczenia dotyczą usług w tle i niejawnych odbiorników emisji, takich jak Android.Content.Intent.ActionBootCompleted
. Ze względu na te ograniczenia mogą wystąpić problemy z rejestrowaniem odbiornika Boot Completed
emisji w nowszych wersjach systemu Android. W takim przypadku należy pamiętać, że te ograniczenia nie mają zastosowania do usług pierwszego planu, które mogą być wywoływane z odbiornika emisji.
Istnieje również możliwość utworzenia filtru intencji, który będzie reagować na intencje niestandardowe. Rozważmy następujący przykład:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here
}
}
Aplikacje przeznaczone dla systemu Android 8.0 (poziom 26 interfejsu API) lub nowsze mogą nie być statycznie rejestrowane na potrzeby niejawnej emisji. Aplikacje mogą nadal statycznie rejestrować się w celu jawnego rozgłaszania. Istnieje niewielka lista niejawnych emisji, które są zwolnione z tego ograniczenia. Te wyjątki opisano w przewodniku Niejawne wyjątki emisji w dokumentacji systemu Android. Aplikacje, które są zainteresowane niejawnymi emisjami, muszą to zrobić dynamicznie przy użyciu RegisterReceiver
metody . Jest to opisane w dalszej części.
Rejestrowanie kontekstu odbiornika emisji
Rejestracja kontekstowa (nazywana również rejestracją dynamiczną) odbiornika jest wykonywana przez wywołanie RegisterReceiver
metody, a odbiornik emisji musi być wyrejestrowany za pomocą wywołania UnregisterReceiver
metody . Aby zapobiec wyciekowi zasobów, ważne jest wyrejestrowanie odbiornika, gdy nie jest już istotne dla kontekstu (działanie lub usługa). Na przykład usługa może rozgłaszać intencję informowania działania, że aktualizacje są dostępne do wyświetlenia użytkownikowi. Po uruchomieniu działania zostanie on zarejestrowany dla tych intencji. Gdy działanie zostanie przeniesione do tła i nie będzie już widoczne dla użytkownika, powinno wyrejestrować odbiornik, ponieważ interfejs użytkownika do wyświetlania aktualizacji nie jest już widoczny. Poniższy fragment kodu to przykład rejestrowania i wyrejestrowania odbiornika emisji w kontekście działania:
[Activity(Label = "MainActivity", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity: Activity
{
MySampleBroadcastReceiver receiver;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
receiver = new MySampleBroadcastReceiver();
// Code omitted for clarity
}
protected override void OnResume()
{
base.OnResume();
RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
// Code omitted for clarity
}
protected override void OnPause()
{
UnregisterReceiver(receiver);
// Code omitted for clarity
base.OnPause();
}
}
W poprzednim przykładzie, gdy działanie zostanie wprowadzone na pierwszym planie, zarejestruje odbiornik emisji, który będzie nasłuchiwać intencji niestandardowej OnResume
przy użyciu metody cyklu życia. Gdy działanie przechodzi do tła, OnPause()
metoda wyrejestruje odbiornik.
Publikowanie emisji
Emisja może zostać opublikowana dla wszystkich aplikacji zainstalowanych na urządzeniu, tworząc obiekt Intent i wysyłając ją za pomocą SendBroadcast
metody lub SendOrderedBroadcast
.
Context.SendBroadcast methods — istnieje kilka implementacji tej metody. Te metody będą emitować intencję do całego systemu. Odbiorniki emisji, które otrzymają intencję w nieokreślonej kolejności. Zapewnia to dużą elastyczność, ale oznacza, że istnieje możliwość zarejestrowania i odebrania intencji przez inne aplikacje. Może to stanowić potencjalne zagrożenie bezpieczeństwa. Aplikacje mogą wymagać zaimplementowania dodatkowych zabezpieczeń, aby zapobiec nieautoryzowanemu dostępowi. Jednym z możliwych rozwiązań jest użycie funkcji
LocalBroadcastManager
, która będzie wysyłać komunikaty tylko w prywatnej przestrzeni aplikacji. Ten fragment kodu jest jednym z przykładów sposobu wysyłania intencji przy użyciu jednej zSendBroadcast
metod:Intent message = new Intent("com.xamarin.example.TEST"); // If desired, pass some values to the broadcast receiver. message.PutExtra("key", "value"); SendBroadcast(message);
Ten fragment kodu to kolejny przykład wysyłania emisji przy użyciu
Intent.SetAction
metody w celu zidentyfikowania akcji:Intent intent = new Intent(); intent.SetAction("com.xamarin.example.TEST"); intent.PutExtra("key", "value"); SendBroadcast(intent);
Context.SendOrderedBroadcast — jest to metoda bardzo podobna do
Context.SendBroadcast
metody , a różnica polega na tym, że intencja zostanie opublikowana pojedynczo dla odbiorników w kolejności zarejestrowania odbiorników.
LocalBroadcastManager
Biblioteka pomocy technicznej platformy Xamarin w wersji 4 udostępnia klasę pomocnika o nazwie LocalBroadcastManager
. Jest LocalBroadcastManager
przeznaczony dla aplikacji, które nie chcą wysyłać ani odbierać emisji z innych aplikacji na urządzeniu. Funkcja LocalBroadcastManager
będzie publikować komunikaty tylko w kontekście aplikacji i tylko do tych odbiorników emisji zarejestrowanych w programie LocalBroadcastManager
. Ten fragment kodu jest przykładem rejestrowania odbiornika emisji za pomocą polecenia LocalBroadcastManager
:
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
Inne aplikacje na urządzeniu nie mogą odbierać komunikatów publikowanych za pomocą polecenia LocalBroadcastManager
. Ten fragment kodu pokazuje, jak wysłać intencję przy użyciu elementu LocalBroadcastManager
:
Intent message = new Intent("com.xamarin.example.TEST");
// If desired, pass some values to the broadcast receiver.
message.PutExtra("key", "value");
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this).SendBroadcast(message);
Linki powiązane
- BroadcastReceiver API
- Context.RegisterReceiver API
- Context.SendBroadcast API
- Context.UnregisterReceiver API
- Interfejs API intencji
- IntentFilter API
- LocalBroadcastManager (Dokumentacja systemu Android)
- Lokalne powiadomienia w przewodniku systemu Android
- Biblioteka pomocy technicznej systemu Android w wersji 4 (NuGet)