介绍
一个 Android 程序主要是由 Activity、Service 和 BroadcastReceiver 三种组件组成,这三种组件是独立的,它们之间可以互相调用、协调工作,最终组成一个真正的 Android 程序。这些组件之间的通讯主要由Intent协助完成。Intent负责对应用中一次操作的Action(动作)、Action涉及的Data(数据)、Extras(附加数据)进行描述,Android 则根据 Intent 的描述,找到对应的组件,将 Intent 传递给调用的组件,并完成组件的调用。因此,Intent 在这里起着一个媒体中介的作用,专门提供组件间互相调用的相关信息,实现调用者与被调用者之间的解耦。
应用
Intent 是一个可以从另一个应用程序请求动作的消息处理对象。它可以实现组件间的通信,主要有以下 3 种基本应用。
- 开启 Activity:通过将一个 Intent 对象传递给 startActivity() 方法,可以启动一个新的Activity,并且还可以携带一些必要的数据。另外,也可以将 Intent 对象传递到 startActivityForResult() 方法中,这样,在需要获取返回结果时,就可以在调用它的 Activity 的 onActivityResult() 方法中接收返回结果了。
- 开启 Service:通过将一个 Intent 对象传递给 startService() 方法,可以启动一个 Service 来完成一次操作(如下载文件)或者传递一个新的指令给正在运行的 Service。另外,将一个 Intent 对象传递给 bindService() 方法,可以建立调用组件和目标服务之间的连接。
- 传递 Broadcast(广播):通过任何一个广播方法(如 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast()方法等),都可以将广播传递给所有感兴趣的广播接收者。
显式Intent
方式一
Intent intent = new Intent(this, TextViewActivity.class);
startActivity(intent);
方式二
Intent intent = new Intent();
intent.setClassName(this,
"com.example.cat.bar.ProgressBarActivity");
//或者
intent.setClassName("com.example.cat",
"com.example.cat.bar.ProgressBarActivity2");
方式三
Intent intent=new Intent();
intent.setClass(this,RatingBarActivity.class);
方式四
intent=new Intent();
intent.setComponent(new ComponentName(this,
"com.example.cat.bar.SeekBarActivity"));
//或者
intent.setComponent(new ComponentName("com.example.cat",
"com.example.cat.bar.SeekBarActivity"));
隐式Intent
隐式 Intent 是指在创建 Intent 对象时,不指定具体的接收者,而是定义要执行的 Action、Category 和 Data,然后让 Android 系统根据相应的匹配机制找到要启动的 Activity。例如,在Activity A 中隐式启动 Activity B 需要经过如图 9.10 所示的过程。
从图9.10可以看出,在Activity A中,创建一个设置了Action的Intent对象,并且把它传递到startActivity()中,然后Android系统将搜索所有的应用程序来匹配这个Intent,当找到匹配后,系统将通过传递Intent到onCreate()方法来启动匹配的Activity B。
- Uri.parse() 方法:用于把字符串解释为 URI 对象,表示需要传递的数据
- 在执行下面的代码时,系统首先根据 Intent.ACTION_VIEW 得知需要启动具备浏览功能的Activity,但是具体的浏览内容,还需要根据第二个参数的数据类型来判断。这里面提供的是 Web地址,所以将使用内置的浏览器显示
Intent intent = new Intent(); //创建Intent对象
intent.setAction(Intent.ACTION_VIEW); //为Intent设置动作
intent.setData(Uri.parse("http://www.baidu.com")); //为Intent设置数据
startActivity(intent);
//或者
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.baidu.com")); //创建Intent对象
startActivity(intent);
在 AndroidManifest.xml 文件中,设置允许该应用拨打电话和发送短信的权限,代码如下:
<!--设置拨打电话权限-->
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<!--设置发送短信权限-->
<uses-permission android:name="android.permission.SEND_SMS" />
//tel:要加,不然会闪退
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL); //调用拨号面板
intent.setData(Uri.parse("tel:1008611"));//设置要拨打的号码
startActivity(intent);
//smsto:
Intent intent = new Intent();
Uri smsToUri = Uri.parse("smsto:10086");
intent.setAction(Intent.ACTION_SENDTO); //调用发送短信息面板
intent.setData(smsToUri);
intent.putExtra("sms_body", "CXLL"); //设置要发送的信息内容
startActivity(intent);
Intent过滤器
使用隐式 Intent 启动 Activity 时,并没有在 Intent 中指明 Activity 所在的类。因此,Android 系统要根据某种匹配机制,找到要启动的 Activity。这种机制就是根据 Intent 过滤器来实现的。Intent过滤器是一种根据Intent中的Action、Data和Category等属性对适合接收该Intent的组件进行匹配和筛选的机制。
配置<action>标记
要设置一个Activity作为初始启动界面时,代码如下
<action android:name="android.intent.action.MAIN"/>
除了使用标准的 Action 常量外,还可以自定义 action 的名字,为了确保名字的唯一性,一定要用该应用程序的包名作为前缀。例如,要设置名字为 DETAIL,可以使用下面的代码:
<action android:name="com.mingrisoft.action.DETAIL "/>
标准Action说明
常量 | 对应字符串 | 说明 |
ACTION_MAIN | android.intent.action.MAIN | 作为初始的 Activity 启动,没有数据输入输出 |
ACTION_VIEW | android.intent.action.VIEW | 将数据显示给用户 |
ACTION_ATTACH_DATA | android.intent.action.ATTACH_DATA | 用于指示一些数据应该附属于其他地方 |
ACTION_EDIT | android.intent.action.EDIT | 将数据显示给用户用于编辑 |
ACTION_PICK | android.intent.action.PICK | 从数据中选择一项,并返回该项 |
ACTION_CHOOSER | android.intent.action.CHOOSER | 显示一个 Activity 选择器 |
ACTION_GET_CONTENT | android.intent.action.GET_CONTENT | 允许用户选择特定类型的数据并将其返回 |
ACTION_DIAL | android.intent.action.DIAL | 使用提供的数字拨打电话 |
ACTION_CALL | android.intent.action.CALL | 使用提供的数据给某人拨打电话 |
ACTION_SEND | android.intent.action.SEND | 向某人发送消息,接收者未指定 |
ACTION_SENDTO | android.intent.action.SENDTO | 向某人发送消息,接收者已指定 |
ACTION_ANSWER | android.intent.action.ANSWER | 接听电话 |
ACTION_INSERT | android.intent.action.INSERT | 在给定容器中插入空白项 |
ACTION_DELETE | android.intent.action.DELETE | 从容器中删除给定数据 |
ACTION_RUN | android.intent.action.RUN | 无条件运行数据 |
ACTION_SYNC | android.intent.action.SYNC | 执行数据同步 |
ACTION_PICK_ACTIVITY | android.intent.action.PICK_ACTIVITY | 选择给定 Intent 的 Activity,返回选择的类 |
ACTION_SEARCH | android.intent.action.SEARCH | 执行查询 |
ACTION_WEB_SEARCH | android.intent.action.WEB_SEARCH | 执行联机查询 |
ACTION_FACTORY_TEST | android.intent.action.FACTORY_TEST | 工厂测试的主入口点 |
配置<data>标记
<data> 标记用于向 Action 提供要操作的数据。它可以是一个 URI 对象或者数据类型(MIME媒体类型)。其中,URI 可以分成 scheme(协议或服务方式)、host(主机)、port(端口)以及path(路径)等,格式如下:
<scheme>://<host>:<port>/<path>
例如下面的 URI:
- content 是 scheme;
- com.example.project 是 host;
- 200 是 port;
- folder/subfolder/etc 是 path
host 和 port 一起组成了 URI 授权,如果 host 没有指定,则忽略 port。这些属性都是可选的,但是相互之间并非完全独立。如果授权有效,则 scheme 必须指定。如果 path 有效,则 scheme 和授权必须指定。
content://com.example.project:200/folder/subfolder/etc
<data>标记的语法格式如下:
<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:mimeType="string" />
- android:scheme:用于指定所需要的特定协议;
- android:host:用于指定一个有效的主机名;
- android:port:用于指定主机的有效端口号;
- android:path:用于指定有效的 URI 路径名;
- android:mimeType:用于指定组件能处理的数据类型,支持使用“*”通配符来包含子类型(如image/* 或者 audio/*)。在过滤器中,该属性比较常用。
例如,要设置数据类型为 JPG 图片,可以使用下面的代码:
<data android:mimeType="image/jpeg"/>
配置<category>标记
<category> 标记用于指定以何种方式去执行 Intent 请求的动作。
例如,要设置其作为用于测试的 Activity(对应常量为 CATEGORY_TEST),那么需要将其指定为 android.intent.category.TEST。代码如下:
<action android:name="android.intent.category.TEST"/>
除了使用标准的 Category 常量外,还可以自定义 Category 的名字,为了确保名字的唯一性,一定要用该应用程序的包名作为前缀,例如,要设置名字为 DETAIL,可以使用下面的代码。
<action android:name="com.personalstudy.category.DETAIL"/>
标准Category说明
常量 | 对应字符串 | 说明 |
CATEGORY_DEFAULT | android.intent.category.DEFAULT | 将 Activity 作为默认动作选项 |
CATEGORY_BROWSABLE | .BROWSABLE | 让 Activity 能够安全地从浏览器中调用 |
CATEGORY_TAB | .TAB | 将 Activity 作为 TabActivity 的选项卡 |
CATEGORY_ALTERNATIVE | .ALTERNATIVE | 将 Activity 作为用户正在查看数据的备用动作 |
CATEGORY_SELECTED_ALTERNATIVE | .SELECTED_ALTERNATIVE | 将 Activity 作为用户当前选择数据的备用动作 |
CATEGORY_LAUNCHER | .LAUNCHER | 让 Activity 在顶层启动器中显示 |
CATEGORY_INFO | .INFO | 用于提供 Activity 所在包的信息 |
CATEGORY_HOME | .HOME | 用于返回 Home Activity(系统桌面) |
CATEGORY_PREFERENCE | .PREFERENCE | 让 Activity 作为一个偏好面板 |
CATEGORY_TEST | .TEST | 用于测试 |
CATEGORY_HE_DESK_DOCK | .CAR_DOCK | 用于在设备插入到 car dock 时运行Activity |
CATEGORY_DESK_DOCK | .DESK_DOCK | 用于在设备插入到 desk dock 时运行Activity |
CATEGORY_LE_DESK_DOCK | .LE_DESK_DOCK | 用于在设备插入到模拟 dock(低端)时运行 Activity |
CATEGORY_HE_DESK_DOCK | .HE_DESK_DOCK | 用于在设备插入到数字 dock(高端)时运行 Activity |
CATEGORY_CAR_MODE | .CAR_MODE | 指定 Activity 可以用于汽车环境 |
CATEGORY_APP_MARKET | .APP_MARKET | 让 Activity 允许用户浏览和下载新应用 |
例子
使用Intent过滤器实现查看大图功能
编写MainActivity布局文件
布局管理器修改为相对布局管理器,添加一个 ImageView 组件(用于显示小图)和一个 Button 组件(单击查看大图)
编写MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button= (Button) findViewById(R.id.btn); //获取按钮组件
//为按钮创建单击事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(); //创建Intent对象
intent.setAction(intent.ACTION_VIEW); //为Intent设置动作
startActivity(intent); //启动Activity
}
});
}
}
编写ContactsActivity布局文件
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/hehua"
android:scaleType="fitXY"/>
</RelativeLayout>
编写AndroidManifest.xml
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ContactsActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
效果
由于有多种匹配ACTION_VIEW的方式,因此需要用户进行选择。运行本实例,将显示如图 9.14 所示的主界面,单击“查看大图”按钮,显示如图 9.15 所示的选择打开方式界面,选择“Intent 过滤器”跳转到第二个 Activity,显示完整图片。