Como verificar se uma intent pode ser tratada a partir de alguma atividade?

115

Eu tenho esse método até agora, mas surgiu como se algo estivesse faltando

por exemplo, eu tenho um arquivo /sdcard/sound.3ga que retorna falso (como se não houvesse nenhuma atividade que pudesse lidar com este tipo de arquivo), mas quando eu o abro no gerenciador de arquivos ele abre com o reprodutor de mídia sem problemas

Acho que esse intent não está completo e preciso fazer algo mais para ter certeza de que a variável handlerExists será falsa SOMENTE se não houver atividade que possa lidar com esse intent

PackageManager pm = getPackageManager();
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uriString)).toString());
String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
intent.setDataAndType(Uri.fromFile(new File(uriString)),mimetype);
boolean handlerExists = intent.resolveActivity(pm) != null;
Lukap
fonte

Respostas:

149

A solução de edwardxu funciona perfeitamente para mim.

Só para esclarecer um pouco:

PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
    Log.d(TAG, "No Intent available to handle action");
}
Sparky1
fonte
1
bem, com android api 30+, nem sempre funciona agora)
user924
86
PackageManager manager = context.getPackageManager();
List<ResolveInfo> infos = manager.queryIntentActivities(intent, 0);
if (infos.size() > 0) {
    //Then there is an Application(s) can handle your intent
} else {
    //No Application can handle your intent
}

Você já tentou esta intenção?

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(yourFileHere));
Mohammad Ersan
fonte
É porque você esqueceu: intent.setType ("text / plain");
Felipe
1
Qual é a bandeira 0 aqui?
RyPope
@RyPope significa <sem sinalizadores>
Mohammad Ersan
Se estivermos usando setPackage()a intenção, isso falhará. Então, devemos ir paraIntent.resolveActivity()
CopsOnRoad
resolveActivity () geralmente retorna um intent, mesmo se não houver nada que possa realmente manipulá-lo, portanto, não funciona para isso. Isso funciona para mim.
Glenn Maynard
51
if (intent.resolveActivity(getPackageManager()) == null) {
    // No Activity found that can handle this intent. 
}
else{
    // There is an activity which can handle this intent. 
}
Edwardaa
fonte
Observe que isso nem sempre funciona: resolveActivity pode retornar um intent que não pode ser manipulado. A abordagem queryIntentActivities funciona melhor para mim.
Glenn Maynard
bem, com android api 30+, nem sempre funciona agora)
user924
2

Você pode usar:

public static boolean isAvailable(Context ctx, Intent intent) {
   final PackageManager mgr = ctx.getPackageManager();
   List<ResolveInfo> list =
      mgr.queryIntentActivities(intent, 
         PackageManager.MATCH_DEFAULT_ONLY);
   return list.size() > 0;
}
CONvid19
fonte
Isso não funciona ao usar setPackage()no intent.
CopsOnRoad
1

Usando Kotlin Se você precisar fazer algo quando o intent não estiver disponível,

fun isIntentAvailable(
                context: Context,
                action: String?
            ): Boolean {
                val packageManager = context.packageManager
                val intent = Intent(action)
                val resolveInfo: List<*> = packageManager.queryIntentActivities(
                    intent,
                    PackageManager.MATCH_DEFAULT_ONLY
                )
                return resolveInfo.isNotEmpty()
            }

Implemente este método como

private const val SAMPLE_INTENT = "com.realwear.barcodereader.intent.action.SCAN_BARCODE"



 if(isIntentAvailable(this,SAMPLE_INTENT)){
  //Do Stuff
 }

Se você não tem nada para fazer,

Intent(SAMPLE_INTENT).also { barcodeReaderIntent ->
            barcodeReaderIntent.resolveActivity(packageManager)?.also {
                barcodeReaderIntent.putExtra(EXTRA_CODE_128, false)
                startActivityForResult(barcodeReaderIntent, BARCODE_REQUEST_CODE)
            }
    }
Varun Chandran
fonte
0

Outra abordagem usando a extensão kotlin

 fun Context.isIntentAvailable(intent: Intent): Boolean {
    val resolveInfo: List<*> = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
    return resolveInfo.isNotEmpty()
 }

Uso dentro do fragmento

val available = requireContext().isIntentAvailable(this)

Uso dentro da atividade

val available = this.isIntentAvailable(this)
Oscar Emilio Perez Martinez
fonte
você deve usar PackageManagerpara sua diversão de extensão em vez de ContextevitarPackageManager.MATCH_DEFAULT_ONLY
user924
this.isIntentAvailable(this)é desnecessariamente prolixo. Basta usarisIntentAvailable()
Zun