安卓启动activity的方式(显式和隐式)

来源:互联网 发布:java httpclient ssl 编辑:程序博客网 时间:2024/06/05 17:06

启动Activity分为两种,显式调用和隐式调用,原则上一个Intent不能既是显示调用又是隐式调用,如果二者共存的话,以显式调用为主。本文主要讲解隐式调用。

显式调用:

1.

Intent intent = new Intent(MainActivity.this,SecondActivity.class);startActivity(intent);

2.

String packageName = "包名";String className = "类名(需要写全名)";Intent intent = new Intent();intent.setClassName(packageName,className);startActivity(intent);

隐式调用:

隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息,如果不匹配将无法启动目标Activity,IntentFilter中的过滤信息有action、category、data,看实例:

<activity    android:name=".SecondActivity"    android:label="@string/app_name2"    android:launchMode="singleTask">    <intent-filter>        <action android:name="action1" />        <action android:name="action2" />        <category android:name="category1" />        <category android:name="category2" />        <category android:name="android.intent.category.DEFAULT" />        <data android:mimeType="text/plain" />    </intent-filter></activity>


为了匹配过滤列表,需要同时匹配过滤列表中的action、category、data信息,否则匹配失败,一个过滤列表中的action、category、data可以有多个,所有的action、category、data分别构成不同类别,只有一个Intent同时匹配action类别、category类别、data类别才算完全匹配,一个Activity中可以有多个intent_filter,一个Intent只要能匹配任何一组intent_filter即可成功启动对应的Activity。

1.action的匹配规则

action是一个字符串,系统预定义了一些action,同时我们也可以在应用中定义自己的action。action匹配要求Intent中的action存在且必须和过滤规则中的其中一个action相同。

2.category匹配规则

category是一个字符串,系统预定义了一些category,同时我们也可以在应用中钉义自己的category。Intent中如果存在category,它必须是过滤规则中已经定义了的category,Intent中可以没有category,原因是系统在调用startActivity或者startActivityForResult的时候会默认为Intent加上“android.intent.category.DEFAULT”这个category,同时,为了我们的activity能够接收隐式调用,intent_filter中必须定义“android.intent.category.DEFAULT”这个category。

3.data的匹配规则

data的匹配规则和action类似,如果过滤规则中定义了data,那么Intent中必须也要定义可匹配的data。

data的语法如下:

<data    android:mimeType="text/plain"    android:host="string"    android:path="/string"    android:pathPattern="/string"    android:pathPrefix="/string"    android:port="8080"    android:scheme="string" />


data由两部分组成,mimeType和URI,mimeType值媒体类型,比如image/jpeg、audio/mpeg4-generic、video/*等,可以表示图片、文本、视频等不同的媒体格式,而URI中包含的数据就比较多了,结构如下:

<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

实例:content://com.example.project:8080/folder/subfolder/etc

   http:www.baidu.com:80/search/info

scheme:URI的模式,比如http、file、content等,是必须指定的

host:主机名,比如www.baidu.com,也是必须指定的

port:端口号,可选

path、pathPattern和pathPrefix:这三的参数表述路径信息,支持正则

举例说明:

<data    android:mimeType="image/*"     />
匹配:这种规则制定了媒体类型为所有类型的图片,那么Intent中的mimeType属性必须为“image/*”才能匹配,这种情况下虽然没有指定URI,但是却有默认值content或file,也必须指定

intent.setDataAndType(Uri.parse("file://abc"),"image/png");
这里需要注意:只能用setDataAndType,不能单独设置setData和setType

再例如:

<data android:mimeType="audio/mpeg" android:scheme="http" /><data android:mimeType="video/mpeg" android:scheme="http" />
Intent:

intent.setDataAndType(Uri.parse("http://abc"),"audio/mpeg");
或者

intent.setDataAndType(Uri.parse("http://abc"),"video/mpeg");


总结:

intent_filter的匹配规则对于service和BroadcaseReceiver也是同样的道理,不过系统对于service的建议是尽量使用显式调用的方式来启动服务。当我们通多隐式启动方式启动一个Activity的时候,可以做一下判断,看是否有Activity能够匹配我们的隐式Intent,判断方法举例:

Intent intent = new Intent();intent.setAction("action1");intent.setDataAndType(Uri.parse("http://abc"),"video/mpeg");ComponentName componentName = intent.resolveActivity(getPackageManager());ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);List<ResolveInfo> resolveInfos = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);Log.e(TAG, "componentName: "+componentName+","+ "resolveInfo: "+resolveInfo+","+"resolveInfos: "+resolveInfos);startActivity(intent);

这个是能够匹配的,打印结果

componentName:ComponentInfo{com.example.administrator.mydiyview/com.example.administrator.mydiyview.SecondActivity},
resolveInfo: ResolveInfo{132d17a0 com.example.administrator.mydiyview/.SecondActivity m=0x608000},
resolveInfos: [ResolveInfo{d25ff59 com.example.administrator.mydiyview/.SecondActivity m=0x608000}]

更改action为abc,就不能匹配了,打印结果如下,并且报错退出了:

componentName: null,

resolveInfo: null,

resolveInfos: [ ]

所以这三个方法任意一个都可以判断能否匹配成功方法中我们使用MATCH_DEFAULT_ONLY,这个标记位的含义是仅仅匹配那些在intent_filter中声明<category androud:name="android.intent.category.DEFAULT"/>这个category的Activity,使用这个标记位的意义在于,只要上述三种方法不返回null或 [ ],那么startActivity一定可以成功,如果不用这个标记位,就会把intent_filter中category不含DEFAULT的那些Activity给匹配出来,从而导致startActivity可能失败,因为不含有DEFAULT这个category的Activity是无法接收隐式Intent的。