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


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.