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


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;

Ответы:


150

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

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

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

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

Обратите внимание, что это не всегда работает: 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;
}

Это не работает при использовании 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()
— Зун
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.