Intent 介绍

535 查看

Intent 是一种消息传递机制,可以在应用程序内使用,也可以在应用程序之间使用。可以使用于:

  • 使用类名显式启动一个特定的 Service 或 Activity
  • 启动 Activity 或 Service 来执行一个动作的 Intent,通常需要使用特定的数据,或者对特定的数据执行动作
  • 广播某个事件已经发生。android 通过广播 Intent 来公布系统事件,比如网络连接状态或者电池电量的改变。


显式启动新 Activity

知道已经要启动的 Activity,需要经常显式的打开指定的 Activity 可以使用。前提是被启动的 Activity 必须包含在应用程序的 Manifest 文件中。在调用新的 Activity 之后,会把该 Activity 添加到栈顶,而按下 Back 键或者调用finish 则依次删除每个 Activity。

Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);

如果使用 startActivity,则在新的启动的 Activity 完成之后,应用程序不会接收到任何通知。要想跟踪来自子 Activity 的反馈,可以使用 startActivityForResult 方法。


隐式的 Intent 和运行时延时绑定

隐式的 Intent 提供了一种机制,可以让匿名的应用程序组件响应动作请求,不必知道被启动的是哪个应用的哪个 Activity,例如调用打电话、通讯录、应用程序安装。

当构建一个新的隐式的 Intent 时,需要指定一个要执行的动作,另外也可以提供执行那个动作需要的数据的URI。还可以通过向 Intent 添加 extra 来向目标 Activity 发送额外的数据。

Intent itnent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:221-221-221"));
startActivity(intent);

当构建一个新的隐式的 Intent 时,需要指定一个动作,另外,也可以提供执行动作所需要的数据的 URI。还可以通过向 Intent 添加 extra 来向目标 Activity 发送额外的数据。


确定 Intent 能否解析

由于通常无法确定,当前调用的第三方应用程序是否被安装了,因此通过调用 Intent 的 resolveActivity 方法,并向该方法传入包管理器,可以对包管理器进行查询,确定都否有 Activity 能够启动以响应该 Intent。

Intent itnent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:221-221-221"));

PackageManager pm = getPackageManager();
ComponentName cn = intent.resolveActivity(pm);

if (cn == null) {
    Uri marketUri = Uri.parse("market://search?q=pname:com.example.packagename");
    Intent marketIntent = new Intent(Intent.ACTION_VIEW).setData(marketUri);

    if (marketIntent.resolveActivity(pm) != null) {
        startActivity(marketIntent);
    } else {
        Log.d("ANT", "Market client not available.");
    }
} else {
    startActivity(intent);
}


从 Activity 返回结果

通过 startActivity 启动的 Activity 独立于其父 Activity,并且在关闭时不会提供反馈。当需要反馈时,必须在应用程序的 manifest 文件中注册子 Activity。在 manifest 文件中注册的任何 Activity 都可以作为子 Activity 打开,包括系统 Activity 和第三方应用程序的 Activity。

当子 Activity 结束时,它会触发调用 Activity 内的事件处理程序 onActivityResult

启动子 Activity

startActivityForResult 的工作方式和 startActivity 差不多,仅有一个区别,还需要多传入一个请求码。这个值将在后面用于唯一标识返回了结果的子 Activity。

private static final int SHOW_SUBACTIVITY = 1;

private void startSubActivity() {
    Intent intent = new Intent(this, SubActivity.class);
    startActivityForResult(itnent, SHOW_SUBACTIVITY);
}
返回结果

当准备好返回子 Activity 时,可以在调用 finish 以前调用 setResult 方法,以便向父 Activity 返回一个结果。

setResult 方法有两个参数:结果码和表示为 Intent 的结果数据本身(包含了结果数据的 Intent)。

结果码是运行子 Activity 的结果,通常是 Activity.RESULT_OK 和 Activity.RESULT_CANCELED。在某些环境下,当 OK 和 CANCELED 都不足以精确描述可用的返回结果时,可以使用自定义的响应吗(response code)来处理应用程序特定的选择:setResult 支持任意整数。

