android.os.FileUriExposedException: file:///... exposed beyond app through Intent.getData() significa que o aplicativo enviou um URI file:// para fora do próprio processo por meio de um Intent ou de outro fluxo entre aplicativos. O Android lança essa exceção de diagnóstico para aplicativos direcionados ao Android N/API 24 ou superior. A primeira ação mais segura é inspecionar os dados do Intent, EXTRA_STREAM, ClipData e qualquer URI de saída da câmera em busca do valor file:// restante antes de alterar as configurações do provedor.

O que significa android.os.FileUriExposedException

A exceção se aplica à exposição de arquivos entre aplicativos, não a todas as falhas de acesso a arquivos no Android. Ela costuma aparecer em fluxos de ACTION_VIEW, ACTION_SEND, ACTION_SEND_MULTIPLE, captura pela câmera, anexos, impressão e compartilhamento.

A exceção foi adicionada no nível 24 da API e é lançada para aplicativos direcionados ao Android N ou superior. A versão do Android no dispositivo e o targetSdkVersion do aplicativo são condições relacionadas, mas não são equivalentes. A referência de FileUriExposedException do Android identifica como substituição compatível um URI content:// com acesso temporário para o aplicativo receptor.

A ausência da exceção em outra configuração de SDK não torna seguro o compartilhamento por file://. O Android descreve a exceção como um recurso de diagnóstico, e não como um mecanismo de segurança por si só.

Localize o URI file:// que está saindo do aplicativo

Quando isto se aplica: faça esta inspeção antes de configurar o FileProvider, inclusive quando a mensagem terminar com Intent.getData() ou ClipData.Item.getUri().

Pré-requisitos: o texto da exceção e o código-fonte do fluxo de saída do Intent.

  1. Inspecione o URI exibido na exceção e confirme se o esquema é file.
  2. Analise os quadros do aplicativo imediatamente anteriores à exceção para localizar onde o URI de saída é criado ou anexado.
  3. Procure por Uri.fromFile() e pela análise de valores iniciados por file://.
  4. Inspecione separadamente os dados do Intent, EXTRA_STREAM, cada item de ClipData e qualquer URI de saída da câmera.
  5. Registre a origem e o local real do arquivo. Esses detalhes determinam se é apropriado usar um URI autorizado existente ou o FileProvider.

Resultado esperado: você identifica todos os URIs file:// no fluxo com falha e o ponto em que cada URI entra no Intent.

Risco e aviso: esta é uma etapa de diagnóstico somente leitura. Não presuma que alterar apenas os dados do Intent será suficiente se outro campo que aceite URI continuar inalterado. A presença de ClipData deve ser confirmada pela inspeção do Intent real.

Escolha a origem correta do URI de conteúdo

Quando esta correção se aplica: use este caminho quando a origem já fornecer um URI content:// autorizado, como um documento selecionado pelo usuário ou um item de mídia compartilhada.

Pré-requisitos: confirme se o URI existente continua autorizado para a operação pretendida.

  1. Preserve o URI content:// existente em vez de convertê-lo em um caminho do sistema de arquivos.
  2. Use o Framework de acesso ao armazenamento para documentos selecionados pelo usuário.
  3. Use um URI apropriado do MediaStore para mídia compartilhada.
  4. Coloque o URI autorizado no campo obrigatório do Intent e prossiga para as verificações de permissões temporárias abaixo.

Resultado esperado: o fluxo entre aplicativos mantém um URI content:// autorizado sem introduzir um novo FileProvider.

Risco e reversão: o risco é baixo. Se a origem não puder fornecer um URI autorizado adequado à operação, use o FileProvider somente quando o aplicativo for o proprietário do arquivo. Não converta todos os caminhos pelo FileProvider por padrão.

Configure o AndroidX FileProvider no manifesto

Quando esta correção se aplica: use o AndroidX FileProvider quando o aplicativo for o proprietário de um arquivo e precisar disponibilizá-lo a outro aplicativo.

Pré-requisitos: o AndroidX FileProvider deve estar disponível, você deve ter controle sobre o manifesto e deve conseguir criar um recurso XML de caminhos do provedor. A autoridade exata é específica de cada aplicativo.

  1. Declare um provedor cujo android:name seja FileProvider ou a subclasse de FileProvider do aplicativo.
  2. Defina android:authorities como uma autoridade específica do aplicativo.
  3. Defina android:exported="false".
  4. Defina android:grantUriPermissions="true".
  5. Adicione a entrada de metadados do FileProvider que faça referência ao recurso XML de caminhos do provedor.
  6. Confirme se a autoridade usada posteriormente para gerar o URI corresponde exatamente à autoridade declarada no manifesto.

A documentação do AndroidX FileProvider oferece suporte a esse modelo de provedor e às permissões temporárias de URI.

Resultado esperado: o aplicativo tem um provedor não exportado capaz de gerar URIs content:// autorizados para os arquivos configurados.

Risco e reversão: o risco é baixo. Remova o provedor e seus metadados se o recurso de compartilhamento for removido. Não publique nem copie um valor de autoridade universal, pois ele deve corresponder à configuração do aplicativo.

Restrinja o XML file_paths aos arquivos que precisam ser compartilhados

Quando esta correção se aplica: conclua esta etapa sempre que o FileProvider for usado.

