119

I have this method so far , but it came up like something is missing

for example I have a file /sdcard/sound.3ga that returns false ( like there is no activity that can handle this type of file ) , But when I open it from the file manager it opens with the media player with no problem

I think this intent is not complete and I need to to something more to make my self sure that the handlerExists variable will be false ONLY if there is no activity that can handle this intent

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;
Ziem
  • 6,059
  • 7
  • 49
  • 83
Lukap
  • 29,596
  • 60
  • 146
  • 239

8 Answers8

152

edwardxu's solution works perfectly for me.

Just to clarify a bit:

PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
    Log.d(TAG, "No Intent available to handle action");
}
Ziem
  • 6,059
  • 7
  • 49
  • 83
Sparky1
  • 2,945
  • 6
  • 22
  • 27
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
}

Have you tried this intent?

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(yourFileHere));
Mohammad Ersan
  • 11,926
  • 8
  • 48
  • 72
54
if (intent.resolveActivity(getPackageManager()) == null) {
    // No Activity found that can handle this intent. 
}
else{
    // There is an activity which can handle this intent. 
}
CopsOnRoad
  • 109,635
  • 30
  • 367
  • 257
xuxu
  • 5,666
  • 1
  • 14
  • 11
2

You can use:

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;
}
Pedro Lobito
  • 75,541
  • 25
  • 200
  • 222
1

Using Kotlin If you need to do something when intent is not available,

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

Implement this method as

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

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

If you don't have anything to do,

Intent(SAMPLE_INTENT).also { barcodeReaderIntent ->
    barcodeReaderIntent.resolveActivity(packageManager)?.also {
        barcodeReaderIntent.putExtra(EXTRA_CODE_128, false)
        startActivityForResult(barcodeReaderIntent, BARCODE_REQUEST_CODE)
    }
}
Community
  • 1
  • 1
Varun Chandran
  • 539
  • 9
  • 19
  • What do you mean by “If you don’t have anything to do” and the code below it. The code below it sounds like it’s for if the intent is available, but maybe i am wrong. – Sakiboy Nov 26 '20 at 23:04
1

The Clear Answer to solve this problem

if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}
0

Another approach using kotlin extension

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

Usage inside fragment

val available = requireContext().isIntentAvailable(this)

Usage inside activity

val available = this.isIntentAvailable(this)
  • 1
    you should use `PackageManager` for your extension fun instead of `Context` and avoid `PackageManager.MATCH_DEFAULT_ONLY` – user924 Jun 24 '20 at 14:34
  • `this.isIntentAvailable(this)` is unnecessarily verbose. Just use `isIntentAvailable()` – Zun Jul 10 '20 at 14:18
0

Small update for one looking for something similar in 2021 :) Since Android 11 it is not desired to call the package manager, so extra efforts are needed. So why don't you just wrap startActivity() in try-catch? Or even better - use Rx beautiful error handing:

....
.flatMapCompletable { 
      doSomethingThrowable()
          .onErrorResumeNext { completableCallbackIfNotResolvable() }
}
.subscribe()
Vadim
  • 111
  • 4