只有一个活动的应用也太简单了吧?没错,你的追求应该更高一点。不管你想创建多少 个活动,方法都和上一节中介绍的是一样的。唯一的问题在于,你在启动器中点击应用的图 标只会进入到该应用的主活动,那么怎样才能由主活动跳转到其他活动呢?我们现在就来一 起看一看。

2.3.1   使用显式 Intent

你应该已经对创建活动的流程比较熟悉了,那我们现在快速地在 ActivityTest 项目中再 创建一个活动。新建一个 second_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_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button 2"

/>

</LinearLayout>

我们还是定义了一个按钮,按钮上显示 Button 2。然后新建活动 SecondActivity 继承自

Activity,代码如下:

public class SecondActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.second_layout);

}

}

最后在 AndroidManifest.xml 中为 SecondActivity 进行注册。

<application
android:allowBackup="true" android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >

<activity

android:name=".FirstActivity"
android:label="This is FirstActivity" >

<intent-filter>

<action android:name="android.intent.action.MAIN"
/>

<category android:name="android.intent.category.LAUNCHER"
/>

</intent-filter>

</activity>

<activity android:name=".SecondActivity" >

</activity>

</application>

由于 SecondActivity 不是主活动,因此不需要配置<intent-filter>标签里的内容,注册活 动的代码也是简单了许多。现在第二个活动已经创建完成,剩下的问题就是如何去启动这第
二个活动了,这里我们需要引入一个新的概念,Intent。

Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组 件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动 服务、以及发送广播等场景,由于服务、广播等概念你暂时还未涉及,那么本章我们的目光 无疑就锁定在了启动活动上面。

Intent
的用法大致可以分为两种,显式 Intent 和隐式 Intent,我们先来看一下显式 Intent如何使用。

Intent 有多个构造函数的重载,其中一个是 Intent(Context packageContext, Class<?> cls)。 这个构造函数接收两个参数,第一个参数 Context 要求提供一个启动活动的上下文,第二个 参数 Class 则是指定想要启动的目标活动,通过这个构造函数就可以构建出 Intent 的“意图”。 然后我们应该怎么使用这个 Intent 呢?Activity 类中提供了一个 startActivity()方法,这个方法 是专门用于启动活动的,它接收一个 Intent 参数,这里我们将构建好的 Intent 传入 startActivity()方法就可以启动目标活动了。

修改 FirstActivity 中按钮的点击事件,代码如下所示:

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 作为目标活动,这样我们的“意图”就非常明显了,即在 FirstActivity 这个活动的基础上打 开 SecondActivity 这个活动。然后通过 startActivity()方法来执行这个 Intent。

重新运行程序,在 FirstActivity 的界面点击一下按钮,结果如图 2.12 所示。

图   2.12

可以看到,我们已经成功启动 SecondActivity 这个活动了。如果你想要回到上一个活动
怎么办呢?很简单,按下 Back 键就可以销毁当前活动,从而回到上一个活动了。

使用这种方式来启动活动,Intent 的“意图”非常明显,因此我们称之为显式 Intent。

2.3.2    使用隐式 Intent

相比于显式 Intent,隐式 Intent 则含蓄了许多,它并不明确指出我们想要启动哪一个活 动,而是指定了一系列更为抽象的 action 和 category 等信息,然后交由系统去分析这个 Intent, 并帮我们找出合适的活动去启动。

什么叫做合适的活动呢?简单来说就是可以响应我们这个隐式 Intent
的活动,那么目前
SecondActivity 可以响应什么样的隐式 Intent 呢?额,现在好像还什么都响应不了,不过很 快就会有了。

通过在<activity>标签下配置<intent-filter>的内容,可以指定当前活动能够响应的 action和 category,打开 AndroidManifest.xml,添加如下代码:

<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> 标 签 中 我 们 指 明 了 当 前 活 动 可 以 响 应 com.example.activitytest.ACTION_ START 这个 action,而<category>标签则包含了一些附加信息,更精确地指明了当前的活动 能够响应的 Intent 中还可能带有的 category。只有<action>和<category>中的内容同时能够匹
配上 Intent 中指定的 action 和 category 时,这个活动才能响应该 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 的活动。那前 面不 是说要 <action> 和<category> 同时 匹配上才 能响应的 吗?怎么 没看到哪 里有指 定 category 呢?这是因为 android.intent.category.DEFAULT 是一种默认的 category ,在调用 startActivity()方法的时候会自动将这个 category 添加到 Intent 中。

重新运行程序,在 FirstActivity 的界面点击一下按钮,你同样成功启动 SecondActivity了。不同的是,这次你是使用了隐式 Intent 的方式来启动的,说明我们在<activity>标签下配置的 action 和 category 的内容已经生效了!

每个 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。

现在重新运行程序,在 FirstActivity 的界面点击一下按钮,你会发现,程序崩溃了!这 是你第一次遇到程序崩溃,可能会有些束手无策。别紧张,其实大多数的崩溃问题都是很 好解决的,只要你善于分析。在 LogCat 界面查看错误日志,你会看到如图 2.13 所示的错误 信息。

