一、Intent
1、意图分类:
- 显示意图:指定了目标组件名的意图对象.
- 隐式意图:没有指定目标组件名的意图对象,它通过意图过滤器中的action,category,data进行匹配找到要启动的目标组件。
2、隐式意图匹配
-
规则一:一个意图过滤器(intent-filter)至少包含一个action,否则它将阻塞所有意图匹配成功.
-
规则二:一个意图(intent)中至少包含一个action,否则它将永远不会匹配成功.
-
规则三:当采用隐式意图使用startActivity(intent)方法激活目标组件时,由于方法startActivity(intent)
内部会自动做如下动作:
intent.addCategory(“android.intent.category.DEFAULT”);因此intent中必须包含category=“android.intent.category.DEFAULT”
的类别,因此如果目标Activity想匹配成功,则必须在意图过滤器中包含
的类别,否则肯定不会匹配成功. -
规则四:如果意图过滤器中有的东西,在意图中可以没有照样匹配成功,反过来,如果意图中有的东西,在意图过滤器中没有则一定不会匹配成功.
-
规则五:在一个activity中可以写多个意图过滤器,只要有一个能够和intent中的信息匹配成功则就可以激活目标组件。
-
规则六:如果在意图过滤器中指定了mimeType则在意图中也必须指定相同的mimeType,否则匹配失败.
-
规则七:如果在意图过滤器中指定了scheme,则在意图中设置data时必须也指定相同的scheme,否则匹配失败;如果同时在意图过滤器中也指定了host,那么只有当intent中data的内容也能和意图过滤器中的scheme和host相匹配才能成功. 如果同时指定了path或者android:pathPrefix或者android:pathPattern,那么意图中如果指定的data的内容整个和path或者android:pathPrefix或者android:pathPattern匹配成功即可匹配成功.
-
规则八:如果在意图过滤器中只设置了data没有设置type,那么意图中也只能设置data不能设置type才能匹配成功.
intent.setData(data); -
规则九:如果在意图过滤器中只设置了type没有设置data,那么意图中也只能设置type不设置data才能匹配成功.
intent.setType(type); -
规则十:如果在意图过滤器中同时设置了data和type,那么在意图中也必须同时设置data和type才能匹配成功.
intent.setDataAndType(data,type);显示意图和隐式意图的使用场景:
1.显示意图一般都使用在同一个应用程序中
2.隐式意图可以应用在用一个应用程序中,也可以用于在不同的应用程序中,由于隐式意图需要通过和意图过滤器中的action,category,data进行匹配从而找到要激活的目标组件,因此效率比较低,所以在同一个应用程序中一般都使用显示意图,在不同的应用程序中才使用隐式意图。
二、action、Category
- 结论一:如果意图过滤器中没有任何Action,则不管Intent中有多少个action都不会匹配成功.
- 结论二:如果意图中没有任何Action,不管意图过滤器中有多少个Action都不会匹配成功.
- 结论三:如果意图中含有的东西,则意图过滤器中必须含有,否则匹配失败.
- 结论四:如果意图过滤器中有的东西可以多于意图中含有的东西也能匹配成功.
- 结论五:一个Activity标签中可以写多个,只要有其中一匹配成功即可激活目标组件.
实例化意图对象并指定动作的方式一:通过构造函数
Intent intent=new Intent("android.intent.action.hsj");
实例化意图对象并指定动作的方式二:通过调用intent.setAction(action);设置动作
Intent intent=new Intent();
intent.setAction("android.intent.action.hsj");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.addCategory("android.intent.category.DEFAULT");
上述两行代码的功能完全相同.
如果通过隐式意图激活目标组件,则startActivity(intent)方法内部会自动执行如下代码:
intent.addCategory("android.intent.category.DEFAULT");
因此在意图被发送出去时其中函数的内容为:
action="android.intent.action.hsj"
category="android.intent.category.DEFAULT"
需要注意的是:category内容的值是在调用startActivity(intent)方法时在系统内部自动添加的,用户无法干预.
三、Data
- 结论一:如果在data中指定了scheme,则在意图中指定URI时必须要求URI的协议和data中的scheme指定的协议相同,否则匹配失败.
- 结论二:如果在指定scheme的同时,也指定了host,则在意图中指定URI时必须要求URI的scheme和host必须和data中指定的scheme和host向匹配,否则匹配失败.
- 结论三:如果在指定scheme,host的同时也指定了port,则在意图中指定URI时必须要求port也匹配,否则失败!
- 结论四:如果在指定scheme,host,port的同时,也指定了path,则必须要求path的值和URI中的路径完全匹配,否则失败.
path必须和URI中指定的Path精确匹配.
- android:path="/hsj/wcf/index.html":path属性要求值精确匹配
- android:pathPrefix="/hsj":pathPrefix要求只要路径部分的前缀匹配即可,需要注意:区分大小写.
- android:pathPattern="/.*":正则表达式匹配.
- android:pathPattern="/hsj/.*/index.html"
- android:scheme=“hsj” android:host=“www.baidu.com” - android:port=“80”
- android:pathPrefix="/hsj"
总结:
通过隐式意图激活详情activity
-
结论一:如果意图过滤器中没有任何Action,则不管Intent中有多少个action都不会匹配成功.
-
结论二:如果意图中没有任何Action,不管意图过滤器中有多少个Action都不会匹配成功.
-
结论三:如果意图中含有的东西,则意图过滤器中必须含有,否则匹配失败.
-
结论四:如果意图过滤器中有的东西可以多于意图中函数的东西也能匹配成功.
-
结论五:一个Activity标签中可以写多个,只要有其中一匹配成功即可激活目标组件.
-
结论六:如果在意图过滤器中指定了data,并且在意图中也指定URI的话,则要求URI的scheme和意图过滤器中data标签的属性
scheme的值项匹配,否则匹配失败! -
结论七:如果在意图中指定了data,则意图过滤器中也必须指定相匹配的data规则才能匹配成功.
-
结论八:如果在意图中指定了mimeType,则在意图过滤器中也必须指定mimeType才能匹配成功.
-
结论九:如果在意图中同时指定了data和mimeType则意图过滤器中也必须同时指定data和mimeType才能匹配成功.
脚下留心:
如果想在意图中同时指定data和type,则一定不能调用intent.setData()和intent.setType()来同时设置
data和type,因为setData()会将之前设置的setType()的值删除,setType()会将之前设置的setData()中设置的值删除.
综上所述,要想同时设置data和type,则只能调用intent.setDataAndType(data,type);
四、通过Intent调用常见系统组件
- 调用浏览器
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:[email protected]");
Intent intent = new Intent(Intent.ACTION_SENDTO, emailUri);
- 直接发邮件
Intent intent = new Intent(Intent.ACTION_SEND);
String[] tos = { "[email protected]" };
String[] ccs = { "[email protected]" };
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);