到目前为止我已经有了这个方法,但它似乎缺少了一些东西
例如,我有一个文件 /sdcard/sound.3ga 返回 false(就像没有活动可以处理此类文件一样),但是当我从文件管理器打开它时,它会使用媒体播放器打开,没有问题
我认为这个意图并不完整,我需要做更多的事情来确保仅当没有可以处理此意图的活动时,handlerExists 变量才会为 false
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;
edwardxu 的解决方案非常适合我。
澄清一下:
PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent);
} else {
Log.d(TAG, "No Intent available to handle action");
}
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));
if (intent.resolveActivity(getPackageManager()) == null) {
// No Activity found that can handle this intent.
}
else{
// There is an activity which can handle this intent.
}
解决此问题的明确答案
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
您可以使用:
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;
}
这是另一个 Kotlin 解决方案。即使对于 Android 30+ 也能完美运行。 首先将其包含在您的应用程序清单中:
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="choose-scheme-goes-here" />
</intent>
</queries>
然后你可以检查是否可以使用此函数处理意图:
private fun isIntentAvailable(intent: Intent): Boolean {
val manager = requireContext().packageManager
val info = manager.queryIntentActivities(intent, 0)
return info.size > 0
}
使用 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)
}
}
对于 2021 年寻找类似内容的人来说,这是一个小更新:) 自 Android 11 以来,不需要调用包管理器,因此需要额外的努力。 那么为什么不将 startActivity() 包装在 try-catch 中呢?或者甚至更好 - 使用 Rx 漂亮的错误处理:
....
.flatMapCompletable {
doSomethingThrowable()
.onErrorResumeNext { completableCallbackIfNotResolvable() }
}
.subscribe()
使用 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)