Как отправить настраиваемое широковещательное действие получателям в манифесте?

MyReceiver.java

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.i("MyReceiver", "MyAction received!");
    }
}

В AndroidManifest.xml (под тегом application)

<receiver android:name = ".MyReceiver">
    <intent-filter>
        <action android:name = "MyAction" />
    </intent-filter>
</receiver>

MainActivity.Java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sendBroadcast(new Intent("MyAction"));
    }
}

MyReceiver.onReceive метод никогда не срабатывает. Я что-то пропустил?

Вы не можете зарегистрировать получатели для большинства действий Intent в манифесте на Android 8.0+. На какой версии Android вы тестируете? Кроме того, если и MainActivity, и MyReceiver находятся в одном приложении, есть лучшие варианты для внутрипроцессных сообщений, такие как LocalBroadcastManager, EventBus greenrobot, шины событий на основе RxJava и т. д.

CommonsWare 09.03.2018 16:45

Я использую Android 8. И да, они в одном приложении. Несмотря на то, что библиотек много, я хочу знать, как работает BroadcastReceiver. Более того, я не хочу объявлять свой ресивер программно, поскольку MyReceiver будет иметь некоторые системные действия в своем теге intent-filter. Я очень хочу, чтобы это было объявлено в манифесте (насколько это возможно).

Yairopro 09.03.2018 16:49

Больно, что Android сломал эту функциональность. Мой вариант использования таков - у меня есть приложение с несколькими вариантами. Для некоторых разновидностей требуется знать, когда приложение было обновлено, чтобы они могли соответствующим образом обновить свою базу данных. Код, обновляющий версию приложения, хотел бы транслировать обновление получателям, которые могут быть или не могут быть зарегистрированы в манифесте в зависимости от варианта. Rx и eventbus не будут работать, так как код для регистрации слушателей уже должен быть запущен. Красота BR заключается в возможности вызывать код, статически регистрируя его в манифесте.

JohnnyLambada 13.04.2020 21:12
15
3
20 943
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

I use Android 8.

Затем вы должны использовать явный Intent, который идентифицирует получателя, например:

sendBroadcast(new Intent(this, MyReceiver.class).setAction("MyAction"));

См. Ограничения Broacast в документации к выпуску Android 8.

Невозможно использовать только действие? Если у меня есть несколько приемников для запуска. Почему Android ограничил свою систему вещания? Где об этом говорится в документации?

Yairopro 09.03.2018 17:38

@Yairopro: "Невозможно использовать только действие?" - на Android 8.0+ - да, по крайней мере, для приемника, который вы также собираетесь использовать для других трансляций. Подробнее см. документация.

CommonsWare 09.03.2018 17:43

@ChRoNoN: В Android всего несколько механизмов IPC. Если вам нужно говорить через границы процессов в приложении, одна из возможностей - «широковещательная рассылка» конкретному получателю. Это не особенно распространенная потребность, и для использования в процессе есть много других вариантов, которые я изложил в комментарии к вопросу.

CommonsWare 10.08.2018 23:14

@ChRoNoN Действие, как указывает его название, сообщает получателю, что оно должно делать.

Yairopro 12.08.2018 08:18

@Commonsware Для IPC, предполагая, что два пользователя имеют одно и то же приложение, есть ли способ настроить явное намерение для пользователя A, чтобы отправить намерение с данными в BroadcastReceiver в приложении пользователя B через приложение SMS по умолчанию для обоих? Мне удалось настроить с использованием неявного намерения, для которого требуется разрешение RECEIVE_SMS, но теперь это разрешение требует одобрения администраторов магазина Google Play.

AJW 16.07.2020 04:05

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

CommonsWare 16.07.2020 12:47

@CommonsWare Подробнее в этом вопросе: stackoverflow.com/questions/62239517/…

AJW 16.07.2020 13:46

@AJW: Ничего из того, что вы там описываете, не имеет практического значения. Существуют сотни, если не тысячи, SMS-клиентов, любой из которых может быть клиентом по умолчанию для пользователя. От кого-либо из них не требуется поддерживать любую форму ссылки в сообщении. Те, кто это делает, будут использовать startActivity(), а не sendBroadcast(), потому что «щелкнуть ссылку, чтобы сделать что-то на устройстве в автоматическом режиме без ведома пользователя» - отличный вектор для вредоносных программ.

