java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent significa que um app Android destinado à API 31 ou superior criou uma PendingIntent sem declarar sua mutabilidade. Isso ocorre em tempo de execução, quando a PendingIntent é criada. A primeira medida mais segura é examinar a pilha de chamadas e identificar a chamada de fábrica exata antes de alterar qualquer flag. Se a chamada pertencer ao código do app e não exigir comportamento de preenchimento, preserve as flags existentes e adicione FLAG_IMMUTABLE.

O que significa o erro de PendingIntent “Targeting S+”

O requisito de mutabilidade de PendingIntent do Android se aplica quando um app destinado ao Android 12/API 31 ou superior chama PendingIntent.getActivity(), getActivities(), getBroadcast(), getService() ou getForegroundService() sem informar uma das duas flags explícitas de mutabilidade.

FLAG_IMMUTABLE e FLAG_MUTABLE são alternativas; não combine as duas. O Android recomenda PendingIntents imutáveis na maioria dos casos. A mutabilidade só é apropriada quando um destinatário ou uma API do Android precisa modificar campos não preenchidos da Intent encapsulada. A referência da API PendingIntent também diferencia essas declarações de mutabilidade das flags de comportamento, como FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT e FLAG_ONE_SHOT.

Essa exceção de tempo de execução não é o requisito separado de android:exported no Android 12, que diz respeito às declarações de componentes no manifesto.

Encontre a chamada de PendingIntent que realmente gera a exceção

A mensagem da exceção identifica a declaração ausente, mas não informa se a chamada pertence ao código do aplicativo, a código gerado ou a uma biblioteca incluída no pacote.

  1. Comece pela java.lang.IllegalArgumentException na pilha de chamadas completa.
  2. Localize o primeiro quadro relevante que não pertença ao framework e esteja associado a um dos métodos de fábrica de PendingIntent.
  3. Associe esse quadro ao respectivo pacote, módulo, componente gerado ou dependência incluída.
  4. Registre o método de fábrica, o código da solicitação, a Intent encapsulada e a expressão completa das flags.
  5. Antes de escolher uma correção, classifique a chamada como pertencente ao aplicativo, a código gerado ou a uma dependência.

Não edite uma PendingIntent sem relação com a falha apenas porque ela aparece no código do app. Se o quadro relevante pertencer a uma dependência, alterar uma flag em outro trecho do aplicativo pode deixar a implementação com falha inalterada.

Corrija o código do app usando FLAG_IMMUTABLE por padrão

Quando se aplica: use este caminho quando a chamada de fábrica pertencer ao código do app e nenhum remetente, destinatário ou API do Android precisar modificar campos não preenchidos da Intent encapsulada.

Pré-requisitos: identifique a chamada exata e mantenha o código da solicitação, a Intent, o método de fábrica e as flags de comportamento existentes. A inclusão de FLAG_IMMUTABLE não pode remover FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT, FLAG_ONE_SHOT nem qualquer outra flag existente que seja necessária.

  1. Mantenha o código da solicitação e a Intent atuais sem alterações.
  2. Combine FLAG_IMMUTABLE com as flags existentes usando or no Kotlin ou | no Java.
  3. Crie a PendingIntent com a expressão combinada.
  4. Reproduza o recurso que envia a PendingIntent.

Exemplo em Kotlin

Antes:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)

Depois:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags or PendingIntent.FLAG_IMMUTABLE)

Exemplo em Java

Antes:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)

Depois:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags | PendingIntent.FLAG_IMMUTABLE)

Resultado esperado: a chamada de fábrica passa a fornecer a declaração de mutabilidade obrigatória. A ação de notificação, abertura de atividade, alarme, widget, callback ou inicialização de serviço afetada ainda deve ser testada para confirmar que o comportamento foi preservado. Uma PendingIntent imutável ainda pode ser atualizada por quem a criou usando FLAG_UPDATE_CURRENT.

Risco e reversão: essa é uma alteração de código de baixo risco, sem risco documentado de perda de dados. Se os testes demonstrarem que o destinatário ou a API da plataforma exige comportamento de preenchimento, reverta apenas a declaração de imutabilidade adicionada e avalie o caminho mutável restrito descrito abaixo.

Use FLAG_MUTABLE somente quando o recurso exigir preenchimento

Quando se aplica: use FLAG_MUTABLE somente quando uma funcionalidade documentada precisar modificar a Intent encapsulada, incluindo respostas diretas, bolhas, callbacks de localização, extras de contagem de alarmes repetidos ou outra operação obrigatória de preenchimento.

Requisito Declaração
Nenhuma modificação pelo destinatário ou pela plataforma é necessária FLAG_IMMUTABLE
Um recurso documentado precisa fornecer dados de preenchimento FLAG_MUTABLE

Pré-requisitos: confirme a necessidade de modificação para o recurso afetado. Preserve todas as flags de comportamento necessárias e, quando possível, use uma Intent base explícita com ação, pacote e componente definidos.

  1. Mantenha o código da solicitação, o tipo de fábrica e as flags de comportamento necessárias.
  2. Adicione FLAG_MUTABLE no lugar de FLAG_IMMUTABLE.
  3. Quando possível, torne a Intent base explícita.
  4. Teste novamente a operação exata que precisa do comportamento de preenchimento.
  5. Confirme que somente os campos documentados precisam permanecer preenchíveis.

