createchooser应用选择器
当我们通过隐式Intent调用Android组件时,系统会根据条件进行过滤,如果有多个组件满足条件,则会弹出选择框,提示用户用那种方式打开。
例如执行如下代码,会弹出选择框。
Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TITLE, "标题信息"); intent.putExtra(Intent.EXTRA_SUBJECT, "主题信息"); intent.putExtra(Intent.EXTRA_TEXT, "内容信息"); startActivity(intent); |
通常我们选择用某个打开方式,可以选择”始终”,也可以选择仅此一次。
当我们选择“始终”,以后该请求条件将始终用选择的方式打开。
我们可以通过设置->应用管理,选择某个应用,然后点击默认打开,点击清除默认设置,进行清除,如下图所示:
有的时候,我们不想让选择列表列出所有候选项,只想按照自己要求,列出某几项备选的打开方式,这就要借助createchooser方法了。如下面代码所示:
Intent it = new Intent(Intent.ACTION_SEND); it.setType("text/plain"); List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(it, 0); if (!resInfo.isEmpty()){ List<Intent> targetedShareIntents = new ArrayList<Intent>(); for (ResolveInfo info : resInfo) { ActivityInfo activityInfo = info.activityInfo; if (activityInfo.packageName.contains("email") || activityInfo.packageName.contains("bluetooth") || activityInfo.packageName.contains("mms") || activityInfo.packageName.contains("weibo")) { Intent targeted = new Intent(Intent.ACTION_SEND); targeted.setType("text/plain"); targeted.putExtra(Intent.EXTRA_TITLE, "title"); targeted.putExtra(Intent.EXTRA_SUBJECT, "subject"); targeted.putExtra(Intent.EXTRA_TEXT, "content"); targeted.setPackage(activityInfo.packageName); targetedShareIntents.add(targeted); } } Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(1), "选择分享APP"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[] {})); startActivity(chooserIntent); } |
运行结果如下所图所示:
下面我解释一下代码
首先我们通过getPackageManager()获取包管理器PackageManager对象。PackageManger的主要职责是管理应用程序包。 通过PackageManager,我们就可以获取应用程序信息,PackageManager获取的信息即来自AndroidManifest.XML。
PageManager对象有个方法,用来根据Intent查询可用的activity信息,方法的签名如下所示:
该方法返回ResolveInfo集合,ResolveInfo这个类是通过解析一个与IntentFilter相对应的intent得到的信息。它部分地对应于从AndroidManifest.xml的<intent>标签收集到的信息。
接着我们判断返回的ResolveInfo对象集合是否为空,如果不为空,则开始循环处理,针对每个ResolveInfo对象,通过activityInfo获取ActivityInfo对象,根据ActivityInfo的packageName获取所属的包名称,并判断名称是否包含email、bluetooth、mms、weibo,如果包含,则添加到备选集合中。
然后调用ceateChooser创建一个ACTION_CHOOSER Intent,关于createChooser的介绍如下所示:
注意我们用第一个备选Intent作为target Intent,然后通过putExtra设置Intent.EXTRA_INITIAL_INTENTS为其他备选Intent,关于EXTRA_INITIAL_INTENTS的描述如下所示:
这里要说明的是,Parcelable是Android为我们提供的序列化的接口,Parcelable相对于Serializable的使用相对复杂一些,但Parcelable的效率相对Serializable也高很多。
这样就会按照我们的要求列出备选的打开方式。
使用createChooser还有一个好处就在于及时我们已经选择始终用某个方式打开,仍然可以弹出选择框进行选择。
此外,我们也可以直接设置Action为Intent.ACTION_CHOOSER,弹出选择框,如下代码所示
Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.setType("text/plain"); Intent intent2 = new Intent(); intent2.setAction(Intent.ACTION_CHOOSER); intent2.putExtra(Intent.EXTRA_TITLE, "please selete a app"); intent2.putExtra(Intent.EXTRA_INTENT, intent); startActivity(intent2); |
这时会列出所有的打开方式,效果如下图所示:
(张伟:2018年10月16日)
(转载时请注明来源)