天天看點

【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

繼續閱讀