Exemplo em Kotlin

PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags or PendingIntent.FLAG_MUTABLE)

Exemplo em Java

PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags | PendingIntent.FLAG_MUTABLE)

Resultado esperado: a chamada de fábrica declara a mutabilidade, preserva as flags de comportamento existentes e mantém disponível a operação documentada de preenchimento pelo destinatário ou pela plataforma.

Risco e reversão: essa é uma decisão de segurança de risco médio, embora não haja risco documentado de perda de dados. Uma PendingIntent mutável delega o controle sobre campos não preenchidos da Intent; portanto, aplicá-la de forma ampla pode aumentar a exposição. Siga as orientações oficiais de segurança para PendingIntent, prefira uma Intent base explícita e substitua FLAG_MUTABLE por FLAG_IMMUTABLE se a necessidade de preenchimento for removida. O mesmo princípio de privilégio mínimo se aplica ao revisar o compartilhamento seguro de URIs entre apps no Android.

Trate uma PendingIntent criada por uma dependência

Se o primeiro quadro relevante da pilha de chamadas pertencer a código gerado ou a um SDK incluído no pacote, alterar uma PendingIntent sem relação com a falha e pertencente ao aplicativo não é uma correção confirmada. A correção de dependências varia conforme o projeto e deve ser verificada na documentação primária do artefato responsável.

  1. Use o pacote ou módulo identificado na pilha de chamadas para localizar o artefato exato incluído no pacote.
  2. Consulte a documentação primária de versões desse artefato e procure uma versão mantida que trate explicitamente da compatibilidade de PendingIntent com o Android 12.
  3. Se essa versão estiver documentada, faça a atualização somente pelo processo de dependências já adotado pelo projeto.
  4. Examine o grafo de dependências resolvidas para confirmar que o artefato pretendido foi selecionado, e não uma versão transitiva mais antiga.
  5. Recompile o app e reproduza o mesmo recurso.
  6. Confirme que a implementação corrigida foi incluída no pacote e que a chamada original sem declaração de mutabilidade não aparece mais.

Resultado esperado: se a versão verificada da dependência contiver a correção e o app recompilado resolver essa versão, a chamada de fábrica pertencente à dependência deverá fornecer uma declaração explícita de mutabilidade. Esse resultado não pode ser presumido apenas com base na versão solicitada.

Risco e reversão: alterações em dependências podem afetar comportamentos fora do recurso com falha. Analise as informações da versão da dependência e restaure o estado anterior das dependências do projeto se a atualização introduzir uma regressão. Não existe uma dependência ou versão corrigida universal estabelecida para essa exceção.

Use PendingIntentCompat quando o tratamento de compatibilidade for adequado

Quando se aplica: use PendingIntentCompat do AndroidX quando o código do app oferecer suporte a versões da plataforma nas quais o auxiliar de compatibilidade for preferível e o chamador ainda puder declarar se a PendingIntent é mutável.

Pré-requisitos: confirme que a versão do AndroidX Core usada pelo projeto contém PendingIntentCompat, identifique o tipo de fábrica original e decida a mutabilidade conforme as necessidades reais do recurso.

  1. Escolha o método auxiliar correspondente à operação original: getActivity, getBroadcast, getService ou getForegroundService.
  2. Forneça ao método auxiliar as flags de comportamento existentes que não sejam de mutabilidade.
  3. Defina isMutable como falso, a menos que exista uma necessidade de modificação verificada.
  4. Mantenha inalterados o código da solicitação e o comportamento da Intent encapsulada.
  5. Teste na configuração afetada destinada ao Android 12 ou superior.

Resultado esperado: o auxiliar de compatibilidade combina a decisão explícita de mutabilidade do chamador com as flags existentes, conforme exigido nas versões compatíveis da plataforma.

Risco e reversão: esse é um caminho de compatibilidade de baixo risco, sem risco documentado de perda de dados, mas a troca de APIs auxiliares pode afetar a estrutura da chamada. Se a alteração causar uma regressão, volte ao método de fábrica equivalente do framework, mantendo uma flag explícita de mutabilidade.

Verifique a correção sem alterar o comportamento da PendingIntent

  1. Execute o app recompilado com um SDK de destino de API 31 ou superior e reproduza o acionador original.
  2. Confirme que a exceção exata Targeting S+ não ocorre mais na chamada de fábrica identificada.
  3. Teste novamente o toque ou a ação de notificação, o alarme, o widget, o callback, a abertura de atividade ou a inicialização de serviço afetada.
  4. Se FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT ou FLAG_ONE_SHOT estava presente, verifique o comportamento original de atualização, cancelamento ou uso único.
  5. Para uma PendingIntent mutável, verifique somente o comportamento de preenchimento necessário e confirme que a Intent base seja explícita quando possível.
  6. Para uma correção de dependência, confirme que o artefato resolvido e incluído no pacote seja a versão verificada, em vez de confiar apenas na declaração da dependência solicitada.

Uma compilação bem-sucedida, por si só, não comprova que o caminho de execução foi corrigido. Também mantenha separadas as restrições do Android 14/API 34 para PendingIntents implícitas e mutáveis: elas produzem uma condição de erro diferente e não são resolvidas por este procedimento referente à API 31.