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 接收的参数:
- 请求码:父 Activity 的请求码
- 结果码:子 Activity 的结果码,用来说明结果状态。
- 数据: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);
可以通过 putExtra
和 setData
等方法去传
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);
}