Android - экспортированный приемник не требует разрешения на приемники, предназначенные для получения от системных служб

У меня есть несколько приемников, объявленных в моем AndroidManifest:

<!-- no warning -->
<receiver
    android:name=".receivers.TriggerMonitoringBootReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<!-- no warning -->
<receiver
    android:name=".receivers.ScanResultsReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.net.wifi.SCAN_RESULTS" />
    </intent-filter>
</receiver>

<!-- warning : Exported receiver does not require permission-->
<receiver
    android:name=".receivers.BatteryMonitoringReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="@string/intent_action_setup_alarm" />
        <action android:name="@string/intent_action_cancel_alarm" />
        <action android:name="@string/intent_action_monitor" />
    </intent-filter>
</receiver>

Первый предназначен для получения действия BOOT_COMPLETED. Второй предназначен для получения android.net.wifi.SCAN_RESULTS. Третий предназначен для приема некоторых действий, которые я транслирую (intent_action_monitor), и некоторых действий, транслируемых AlarmManager (intent_action_setup_alarm и т. д.).

Два вопроса:

  • Почему я не получаю предупреждение на всех приемниках?
  • Какие разрешения мне нужно установить для приемников, предназначенных для получения от системных служб, чтобы исправить предупреждение (я понимаю, о чем идет речь, и я все равно не хочу, чтобы кто-либо использовал мои приемники)? Будет exported="false" подходить для загрузочных приемников, приемников Wi-Fi, приемников сигналов тревоги и т. д.?
    Я подумал об использовании пользовательское разрешение с android:protectionLevel="signatureOrSystem", но в документации не рекомендуется использовать оба этих уровня защиты и настраиваемые разрешения. Итак, как я должен обрабатывать это предупреждение?

Ссылки на документы и/или некоторый код будут высоко оценены.




Ответы (5)


Почему я не получаю предупреждение на всех приемниках?

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

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

Правильное решение — удалить файл <intent-filter>. Если вы транслируете эти Intents или заключаете Intent в getBroadcast() PendingIntent, вам не нужны строки действий. Используйте конструктор Intent, который принимает объект класса Java в качестве второго параметра, и используйте его:

new Intent(this, BatteryMonitoringReceiver.class)

Вы можете по-прежнему прикреплять строку действия к этому Intent, если хотите, но вы можете сбросить <intent-filter> (маршрутизация будет основываться на предоставленном компоненте, в данном случае на классе Java).

Используйте <intent-filter> только в том случае, если вы ожидаете, что ОС или сторонние приложения сами инициируют Intent (выполнение созданного вами PendingIntent не считается).

person CommonsWare    schedule 19.04.2013
comment
ООО Спасибо ! просто для большей ясности - первые два явно предназначены для трансляции на Android Я так и думал, но они все еще экспортируются, не так ли? - так что, если я удалю намерения, кто-то все еще может использовать приемники - будет ли добавление exported="false" иметь какое-либо значение? (Кроме того: мне нужны действия, но ваше разъяснение Используйте «фильтр намерений» только тогда, когда вы ожидаете, что ОС или сторонние приложения сами инициируют намерение (выполнение созданного вами PendingIntent не считается). очень, очень приветствуется - +1) - person Mr_and_Mrs_D; 20.04.2013
comment
@Mr_and_Mrs_D: вы не получаете предупреждение о первых двух, поэтому мой ответ сосредоточен на третьем. Я так и думал, но они все еще экспортируются, не так ли? -- да. поэтому, если я удалю намерения, кто-то все еще может использовать приемники - поскольку вы не получаете предупреждений для них, оставьте их в покое. - person CommonsWare; 20.04.2013
comment
Интересно, создание пользовательских разрешений полезно. Так же, как действие Намерения. Я могу использовать инструменты декомпиляции, чтобы извлечь файл manifest.xml и прочитать имя действия. Тогда имя разрешения также может столкнуться с тем же самым... - person Yeung; 24.01.2014

Предупреждение "Экспортированный приемник не требует разрешения" означает, что у вас есть intent-filter с некоторым действием (это означает, что по умолчанию у вас установлено android:exported="true", и теперь он может receive broadcasts от ЛЮБЫХ вещателей за пределами вашего application). может receive broadcasts из ЛЮБОГО broadcasters за пределами вашего приложения, он предупреждает вас, говоря: "Эй, вы уверены, что ЛЮБОЙ вещатель может вызывать вас? На мой взгляд, лучше, если вы позволите вызывать вас только тем broadcasters, у которых есть permission, которые вы установили для этого с receiver по android:permission"

Вы можете удалить это предупреждение, добавив android:exported="false" к тегу получателя.

person AndroidGeek    schedule 19.02.2015

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

<permission
    android:name="com.yourpage.permission.YOUR_PERMISSION"
    android:protectionLevel="normal" />

<uses-permission
    android:name="com.yourpage.permission.YOUR_PERMISSION" />

<receiver <!-- warning : Exported receiver does not require permission-->
    android:name=".receivers.BatteryMonitoringReceiver"
    android:permission="com.yourpage.permission.YOUR_PERMISSION"
    android:enabled="false" >
    <intent-filter>
        <action android:name="@string/intent_action_setup_alarm" />
        <action android:name="@string/intent_action_cancel_alarm" />
        <action android:name="@string/intent_action_monitor" />
    </intent-filter>
</receiver> 

для получения дополнительной информации см. http://developer.android.com/training/articles/security-tips.html

person Lubo    schedule 11.07.2013
comment
Это правильное решение, когда вам нужно объявить собственное разрешение. Однако, как рекомендует официальная документация: создание нового разрешения является относительно необычным для большинства приложений, поскольку системные разрешения охватывают множество ситуаций, вам следует проверить системный список: developer.android.com/reference/android/ - person cuddlecheek; 29.01.2017

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

андроид: экспортировано = ложь

тегу получателя в файле манифеста. Решение CommonsWare, очевидно, подходит для долгосрочной перспективы, но оно временно устраняет проблему, если вы используете настраиваемые намерения и не хотите их экспортировать.

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

person navjotk    schedule 11.09.2014

Чтобы скрыть это предупреждение, добавьте tools:ignore="ExportedReceiver" к приемнику:

<receiver
    android:name=".MyReceiverIndentedForOtherAppsWithoutPermissions"
    tools:ignore="ExportedReceiver">
    <intent-filter>
        <action android:name="com.my.app.CUSTOM_ACTION" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>
person Pierre    schedule 08.01.2021