Android Intent详解

一、简介

  在Android OS中,隐式Intent可以启动其它应用Activity。在显示Intent中,指定要启动的Activity类,OS会负责启动它。在隐式Intent中,描述清楚要完成的任务,OS会找到合适的应用,并在其中启动相应的Activity。

二、典型隐式Intent的组成

  • 一个隐式Intent的主要组成部分:

    1. 要执行的操作

    通常以Intent类中的常量表示。例如,要访问查看某个URL,可以使用Intent.ACTION_VIEW;要发送邮件,可以使用Intent.ACTION_SEND。

    2. 要访问数据的位置

    可能是设备以外资源,如某个网页UIL,也可以是指向某个文件的URI,或者是指向ContentProvider中某条记录的某个内容URI(Content URI)。

    3. 操作涉及的数据类型

    指的是MIME形式的数据数据,如text/htme或audio/mpeg3。如果一个Intent包含某类数据的位置,那么通常可以从中推测出数据类型。

    4. 可选类别

    如果操作用于描述具体要做什么,那么类别通常用来描述我们何时、何地或者说如何使用某个Activity的。Android的android.intent.category.LAUNCHER类别表明,activity应该显示在顶级应用启动器中。而android.intent.category.INFO类别表明,虽然Activity向用户显示包信息,但它不应该显示在启动器中。

PS:一个Intent由四方面组成,分别为:动作(action)、 操作类别(category)、数据、数据类型。

  动作(action):通过Intent类,指定activity做什么操作,比如:发送邮件。

  类别(category):动作的描述,选择用哪些activity来完成任务。

  数据:Intent传递的数据。

  数据类型(MIME):传递数据的格式。

示例:

  一个用来查看某个网址的简单隐式Intent会包括一个Intent.ACTION_VIEW操作,以及某个具体URL网址的URI数据。

  基于以上信息,操作系统将启动适用应用的适用Activity(如果有多个适用应用可选,用户可自行如何选择)。

  通过配置文件中的Intent过滤器设置,activity会对外宣称自己是适合处理ACTION_VIEW的Activity。如果是开发一款浏览器应用,为响应ACTION_VIEW操作,需要在Activity声明中包含以下过滤器:

1 <activity
2     android:name=".BrowserActivity"
3     android:label="@string/app_name">
4     <intent-filter>
5         <action android:name="android.intent.action.VIEW"/>
6         <category android:name="android.intent.category.DEFAULT"/>
7         <data android:scheme="http" android:host="www.baidu.com"/>
8     </intent-filter>
9 </activity>

  DEFAULT类别必须明确地在Intent过滤器中进行设置。Intent过滤器中的action元素告诉OS,activity能够处理指定的任务,DEFAULT类别告诉OS,activity愿意处理某项任务。

  DEFAULT类别实际隐含添加到了几乎每一个隐式Intent中。(唯一的例外是LAUNCHER类别)

隐藏Intent启动OS中其它应用的与此Intent相匹配的activity:

 1 Button choose = (Button)v.findViewById(R.id.choose_btn);
 2 choose.setOnClickListener(new Button.OnClickListener()
 3 {
 4     @Override
 5     public void onClick(View v)
 6     {
 7         Intent i = new Intent(Intent.ACTION_SEND);
 8         i.setType("text/plain");
 9         i.putExtra(Intent.EXTRA_TEXT, "Choose");
10         i.putExtra(Intent.EXTRA_SUBJECT, "Choose Suspect");
11         i = Intent.createChooser(i, "Chooser");
12         startActivity(i);
13     }
14 });

   使用隐式Intent,通过startActivity(...)方法启动activity,启动外部应用,隐式的将类别附给Intent,启动的activity是应用中manifest文件中,对activity配置了DEFAULT类别。实际上调用startActivity(Intent)方法意味着“启动与发送的隐式Intent相匹配的默认Activity”。

  前面说过,MAIN/LAUNCHER intent过滤器并不一定包含CATEGORY DEFAULT类别,因此,是否可以与通过startActivity(Intent)方法发送的隐式Intent匹配,谁也说不准。

  在设备已经安装的应用中,使用隐式Intent对象,匹配相同类别的应用中的Activity。因为,不能确保Intent过滤器,一定设置了GATEGORY DEFAULT类别,所以,通过包管理器查找,PackageManager类设备已经安装应用的包管理器。

  示例:通过PackageManager获取已安装的应用中与Intent相匹配的Activity列表:

1 // Intent对象,设置动作
2 Intent startIntent = new Intent(Intent.ACTION_MAIN);
3 // 设备Intent对象的操作类别
4 startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
5 // 获取PackageManager对象
6 PackageManager pm = getActivity().getPackageManager();
7 // 获取Activity列表,及相关应用包的信息和Activity信息
8 List<ResolveInfo> activities = pm.queryIntentActivities(startIntent, 0);

  对象获取的Activity列表排序,按字母排序:

 1 // new Comparator<T>(){}此写法是对Comparator类的compare(...)覆盖重写
 2 Collections.sort(activities, new Comparator<ResolveInfo>()
 3 {
 4     // 重写排序方法的实现
 5     @Override
 6     public int compare(ResolveInfo lhs, ResolveInfo rhs)
 7     {
 8         // 获取PackManager对象
 9         PackageManager pm = getActivity().getPackageManager();
10         // loadLabel(...)方法是按字母排序
11         int ret = String.CASE_INSENSITIVE_ORDER.compare(lhs.loadLabel(pm).toString(),
12                                                         rhs.loadLabel(pm).toString());
13         return ret;
14     }
15 });

  在列表ListView上显示应用名称列表:

 1 // 使用匿名内部类,创建适配器。在列表中显示
 2 ArrayAdapter<ResolveInfo> adapter = new ArrayAdapter<ResolveInfo>(getActivity(),
 3                                                                   android.R.layout.simple_list_item_1, activities)
 4 {
 5     // 覆盖基类的getView(...)方法
 6     @Override
 7     public View getView(int pos, View converView, ViewGroup parent)
 8     {
 9         View v = super.getView(pos, converView, parent);
10         // 获取PackageManager对象
11         PackageManager pm = getActivity().getPackageManager();
12         // 获取指定包的相关信息
13         ResolveInfo info = getItem(pos);
14         TextView tv = (TextView)v;
15         tv.setText(info.loadLabel(pm));
16         tv.setTextColor(Color.rgb(255, 64, 129));
17         
18         return v;
19     }
20 };
21 // 指定适配器对象
22 setListAdapter(adapter);

PS:ArrayAdapter<T>对象创建就使用的匿名内部类

  通过显示Intent对象启动指定的Activity:

 1 @Override
 2 public void onListItemClick(ListView listView, View view, int pos, long id)
 3 {
 4     // 获取选定应用的应用信息,包括包信息及Activity信息
 5     ResolveInfo resolveInfo = (ResolveInfo)listView.getAdapter().getItem(pos);
 6     // 获取指定的Activity信息
 7     ActivityInfo activityInfo = resolveInfo.activityInfo;
 8     
 9     if (null == activityInfo)
10     {
11         return;
12     }
13     // 创建显示的Intent对象
14     Intent i = new Intent(Intent.ACTION_MAIN);
15     // 指定要启动的Activity信息,包名和Activity名
16     i.setClassName(activityInfo.applicationInfo.packageName, activityInfo.name);
17     startActivity(i);
18 }
原文地址:https://www.cnblogs.com/naray/p/5300592.html