如何使用隐式 Intent

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

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

使用隐式 Intent

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

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="pub.weber.bym.activitytest.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="com.example.activitytest.MY_CATEGORY"/>
    </intent-filter>
</activity>

<action>标签中我们指明了当前活动可以响应 com.example.activitytest.ACTION_START这个 action,而<category>标签则包含了一些附加信息,更精确地指明了当前的活动能够响应的 Intent 中还可能带有的 category。只有<action><category>中的内容同时能够匹配上 Intent 中指定的 action 和 category 时,这个活动才能响应该 Intent。

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

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("pub.weber.bym.activitytest.ACTION_START");
        startActivity(intent);
    }
});

可以看到,我们使用了 Intent 的另一个构造函数,直接将 action 的字符串传了进去,表明我们想要启动能够响应 com.example.activitytest.ACTION_START 这个 action 的活动。那前面不是说要<action><category>同时匹配上才能响应的吗?怎么没看到哪里有指定category 呢?这是因为 android.intent.category.DEFAULT 是一种默认的 category,在调用startActivity()方法的时候会自动将这个 category 添加到 Intent 中。

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

每个 Intent 中只能指定一个 action,但却能指定多个 category。目前我们的 Intent 中只有一个默认的 category,那么现在再来增加一个吧。

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

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("pub.weber.bym.activitytest.ACTION_START");
        intent.addCategory("com.example.activitytest.MY_CATEGORY");
        startActivity(intent);
    }
});

可以调用 Intent 中的 addCategory()方法来添加一个 category,这里我们指定了一个自定义的 category,值为 com.example.activitytest.MY_CATEGORY

现在重新运行程序,在 MainActivity 的界面点击一下按钮,你会发现,程序崩溃了!

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

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="pub.weber.bym.activitytest.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="com.example.activitytest.MY_CATEGORY"/>
    </intent-filter>
</activity>

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

更多隐式 Intent 的用法

使用隐式 Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得 Android多个应用程序之间的功能共享成为了可能。比如说你的应用程序中需要展示一个网页,这时你没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要调用系统的浏览器来打开这个网页就行了。

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

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://weber.pub/"));
        startActivity(intent);
    }
});

这里我们首先指定了 Intent 的 action 是 Intent.ACTION_VIEW,这是一个 Android 系统内置的动作,其常量值为 android.intent.action.VIEW。然后通过 Uri.parse()方法,将一个网址字符串解析成一个 Uri 对象,再调用 Intent的 setData()方法将这个 Uri 对象传递进去。

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

如何使用隐式 Intent

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

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

  • android:scheme
    用于指定数据的协议部分,如上例中的 http 部分。
  • android:host
    用于指定数据的主机名部分,如上例中的http://weber.pub/部分。
  • android:port
    用于指定数据的端口部分,一般紧随在主机名之后。
  • android:path
    用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
  • android:mimeType
    用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

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

新建一个 activity_third.xml 布局文件

<?xml version="1.0" encoding="utf-8"?>
<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,代码如下:

package pub.weber.bym.activitytest;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;

public class ThirdActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_third);
    }
}

最后在 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 的界面点击一下按钮,结果如图所示。

如何使用隐式 Intent

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

除了 http 协议外,我们还可以指定很多其他协议,比如 geo 表示显示地理位置、tel 表示拨打电话。下面的代码展示了如何在我们的程序中调用系统拨号界面。

button.setOnClickListener(new View.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。重新运行一下程序,在 MainActivity 的界面点击一下按钮,结果如图所示。

如何使用隐式 Intent

by web开发者 from http://weber.pub/

本文地址: http://weber.pub/安卓笔记6-如何使用隐式intent/293.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章