CommonsWare 16.07.2020 13:55

@CommonsWare Я понимаю. Целью нажатия на ссылку является одобрение получателем ввода данных в приложение от отправителя. Отправитель - известный и надежный друг, член семьи, сотрудник и т. д. Это не обязательно должна быть ссылка, но я подумал, что это будет удобный способ для получателя подтвердить свое согласие. Что касается вредоносного ПО, если получатель доверяет отправителю и доверяет приложению безопасную доставку данных, я не думаю, что у них возникнут проблемы с утверждением ссылки. Каким-то образом могло быть добавлено вредоносное ПО, например получение вредоносного электронного письма.

AJW 16.07.2020 14:08

@AJW: «Что касается вредоносного ПО, если получатель доверяет отправителю и доверяет приложению безопасную доставку данных, я не думаю, что у них возникнут проблемы с утверждением ссылки» - возможно, в вашем конкретном случае. Но вы выступаете за функцию (отправка широковещательной рассылки из SMS-клиента), которую авторы вредоносных программ могли бы использовать пускать слюни. Меня беспокоит количество пользователей на всей планете, и поэтому я искренне надеюсь, что ни один SMS-клиент не обладает такими возможностями.

CommonsWare 16.07.2020 14:18

@CommonsWare Поэтому мне следует избегать отправки данных через SMS, потому что законное приложение с защитой, например: опубликовано с одним и тем же сертификатом apk, setPackage () одинаково для отправителя и получателя и android: уровень защиты устанавливается с разрешением уровня подписи, приложение будет быть слишком большой целью для злоумышленников? Если да, то было бы лучше отправлять данные по электронной почте? Или мне нужно полагаться на сервер, потому что он намного безопаснее, чем защита SMS? Проблемы с решением для доставки данных.

AJW 16.07.2020 14:27

@AJW: "легитимное приложение с такой защитой, как: опубликовано с одним и тем же сертификатом apk, setPackage () одинаково для отправителя и получателя и для Android: уровень защиты установлен с разрешением уровня подписи, приложение будет слишком большой целью для злоумышленники? " - эта защита имеет значение только тогда, когда вы говорите о реальном IPC (межпроцессном взаимодействии) между двумя приложениями на том же устройстве. "было бы лучше отправлять данные по электронной почте?" - нет, в этом случае почтовый клиент не должен отправлять широковещательную рассылку в ответ на что-то, содержащееся в электронном письме.

CommonsWare 16.07.2020 14:36

@AJW: SMS-клиенты и почтовые клиенты, если они вообще обрабатывают ссылки, будут начинать действия, а не отправлять широковещательные сообщения. Я не знаю, почему вы хотите отправить трансляцию, но ни один из таких клиентов не сделает этого за вас. «Или мне нужно полагаться на сервер» - это, безусловно, типичный подход, который уводит вас от вмешательства в другую инфраструктуру. Но если бы вы могли переключить свою ментальную модель на действия, а не на трансляции, вы могли бы обнаружить, что SMS или электронная почта подойдут для ваших нужд.

CommonsWare 16.07.2020 14:41

@CommonsWare Я рад переключиться на действия по SMS. Единственное, над чем мне нужно поработать, - это не раздражать пользователя, просто запустив мое приложение, когда приходит SMS, потому что они могут делать что-то еще на устройстве. Вот почему я подумал о кликабельной ссылке или кликабельном изображении, потому что он не открывает действие сразу, это похоже на pendingIntent в Activity ... он ждет одобрения от получателя, а затем действие может открыться для отображения новые данные. Будет ли запуск активности намного безопаснее от злоумышленников, чем трансляции?

AJW 16.07.2020 14:53

@AJW: «Единственное, над чем мне нужно поработать, это не раздражать пользователя, просто запустив мое приложение, когда приходит SMS, потому что они могут делать что-то еще на устройстве» - ничего не произойдет, пока пользователь не щелкнет ссылку. И ваш вопрос ко мне был о трансляциях, а не о деятельности. «Запуск активности будет намного безопаснее от злоумышленников, чем трансляции?» - да, в том смысле, что пользователь должен как минимум щелкнуть ссылку. SMS-клиенты могут предлагать другие средства защиты (например, диалог подтверждения).

CommonsWare 16.07.2020 15:03