图   2.13

错误信息中提醒我们,没有任何一个活动可以响应我们的 Intent,为什么呢?这是因为
我们刚刚在 Intent 中新增了一个 category,而 SecondActivity 的<intent-filter>标签中并没有声 明可以响应这个 category,所以就出现了没有任何活动可以响应该 Intent 的情况。现在我们 在<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>

再次重新运行程序,你就会发现一切都正常了。

2.3.3    更多隐式 Intent 的用法

上一节中,你掌握了通过隐式 Intent 来启动活动的方法,但实际上隐式 Intent 还有更多 的内容需要你去了解,本节我们就来展开介绍一下。

使用隐式 Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,
这使得
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
对象传递进去。

重新运行程序,在 FirstActivity 界面点击按钮就可以看到打开了系统浏览器,如图 2.14

所示。

图   2.14

上述的代码中,可能你会对 setData()部分感觉到陌生,这是我们前面没有讲到过的。这
个方法其实并不复杂,它接收一个 Uri 对象,主要用于指定当前 Intent 正在操作的数据,而 这些数据通常都是以字符串的形式传入到 Uri.parse()方法中解析产生的。

与此对应,我们还可以在<intent-filter>标签中再配置一个<data>标签,用于更精确地指 定当前活动能够响应什么类型的数据。<data>标签中主要可以配置以下内容。

1.    android:scheme

用于指定数据的协议部分,如上例中的 http 部分。

2.    android:host

用于指定数据的主机名部分,如上例中的 www.baidu.com部分。

3.    android:port

用于指定数据的端口部分,一般紧随在主机名之后。

4.    android:path

用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。

5.    android:mimeType

用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

只有<data>标签中指定的内容和 Intent 中携带的 Data 完全一致时,当前活动才能够响应
该 Intent。不过一般在<data>标签中都不会指定过多的内容,如上面浏览器示例中,其实只 需要指定 android:scheme 为 http,就可以响应所有的 http 协议的 Intent 了。

为了让你能够更加直观地理解,我们来自己建立一个活动,让它也能响应打开网页的

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>

然后新建活动 ThirdActivity 继承自 Activity,代码如下:

public class ThirdActivity extends Activity {

@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> 中 配 置 了 当 前 活 动 能 够 响 应 的 action 是Intent.ACTION_VIEW 的常量值,而 category 则毫无疑问指定了默认的 category 值,另外在<data>标签中我们通过 android:scheme 指定了数据的协议必须是 http 协议,这样 ThirdActivity
应该就和浏览器一样,能够响应一个打开网页的 Intent 了。让我们运行一下程序试试吧,在
FirstActivity 的界面点击一下按钮,结果如图 2.15 所示。

图   2.15

可以看到,系统自动弹出了一个列表,显示了目前能够响应这个 Intent 的所有程序。点 击 Browser 还会像之前一样打开浏览器,并显示百度的主页,而如果点击了 ActivityTest,则 会启动 ThirdActivity。需要注意的是,虽然我们声明了 ThirdActivity 是可以响应打开网页的
Intent 的,但实际上这个活动并没有加载并显示网页的功能,所以在真正的项目中尽量不要 去做这种有可能误导用户的行为,不然会让用户对我们的应用产生负面的印象。

除了 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。重新运行一下程序,在 FirstActivity 的界面点击一下按钮,结果如图 2.16 所示。

图   2.16

最新文章

  1. 螺旋方阵(4x4)(java实现)
  2. 动手搭个wordpress
  3. html5开发制作,漂亮html5模板欣赏,H5网站建设
  4. cf707D. Persistent Bookcase(离线+dfs)
  5. Understanding Python metaclasses
  6. dubbo使用方法
  7. QTableView 固定列宽度(鼠标拖动后,仍可固定)
  8. Opengl坐标转换
  9. 个人作业2——英语学习APP案例分析(必应词典的使用)
  10. 版本控制之一:SVN服务器搭建与安装(转)
  11. python爬虫爬取大众点评并导入redis
  12. 最简单的基于librtmp的示例:发布H.264(H.264通过RTMP发布)
  13. 科学地增加postgresql最大连接数
  14. web项目如何使用Material Icons
  15. 为什么使用 Spring Boot?
  16. 分布式系统:CAP
  17. JavaNIO学习一
  18. HDU1024 Max Sum Plus Plus 【DP】
  19. Overflow与块状格式上下文
  20. 7. Reverse Integer 反向输出整数 easy 9. Palindrome Number 判断是否是水仙花数 easy

热门文章

  1. springcloud配置详解
  2. sublime sftp 打开远程文件夹
  3. vs 连接过程报错 dll 分析 ------- DLL动态链接库
  4. laravel 批量更新
  5. scanf 输入加逗号(或者不加逗号)出现的异常及解决方案
  6. mavean项目的jar位置的影响
  7. 德卡Z90读卡器读取社保卡,德卡Z90读卡器CSharp示例程序源码
  8. 说commit,rollback
  9. SpringBoot的搭建
  10. P2690 接苹果