相比显性Intent,隐性Intent不用指定目的Activity.class,而是设置Action和Category等信息,然后交由系统去分析这个Intent,并找到适合的Activity启动。
打开AndroidManifest.xml,代码如下:
<activity android:name=".DestinationActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> |
Action属性的值为一个字符串,它代表了系统中已经定义了一系列常用的动作。通过setAction()方法或在清单文件AndroidManifest.xml中设置,默认为:DEFAULT。Category属性用于指定当前动作(Action)被执行的环境。通过addCategory()方法或在清单文件AndroidManifest.xml中设置,默认为:CATEGORY_DEFAULT。<intent-filter>用于响应intent的Action和Category进行过滤,只有intent提交的Action和Category与注册在<intent-filter>中的Action和Category相匹配才能启动Activity。Action和Category即可以自定义,也可以使用系统内置的,系统内置了大量预定义的Action和Category,以下是常见的举例:
标准Action
ACTION_MAIN | Android Application的入口,每个Android应用必须且只能包含一个此类型的Action声明。 |
ACTION_VIEW | 系统根据不同的Data类型,通过已注册的对应Application显示数据。 |
ACTION_EDIT | 系统根据不同的Data类型,通过已注册的对应Application编辑示数据。 |
ACTION_DIAL | 打开系统默认的拨号程序,如果Data中设置了电话号码,则自动在拨号程序中输入此号码。 |
ACTION_CALL | 直接呼叫Data中所带的号码。 |
ACTION_ANSWER | 接听来电。 |
ACTION_SEND | 由用户指定发送方式进行数据发送操作。 |
ACTION_SENDTO | 系统根据不同的Data类型,通过已注册的对应Application进行数据发送操作。 |
ACTION_ATTACH_DATA | 别用于指定一些数据应该附属于一些其他的地方,例如,图片数据应该附属于联系人 |
ACTION_PICK | 从数据中选择一个子项目,并返回你所选中的项目 |
ACTION_CHOOSER | 显示一个activity选择器,允许用户在进程之前选择他们想要的 |
ACTION_GET_CONTENT | 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音) |
ACTION_INSERT | 插入一条空项目到已给的容器 |
ACTION_DELETE | 从容器中删除已给的数据 |
ACTION_RUN | 运行数据,无论怎么 |
ACTION_SYNC | 同步执行一个数据 |
ACTION_PICK_ACTIVITY | 为已知的Intent选择一个Activity,返回别选中的类 |
ACTION_SEARCH | 执行一次搜索 |
ACTION_WEB_SEARCH | 执行一次web搜索 |
ACTION_FACTORY_TEST | 工场测试的主要进入点 |
广播Action
ACTION_TIME_TICK | 当前时间改变,每分钟都发送,不能通过组件声明来接收,只有通过Context.registerReceiver()方法来注册 |
ACTION_TIME_CHANGED | 时间被设置 |
ACTION_TIMEZONE_CHANGED | 时间区改变 |
ACTION_BOOT_COMPLETED | 系统完成启动后,一次广播 |
ACTION_PACKAGE_ADDED | 一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播) |
ACTION_PACKAGE_CHANGED | 一个已存在的应用程序包已经改变,包括包名 |
ACTION_PACKAGE_REMOVED | 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播) |
ACTION_PACKAGE_RESTARTED | 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播) |
ACTION_PACKAGE_DATA_CLEARED | 用户已经清除一个包的数据,包括包名(清除包程序不能接收到这个广播) |
ACTION_BATTERY_CHANGED | 电池的充电状态、电荷级别改变,不能通过组建声明接收这个广播,只有通过Context.registerReceiver()注册 |
ACTION_UID_REMOVED | 一个用户ID已经从系统中移除 |
常见Category
CATEGORY_DEFAULT | Android系统中默认的执行方式,按照普通Activity的执行方式执行 |
CATEGORY_HOME | 设置该组件为Home Activity |
CATEGORY_PREFERENCE | 设置该组件为Preference |
CATEGORY_LAUNCHER | 设置该组件为在当前应用程序启动器中优先级最高的Activity,通常为入口ACTION_MAIN配合使用 |
CATEGORY_BROWSABLE | 设置该组件可以使用浏览器启动 |
CATEGORY_GADGET | 设置该组件可以内嵌到另外的Activity中 |
在使用intent时,可以附件Data和Extras,Data通常是URI格式定义的操作数据。例如:tel:// 。通过setData()方法设置;Extras属性主要用于传递目标组件所需要的额外的数据。通过putExtras()方法设置。
常见Data
tel:// | 号码数据格式,后跟电话号码 |
mailto:// | 邮件数据格式,后跟邮件收件人地址 |
smsto:// | 短息数据格式,后跟短信接收号码 |
content:// | 内容数据格式,后跟需要读取的内容 |
file:// | 文件数据格式,后跟文件路径 |
market://search?q=pname:pkgname | 市场数据格式,在Google Market里搜索包名为pkgname的应用 |
geo://latitude,longitude | 经纬数据格式,在地图上显示经纬度指定的位置 |
常见Extras
EXTRA_BCC | 存放邮件密送人地址的字符串数组 |
EXTRA_CC | 存放邮件抄送人地址的字符串数组 |
EXTRA_EMAIL | 存放邮件地址的字符串数组 |
EXTRA_SUBJECT | 存放邮件主题字符串 |
EXTRA_TEXT | 存放邮件内容 |
EXTRA_KEY_EVENT | 以KeyEvent对象方式存放触发Intent的按键 |
EXTRA_PHONE_NUMBER | 存放调用ACTION_CALL时的电话号码 |
在intent-filter中指定data属性的实际目的是:要求接收的Intent中的data必须符合intent-filter中指定的data属性,这样达到反向限定Intent的作用
例如:在AndroidManifest.xml 中进行如下设置:
<activity android:name=".TestActivity"> <intent-filter> <action android:name="com.jony.test"/> <data android:scheme="file"/> </intent-filter> </activity> |
那么启动该Activity的Intent必须进行如下设置:
Intent intent = new Intent(); Uri uri = Uri.parse("file://com.android.test:520/mnt/sdcard"); intent.setData(uri); |
data属性解析:android:scheme、android:host、android:port、android:path、android:mimeType
data的前四个属性构成了URI的组成部分,mimeType设置了数据的类型
data元素组成的URI模型如下:
scheme://host:port/path
举例说明:
URI file://com.android.jony.test:520/mnt/sdcard
scheme-->file:
host-->com.android.jony.test
port-->520
path-->mnt/sdcard
其中host和port为URI的authority,如果没有指定host,port将被忽略
data的各属性并不是独立的,data的各属性构成了URI的整个组成部分。要使authority(host和port)有意义,必须指定scheme;要使path有意义,必须使scheme和authority(host和port)有意义。
URI和intent-filter匹配:
Intent中URI和intent-filter进行比较的时候只会进行部分的比较:
(1)当intent-filter中只设置了scheme,只会比较URI的scheme部分;
(2)当intent-filter中只设置了scheme和authority,那么只会匹配URI中的scheme和authority;
(3)当intent-filter中设置了scheme、authority和path,那么只会匹配URI中的scheme、authority、path;(path可以使用通配符进行匹配)
- 当intent-filter中设置了mimeType,还会进行数据类型的匹配。
总结:
(1)在AndroidMainfest.xml 中对每一个Activity都做了说明——intent-filter,intent-filter声明了需要接收怎样的Intent,当发送的Intent和intent-filter中定义的相符合,就会启动相应的Activity;
(2)当有多个Activity符合发送的Intent时,Android系统会列出所有满足Intent的Activity,用户可以通过选择进行相关的操作;
(3)在一个Activity的intent-filter中可以有多个action、多个category、多个data,这样可以有多种组合与Intent进行匹配。注意:如果在一个Activity中有多个Intent进行匹配的时候,建议使用多个intent-filter与Intent进行匹配。猜测:这样应该可以提高Intent的匹配速度。
- data属性,这是一个进行反向限制Intent的操作,要求Intent的data必须是intent-filter中声明的数据之一(因为在一个intent-filter中可以设置多个data)。注意:如果要启动目标Activity,但是指定的data数据类型与Activity中data数据类型不匹配,将会造成ActivityNotFoundException异常。
// 调用浏览器
Uri webViewUri = Uri.parse("http://blog.csdn.net/zuolongsnail");
Intent intent = new Intent(Intent.ACTION_VIEW, webViewUri);
// 调用地图
Uri mapUri = Uri.parse("geo:100,100");
Intent intent = new Intent(Intent.ACTION_VIEW, mapUri);
// 播放mp3
Uri playUri = Uri.parse("file:///sdcard/test.mp3");
Intent intent = new Intent(Intent.ACTION_VIEW, playUri);
intent.setDataAndType(playUri, "audio/mp3");
// 调用拨打电话
Uri dialUri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent.ACTION_DIAL, dialUri);
// 直接拨打电话,需要加上权限<uses-permission id="android.permission.CALL_PHONE" />
Uri callUri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent.ACTION_CALL, callUri);
// 调用发邮件(这里要事先配置好的系统Email,否则是调不出发邮件界面的)
Uri emailUri = Uri.parse("mailto:zuolongsnail@163.com");
Intent intent = new Intent(Intent.ACTION_SENDTO, emailUri);
// 直接发邮件
Intent intent = new Intent(Intent.ACTION_SEND);
String[] tos = { "zuolongsnail@gmail.com" };
String[] ccs = { "zuolongsnail@163.com" };
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT, "the email text");
intent.putExtra(Intent.EXTRA_SUBJECT, "subject");
intent.setType("text/plain");
Intent.createChooser(intent, "Choose Email Client");
// 发短信
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra("sms_body", "the sms text");
intent.setType("vnd.android-dir/mms-sms");
// 直接发短信
Uri smsToUri = Uri.parse("smsto:10086");
Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);
intent.putExtra("sms_body", "the sms text");
// 发彩信
Uri mmsUri = Uri.parse("content://media/external/images/media/23");
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "the sms text");
intent.putExtra(Intent.EXTRA_STREAM, mmsUri);
intent.setType("image/png");
// 卸载应用
Uri uninstallUri = Uri.fromParts("package", "com.app.test", null);
Intent intent = new Intent(Intent.ACTION_DELETE, uninstallUri);
// 安装应用
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File("/sdcard/test.apk"), "application/vnd.android.package-archive");
// 在Android Market中查找应用
Uri uri = Uri.parse("market://search?q=愤怒的小鸟");
Intent intent = new Intent(Intent.ACTION_VIEW, uri); |