Como iniciarActivityForResult no Android 11?

Oct 15 2020

Estou carregando imagens em meu aplicativo startActivityForResult()fazendo algo assim:

val intentForLoadingImage = Intent(Intent.ACTION_GET_CONTENT)
intentForLoadingImage.type = "image/*"
if (intentForLoadingImage.resolveActivity(packageManager) != null) {
    startActivityForResult(intentForLoadingImage, IMAGE_REQUEST_CODE)
}

Eu substituí onActivityResult()minha lógica para carregar a imagem em um ImageView. Funciona em todas as versões do Android (a minSdkVersion do meu aplicativo é 21), mas não faz absolutamente nada no Android 11. Porque intentForLoadingImage.resolveActivity(packageManager)retorna null e a atividade de carregamento de imagens não começa.

Respostas

1 ianhanniballake Oct 15 2020 at 05:46

De acordo com a ACTION_GET_CONTENTdocumentação , a string real é android.intent.action.GET_CONTENTe não android.media.action.GET_CONTENT aquela que você tem em seu código. Portanto, a consulta correta de visibilidade do pacote é

<queries>
    <intent>
        <action android:name="android.intent.action.GET_CONTENT" />
        <data android:mimeType="image/*"/>
    </intent>
</queries>

Como alternativa, você também pode detectar o ActivityNotFoundExceptionque ocorre no raro caso em que o Storage Access Framework (que é o que controla ACTION_GET_CONTENT) foi desativado como parte de uma ROM personalizada. Esta abordagem não requer tags de visibilidade do pacote:

val intentForLoadingImage = Intent(Intent.ACTION_GET_CONTENT)
intentForLoadingImage.type = "image/*"
try {
    startActivityForResult(intentForLoadingImage, IMAGE_REQUEST_CODE)
} catch (e: ActivityNotFoundException) {
}
1 AbhishekChoudhary Oct 18 2020 at 07:13

Aprendi sobre atualizações de privacidade de visibilidade de pacote no Android 11 . Que diz,

O Android 11 muda a forma como os aplicativos podem consultar e interagir com outros aplicativos que o usuário instalou em um dispositivo. Usando o elemento, os aplicativos podem definir o conjunto de outros pacotes que eles podem acessar. Este elemento ajuda a encorajar o princípio do menor privilégio, informando ao sistema quais outros pacotes tornar visíveis para seu aplicativo, e ajuda as lojas de aplicativos como o Google Play a avaliar a privacidade e segurança que seu aplicativo oferece aos usuários.

Se o seu aplicativo for direcionado ao Android 11 ou superior, pode ser necessário adicionar o elemento ao arquivo de manifesto do seu aplicativo. Dentro do elemento, você pode especificar pacotes por nome, por assinatura de intenção ou por autoridade do provedor.

Então, adicionei as seguintes tags em meu arquivo de manifesto:

<queries>
    <intent>
        <action android:name="android.intent.action.GET_CONTENT" />
        <data android:mimeType="image/*"/>
    </intent>
</queries>

E é isso!