1. 程式人生 > >android Intent (隱式意圖和顯示意圖)

android Intent (隱式意圖和顯示意圖)

2. 顯式意圖、隱式意圖
    Intent可以劃分成顯式意圖和隱式意圖。
    顯式意圖:呼叫Intent.setComponent() 或 Intent.setClassName() 或 Intent.setClass()方法明確指定了元件名的Intent為顯式意圖,顯式意圖明確指定了Intent應該傳遞給哪個元件。
        如: 在 MainActicity 中開啟一個新的 Acticity -- OtherActivity
            1. Intent intent = new Intent();
            2. intent.setComponent(new ComponentName(MainActivity.this, OtherActivity.class));
            3. 第二行程式碼可以更換為:intent.setClass(MainActivity.this, OtherActivity.class);
                4. 也可以使用構造器來指定元件: Intent intent = new Intent(MainActivity.this, OtherActivity.class)
            三種 “顯式意圖” 指定方式等價    
    隱式意圖:沒有明確指定元件名的Intent為隱式意圖。
          Android系統會根據隱式意圖中設定的動作(action)、類別(category)、資料(data: URI和資料型別)找到最合適的元件來處理這個意圖
          例如撥打電話的意圖:
                  Uri uri = Uri.parse("tel:" + phoneCode);
                Intent intent = new Intent(Intent.ACTION_CALL, uri);
    
    
    對於隱式意圖,Android是怎樣尋找到這個最合適的元件呢?記的前面我們在定義活動時,指定了一個intent-filter,Intent Filter(意圖過濾器)其實就是用來匹配隱式Intent的,當一個意圖物件被一個意圖過濾器進行匹配測試時,只有三個方面會被參考到:動作、資料(URI以及資料型別)和類別。
    
    動作測試(Action test)
      一個意圖物件只能指定一個動作名稱,而一個過濾器可能列舉多個動作名稱。如果意圖物件或過濾器沒有指定任何動作,結果將如下:
        + 如果過濾器沒有指定任何動作,那麼將阻塞所有的意圖,因此所有的意圖都會測試失敗。沒有意圖能夠通過這個過濾器。 
            <intent-filter><!-- 空的 --></intent-filter>
        + 另一方面,只要過濾器包含至少一個動作,一個沒有指定動作的意圖物件自動通過這個測試
    
    類別測試(Category test)
        對於一個能夠通過類別匹配測試的意圖,意圖物件中的類別必須匹配過濾器中的類別。這個過濾器可以列舉另外的類別,但它不能遺漏在這個意圖中的任何類別。
        原則上一個沒有類別的意圖物件應該總能夠通過匹配測試,而不管過濾器裡有什麼。大部分情況下這個是對的。
        但有一個例外,Android把所有傳給startActivity()的隱式意圖當作他們包含至少一個類別:"android.intent.category.DEFAULT" (CATEGORY_DEFAULT常量)。 
        因此自定義 Activity 的時候,不要以為光定義一個 action 就夠了。這樣用 startActivity() 來啟用這個 Activity 的時候將一直報錯。
        原因就是,他內部要求去匹配 android.intent.category.DEFAULT 這個類別。
        
        因此,想要接收隱式意圖的活動必須在它們的意圖過濾器中包含"android.intent.category.DEFAULT"。
            (帶"android.intent.action.MAIN"和"android.intent.category.LAUNCHER"設定的過濾器是例外)
    
    資料測試(Data test)
        當一個意圖物件中的URI被用來和一個過濾器中的URI比較時,比較的是URI的各個組成部分。
        例如,如果過濾器僅指定了一個scheme,所有該scheme的URIs都能夠和這個過濾器相匹配;
            如果過濾器指定了一個scheme、主機名但沒有路經部分,所有具有相同scheme和主機名的URIs都可以和這個過濾器相匹配,而不管它們的路經;
            如果過濾器指定了一個scheme、主機名和路經,只有具有相同scheme、主機名和路經的URIs才可以和這個過濾器相匹配。
            當然,一個過濾器中的路徑規格可以包含萬用字元,這樣只需要部分匹配即可。
        資料測試同時比較意圖物件和過濾器中指定的URI和資料型別。規則如下:
        a. 一個既不包含URI也不包含資料型別的意圖物件僅在過濾器也同樣沒有指定任何URIs和資料型別的情況下才能通過測試。
        b. 一個包含URI但沒有資料型別的意圖物件僅在它的URI和一個同樣沒有指定資料型別的過濾器裡的URI匹配時才能通過測試。
           這通常發生在類似於mailto:和tel:這樣的URIs上:它們並不引用實際資料。
        c. 一個包含資料型別但不包含URI的意圖物件僅在這個過濾器列舉了同樣的資料型別而且也沒有指定一個URI的情況下才能通過測試。
        d. 一個同時包含URI和資料型別(或者可從URI推斷出資料型別)的意圖物件可以通過測試,如果它的型別和過濾器中列舉的型別相匹配的話。
           如果它的URI和這個過濾器中的一個URI相匹配或者它有一個內容content:或者檔案file: URI而且這個過濾器沒有指定一個URI,那麼它也能通過測試。
           換句話說,一個元件被假定為支援content:和file: 資料如果它的過濾器僅列舉了一個數據型別。