¿Cómo comprobar si se puede manejar una intención a partir de alguna actividad?

115

Tengo este método hasta ahora, pero me pareció que faltaba algo

por ejemplo, tengo un archivo /sdcard/sound.3ga que devuelve falso (como si no hubiera actividad que pueda manejar este tipo de archivo), pero cuando lo abro desde el administrador de archivos se abre con el reproductor multimedia sin problema

Creo que esta intención no está completa y necesito algo más para asegurarme de que la variable handlerExists será falsa SOLO si no hay actividad que pueda manejar esta intención

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
fuente

Respuestas:

149

La solución de edwardxu funciona perfectamente para mí.

Solo para aclarar un poco:

PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
    Log.d(TAG, "No Intent available to handle action");
}
Sparky1
fuente
1
bueno, con Android api 30+, no siempre funciona ahora)
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
}

¿Has probado esta intención?

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(yourFileHere));
Mohammad Ersan
fuente
Es porque olvidó: intent.setType ("text / plain");
Felipe
1
¿Qué es la bandera 0 aquí?
RyPope
@RyPope significa <sin banderas>
Mohammad Ersan
Si usamos setPackage()en la intención, esto fallará. Entonces, deberíamos ir porIntent.resolveActivity()
CopsOnRoad
resolveActivity () a menudo devuelve un intent incluso si no hay nada que pueda manejarlo, por lo que no funciona para esto. Esto funciona para mí.
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
fuente
Tenga en cuenta que esto no siempre funciona: resolveActivity puede devolver una intención que no se puede manejar. El enfoque queryIntentActivities funciona mejor para mí.
Glenn Maynard
bueno, con Android api 30+, no siempre funciona ahora)
user924
2

Puedes 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
fuente
Esto no funciona cuando se usa setPackage()en la intención.
CopsOnRoad
1

Uso de Kotlin Si necesita hacer algo cuando la intención no está disponible,

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
 }

Si no tienes nada que hacer,

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

Otro enfoque usando la extensión de kotlin

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

Uso dentro del fragmento

val available = requireContext().isIntentAvailable(this)

Uso dentro de la actividad

val available = this.isIntentAvailable(this)
Oscar Emilio Pérez Martínez
fuente
debe usar PackageManagerpara su extensión diversión en lugar de Contexty evitarPackageManager.MATCH_DEFAULT_ONLY
user924
this.isIntentAvailable(this)es innecesariamente detallado. Solo useisIntentAvailable()
Zun