[TOC]
1. 显式Intent
一般在构造intent的对象的时候,就指定了它的意图,通常用在程序内,知道具体的要启动哪一个activity的时候.
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
复制代码
activity类提供了一个专门用于启动活动的方法,此外还有startSearch();用于启动服务
Intent,第一个参数Context,要求提供一个启动活动的上下文,第二个参数Class,则是指定想要启动的目标活动,这样就构造出了intent的意图.
2. 隐式Intent
它并不明确指出需要启动哪个活动,而是交给系统去解析intent,通过与action和category的配对来启动合适的activity,如果没有匹配到相应的activity则这个程序会抛出异常并停止运行.
一个Intent只能指定一个action,但是可以指定多个category
通过解析,将Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。
Intent intent=new Intent("intent1");
//intent.addCategory(Intent.CATEGORY_DEFAULT);
//此处并不需要添加category 因为这是一个默认的category,调用下面的时候会自动添加上这个category
startActivity(intent);
复制代码
只有action和category中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应该Intent
3. Intent Filter匹配规则
Intent Filter就是Intent的过滤器,当我们隐式的启动系统组件的时候,就会在AndroidManiFest.xml中根据IntentFilter来筛选除合适的活动来进行启动.
现在我们知道了可以在Intent
启动的时候对应设置Action
、Category
、DataAndType
,这里设置的是为了过滤的时候对应IntentFilter
匹配action
、category
、data
。
除开过滤广播的的IntentFilter
可以在代码中创建外,其它的IntentFilter
都得在AndroidManifest.xml
中给设置。
AndroidManiFest.xml中,每个组件可以有多个(IntentFilter)过滤器,但只要一个满足,就会启动这个activity
3.1 action匹配规则
Intent intent=new Intent("intent1");
//intent.setAction("...");
复制代码
通过给intent指定一个action(一个intent只能指定一个aciton,但可以指定多个category)来进行匹配,上面的两种方法都可以.
3.2 category匹配规则
每个过滤器可以有多个category,但是在Intent中必须把过滤器中的所有category加上,否则是无法匹配成功的.
intent发起意图的时候,并不是不需要category,只是它默认的会给这个intent添加一个默认的category,所以意图过滤器中必须加上默认的category(),否则因为intent会自动附加默认的category,就会造成匹配失败.
3.3 data的匹配规则
只有标签中指定的内容和Intent中携带的Data完全一致的时候,当前活动才可以响应该Intent
不过一般在标签中都不会指定过多的内容 比如 android:scheme 为http的时候,就可以响应所有http的intent了.
data主要包括的就是一个URI和mimeType ,URI资源类型符,mimeType媒体类型
标签中包含了以下几种子元素,他们定义了url的匹配规则:
android:scheme 匹配url中的前缀,除了“http”、“https”、“tel”...之外,我们可以定义自己的前缀
android:host 匹配url中的主机名部分,如“google.com”,如果定义为“*”则表示任意主机名
android:port 匹配url中的端口
android:path 匹配url中的路径
如果过滤器只是单纯的设置URI或者只设置了mimeType的话可以在初始化intent对象的时候调用setData(String ..)或者setType(String ..)
但是,如果URI和mimeType都需要设置的话,则需要调用SetDataAndType(String ..., String ...); 这个方法了,因为如果先调用setData,再调用setType()方法的时候,它会清除掉前一个setData的数据,所以为了避免匹配失败,要看清楚需要匹配哪些东西.
public @NonNull Intent setData(@Nullable Uri data) {
mData = data;
mType = null;
//type会被设置为空
return this;
}
复制代码
public @NonNull Intent setType(@Nullable String type) {
mData = null; //data会被设置为空
mType = type;
return this;
}
复制代码
public @NonNull Intent setDataAndType(@Nullable Uri data, @Nullable String type) {
mData = data;
mType = type;
//不会被设置为空
return this;
}
复制代码
3.4 通过data调用系统应用
intent.setData(Uri.parse(":"));
这个方法可以自动的判断 前:后 前就是这个数据的类型,后就是数据
我们可以将一个指定前缀的字符串转换成特定的URI类型,如:“http:”或“https:”表示网络地址类型,“tel:”表示电话号码类型,“mailto:”表示邮件地址类型,等等。
Intent intent=new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:123456"));
startActivity(intent);
复制代码
3.5 android.intent.action.MAIN 与android.intent.category.LAUNCHER的区别(参考了:猴子搬来的救兵Castiel)
区别一: android.intent.action.MAIN决定一个应用程序最先启动那个组件 android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里(说白了就是是否在桌面上显示一个图标) 这两个属性组合情况: 第一种情况:有MAIN,无LAUNCHER,程序列表中无图标 原因:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里 第二种情况:无MAIN,有LAUNCHER,程序列表中无图标 原因:android.intent.action.MAIN决定应用程序最先启动的Activity,如果没有Main,则不知启动哪个Activity,故也不会有图标出现 所以这两个属性一般成对出现。 如果一个应用中有两个组件intent-filter都添加了android.intent.action.MAIN和 android.intent.category.LAUNCHER这两个属性, 则这个应用将会显示两个图标, 写在前面的组件先运行。 区别二:
android.intent.category.LAUNCHER:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里,就是android开机后的主程序列表。 android.intent.category.HOME:按住“HOME”键,该程序显示在HOME列表里。
4. 决解隐式Intent匹配失败时的程序崩溃
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:123456"));
PackageManager packageManager = getPackageManager();
List<ResolveInfo> mInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (mInfo.size() != 0) {
startActivity(intent);
} else {
Log.d("TAG", "onCreate: 匹配不到");
}
复制代码
上面的方法可以获取到匹配成功的集合,如果为0就表示匹配不到,这是条件选择不执行启动就不会导致程序崩溃了
5. Intent Filter匹配的优先级
Intent-Filter 按照以下优先关系查找 : action>category>data
6. 通过Intent启动其他的应用程序
7. 通过intent跨Activity传输数据
intent.putExtra("text",1);
//通过intent传递值 启动另一个activity
.....
Intent intent1=getIntent();
int x=intent1.getIntExtra("text",0);
//获取上一个activity传递过来的值
//也可以获取一个其他类型的对象,不过该对象来实现序列化接口才可以传递过来
复制代码