Широковещательные приемники в Xamarin.Android

В этом разделе описывается использование приемника широковещательной трансляции.

Обзор широковещательного приемника

Широковещательный приемник — это компонент Android, позволяющий приложению реагировать на сообщения (Android), которые передаются операционной системой Android Intentили приложением. Трансляции следуют модели публикации и подписки — событие приводит к публикации и получению трансляции этими компонентами, заинтересованными в событии.

Android определяет два типа трансляций:

  • Явная трансляция — эти типы широковещательных трансляций предназначены для конкретного приложения. Наиболее распространенное использование явной трансляции — запуск действия. Пример явной трансляции, когда приложению необходимо назвонить номер телефона; Он отправляет намерение, которое предназначено для приложения Телефон в Android и передает телефонный номер, который нужно назвонить. Затем Android перенаправит намерение в приложение Телефон.
  • Неявная трансляция — эти трансляции отправляются во все приложения на устройстве. Пример неявного вещания — ACTION_POWER_CONNECTED намерение. Это намерение публикуется каждый раз, когда Android обнаруживает, что заряд батареи на устройстве. Android перенаправит это намерение всем приложениям, зарегистрированным для этого события.

Приемник трансляции BroadcastReceiver является подклассом типа, и он должен переопределить OnReceive метод. Android будет выполняться OnReceive в основном потоке, поэтому этот метод должен быть разработан для быстрого выполнения. Будьте внимательны при создании потоков OnReceive , так как Android может завершить процесс после завершения метода. Если приемник трансляции должен выполнять длительные работы, рекомендуется запланировать задание с помощью JobScheduler диспетчера заданий Firebase. Планирование работы с заданием будет рассмотрено в отдельном руководстве.

Фильтр намерений используется для регистрации широковещательного приемника, чтобы Android могли правильно направлять сообщения. Фильтр намерений можно указать во время выполнения (иногда это называется зарегистрированным в контексте получателем или динамической регистрацией) или статически определен в манифесте Android (зарегистрированный манифестом получатель). Xamarin.Android предоставляет атрибут C#, IntentFilterAttributeкоторый будет статически регистрировать фильтр намерений (это будет подробно описано далее в этом руководстве). Начиная с Android 8.0, невозможно статически зарегистрировать приложение для неявной трансляции.

Основное различие между зарегистрированным манифестом приемником и зарегистрированным в контексте приемником заключается в том, что зарегистрированный в контексте получатель будет реагировать только на трансляции во время работы приложения, в то время как зарегистрированный в манифесте получатель может реагировать на трансляции, даже если приложение не может работать.

Существует два набора API для управления приемником трансляции и отправки трансляций:

  1. Context — Класс Android.Content.Context можно использовать для регистрации широковещательного приемника, который будет отвечать на системные события. Он Context также используется для публикации широковещательных трансляций на уровне системы.
  2. LocalBroadcastManager — Это API, доступный через пакет NuGet библиотеки поддержки Xamarin версии 4. Этот класс используется для изоляции широковещательных и широковещательных приемников в контексте приложения, использующее их. Этот класс может быть полезен для предотвращения реагирования других приложений на трансляции только приложений или отправки сообщений частным получателям.

Широковещательный приемник может не отображать диалоговые окна, и настоятельно не рекомендуется запускать действие из широковещательного приемника. Если получатель трансляции должен уведомить пользователя, он должен опубликовать уведомление.

Невозможно привязать или запустить службу из широковещательного приемника.

В этом руководстве описано, как создать широковещательный приемник и как зарегистрировать его, чтобы он мог получать трансляции.

Создание приемника широковещательной трансляции

Чтобы создать приемник широковещательной трансляции в Xamarin.Android, приложение должно подклассить BroadcastReceiver класс, украшать OnReceive его и BroadcastReceiverAttributeпереопределить метод:

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

Когда Xamarin.Android компилирует класс, он также обновит AndroidManifest с необходимыми метаданными для регистрации приемника. Для статически зарегистрированного приемника широковещательной трансляции необходимо задать правильное Enabled значение true, в противном случае Android не сможет создать экземпляр приемника.

Свойство Exported определяет, может ли получатель трансляции получать сообщения извне приложения. Если свойство не задано явным образом, значение свойства по умолчанию определяется Android на основе наличия фильтров намерений, связанных с приемником трансляции. Если для приемника широковещательной трансляции есть по крайней мере один фильтр намерений, Android предполагает, что Exported это свойство true. Если с приемником трансляции нет фильтров намерений, то Android предполагает, что значение равно false.

Метод OnReceive получает ссылку на Intent то, что было отправлено получателю трансляции. Это позволяет отправителю намерения передавать значения получателю трансляции.

Статически регистрация приемника широковещательной трансляции с помощью фильтра намерений

