(1)启动Activity分为两种,显示调用和隐式调用。显示调用需要明确的指定被启动对象的组件信息,包括包名和类名;而隐式意图则不需要明确指定调用信息。原则上一个intent不应该即是显式又是隐式调用,如果二者共存的话以显式调用为主。
(2)隐式调用需要intent能够匹配目标组件的IntentFilter中所设置的过滤信息,一个Activity钟可以有多个intent-filter,一个intent只要能匹配一组intent-filter即可成功启动Activity,如下代码:
(3)intent到底发给哪个activity,需要进行三个匹配:action、category和data。
(1)action是一个字符串,系统预定了一些actio,同时我们也可以在应用中定义自己的action。
(2)action要求Intent中必须有一个action,且必须和过滤规则中的某一个action相同。另外,action区分大小写,大小写不同的字符串匹配也会失败。
(1)category是一个字符串,系统预定义了一些category,同时我们也可以在应用中定义自己的category。
(2)category要求Intent可以没有category,但是如果一旦有category,不管有几个,每个都要能和过滤规则中的任何一个category相同。
为了匹配前面的过滤规则中的category,可出下面的
①Intent,intent.addcategory (“com.ryg.category.c”);
②或者Intent.addcategory (“com rcategory.d);
③亦或者不设category
(3)为什么不设置category也可以匹配呢?
因为在调用startActivity或者startActivityForResult的时候会默认为Intent加上“android.intent.category.DEFAULT”这个category,所以这个category就可以匹配前面的过滤规则中的第三个category。同时,为了我们的activity能够接收隐式调用,就必须在intent-filter中指定“android intent categor.DEFAULT”这个category,原因刚才已经说明了。
(4)我们定义的activity如果接受隐式intent的话,intent filer就一定要加上android.intent.category.DEFAULT这个category。
(5)学习链接
我们需要什么时候加android.intent.category.DEFAULT呢?
data由两部分组成,mimeType和URI,前者是媒体类型,比如image/jpeg等,可以表示图片等;而URI包含的数据可就多了,下面的URI的结构:
://:/[||]
// 例子
content://com.seniorlibs.lifecycle:200/folder/subfolder/etc
http://www.baidu.com:80/search/info
(1)Scheme:URI的模式,比如http、file、content等。如果URI中没有指定的scheme,那么整个URI的其他参数无效,这也意味着URI无效。
(2)Host:URI的主机,比如"www.baidu.com"。如果host未指定,那么整个URI中的其他参数无效,这也意味着URI无效。
(3)Port:URI中的端口号,比如80,不过需要指定上面两个才有意义。
(4)Path、pathPattem和pathPrefix:这三个参数表述路径信息,其中path表示完整的路径信息;pathPattern也表示完整的路径信息,但是它里面可以包含通配符“ * ”,“ * ” 表示0个或多个任意字符,需要注意的是,由于正则表达式的规范,如果想表示真实的字符串,那么“* ” 要写成 “ *”,“ \ ”要写成“ \ ”;pathPrefix表示路径的前缀信息。
data的匹配规则和action类似,它要求Intent中必须含有data数据,并且data数据能够完全匹配过滤规则中的某一个data,这里的完全匹配是指过滤规则中出现的data部分也出现在了Intent中的data中。
(1)如下过滤规则
过滤规则没有指定URI,但是却有默认值,URI的默认值为content何file。也就是说,虽然没有指定URI,但是Intent中的URI部分的scheme必须为content或者file才能匹配,如下:
intent.setDataAndType(Uri.parse("file://abc"),"image/png");
另外,如果要为Intent指定完整的data,必须调用setDataAndType方法,不能县调用setData在调用setType,因为这两个方法彼此会清除对方的值:
// setData会把类型设置为null,同样的,对方也是
public Intent setData(Uri data) {
mData = data;
mType = null;
return this;
}
(2)如下过滤规则
// 指出了完整的属性值,既有URI又有类型
intent.setDataAndType(Uri.parse("http://abc"),"video/png");
// 或者
intent.setDataAndType(Uri.parse("http://abc"),"audio/png");
// 两个intent-filter作用一样
Intent intent = new Intent();
// Action只能设置一个,重复设置即被替换,Action是"com.ryg.charpter_1.c"
intent.setAction(Intent.ACTION_VIEW);
intent.setAction("com.ryg.charpter_1.c");
intent.putExtra("time", System.currentTimeMillis());
// Category可以添加多个,但是intent中添加的都必须在规则中匹配。Category包括"com.ryg.category.c"和"android.intent.category.DEFAULT"。
intent.addCategory("com.ryg.category.c");
intent.setDataAndType(Uri.parse("file://abc"), "text/plain");
startActivity(intent);
String url = "http://app.cn/index.php/articledesc?id=10943&uid=111&isopen=好好";
//将String类型的地址转变为URI类型
Uri uri = Uri.parse(url);
//通过URI的getQueryParameter()获取参数值
String id= uri.getQueryParameter("id"); //id 值 10943
String uid= uri.getQueryParameter("uid");//uid 值 111
String isopen= uri.getQueryParameter("isope");//isopen 值 好好
(1)方法介绍
public abstract ListqueryIntentActivities(Intent intent,int fladgs);
第二个参数需要注意,要使用MATCH_DEFAULT_ONLY这个标记位,这个标记位的含义是仅仅匹配那些在intentfilter中声明了 < category android-name=”android.intent.category DEFAULT”>这个category的Activity。使用这个标记位的意义在于,只要上述两个方法不返回null,那么startActivity一定可以成功。
如果不用这个标记位,就可以把intent-filter中category不含DEFAULT的那些Activity给匹配出来,从而导致startActivity可能失败。因为不含有DEFAULT这个category的Activity是无法接收隐式Intent的。在action和 category中,有一类action和category比较重要,他们是:
// 共同作用是用来标明这是一个入口Activity并且会出现在系统的应用列表中,
// 少了任何一个都没有实际意义,也无法出现在系统的应用列表中
(2)模板例子
// 浏览器
public static final int THIRD_ACTIVITY_BROWSABLE = 1;
// 微信
public static final int THIRD_ACTIVITY_WEIXIN = 2;
/**
* 跳转第三方应用
* 通过隐式Intent的跳转,在发出Intent之前必须通过resolveActivity检查,避免找不到合适的调用组件,造成ActivityNotFoundException的异常
*
* @param context
* @param url
*/
public static boolean openThirdActivity(Context context, String url, int name) {
if (context == null || TextUtils.isEmpty(url)) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
if (name == THIRD_ACTIVITY_BROWSABLE) {
intent.addCategory(Intent.CATEGORY_BROWSABLE);
}
if (context.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
try {
context.startActivity(intent);
return true;
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (name == THIRD_ACTIVITY_BROWSABLE) {
ToastUtils.showToast(context, "浏览器未安装"));
} else if (name == THIRD_ACTIVITY_WEIXIN) {
ToastUtils.showToast(context, "微信未安装"));
}
}
return false;
}
// 1、外部浏览器
ActivityUtils.openThirdActivity(activity, deploy.onClickUrl, ActivityUtils.THIRD_ACTIVITY_BROWSABLE);
// 2、外部调起微信url前缀
ActivityUtils.openThirdActivity(context, "weixin://", ActivityUtils.THIRD_ACTIVITY_WEIXIN);
// 2、微信
ActivityUtils.openThirdActivity(UCActivity.this, "weixin://", ActivityUtils.THIRD_ACTIVITY_WEIXIN);
它不是返回最佳匹配的Activity信息而是返回所有成功匹配的Activity信息,
public abstract ListqueryIntentActivities(Intent intent,int fladgs);
Android开发艺术探索笔记——第一章:Activity的生命周期和启动模式