天天看点

【Android Activity】IntentFilter的匹配规则

启动 Activity 分为两种,显式调用和隐式调用。显式调用需要明确指出被启动组件的包名类名。隐式调用需要 Intent 能够匹配目标组件的 IntentFilter 中所设置的过滤信息,如果不匹配将无法启动目标 Activity

一、IntentFilter 简介

  • 意图过滤器的意思
  • manifest文件中activity标签的子标签。
  • IntentFilter 的过滤信息(子标签)有 action、category、data

1、IntentFilter 注意点

1、一个activity下可能有多个intentfilter,一个intent只要能匹配任何一组intentFilter下的信息便可成功启动activity。

2、一个intentFilter中action 、category、data都可以有多个。

3、想要隐式开启activity 必须在intentFilter添加 <category android:name=“android.intent.category.DEFAULT” />

二、Action规则

1、系统定义了一些Action字符串

<activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
  </activity>
           

2、我们也可以自定义Action字符串

<activity android:name=".ActivityC">
            <intent-filter>
                <action android:name="com.example.test" />//添加自定义字符串即可
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
 </activity>
           

3、Action匹配规则

1、intentFilter中的action可以有很多,只要intent添加的action和intentFilter中其中一个action匹配即可

2、action区分大小写,大小写不同的字符串是不同的action。

3、intentFilter 至少要有一个action

4、栗子

Intent intent = new Intent();
intent.setAction("com.example.test"); //intent 添加action。匹配intent-filter 下的一个action即可成功打开activity
startActivity(intent);

<activity android:name=".ActivityC">
            <intent-filter>
                <action android:name="com.example.test" />
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
 </activity>
           

三、Category规则

1、匹配规则

1、intentFilter中的category可以有很多,只要intent设置的category和intentFilter的匹配即可。

2、系统在调用startActivity或者startActivityForResult时,会默认为intent加上了android.intent.category.DEFAULT这个category。所以为了activity能够接受隐式调用必须在intentFilter下设置android.intent.category.DEFAULT。

2、栗子

mainactivity开启main2Activity。

#MainActivity

【Android Activity】IntentFilter的匹配规则

#main2activity的配置

【Android Activity】IntentFilter的匹配规则

#点击按钮(直接崩溃 如下)

【Android Activity】IntentFilter的匹配规则
找不到activity?我明明添加了action还和intentFilter下的其中一个action匹配,并且我添加了category也匹配了。这是为啥???还记得我们之前说过得系统在调用startActivity或者startActivityForResult时,默认为intent加上了android.intent.category.DEFAULT这个categor所以要想隐式开启activity这个categrory必须添加待intent-filter中。
Intent intent = new Intent();
 intent.setAction("com.example.test1");
 intent.addCategory(Intent.CATEGORY_DEFAULT); // 实际还有这个 系统封装在startActivity中了
 intent.addCategory("com.example.category2");
 startActivity(intent);
           
【Android Activity】IntentFilter的匹配规则

四、 data匹配规则

1、data简介

data由两部分组成mimeType和URI,语法如下。
<data android:scheme="string"
                    android:host="string"
                    android:port="string"
                    android:path="string"
                    android:pathPattern="string"
                    android:pathPrefix="string"
                    android:mimeType="string"/>
           

2、mimeType

1、媒体类型,如image/jpeg 、audio/mpeng4-generic、vodeo/* 可以表示图片文本视屏等不同媒体格式。

2、data 中可以不指定这个属性。

3、URI结构

1、scheme:URI的模式,比如http,file,content等字符串,此属性不可省略。

2、Host:URI的主机名比如 “www.baidu.com” ,此属性不可省略。

3、Port:URI中的端口号,比如80此属性可省略

4、parth ,pathPattern,pathPrefix 这三个参数表示路径信息。此属性可省略

4、栗子

<activity android:name=".SecActivity">
            <!--  action 、category、data-->
            <intent-filter>
                <action android:name="aaa" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:host="secactivity"
                    android:scheme="test" />
            </intent-filter>
      
        </activity>
           
val intent = Intent()
 intent.action = "aaa"
 //这里可以不写CATEGORY_DEFAULT 
 // intent.addCategory(Intent.CATEGORY_DEFAULT) 系统在startActivity时会默认加上
 intent.data = Uri.parse("test://secactivity")
 startActivity(intent)
           

5、tips

1、URI是有默认值的。URI默认值为content或file。

2、如果需要为intent指定完整的data需要调用intent.setDataAndType(uri,type);这个方法,

3、setData 设置data的uri,setType 设置data的miniType但是 setData setType这两个方法彼此会清除对方值。(参考两个方法源码)

这样匹配规则就总结完了,另外注意intentFilter的匹配规则对Service,broadcastReceiver同样适用,不过系统对于Service的建议尽量使用显示意图来启动服务。

当组件设置了intent filter后便可支持隐式开启,这时exported属性默认会为true,组件支持外部应用开启。无intent filtre时组件的exported默认为false。

五、activity相关的常用方法

1、onNewIntent 触发条件有哪些?

1、activity 设置为SingleTop 且位于栈顶:再次开启activity会走 onNewIntent

2、activity设置为SingleTask、singleinstance任务栈中存在实例:再次开启activity会走onNewIntent

2、resolveActivity

避免找不到隐式activity而crash。注意参数PackageManager.MATH_DEFAULT_ONLY的使用。
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
            startActivity(intent);
        } else {
            Toast.makeText(this, "Activity Not Found", Toast.LENGTH_SHORT).show();
        }
           

4、异常状态下的数据恢复

onSaveInstanceState()

onRestoreInstanceState()

#思想:委托思想

首先 Activity 被意外终止时,Activity 会调用 onSaveInstanceState 去保存数据,然后 Activity 会委托 Window 去保存数据,接着 Window 在委托它上面的顶级容器再去一一通知它的子元素来保存数据,这样整个数据保存过程就完成了。

5、startActivityForResult使用

#mainActivity

...
   ...
   Intent intent = new Intent(this, SecondActivity.class);
   startActivityForResult(intent, 0x01);
   ...
   ...

 @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0x01 && resultCode == 0x02
                && data != null) {
            // todo
        }
    }
           

#secondActivity

Intent intent = new Intent();
        intent.putExtra("name", "i am second");
        setResult(0x02, intent);
        finish();
           

The end

继续阅读