Jak sprawdzić, czy zamiar można obsłużyć z jakiejś czynności?


115

Na razie mam tę metodę, ale wyszło, że czegoś brakuje

na przykład mam plik /sdcard/sound.3ga, który zwraca false (jak nie ma aktywności, która mogłaby obsłużyć ten typ pliku), ale kiedy otwieram go z menedżera plików, otwiera się z odtwarzaczem multimedialnym bez problemu

Myślę, że ten zamiar nie jest kompletny i muszę zrobić coś więcej, aby upewnić się, że zmienna handlerExists będzie fałszywa TYLKO jeśli nie ma działania, które mogłoby obsłużyć ten zamiar

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;

Odpowiedzi:


149

Rozwiązanie edwardxu działa idealnie dla mnie.

Żeby trochę wyjaśnić:

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

1
cóż, z Androidem API 30+ to nie zawsze działa teraz)
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
}

Czy próbowałeś tego zamiaru?

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

To dlatego, że zapomniałeś: intent.setType ("text / plain");
Felipe

1
Jaka jest tutaj flaga 0?
RyPope,

@RyPope to znaczy <bez flag>
Mohammad Ersan

Jeśli używamy setPackage()intencji, to się nie powiedzie. Tak więc powinniśmy iśćIntent.resolveActivity()
CopsOnRoad

olveActivity () często zwraca intencję, nawet jeśli nie ma nic, co mogłoby ją obsłużyć, więc nie działa w tym przypadku. To działa dla mnie.
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. 
}

Zwróć uwagę, że to nie zawsze działa: solutionActivity może zwrócić intencję, której nie można obsłużyć. Podejście queryIntentActivities działa lepiej dla mnie.
Glenn Maynard

cóż, z Androidem API 30+ to nie zawsze działa teraz)
user924

2

Możesz użyć:

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

To nie działa, gdy używasz setPackage()intencji.
CopsOnRoad

1

Korzystanie z Kotlina Jeśli musisz coś zrobić, gdy zamiar nie jest dostępny,

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

Zaimplementuj tę metodę jako

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



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

Jeśli nie masz nic do roboty,

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

0

Inne podejście wykorzystujące rozszerzenie kotlin

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

Wykorzystanie wewnątrz fragmentu

val available = requireContext().isIntentAvailable(this)

Wykorzystanie w działalności

val available = this.isIntentAvailable(this)

powinieneś używać PackageManagerdo zabawy z rozszerzeniem zamiast Contexti unikaćPackageManager.MATCH_DEFAULT_ONLY
user924

this.isIntentAvailable(this)jest niepotrzebnie gadatliwy. Po prostu użyjisIntentAvailable()
Zun
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.