Avatar ·

Ошибка android:exported для Activity в Android 12 и выше: как исправить?

Привет! Я начинающий разработчик на Kotlin, и недавно столкнулся с проблемой при сборке проекта для Android 12 (API 31). После обновления targetSdkVersion до 31, Gradle выдаёт ошибку: ``` android:exported needs to be explicitly specified for . Apps targeting Android 12 and higher are required to specify an explicit value for android:exported when the corresponding component has an intent filter defined. ``` У меня в манифесте объявлено несколько Activity, например: ```xml ``` Я понимаю, что нужно добавить `android:exported`, но не знаю, какое значение ставить. Для MainActivity — `true` или `false`? А для SecondActivity? И что будет, если я просто добавлю `false` везде? Приложение перестанет запускаться? Объясните, пожалуйста, как правильно решить эту проблему. <<>>

Причина ошибки

Начиная с Android 12 (API 31), Google ужесточил требования безопасности. Если в вашем AndroidManifest.xml для компонента (Activity, Service, BroadcastReceiver или ContentProvider) объявлен intent-filter, вы обязаны явно указать атрибут android:exported. Раньше система подставляла значение по умолчанию (если есть intent-filter — true, иначе — false), но теперь это поведение запрещено.

Что означает android:exported?

  • android:exported="true" — компонент может быть запущен из других приложений (или системой).
  • android:exported="false" — компонент доступен только внутри вашего приложения.

Как исправить для MainActivity (Launcher)

Главная Activity, которая запускается по нажатию на иконку приложения, обязательно должна иметь android:exported="true". Иначе система не сможет запустить ваше приложение.

<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Как исправить для SecondActivity (без intent-filter)

Для SecondActivity у вас нет intent-filter. В этом случае атрибут android:exported можно не указывать (ошибка не возникнет), но для единообразия и явности кода лучше добавить android:exported="false":

<activity
    android:name=".SecondActivity"
    android:exported="false" />

Если вы планируете, чтобы SecondActivity запускалась из других приложений (например, через явный Intent), поставьте true.

Общий алгоритм для всех компонентов

  1. Проверьте, есть ли у компонента <intent-filter>.
  2. Если есть — обязательно добавьте android:exported="true" (если компонент должен быть доступен извне) или android:exported="false" (если только для внутреннего использования).
  3. Если intent-filter нет — атрибут не обязателен, но рекомендуется явно указать android:exported="false" для безопасности.

Пример полного исправления

<application ...>
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:name=".SecondActivity"
        android:exported="false" />

    <!-- Для BroadcastReceiver с intent-filter -->
    <receiver
        android:name=".MyReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>

Совет для Kotlin-разработчиков

Если вы используете Compose Navigation или Activity Result API, это не отменяет требования к манифесту. Проверьте все Activity, Service, Receiver и Provider в вашем проекте, включая библиотеки (например, Firebase, Google Sign-In). Если библиотека добавляет свои компоненты с intent-filter, она должна сама указывать android:exported — но лучше перепроверить.

Что будет, если поставить false для MainActivity?

Приложение не сможет запуститься из лаунчера. Система не найдёт точку входа. Вы получите ошибку во время выполнения (или приложение просто не появится в списке приложений).

<<>>

Альтернативный подход: использование инструментов автоматической проверки

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

1. Запуск Lint в Android Studio

Откройте Analyze → Inspect Code и выберите профиль Android Lint. Lint подсветит все Activity, Service, Receiver и Provider, у которых отсутствует android:exported.

2. Использование Gradle-задачи

Добавьте в build.gradle.kts (уровень модуля):

android {
    lint {
        checkReleaseBuilds = true
        abortOnError = true
        // Включите проверку exported
        check "MissingExportedAttribute"
    }
}

Теперь при сборке (например, ./gradlew lintRelease) вы получите отчёт со всеми проблемными местами.

3. Быстрое исправление через поиск

В Android Studio нажмите Ctrl+Shift+F и найдите все вхождения <activity, <service, <receiver. Просмотрите каждый блок и добавьте атрибут. Это скучно, но надёжно.

4. Если вы используете модули библиотек

Иногда ошибка возникает из-за сторонних библиотек, которые объявляют Activity с intent-filter, но не указывают android:exported. В таком случае добавьте атрибут через merge rule в вашем манифесте:

<activity
    android:name="com.some.library.LibraryActivity"
    android:exported="true"
    tools:node="merge" />

Не забудьте добавить xmlns:tools="http://schemas.android.com/tools" в корневой элемент <manifest>.

Этот способ не заменяет понимание логики android:exported, но помогает быстро найти и исправить все пропуски.