@linux1s1s
2019-02-14T15:05:59.000000Z
字数 6320
阅读 2155
AndroidMechanism
2015-05
先来看一下Google 官方文档关于intent-filter的说明 或者 intent 的官方说明
看完上面的官方文档,我们来回答几个问题:
好了,看完上面的官方文档,如果你觉得回答不了上面的几个问题,那么有必要继续往下看了
在了解Intent-Filter
之前先来考虑这样一个场景,用过Android手机的人应该都知道,比如说我在某个App例如新浪微博中点击拍照,会跳转到照相机的界面。但是当我新装了camer360
或之类的第三方照相app的时候在微博中点击照相就会先弹出一个Dialog
来让我选择是使用默认camer
还是camer360
.
对于上面的场景,我们来看一下Android官方文档是如何解释上面一系列动作的。
为了看懂这张图,有必要说明一下Android生成Intent的两种方式:
显式Intent直接用组件的名称定义目标组件,这种方式很直接。但是由于开发人员往往并不清楚别的应程序的组件名称。因此,显式Intent更多用于在应用程序内部传递消息。
Intent intent = new Intent(MainActivity.this,SubActivity.class);
隐式Intent它不会用组件名称定义需要激活的目标组件,它更广泛地用于在不同应用程序之间传递消息。如果要跳转到一个未知路径,但是已知功能的Activity就要用到隐式intent。
Intent intent = new Intent(Intent.ACTION_SEND);
接下来我们把上面的情景模拟一下
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".BActivity"
android:label="@string/title_activity_main"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="com.h3c.intent.ACTION_VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name=".CActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="com.h3c.intent.ACTION_VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
然后在MainActivity代码中这样启动一个Activity会发生什么?
//隐式声明Intent实例
Intent intent = new Intent("com.h3c.intent.ACTION_VIEW");
startActivity(intent);
这时就会重现上面的情景,出现一个供用户可以选择的界面,让用户去决定选择哪个Activity。
如果不想让用户去选择怎么办,很简单,直接通过显示Intent来做即可
//显式声明Intent实例
Intent intent = new Intent(MainActivity.this,BActivity.class);
startActivity(intent);
接下来我们回到一开始的Document,看一看这些属性的含义
先来说一下必须包含的属性,action属性。
翻译成中文就是动作测试
<activity android:name="com.x210.intentfilters.OneActivity" android:label="oneActivity">
<intent-filter>
<action android:name="myapp.action.test1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.x210.intentfilters.OtherActivity" android:label="otherActivity">
<intent-filter>
<category android:name="cate1"/>
<category android:name="cate2"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
只能得到一个悲催的结局:任何Intent请求都无法与该匹配
<activity android:name="com.x210.intentfilters.OneActivity" android:label="oneActivity">
<intent-filter>
<action android:name="myapp.action.test1" />
<action android:name="myapp.action.test2" />
<action android:name="myapp.action.test3" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity> <span style="color:#ff0000">
凡是隐式声明中含有上面其中一个action都满足匹配要求,比如:
//action = myapp.action.test1
Intent intent = new Intent("myapp.action.test1");
startActivity(intent);
//action = myapp.action.test2
Intent intent = new Intent("myapp.action.test2");
startActivity(intent);
关于action说到这里,接下来说另外一个重要的属性category
接着说一下另外一个很重要的属性,类别测试,这个属性不是必须的,下面解释一下为什么不是必须的。
理论上来说,如果intent不指定category,那么无论intent filter的内容是什么都应该是匹配的。但是,如果是implicit intent,android默认给加上一个CATEGORY_DEFAULT,这样的话如果intent filter中没有android.intent.category.DEFAULT这个category的话,匹配测试就会失败。所以,如果你的 activity支持接收implicit intent的话就一定要在intent filter中加入android.intent.category.DEFAULT。
当然了,也不是所有的隐式申明都得加这个DEFAULT,比如下面这个:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
这个是启动主Activity,所以隐式申明的时候不用这个DEFAULT值。
除此之外,category的用途还有很多
比如做个桌面,按home键时启动自己做的应用
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.HOME" />
</intent-filter>
</activity>
另外顺便说一下,显试声明Intent,就是在代码里面生成Intent实例如何做,这个跟隐式声明没有啥区别,像下面这样
intent.setAction(action);intent.setData(data);intent.addCategory(category);
intent.setAction(action);
intent.setData(data);
intent.addCategory(category);
接下来说最后一个属性:data,数据测试
开始之前,我们先说一个比较意思的事情:假如主Activity这么声明会发生什么事情?
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:scheme="gametime" />
</intent-filter>
如果感兴趣的话可以自己动手做个试验,不感兴趣的话只需要知道结果就可以了:程序虽然能正常跑起来,却找不到App 在桌面上的快捷方式。究其原因,自己考虑一下。这里提示一下Android官方文档对于ACTION_MAIN
http://developer.android.com/guide/components/intents-filters.html
The ACTION_MAIN action indicates this is the main entry point and does not expect any intent data.
解释一下:ACTION_MAIN 行动测试代表这是App的主入口,并不期望带有数据的任何意图。
好了说完上面比较有趣的事情,接下来我们切入正题:
元素指定了希望接受的Intent请求的数据URI和数据类型,URI被分成三部分来进行匹配:scheme、 authority和path
。其中,用setData()设定的Inteat请求的URI数据类型和scheme必须与IntentFilter中所指定的一致。若IntentFilter中还指定了authority或path,它们也需要相匹配才会通过测试。
<intent-filter>
<data android:type="video/mpeg" android:scheme="http"/>
<data android:type="audio/mpeg" android:scheme="http"/>
</intent-filter>
data有一个比较重要的功能就是deepLink,所以这里说一下如何配置deepLink
- 配置build.gradle
productFlavors {
//flavor name
trunk {
applicationId project.hasProperty('flavorPackageName') ? flavorPackageName : 'com.nel.nevideo'
manifestPlaceholders = [deeplinkScheme: project.hasProperty('schemeName') ? schemeName : 'nevideo']
}
}
上面的配置可以通过gradlew -P 参数传进来,这个不再扩展开了,我们主要看一下deeplinkScheme
这个占位符,这个占位符将在Manifest中占位,如下所示
- 配置AndroidManifest
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="${deeplinkScheme}" />
</intent-filter>
当然了,如果主Activity需要这么一个deepLink怎么办,好办,就再加一个 intent-filter 即可,如下
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="${deeplinkScheme}" />
</intent-filter>
上面的配置,存在多个intent-filter 这些intent-filter是或的关系,只要其中一个满足,即可通过测试
参考文档:
http://blog.csdn.net/h3c4lenovo/article/details/7722259
http://my.oschina.net/hadescen/blog/90286
http://blog.csdn.net/andie_guo/article/details/9271973
http://blog.csdn.net/jason0539/article/details/10049899