隐式Intent,IntentFilter与Uri

参考

        参考1

        参考2

Intent

概述

        Intent对象可以向操作系统描述我们需要处理的任务。使用显式Intent,我们需要指定具体的类名;而使用隐式Intent,我们只需要向操作系统描述清楚我们的工作意图,操作系统会去启动那些对外宣称能够完成任务的activity(即能匹配成功intent-filter的)。如果操作系统找到多个activity,那么用户将会看到可选列表,然后看用户自己如何选择了。通过隐式意图启动一些组件时,必须满足该组件所对应的<intent-filter>。

        虽然隐式意图也可以带extra数据,但操作系统在寻找合适的activity时并不会使用任何附加在隐式意图上的extra信息。这并不意味着隐式意图上的extra信息没有用,同显式意图一样,intent一样会将它所带的extra信息带到寻找到的activity中

flag

        FLAG_ACTIVITY_NEW_TASK:例如现在栈1的情况是:A B C。C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK标记,如果D这个Activity在Manifest.xml中的声明中添加了Task affinity,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。如果D的Task affinity默认没有设置,则会把其压入栈1,变成:A B C D,这样就和不加FLAG_ACTIVITY_NEW_TASK标记效果是一样的了。(参见)。注意:从非activity开启activity的话,必须为intent设置该标签

        FLAG_ACTIVITY_NO_HISTORY:当前启动的activity不会在栈中存在,也就是说,按返回键的时候是没有办法返回到该activity的。和<activity>中的noHistory=true是一样的效果。

<intent-filter>

下面是一个清单文件中的intent-filter
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="http" />
                <data android:scheme="https" />
                <data android:scheme="inline" />
                <data android:mimeType="text/html"/>
                <data android:mimeType="text/plain"/>
                <data android:mimeType="application/xhtml+xml"/>
                <data android:mimeType="application/vnd.wap.xhtml+xml"/>
            </intent-filter>
可以看出<intent-filter>有三个子结点<action>,<category>,<data>。

<action>

        它指的是intent要执行的操作,比如当前的intent想获取某个内容(比如照相等) 可以通过Intent.setAction()来为intent对象设置action,它会自动匹配<intent-filter>中的<action>结点。 
        从Intent#setAction()的方法名可以看出,一个Intent只能含有一个action属性。所以getAction()返回的是String,而不是一个集合。
        匹配规则:一个<Intent-filter>中可能含有多个<action>,只要能和其中的任意一个完全一样就算匹配成功。另外,action区分大小写。并且,如果Intent中没有指定action,那也匹配失败

<category>

        它指intent的可选类别,常用来描述我们何时、何地甚至如何使用某个activity。通过Intent#addCategory()为Intent对象设置category。它会自动匹配<intent-filter>中的<category>结点。

        设置category时,用的是add,而且Intent#getCategories()返回的是一个Set集合,这表明一个Intent可以含有多个category。同理<intent-filter>中也可以设置多个<category>。

        匹配规则:如果Intent中没有定义category属性,那么会匹配成功。如果Intent中定义了category,无论是多少个,每一个都必须是在<intent-filter>中定义过的,否则会匹配不成功。也就是说addCategory()指定的category值必须是<category>指定的子集

此处需注意一点

        如果该intent传入到startActivity()中当作参数,系统会默认的加上一个值为android.intent.category.DEFAULT的category。因此,如果<intent-filter>没有设置<category android:name="android.intent.category.LAUNCHER" />它是不会被隐式意图启动的。

<data>

        要操作的数据及数据类型。可以通过Intent.setType(),Intent.setData()和Intent.setDataAndType()为Intent对象设置数据和数据类型。前两个方法分别用来设置类型和数据,但由于setType()与setData()两个方法互斥,后写的方法会清空掉前写的方法所设置的值,所以如果同时要设置type与data应调用Intent.setDataAndType(),而不是分别调用前两个方法。

        匹配规则:如果Intent中没有设置data,但<intent-filter>中定义了,则匹配不成功。其余见下面Uri部分。

它的具体属性值如下:

        android:mimeType,应该通过intent.setType(type)来匹配mimeType的值,表示数据类型。

        android:scheme:指向的是Uri中的scheme的值。

        android:path:指向的是Uri中的path的值。

        android:port:指向的是Uri中的port的值。

        android:host:指向的是Uri中的host的值。

Uri

        Intent.setData()中的参数是一个Uri,而对于一个Uri来说,它的标准样式如下:

scheme://host:port/path

        当没有设置host的值时,port,path的值是无效的,并且data并不是完全匹配的。只要传入的Uri中的scheme,host,port,path分别满足<intent-filter>中的对应的值,该activity就会启动。假如:一个<intent-filter>中设置了scheme,host,port。而一个Uri中的scheme,host,port匹配相应的值,而且该Uri中还有path,那么这个<intent-filter>对应的activity也会启动。例如下面的intent是可以匹配下面的intent-filter,虽然intent比<intent-filter>在data上多了host值

Intent对象

Intent intent = new Intent("xx");
intent.addCategory("xxxx");
intent.setData(Uri.parse("ab://dafdaf"));
startActivity(intent);
intent-filter
<intent-filter>
                <action android:name="xx" />
                <category android:name="xxxx" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="ab"/>
            </intent-filter>

        如果Intent中没有传入Uri,也没有传入type,只有filter中同样没有指定uri和type时才能匹配成功。

注意事项

        在使用隐式意图调用别的activity时,如果没有activity满足该intent对象,那么程序就会崩溃。因此,在调用隐式意图之前需要判断有没有activity能满足当前的隐式意图。判断的代码如下:

	public boolean hasActivities(Intent intent) {
		PackageManager pm = getPackageManager();
		List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
		return activities.size() > 0;
	}

        当系统中有多个应用可以响应当前的intent,默认情况下会弹出一个dialog,让用户进行选择,并且在选择的时候设置成默认的打开应用。

        一旦将某个应用设置成默认的打开应用,那么下次该种类型的intent会直接使用该应用打开,而不会再弹出dialog让用户进行选择。如果想每一次都让用户进行选择,那么可以使用Intent.createChooser(Intent,String),其中第二个参数为弹出dialog中的title,第一个参数为要响应的intent。该方法也会返回一个intent对象,将该对象直接使用到startActivity或者startActivityForResult()中即可。

        一般地,第二个参数使用PackageManager.MATCH_DEFAULT_ONLY。该参数的含义是:仅匹配在<intent-filter>中添加了android.intent.category.DEFAULT的category,如果没有即使别的所有的都匹配成功也不会返回。这样就避免了在startActivity()的时候造成崩溃。这是因为startActivity()的时候,intent默认是添加上了DEFAULT的category,所以<intent-filter>中如果没有该值的话,在启动时是无法启动的,从而可能造成崩溃。










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值