@CommonsWare Трансляция должна была отправить данные из SMS в BroadcastReceiver, который затем запускает JobIntentService, который затем запускает Activity. Поэтому, если трансляция небезопасна, я просто включу ссылку в SMS, и нажатие на ссылку запустит Activity для отображения данных (в CardView). Затем я мог бы добавить всплывающее диалоговое окно, чтобы подтвердить, что пользователь желает принять данные. Хороший копацетат с вашей точки зрения?

AJW 16.07.2020 15:25

@AJW: Конечно. Вот как я ожидал, что это сработает. И то, что вы хотели («JobIntentService, который затем запускает Activity»), в любом случае невозможно в современных версиях Android (фоновая активность не запускается). Вопрос, на который вы связались, касается деталей сообщения, чтобы осуществить это, и я думаю, что то, что вы хотите, будет слишком необычным, чтобы быть надежным. Но общий поток «вы отправляете сообщение с глубокой ссылкой, а получатель нажимает на эту ссылку, чтобы запустить свою копию приложения для выполнения какой-либо работы» вполне разумно.

CommonsWare 16.07.2020 15:28

@CommonsWare Отлично, я ценю все отзывы. Ваше здоровье.

AJW 16.07.2020 15:47

@CommonsWare Еще одна проблема, с которой я борюсь, - это передача данных от пользователя приложения A к MainActivity того же пользователя приложения B. Что мне нужно сделать, чтобы передать простые / текстовые данные, полученные в приложение SMS по умолчанию пользователя B, в MainActivity пользователя B? Я не думаю, что у меня есть доступ к приложению SMS по умолчанию, и я избегаю использования BroadcastReceiver, поэтому не могу использовать методы Object [], .get ("pdus") и creatFromPdu (), которые я вижу в других ответах на stackoverflow .

AJW 19.07.2020 14:47

@AJW: поместите его в URL-адрес, который вы используете для своей deeplink. Или поместите идентификатор в этот URL-адрес, который позволяет приложению B получать данные из вашей веб-службы.

CommonsWare 19.07.2020 15:02

@CommonsWare Веб-службы не существует, просто пользователь A отправляет текстовое сообщение пользователю B с помощью приложения для SMS по умолчанию. Так что просто прикрепите данные (JSONObject) к интерактивной ссылке URL?

AJW 19.07.2020 15:07

@AJW: «Веб-службы нет, просто пользователь A отправляет текстовое сообщение пользователю B с помощью приложения для SMS по умолчанию» - если вы хотите передать важные данные, SMS - это ужасный транспортный механизм. «Так что просто прикрепите данные (JSONObject) к интерактивной ссылке URL?» - Вы не оставляете себе другого выбора, AFAICT.

CommonsWare 19.07.2020 15:13

@CommonsWare Не имеет значения, и будет пробовать маршрут URL, ты!

AJW 19.07.2020 15:16

@CommonsWare Я не нахожу хороших примеров или руководств по stackoverflow или поиску в Google по прикреплению JsonObject к URL-адресу ... знаете ли вы какие-либо примеры или учебные пособия, которые могут направить меня в правильном направлении?

AJW 21.07.2020 04:09

@AJW: Я не знаю, о каком именно JsonObject вы говорите. Преобразование объекта в строку JSON выполняется довольно часто. Я обычно использую Moshi, и он покрыт в самом первом разделе README. Если у вас есть строка JSON, вы можете поместить ее в качестве параметра запроса в URL-адрес, как и любую другую строку или число.

CommonsWare 21.07.2020 12:54

@CommonsWare Итак, я могу отправлять данные между двумя пользователями. Но значение String в качестве параметра запроса добавляется в конец схемы / хоста URL. Если строка содержит много символов, тогда URL-ссылка становится очень длинной и неудобной для пользователя i / m / o. Есть ли способ передать символы String, прикрепив их, скажем, как объект для значения параметра запроса? Тогда объект может иметь гораздо более короткое имя, так что интерактивная ссылка будет намного короче. Затем объект будет «распакован» (например, при синтаксическом анализе JSON?), Чтобы получить символы String, которые были отправлены в Activity другого пользователя через SMS?

AJW 03.08.2020 23:55

@AJW: "Есть ли способ передать символы String, прикрепив их, скажем, как объект для значения параметра запроса?" - не более того, чем вы можете сделать это для веб-URL, который, по сути, и создается вами.

