Awareness API и Android O с помощью BroadcastReceiver

У меня есть приложение для Android, которое использует API Awareness для настройки забора при подключении гарнитуры.

Я внедрил AwarenessFence, используя код, как в примерах: https://developers.google.com/awareness/android-api/fence-register.

У меня есть PendingIntent, определяемый как:

PendingIntent.getBroadcast(context, 0, new Intent("my.application.packageFENCE_RECEIVER_ACTION"), 0)

Затем в моем файле AndroidManifest.xml у меня есть

<receiver android:name=".fence.FenceDetector$MyFenceReceiver">
<intent-filter>
    <action android:name="my.application.packageFENCE_RECEIVER_ACTION" />
</intent-filter>

Это объявлено в манифесте из-за того, что я хочу получать трансляции, даже когда мое приложение находится в фоновом режиме.

Все это отлично работало на Android 7.0 и ниже, но когда я запускаю его на Android 8.0, я получаю сообщение об ошибке:

BroadcastQueue: Background execution not allowed: receiving Intent { act=my.application.packageFENCE_RECEIVER_ACTION

Я предполагаю, что это связано с новыми ограничениями для выполнения фона на Android O.

Может кто-нибудь сказать мне, как зарегистрировать широковещательный приемник, который может прослушивать триггеры оповещения для оповещений, когда он находится в фоновом режиме на устройстве Android с API 26.

Сообщите мне Если есть что-то непонятное или мне нужно что-то уточнить.

Заранее спасибо

Ответ 1

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

Это означает вместо этого:

// implicit intent matching action
PendingIntent.getBroadcast(context, 0,
    new Intent("my.application.packageFENCE_RECEIVER_ACTION"), 0)

вы делаете это:

// explicit intent directly targeting your class
PendingIntent.getBroadcast(context, 0,
    new Intent(context, FenceDetector.MyFenceReceiver.class), 0)

Ответ 2

Я немного погулял и наткнулся на этот пост в блоге CommonsWare. В нем оговаривается сама проблема, с которой вы столкнулись.

Из вышеприведенного сообщения: -

Одна из наиболее противоречивых изменений в Android O - для приложений с достаточно высокий targetSdkVersion - это эффективный запрет на неявный трансляций.

Итак, в соответствии с этим, я не думаю, что ваша проблема имеет какое-либо отношение к API-интерфейсу Awareness. Вместо этого, это из-за нового поведения, введенного в Android 8.

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

Если вы принимаете неявные трансляции, отправленные системой (например, ACTION_PACKAGE_ADDED), сохраните цель targetSdkVersion на уровне 25 или ниже, пока мы не выясним лучшие обходные пути, которые (надеюсь) не привлекают опрос.

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

Ответ 3

Ваше понимание очень правильно.

Приложения, ориентированные на Android 8.0 или более поздние версии, больше не могут регистрировать широковещательные приемники для неявных передач в своем манифесте. Неявная трансляция - это широковещательная передача, которая специально не предназначена для этого приложения.

Приложения могут продолжать регистрироваться для явных передач в своих манифестах.

Источник

Если вас интересует настроить забор, когда гарнитура подключена к. Вы можете использовать

Примечание. В настоящее время ряд неявных трансляций освобождается от этого ограничения. Приложения могут продолжать регистрировать приемники для этих трансляций в своих манифестах, независимо от уровня API, на который нацелены приложения. Список исключенных трансляций см. В Неявные исключения трансляции.

Вы можете запросить ACTION_HEADSET_PLUG в Android Manifest. В onReceive вы можете:

  • запустите NotificationManager.startServiceInForeground(), чтобы вы могли выполнять работу в фоновом режиме.
  • Найдите способ дублирования функциональных возможностей службы с запланированным заданием. Если служба не делает что-то сразу же заметное для пользователя, вы обычно должны иметь возможность использовать запланированное задание. См. Планировщик заданий
  • Отложите фоном работу до тех пор, пока приложение не будет естественно на переднем плане.

Я бы предложил использовать комбинацию Планировщик заданий с ACTION_HEADSET_PLUG, если необходимо выполнить длительную работу.

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

A BroadcastReceiver, который использует goAsync(), чтобы отметить, что ему нужно больше времени для завершения после завершения onReceive(). Это особенно полезно, если работа, которую вы хотите заполнить в onReceive(), достаточно длинна, чтобы заставить поток пользовательского интерфейса пропускать кадр ( > 16 мс), что делает его более подходящим для фонового потока.

вы не должны запускать длинные потоки фона из широковещательного приемника. После onReceive() система может убить процесс в любое время, чтобы восстановить память, и при этом он завершает порожденный поток, выполняемый в этом процессе. Чтобы этого избежать, вы должны либо вызвать goAsync() (если вам нужно немного больше времени для обработки широковещательной передачи в фоновом потоке), либо назначить JobService из приемника с помощью JobScheduler, поэтому система знает, что процесс продолжает выполнять активные Работа.

Источник