Por que seu aplicativo parou de funcionar repentinamente no Android 12?
\n\nVocê atualizou o targetSdkVersion para 31 ou superior, compilou o APK, executou — e recebeu um crash com a mensagem misteriosa:
android:exported needs to be explicitly specified for <activity>. \nApps targeting Android 12 and higher are required to specify \nan explicit value for `android:exported` when the corresponding \ncomponent has an intent filter defined.\n\nFamiliar? Se você deu uma olhada no Stack Overflow, viu que essa pergunta acumulou milhares de visualizações. Desenvolvedores em pânico, usuários confusos. Mas não se apresse em excluir o projeto. Neste artigo, vamos entender o que é esse tal android:exported, por que o Google endureceu os requisitos e como corrigir rapidamente o erro em Kotlin. Vamos lá!
O que é android:exported e para que serve?
\n\nandroid:exported é um atributo no AndroidManifest.xml que controla se outros aplicativos (ou o próprio sistema) podem iniciar seu componente (Activity, Service, BroadcastReceiver ou ContentProvider). Se o atributo estiver definido como true — o componente está acessível externamente. Se false — apenas dentro do seu aplicativo.
Antes do Android 12 (API 31), esse atributo era opcional. Se você não o especificasse, o sistema decidia por conta própria se o componente era acessível:
\n- \n
- Se a Activity tiver um
<intent-filter>— o sistema considerava queexported = true. \n - Se não houver filtro —
exported = false. \n
Mas esse comportamento "automático" é uma falha de segurança. Imagine: você criou uma Activity para login no aplicativo e acidentalmente adicionou um intent-filter. Qualquer aplicativo de terceiros pode chamar sua Activity e roubar tokens. Por isso, o Google decidiu: a partir do Android 12, você é obrigado a declarar explicitamente android:exported para qualquer componente que tenha um <intent-filter>.
Como o erro se manifesta na prática?
\n\nSuponha que você tenha um manifesto simples:
\n\n<activity android:name=".MainActivity">\n <intent-filter>\n <action android:name="android.intent.action.MAIN" />\n <category android:name="android.intent.category.LAUNCHER" />\n </intent-filter>\n</activity>\n\nSe targetSdkVersion = 31 ou superior, você receberá um erro na compilação ou execução. A solução é adicionar android:exported:
<activity \n android:name=".MainActivity"\n android:exported="true">\n <intent-filter>\n <action android:name="android.intent.action.MAIN" />\n <category android:name="android.intent.category.LAUNCHER" />\n </intent-filter>\n</activity>\n\nPara a Activity principal, que é iniciada a partir da tela inicial, exported deve ser true — caso contrário, o launcher não conseguirá abri-la.
Como corrigir corretamente: guia passo a passo
\n\nPasso 1. Abra o AndroidManifest.xml
\nEncontre todos os <activity>, <service>, <receiver> e <provider> que possuem <intent-filter>. Para cada um deles, adicione android:exported.
Passo 2. Determine o valor do atributo
\nAqui está uma regra simples:
\n- \n
- true — se o componente deve estar acessível a partir de outros aplicativos (por exemplo, Activity para login via Google, BroadcastReceiver para eventos do sistema, Activity principal com filtro LAUNCHER). \n
- false — se o componente é usado apenas dentro do seu aplicativo (por exemplo, Activity que é aberta ao pressionar um botão no seu próprio código). \n
Passo 3. Exemplos para diferentes cenários
\n\nCenário 1: Activity principal (Launcher)
\n