CommonsWare 03.08.2020 23:59

Сама строка значения не имеет, просто она должна быть одинаковой во всех местах и ​​уникальной, я использую полностью определенное имя константы.

<receiver android:name = "com.mypackage.receivers.MyBroadcastReceiver">
    <intent-filter>
        <action android:name = "com.mypackage.receivers.MyBroadcastReceiver.ACTION_CUSTOM"/>
    </intent-filter>
</receiver>

Получатель:

package com.mypackage.receivers;

public class MyBroadcastReceiver extends BroadcastReceiver {
    public static final String ACTION_CUSTOM = "com.mypackage.receivers.MyBroadcastReceiver.ACTION_CUSTOM";
@Override
    public void onReceive(Context context, Intent intent) {
      if (ACTION_CUSTOM.equals(intent.getAction())) {
            // do custom action
        }
    }
}

Чтобы транслировать намерение:

sendBroadcast(new Intent(MyBroadcastReceiver.ACTION_CUSTOM));

На Android 8, похоже, вы больше не можете этого делать.

Yairopro 12.08.2018 08:16

Действительно, они изменили его на Oreo.

ChRoNoN 13.08.2018 17:38

В Android 8 onwords

  • Нам нужно предоставить явный класс для обработки, то есть параметр setcomponent вместе с действием

Пример :

  private void triggerBroadCast(String firstFavApp, String secondFavApp) {
        Intent intent = new Intent("FavAppsUpdated");
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
        intent.putExtra("FIRST_FAV_APP", firstFavApp);
        intent.putExtra("SECOND_FAV_APP", secondFavApp);
        intent.setComponent(new
                ComponentName("com.android.systemui",
                "com.android.systemui.statusbar.phone.FavAppsChanged"));

        Log.i(TAG, "Trigger Fav Apps" + firstFavApp + " " + secondFavApp);
        favouriteContract.getAppContext().sendBroadcast(intent);
    }

Ниже Android 8

  • Достаточно только действия для получения трансляции

   void broadCastParkingStates(Context context) {
        Intent intent = new Intent("ReverseCameraStates");
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
        intent.putExtra("PARKING_GUIDE", ReverseCameraPreference.getParkingGuide(context));
        intent.putExtra("PARKING_SENSOR", ReverseCameraPreference.getParkingSensor(context));
        intent.putExtra("TRAJECTORY", ReverseCameraPreference.getTrajectory(context));
        Log.i("BootCompletedReceiver", "Sending Reverse Camera settings states BaordCast");
        Log.i("BootCompletedReceiver", "States Parking:Sensor:Trajectory = "
                + intent.getExtras().getBoolean("PARKING_GUIDE")
                + ":" + intent.getExtras().getBoolean("PARKING_SENSOR")
                + ":" + intent.getExtras().getBoolean("TRAJECTORY")
        );
        context.sendBroadcast(intent);
    }

Работает ли ваше решение для двух пользователей, использующих одно и то же приложение? Я хотел бы увидеть, есть ли способ настроить явное намерение для пользователя A отправить намерение с данными в BroadcastReceiver в приложении пользователя B через приложение SMS по умолчанию для обоих? Мне удалось настроить с использованием неявного намерения, для которого требуется разрешение RECEIVE_SMS, но теперь это разрешение требует одобрения администраторов магазина Google Play.

AJW 16.07.2020 04:18

Только что проверил, он работает и внутри приложения. Спасибо.

Vinayak 24.07.2020 10:27

В Котлине:

val intent = Intent(this, MyBroadCastReceiver::class.java)
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.action = "my.custom.broadcast"
sendBroadcast(intent)

Измените код MainActivity следующим образом:

Intent intent = new Intent(this, MyReceiver.class);
intent.setAction("MyAction");
sendBroadcast(intent);

Этот код такой же, как в ответе CommonsWare (просто разделен на 3 строки). Пожалуйста, избегайте повторяющихся ответов.

Minding 25.10.2019 01:53

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

Примечание: я использовал adb, чтобы протестировать его на Android 10, вы можете добавить его в приложение

FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000

adb shell am broadcast -a MyAction -f 0x01000000

Флаг -f помог мне протестировать на Android 10.

spartygw 15.12.2020 19:49

Другие вопросы по теме