BroadcastReceiver При украшении IntentFilterAttributeXamarin.Android добавит необходимый <intent-filter> элемент в манифест Android во время компиляции. Следующий фрагмент кода является примером широковещательного приемника, который будет выполняться после завершения загрузки устройства (если соответствующие разрешения Android были предоставлены пользователем):

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

Примечание.

В Android 8.0 (API 26 и выше) Google установил ограничения на то, что приложения могут делать, пока пользователи не взаимодействуют с ними напрямую. Эти ограничения влияют на фоновые службы и неявные приемники трансляции, такие как Android.Content.Intent.ActionBootCompleted. Из-за этих ограничений у вас могут возникнуть трудности с Boot Completed регистрацией приемника трансляции в более новых версиях Android. Если это так, обратите внимание, что эти ограничения не применяются к службам переднего плана, которые можно вызывать из приемника трансляции.

Кроме того, можно создать фильтр намерений, который будет отвечать на пользовательские намерения. Рассмотрим следующий пример:

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Do stuff here
    }
}

Приложения, предназначенные для Android 8.0 (уровень API 26) или более поздней версии, не могут статически регистрироваться для неявной трансляции. Приложения по-прежнему могут статически регистрироваться для явной трансляции. Существует небольшой список неявных трансляций, исключенных из этого ограничения. Эти исключения описаны в руководстве по неявным исключениям широковещательной трансляции в документации по Android. Приложения, которые заинтересованы в неявных трансляциях, должны сделать это динамически с помощью RegisterReceiver метода. Далее описано.

Регистрация приемника трансляции в контексте

Регистрация контекста (также называемая динамической регистрацией) приемника выполняется путем вызова RegisterReceiver метода, и приемник трансляции должен быть отменяется при вызове UnregisterReceiver метода. Чтобы предотвратить утечку ресурсов, важно отменить регистрацию получателя, если он больше не относится к контексту (действие или служба). Например, служба может транслировать намерение сообщить о действии, которые доступны для отображения пользователю. При запуске действия будет зарегистрировано для этих намерений. Когда действие перемещается в фоновом режиме и больше не отображается пользователю, он должен отменить регистрацию получателя, так как пользовательский интерфейс для отображения обновлений больше не отображается. Следующий фрагмент кода — это пример регистрации и отмены регистрации приемника трансляции в контексте действия:

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

В предыдущем примере, когда действие попадает на передний план, он будет регистрировать приемник трансляции, который будет прослушивать пользовательское намерение с помощью OnResume метода жизненного цикла. По мере перемещения действия в фоновом режиме OnPause() метод отменит регистрацию приемника.

Публикация широковещательной трансляции

Широковещательная трансляция может быть опубликована во всех приложениях, установленных на устройстве, создав объект "Намерение" и отправляя его с помощью SendBroadcast метода или SendOrderedBroadcast метода.

  1. Методы Context.SendBroadcast. Существует несколько реализаций этого метода. Эти методы будут транслировать намерение всей системе. Широковещательные приемники, которые получат намерение в неопределенном порядке. Это обеспечивает большую гибкость, но означает, что другие приложения могут регистрировать и получать намерение. Это может привести к потенциальному риску безопасности. Приложениям может потребоваться реализовать дополнительные средства безопасности, чтобы предотвратить несанкционированный доступ. Одним из возможных решений является использование LocalBroadcastManager только отправки сообщений в частном пространстве приложения. Этот фрагмент кода является одним из примеров того, как отправить намерение с помощью одного из SendBroadcast методов:

    Intent message = new Intent("com.xamarin.example.TEST");
    // If desired, pass some values to the broadcast receiver.
    message.PutExtra("key", "value");
    SendBroadcast(message);
    

    Этот фрагмент является еще одним примером отправки трансляции с помощью Intent.SetAction метода для идентификации действия:

    Intent intent = new Intent();
    intent.SetAction("com.xamarin.example.TEST");
    intent.PutExtra("key", "value");
    SendBroadcast(intent);
    
  2. Context.SendOrderedBroadcast . Это метод очень похож Context.SendBroadcastна метод, с отличием от того, что намерение будет опубликовано один раз для получателей в том порядке, в котором были зарегистрированы получатели.

LocalBroadcastManager

Библиотека поддержки Xamarin версии 4 предоставляет вспомогательный класс LocalBroadcastManager. Он LocalBroadcastManager предназначен для приложений, которые не хотят отправлять или получать трансляции из других приложений на устройстве. Будут LocalBroadcastManager публиковаться только сообщения в контексте приложения, а также только для тех получателей широковещательной трансляции, которые зарегистрированы в приложении LocalBroadcastManager. Этот фрагмент кода является примером регистрации широковещательного приемника с помощью LocalBroadcastManager:

Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));

Другие приложения на устройстве не могут получать сообщения, опубликованные с помощью .LocalBroadcastManager В этом фрагменте кода показано, как отправить намерение с помощью 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);