android:exported: salvando do crash no Android 12 com Kotlin

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que seu aplicativo parou de funcionar repentinamente no Android 12?

\n\n

Você atualizou o targetSdkVersion para 31 ou superior, compilou o APK, executou — e recebeu um crash com a mensagem misteriosa:

\n\n
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\n

Familiar? 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á!

\n\n

O que é android:exported e para que serve?

\n\n

android: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.

\n\n

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 que exported = true.
  • \n
  • Se não houver filtro — exported = false.
  • \n
\n\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>.

\n\n

Como o erro se manifesta na prática?

\n\n

Suponha 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\n

Se targetSdkVersion = 31 ou superior, você receberá um erro na compilação ou execução. A solução é adicionar android:exported:

\n\n
<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\n

Para a Activity principal, que é iniciada a partir da tela inicial, exported deve ser true — caso contrário, o launcher não conseguirá abri-la.

\n\n

Como corrigir corretamente: guia passo a passo

\n\n

Passo 1. Abra o AndroidManifest.xml

\n

Encontre todos os <activity>, <service>, <receiver> e <provider> que possuem <intent-filter>. Para cada um deles, adicione android:exported.

\n\n

Passo 2. Determine o valor do atributo

\n

Aqui 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
\n\n

Passo 3. Exemplos para diferentes cenários

\n\n

Cenário 1: Activity principal (Launcher)

\n
                

Blogs

Book Recommendations