Come verificare se un intento può essere gestito da un'attività?


115

Finora ho questo metodo, ma mi è sembrato che mancasse qualcosa

ad esempio ho un file /sdcard/sound.3ga che restituisce false (come se non ci fossero attività in grado di gestire questo tipo di file), ma quando lo apro dal file manager si apre con il lettore multimediale senza problemi

Penso che questo intento non sia completo e devo fare qualcosa di più per assicurarmi che la variabile handlerExists sia falsa SOLO se non ci sono attività in grado di gestire questo intento

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;

Risposte:


149

La soluzione di edwardxu funziona perfettamente per me.

Giusto per chiarire un po ':

PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
    Log.d(TAG, "No Intent available to handle action");
}

1
beh, con Android api 30+, non funziona sempre ora)
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
}

Hai provato questo intento?

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(yourFileHere));

È perché hai dimenticato: intent.setType ("text / plain");
Felipe

1
Qual è il flag 0 qui?
RyPope

@RyPope significa <niente bandiere>
Mohammad Ersan

Se stiamo usando setPackage()l'intento, questo fallirà. Quindi, dovremmo andare perIntent.resolveActivity()
CopsOnRoad

resolActivity () spesso restituisce un intento anche se non c'è nulla che possa effettivamente gestirlo, quindi non funziona per questo. Questo funziona per me.
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. 
}

Nota che questo non sempre funziona: resolActivity può restituire un intento che non può essere gestito. L'approccio queryIntentActivities funziona meglio per me.
Glenn Maynard

beh, con Android api 30+, non funziona sempre ora)
user924

2

Puoi usare:

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;
}

Questo non funziona quando si utilizza setPackage()sull'intento.
CopsOnRoad

1

Usare Kotlin Se devi fare qualcosa quando l'intento non è disponibile,

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()
            }

Implementa questo metodo come

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



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

Se non hai niente da fare,

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

0

Un altro approccio che utilizza l'estensione kotlin

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

Utilizzo all'interno del frammento

val available = requireContext().isIntentAvailable(this)

Utilizzo all'interno dell'attività

val available = this.isIntentAvailable(this)

dovresti usare PackageManagerper divertimento la tua estensione invece di Contexted evitarePackageManager.MATCH_DEFAULT_ONLY
user924

this.isIntentAvailable(this)è inutilmente prolisso. Basta usareisIntentAvailable()
Zun
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.