使用 Intent 在 Activity 之间穿梭
2016-03-09 18:03
549 查看
Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动 Activity、启动服务、以及发送广播等场景。
Intent 的用法大致可以分为两种,显示 Intent和隐式 Intent,我们先来看一下显示 Intent 如何使用。
1. 使用显示 Intent
Intent 有多个构造函数的重载,其中一个是 Intent(Context packageContext, Class<?> cls)。这个构造函数接收两个参数,第一个参数 Context 要求提供一个启动 Activity 的上下文,第二个参数 Class 则是指定想要启动的目标 Activity,通过这个构造函数就可以构件出 Intent 的“意图”。然后我们应该怎么使用这个 Intent 呢?Activity 类中提供了一个 startActivity() 方法,这个方法是专门用于启动
Activity 的,它接收一个 Intent 参数,这里我们将创建好的 Intent 传入 startActivity() 方法就可以启动目标活动了。
我们首先构建出了一个 Intent,传入 FirstActivity.this 作为上下文,传入 SecondActivity.class 作为目标 Activity,这样我们的“意图”就非常明显了,即在 FirstActivity 这个 Activity 的基础上打开 SecondActivity 这个 Activity。然后通过 startActivity() 方法来执行这个 Intent。
使用这种方式来启动 Activity,Intent 的“意图”非常明显,因此我们称之为显示 Intent。
什么叫做合适的 Activity 呢?简单来说就是可以响应我们这个隐式 Intent 的 Activity,通过在 <activity>标签下配置<intent-filter>的内容,可以指定当前 Activity 能够响应的 action 和 category。
在 <action> 标签中我们指明了当前 Activity 可以响应 com.example.activitytest.ACTION_START 这个 action,而 <category> 标签则包含了一些附加信息,更精确地指明了当前的 Activity 能够响应的 Intent 中还可能带有的 category 。只有<action> 和 <category> 中的内容同时能够匹配上
Intent 中指定的 action 和 category 时,这个 Activity 才能响应该 Intent。
修改 FirstActivity 中按钮的点击事件,代码如下所示:
可以看到,我们使用了 Intent 的另一个构造函数,直接将 action 的字符串穿了进去,表明我们想要启动能够响应 com.example.activitytest.ACTION_START 这个 action 的 Activity。那前面不是说要 <action> 和 <category> 同时匹配上才能响应的吗?怎么没看到哪里有指定 category 呢?这是因为 android.intent.category.DEFAULT
是一种默认的 category,在调用 startActivity() 方法的时候会自动将这个 category 添加到 Intent 中。
每个 Intent 中只能指定一个 action,但却能指定多个 category。目前我们的 Intent 中只有一个默认的 category,那么现在再来增加一个吧。修改 FirstActivity 中按钮的点击事件,代码如下所示:
可以调用 Intent 中的 addCategory() 方法来添加一个 category,这里我们指定了一个自定义的 category,值为 com.example.activitytest.MY_CATEGORY ,然后在 <intent-filter> 中再添加一个 category 的声明,如下所示:
修改 FirstActivity 中按钮的点击事件的代码,如下所示:
这里我们首先指定了 Intent 的 action 是
Intent.ACTION_VIEW,这是一个 Android 系统内置的动作,其常量值为 android.intent.action.VIEW。然后通过 Uri.parse() 方法,将一个网址字符串解析成一个 Uri 对象,再调用 Intent 的 setData() 方法将这个 Uri 对象传递进去。
上述的代码中,可能你会对 setData() 部分感觉到陌生,这时我们前面没有讲到过的。这个方法其实并不复杂,它接收一个 Uri 对象,主要用于指定当前 Intent 正在操作的数据,而这些数据通常都是以字符串的形式传入到 Uri.parse() 方法中解析产生的。
与此对应,我们还可以在 <intent-filter> 标签中再配置一个 <data> 标签,用于更精确地指定当前 Activity 能够响应什么类型的数据。<data> 标签中主要可以配置以下内容。
android:scheme
用于指定数据的协议部分,如上例中的 http 部分。
android:host
用于指定数据的主机名部分,如上例中的 www.baidu.com 部分。
android:port
用于指定数据的端口部分,一般紧随在主机名之后。
android:path
用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
android:mimeType
用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
只有 <data> 标签中指定的内容和 Intent 中携带的 Data 完全一致时,当前 Activity 才能够响应该 Intent。不过一般在 <data> 标签中都不会指定过多的内容,如上面浏览器示例中,其实只需要指定 android:scheme 为 http,就可以响应所有的 http 协议的 Intent 了。
为了能够更加直观地理解,我们来自己建立一个 Activity,让它也能响应打开网页的 Intent 。
新建 third_layout.xml 布局文件,代码如下:
然后新建 ThridActivity 继承自 Activity,代码如下:
最后在 AndroidManifest.xml 中为 ThirdActivity 进行注册。
我们在 ThirdActivity 的 <intent-filter> 中配置了当前 Activity 能够响应的 action 是 Intent.ACTION_VIEW 的常量值,而 category 则毫无疑问指定了默认的 category 值,另外在 <data> 标签中我们通过 android:scheme 指定了数据的协议必须是 http 协议,这样 ThirdActivity 应该就和浏览器一样,能够响应一个打开网页的 Intent 了。需要注意的是,虽然我们声明了
ThirdActivity 是可以响应打开网页的 Intent 的,但实际上这个 Activity 并没有加载并显示网页的功能,所以在真正的项目中尽量不要去做这种有可能误导用户的行为,不然会让用户对我们的应用产生负面的印象。
除了 http 协议外,我们还可以指定很多其他协议,比如 geo 表示显示地理位置、tel 表示拨打电话。下面的代码展示了如何在我们的程序中调用系统拨号界面。
首先指定了 Intent 的 action 是
Intent.ACTION_DIAL,这又是一个 Android 系统的内置动作。然后在 data 部分指定了协议是 tel,号码是 10086。
摘自《第一行代码》
Intent 的用法大致可以分为两种,显示 Intent和隐式 Intent,我们先来看一下显示 Intent 如何使用。
1. 使用显示 Intent
Intent 有多个构造函数的重载,其中一个是 Intent(Context packageContext, Class<?> cls)。这个构造函数接收两个参数,第一个参数 Context 要求提供一个启动 Activity 的上下文,第二个参数 Class 则是指定想要启动的目标 Activity,通过这个构造函数就可以构件出 Intent 的“意图”。然后我们应该怎么使用这个 Intent 呢?Activity 类中提供了一个 startActivity() 方法,这个方法是专门用于启动Activity 的,它接收一个 Intent 参数,这里我们将创建好的 Intent 传入 startActivity() 方法就可以启动目标活动了。
button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent); } });
我们首先构建出了一个 Intent,传入 FirstActivity.this 作为上下文,传入 SecondActivity.class 作为目标 Activity,这样我们的“意图”就非常明显了,即在 FirstActivity 这个 Activity 的基础上打开 SecondActivity 这个 Activity。然后通过 startActivity() 方法来执行这个 Intent。
使用这种方式来启动 Activity,Intent 的“意图”非常明显,因此我们称之为显示 Intent。
2. 使用隐式 Intent
相比于显示 Intent,隐式 Intent 则含蓄了许多,它并不明确指出我们想要启动哪一个 Activity,而是指定了一系列更为抽象的 action 和 category 等信息,然后交由系统去分析这个 Intent,并帮我们找出合适的 Activity 去启动。什么叫做合适的 Activity 呢?简单来说就是可以响应我们这个隐式 Intent 的 Activity,通过在 <activity>标签下配置<intent-filter>的内容,可以指定当前 Activity 能够响应的 action 和 category。
<activity android:name=".SecondActivity" > <intent-filter> <action android:name="com.example.activitytest.ACTION_START" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
在 <action> 标签中我们指明了当前 Activity 可以响应 com.example.activitytest.ACTION_START 这个 action,而 <category> 标签则包含了一些附加信息,更精确地指明了当前的 Activity 能够响应的 Intent 中还可能带有的 category 。只有<action> 和 <category> 中的内容同时能够匹配上
Intent 中指定的 action 和 category 时,这个 Activity 才能响应该 Intent。
修改 FirstActivity 中按钮的点击事件,代码如下所示:
button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.activitytest.ACTION_START"); startActivity(intent); } });
可以看到,我们使用了 Intent 的另一个构造函数,直接将 action 的字符串穿了进去,表明我们想要启动能够响应 com.example.activitytest.ACTION_START 这个 action 的 Activity。那前面不是说要 <action> 和 <category> 同时匹配上才能响应的吗?怎么没看到哪里有指定 category 呢?这是因为 android.intent.category.DEFAULT
是一种默认的 category,在调用 startActivity() 方法的时候会自动将这个 category 添加到 Intent 中。
每个 Intent 中只能指定一个 action,但却能指定多个 category。目前我们的 Intent 中只有一个默认的 category,那么现在再来增加一个吧。修改 FirstActivity 中按钮的点击事件,代码如下所示:
button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.activitytest.ACTION_START"); intent.addCategory("com.example.activitytest.MY_CATEGORY"); startActivity(intent); } });
可以调用 Intent 中的 addCategory() 方法来添加一个 category,这里我们指定了一个自定义的 category,值为 com.example.activitytest.MY_CATEGORY ,然后在 <intent-filter> 中再添加一个 category 的声明,如下所示:
<activity android:name=".SecondActivity"> <intent-filter> <action android:name="com.example.activitytest.ACTION_START" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="com.example.activitytest.MY_CATEGORY" /> </intent-filter> </activity>
3. 更多隐式 Intent 的用法
使用隐式 Intent,我们不仅可以启动自己程序内的 Activity,还可以启动其他程序的 Activity,这使得 Android 多个应用程序之间的功能共享成为了可能。比如说你的应用程序中需要展示一个网页,这时你没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要调用系统的浏览器来打开这个网页就行了。修改 FirstActivity 中按钮的点击事件的代码,如下所示:
button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com")); startActivity(intent); } });
这里我们首先指定了 Intent 的 action 是
Intent.ACTION_VIEW,这是一个 Android 系统内置的动作,其常量值为 android.intent.action.VIEW。然后通过 Uri.parse() 方法,将一个网址字符串解析成一个 Uri 对象,再调用 Intent 的 setData() 方法将这个 Uri 对象传递进去。
上述的代码中,可能你会对 setData() 部分感觉到陌生,这时我们前面没有讲到过的。这个方法其实并不复杂,它接收一个 Uri 对象,主要用于指定当前 Intent 正在操作的数据,而这些数据通常都是以字符串的形式传入到 Uri.parse() 方法中解析产生的。
与此对应,我们还可以在 <intent-filter> 标签中再配置一个 <data> 标签,用于更精确地指定当前 Activity 能够响应什么类型的数据。<data> 标签中主要可以配置以下内容。
android:scheme
用于指定数据的协议部分,如上例中的 http 部分。
android:host
用于指定数据的主机名部分,如上例中的 www.baidu.com 部分。
android:port
用于指定数据的端口部分,一般紧随在主机名之后。
android:path
用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
android:mimeType
用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
只有 <data> 标签中指定的内容和 Intent 中携带的 Data 完全一致时,当前 Activity 才能够响应该 Intent。不过一般在 <data> 标签中都不会指定过多的内容,如上面浏览器示例中,其实只需要指定 android:scheme 为 http,就可以响应所有的 http 协议的 Intent 了。
为了能够更加直观地理解,我们来自己建立一个 Activity,让它也能响应打开网页的 Intent 。
新建 third_layout.xml 布局文件,代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/button_3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button 3" /> </LinearLayout>
然后新建 ThridActivity 继承自 Activity,代码如下:
public class ThirdActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.third_layout); } }
最后在 AndroidManifest.xml 中为 ThirdActivity 进行注册。
<activity android:name=".ThirdActivity" > <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="http" /> </intent-filter> </activity>
我们在 ThirdActivity 的 <intent-filter> 中配置了当前 Activity 能够响应的 action 是 Intent.ACTION_VIEW 的常量值,而 category 则毫无疑问指定了默认的 category 值,另外在 <data> 标签中我们通过 android:scheme 指定了数据的协议必须是 http 协议,这样 ThirdActivity 应该就和浏览器一样,能够响应一个打开网页的 Intent 了。需要注意的是,虽然我们声明了
ThirdActivity 是可以响应打开网页的 Intent 的,但实际上这个 Activity 并没有加载并显示网页的功能,所以在真正的项目中尽量不要去做这种有可能误导用户的行为,不然会让用户对我们的应用产生负面的印象。
除了 http 协议外,我们还可以指定很多其他协议,比如 geo 表示显示地理位置、tel 表示拨打电话。下面的代码展示了如何在我们的程序中调用系统拨号界面。
button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:10086")); startActivity(intent); } });
首先指定了 Intent 的 action 是
Intent.ACTION_DIAL,这又是一个 Android 系统的内置动作。然后在 data 部分指定了协议是 tel,号码是 10086。
摘自《第一行代码》
相关文章推荐
- TabBar的自动渲染为蓝色改成图片本身颜色
- Java 折半插入排序
- 玩儿转物联网IoT - 在Beagle Bone Black上运行node.js 程序
- 高级查询--嵌套和相关,两套分页!!!
- [LeetCode][JavaScript]Find Minimum in Rotated Sorted Array
- Servlet相关接口和Servlet的生命周期
- git 常用命令
- IDC:全球以太网交换机和路由器市场报告
- Ubuntu 14.04下安装GitLab指南
- java学习之文件的读取
- androidtv-Leanback开源项目解析
- java转换xml、list、map和json
- 基数排序的PHP实现
- 科技界大佬对围棋世纪大战的预测结果
- C语言字符串函数(九)
- There is no Action mapped for namespace
- 阿里移动安全发布《2015物联网安全年报》,威胁攻击日益凸显
- 5. Longest Palindromic Substring
- 手机获取验证码的倒计时效果
- 两个远程数据库之间get数据