通常返回的 Intent 包含了处理结果数据(例如:选择的联系人、电话号码或媒体文件)的 URI 和用于返回附加信息的一组 extra。

Button okButton = (Button) findViewById(R.id.ok_button);
okButton.setOnClickListener(new View.OnClickListener() {
    public void onClick(View view) {
        long selected_horse_id = listView.getSelectedItemId();

        Uri selectedHorse = Uri.parse("content://horses/" + selected_horse_id);
        Intent result = new Intent(Intent.ACTION_PICK, selectedHorse);

        setResult(Activity.RESULT_OK, result);
        finish();
    }
});

Button cancelButton = findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
    public void onClick(View view) {
        setResult(Activity.RESULT_CANCELED);
        finish();
    }
});

如果用户通过按下返回键或者调用 finish 关闭 Activity 以前没有设置 setResult,那么结果码将被设置为 “RESULT_CANCELED”,结果 Intent 将被设置为 null。

处理返回的结果

当子 Activity 处于关闭的时候,它会触发父 Activity 的 onActivityResult 事件处理程序。可以重写这个方法来处理从子 Activity 返回的结果。
onActivityResult 接收的参数:

  1. 请求码:父 Activity 的请求码
  2. 结果码:子 Activity 的结果码,用来说明结果状态。
  3. 数据:Intent 包装返回的数据。
private static final int SELECT_HORSE = 1;


private static final int SELECT_GUN = 2;

Uri selectedHorse = null;
Uri selectedGun = null;

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
        case (SELECT_HORSE):
            if (resultCode == Activity.RESULT_OK)
                selectedHorse = data.getData();
        break;

        case (SELECT_HORSE):
            if (resultCode == Activity.RESULT_OK)
                selectedGun = data.getData();
        break;

        default: break;
    }
}


原生 Android 动作

  • ACTION_ALL_APPS
  • ACTION_ANSWER
  • ACTION_BUG_REPORT
  • ACTION_CALL
  • ACTION_CALL_BUTTON
  • ACTION_DELETE
  • ACTION_DIAL
  • ACTION_EDIT
  • ACTION_INSERT
  • ACTION_PICK
  • ACTION_SEARCH
  • ACTION_SEARCH_LONG_PRESS
  • ACTION_SENDTO
  • ACTION_SEND
  • ACTION_VIEW
  • ACTION_WEB_SEARCH
  • ACTION_INSTALL_PACKAGE

安装android应用:

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setDataAndType(Uri.fromFile(new File("/sdcard/qq.apk"), "application/vnd.android.package-archive");
startActivity(intent);

可以通过 putExtrasetData 等方法去传


Intent FLAG

  • FLAG_ACTIVITY_CLEAR_TOP 用来标记,要跳转的Activity之上的其他Activity都被销毁。
  • FLAG_ACTIVITY_NEW_TASK 用来标记,如果两个程序之间的Activity跳转,当用户点击操作栏的图标返回时可以返回到第一个程序的Activity


Linkify 简介

Linkify 是一个辅助类,能够自动的通过RegEx匹配到 TextView 中的文本,创建 Intent 超链接,例如:电话号码、邮箱地址,等于默认包装了隐式的 Intent 对象。

通过 Linkify 类的 addLinks 静态方法添加 对应的检测类型:

TextView textView = findViewById(R.id.textView);
Linkify.addLinks(textView, Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES);

也可以通过 XML 配置文件配置,通过设置 android:autoLink 属性来在一个布局内部链接视图,支持一个或多个值:none、web、email、phone、all

创建定制的链接字符串

也可以自定义一个匹配的正则表达式,然后指定一个对应的 Intent Uri,当匹配到了,自动封装 对应 Uri 的 Intent

String baseUri = "content://com.example.earthquake/earthquake";

PackageManager pm = getPackageManager();
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(baseUri));
boolean activityExists = intent.resolveActivity(pm) != null;

if (activityExists) {
    int flags = Pattern.CASE_INSENSITIVE;
    Pattern p = Pattern.compile("\\bquake[\\s]?[0-9]+\\b", flags);
    Linkiry.addLinks(textView, p, baseUri);
}