Escanear a partir de outro app
Os intents
| Ação | Filtro no manifesto | O que acontece | Resultado |
|---|---|---|---|
com.google.zxing.client.android.SCAN | Sim, intents implícitos funcionam. | Abre o leitor. O primeiro código que a pessoa fixa é devolvido, como o ZXing Barcode Scanner fazia. | RESULT_OK com SCAN_RESULT e SCAN_RESULT_FORMAT |
app.scanner.action.SCAN | Sim. | Abre o leitor. Iniciado para um resultado (um result launcher ou startActivityForResult), devolve o código do mesmo jeito; iniciado sem mais, só abre o app no leitor. | RESULT_OK com os dois extras quando iniciado para um resultado |
app.scanner.action.CARD | Sem filtro: apenas um intent explícito com o pacote com.verdettoqr.scanner. | Abre o editor do cartão de contato da própria pessoa, o código que ela mostra para compartilhar seus dados. Feito para os widgets e atalhos do próprio app; outro app pode chamá-lo, mas nada volta. | Nenhum |
android.intent.action.SEND com image/* | Sim. | Decodifica uma imagem: o app mostra a folha de resultado com os códigos que ela contém. | Nenhum |
A pessoa pode desligar a devolução em Configurações, em "Entregar resultados a outros apps" ("Quando um app pede um escaneamento, o código volta para ele"), que vem ligada. Desligada, qualquer das duas ações de leitura abre o leitor como uma abertura normal e seu launcher recebe RESULT_CANCELED quando a pessoa sai. Voltar do leitor também é RESULT_CANCELED.
Nenhum extra da requisição é lido hoje: nem SCAN_MODE, SCAN_FORMATS, PROMPT_MESSAGE, SAVE_HISTORY, nem qualquer outro. O leitor lê todas as simbologias que conhece em toda chamada. Um código que as verificações do app sinalizam ainda é devolvido; a pessoa vê o alerta primeiro e decide.
O resultado
SCAN_RESULT(String): o conteúdo do código, exatamente os bytes que ele carregava, decodificados como texto (UTF-8 onde a simbologia permite, e o conjunto de caracteres da própria simbologia nos outros casos).SCAN_RESULT_FORMAT(String): a simbologia em maiúsculas com sublinhados, com os nomes do ZXing onde existem. Entregues hoje:QR_CODE,MICRO_QR_CODE,RMQR_CODE,DATA_MATRIX,AZTEC,PDF417,MAXICODE,HAN_XIN,EAN_13,EAN_8,UPC_A,UPC_E,CODE_128,CODE_39,CODE_93,CODABAR,ITF,DATABAR,DATABAR_EXPANDED,DATABAR_LIMITED,DX_FILM_EDGE, e as outras simbologias que os decodificadores próprios do app acrescentam, na mesma grafia (o nome mostrado na folha de resultado, em maiúsculas, com espaços e hifens como sublinhados).
Nada mais viaja: nenhuma imagem, nenhuma localização, nenhum histórico.
Kotlin
private val scan = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val text = result.data?.getStringExtra("SCAN_RESULT")
val format = result.data?.getStringExtra("SCAN_RESULT_FORMAT")
// use text and format
}
}
fun startScan() {
val intent = Intent("app.scanner.action.SCAN")
if (intent.resolveActivity(packageManager) != null) scan.launch(intent)
else startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(GET_VERDETTO)))
}
// the store page, with the developers referrer
private const val GET_VERDETTO =
"https://play.google.com/store/apps/details?id=com.verdettoqr.scanner&referrer=utm_source%3Ddevelopers%26utm_medium%3Ddocs%26utm_campaign%3Ddevelopers"
No Android 11 e posteriores, adicione a consulta ao seu manifesto para que resolveActivity consiga ver o app:
<queries>
<intent>
<action android:name="app.scanner.action.SCAN" />
</intent>
</queries>
Java
private final ActivityResultLauncher<Intent> scan = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
String text = result.getData().getStringExtra("SCAN_RESULT");
String format = result.getData().getStringExtra("SCAN_RESULT_FORMAT");
// use text and format
}
});
void startScan() {
Intent intent = new Intent("app.scanner.action.SCAN");
if (intent.resolveActivity(getPackageManager()) != null) scan.launch(intent);
else startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(GET_VERDETTO)));
}
A ação do ZXing
Código escrito para o ZXing Barcode Scanner continua funcionando: envie com.google.zxing.client.android.SCAN do mesmo jeito e leia os mesmos dois extras. Se mais de um leitor no celular responder, o sistema pergunta à pessoa qual usar; enviar o intent para o pacote com.verdettoqr.scanner pula isso.
O que a pessoa vê
O leitor abre como sempre, com suas próprias verificações. Quando um código é fixado, o app o devolve e fecha; nada seu aparece na tela, e nada dela (histórico, configurações, lista de segurança) é tocado pela chamada.
Testar em um celular sem o app. A página da loja com o referrer de desenvolvedores, o mesmo endereço que o fallback dos exemplos abre: Disponível no Google Play. A fonte desta página é o INTENT.md do próprio app; quando os dois divergem, o repositório do app está certo e esta página está atrasada.