Pré-requisitos: conheça o diretório exato que contém o arquivo que precisa ser compartilhado.

  1. Defina somente o diretório ou os diretórios exigidos pelo recurso de compartilhamento.
  2. Prefira o diretório mais restrito que ainda contenha o arquivo pretendido.
  3. Evite raízes amplas que incluam arquivos não relacionados do aplicativo ou do armazenamento compartilhado.
  4. Antes de gerar o URI de conteúdo, verifique se o arquivo é resolvido dentro de uma das raízes configuradas.

A entrada XML exata não pode ser universal porque depende do local em que o aplicativo armazena o arquivo. As alterações de exposição de URI de arquivo do Android 7.0 recomendam a migração para o FileProvider em vez da continuidade da exposição de URIs de arquivo.

Resultado esperado: o FileProvider consegue resolver o arquivo pretendido, enquanto os locais não relacionados permanecem fora do escopo configurado do provedor.

Risco e reversão: o risco é médio porque uma raiz excessivamente ampla pode expor mais arquivos do que o pretendido. Restrinja o XML de caminhos se a análise ou os testes mostrarem uma cobertura excessiva; não amplie os caminhos apenas para contornar uma falha de raiz configurada.

Substitua file:// e conceda somente o acesso temporário necessário

Crie e anexe o URI de conteúdo do FileProvider

Quando esta correção se aplica: use-a depois de configurar a autoridade no manifesto e os caminhos restritos do provedor para um arquivo pertencente ao aplicativo.

Pré-requisitos: o arquivo deve estar dentro de uma raiz permitida do provedor, e a autoridade usada para gerar o URI deve corresponder à do manifesto.

  1. Crie o URI com o FileProvider em vez de usar Uri.fromFile() ou um valor file:// construído manualmente.
  2. Coloque o URI content:// resultante nos dados do Intent, em EXTRA_STREAM ou no campo de saída da câmera exigido pelo fluxo existente.
  3. Para vários arquivos, substitua todos os URIs expostos, e não apenas o primeiro item.
  4. Inspecione ClipData e qualquer outro campo que aceite URI para garantir que o URI de arquivo antigo não permaneça em outro local.

Resultado esperado: o Intent de saída transporta URIs content:// do FileProvider em vez de URIs file://.

Risco e reversão: o risco é baixo, e esta operação não exclui o arquivo. Não restaure o compartilhamento entre aplicativos por file:// em produção; a origem anterior do URI é adequada apenas para depuração local isolada que não exponha o URI.

Conceda permissões temporárias de URI

Quando esta correção se aplica: use concessões temporárias quando o aplicativo receptor precisar ler ou modificar o conteúdo referenciado pelo Intent.

Pré-requisitos: o Intent deve transportar um URI content:// válido, e o nível de acesso exigido pelo receptor deve ser conhecido.

  1. Adicione FLAG_GRANT_READ_URI_PERMISSION quando o receptor precisar ler o arquivo.
  2. Adicione FLAG_GRANT_WRITE_URI_PERMISSION somente quando o receptor precisar modificar o arquivo.
  3. Anexe o URI por meio de ClipData quando isso for necessário para propagar a permissão no fluxo compatível.
  4. Não adicione permissões mais amplas do sistema de arquivos nem acesso de gravação não relacionado à operação.

Resultado esperado: o receptor obtém o acesso temporário mínimo necessário enquanto o provedor permanece não exportado.

Risco e reversão: o risco é baixo quando o acesso é limitado. Remova os sinalizadores de concessão de leitura ou gravação quando o receptor não precisar mais dessa capacidade. A propagação por ClipData depende do fluxo e deve ser testada nas versões compatíveis do Android.

Verifique se o aplicativo receptor consegue acessar o URI de conteúdo

Quando isto se aplica: verifique o fluxo completo depois de substituir o URI e aplicar as concessões temporárias.

Pré-requisitos: o componente receptor pretendido deve estar disponível para testes.

  1. Confirme se todos os URIs de saída usam o esquema content.
  2. Confirme se a autoridade do URI gerado corresponde exatamente à autoridade do provedor declarada no manifesto.
  3. Confirme se o arquivo está dentro de uma raiz configurada do provedor.
  4. Verifique novamente os dados do Intent, EXTRA_STREAM, ClipData e os URIs de saída em busca de qualquer valor file:// restante.
  5. Teste o aplicativo receptor real com permissão de leitura e adicione permissão de gravação somente se for necessário modificar o arquivo.
  6. Confirme se o receptor consegue realizar a operação pretendida sem ampliar a raiz do provedor ou as permissões.

Resultado esperado: o fluxo de saída deixa de expor um URI de arquivo, e o componente receptor consegue acessar o URI de conteúdo autorizado com a concessão mínima necessária. Isso deve ser confirmado por testes; apenas alterar o esquema não garante o acesso do receptor.

Risco e aviso: a verificação apresenta baixo risco. Se a exceção original desaparecer, mas o acesso continuar falhando, verifique manualmente a autoridade, os metadados do provedor, os caminhos configurados, as concessões de URI e o local real do arquivo. Não desative a detecção com StrictMode.VmPolicy, não reduza o targetSdkVersion, não exponha raízes amplas e não conceda acesso de gravação por padrão. Essas ações ocultam ou enfraquecem o problema em vez de corrigir o projeto de compartilhamento entre aplicativos.