Как проверить, можно ли обработать намерение с помощью некоторой активности?

116

У меня пока есть этот метод, но похоже, что чего-то не хватает

например, у меня есть файл /sdcard/sound.3ga, который возвращает false (например, нет активности, которая может обрабатывать этот тип файла), но когда я открываю его из файлового менеджера, он открывается с медиаплеером без проблем

Я думаю, что это намерение не завершено, и мне нужно кое-что еще, чтобы убедиться, что переменная handlerExists будет ложной ТОЛЬКО в том случае, если нет активности, которая может обработать это намерение

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
источник

Ответы:

150

Решение edwardxu отлично работает для меня.

Просто чтобы немного уточнить:

PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
    Log.d(TAG, "No Intent available to handle action");
}
Sparky1
источник
1
ну с android api 30+ сейчас не всегда работает)
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
}

Вы пробовали это намерение?

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(yourFileHere));
Мохаммад Эрсан
источник
Это потому, что вы забыли: intent.setType ("text / plain");
Фелипе
1
Что здесь за флаг 0?
RyPope
@RyPope это означает <без флагов>
Мохаммад Эрсан
Если мы используем setPackage()намеренно, это не удастся. Итак, мы должны пойти наIntent.resolveActivity()
CopsOnRoad
resolveActivity () часто возвращает намерение, даже если на самом деле нет ничего, что могло бы его обработать, поэтому он не работает для этого. Это работает для меня.
Гленн Мейнард
52
if (intent.resolveActivity(getPackageManager()) == null) {
    // No Activity found that can handle this intent. 
}
else{
    // There is an activity which can handle this intent. 
}
edwardaa
источник
Обратите внимание, что это не всегда работает: resolveActivity может возвращать намерение, которое невозможно обработать. Мне больше подходит подход queryIntentActivities.
Glenn Maynard
ну с android api 30+ сейчас не всегда работает)
user924
2

Ты можешь использовать:

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
источник
Это не работает при использовании setPackage()по назначению.
CopsOnRoad
1

Использование Kotlin Если вам нужно что-то сделать, когда намерение недоступно,

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

Реализуйте этот метод как

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



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

Если тебе нечего делать,

Intent(SAMPLE_INTENT).also { barcodeReaderIntent ->
            barcodeReaderIntent.resolveActivity(packageManager)?.also {
                barcodeReaderIntent.putExtra(EXTRA_CODE_128, false)
                startActivityForResult(barcodeReaderIntent, BARCODE_REQUEST_CODE)
            }
    }
Варун Чандран
источник
0

Другой подход с использованием расширения kotlin

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

Использование внутри фрагмента

val available = requireContext().isIntentAvailable(this)

Использование внутри деятельности

val available = this.isIntentAvailable(this)
Оскар Эмилио Перес Мартинес
источник
вы должны использовать его PackageManagerдля развлечения, а не Contextи избегатьPackageManager.MATCH_DEFAULT_ONLY
user924,
this.isIntentAvailable(this)излишне многословен. Просто используйтеisIntentAvailable()
Зун