2012年11月2日 星期五

Intent與Intent-Filter 2013-09-04 Updated

       Intent在Android系統當中是很重要的訊息角色,在一些書裡翻成「意圖」,個人覺得翻譯的非常貼切,也就是告訴Android系統目前我想要做甚麼,把要做的事情、需要的資訊等等,使用Intent將其描述出來,然後在Android系統裡進行傳遞,Android就會依照Intent所描述的進行處理,而能夠使用Intent來啟動並彼此間傳遞訊息的Component則有Activity、Service、BroadcastReceiver三大Component;而對Intent進行使用的則是在Android裡的Context,這是一個可以讓你對於整個Android系統的來龍去脈進行相關處理,當然這裡面包含了對於Intent訊息的處理,例如:Context.startActivity()、Context.startService()、Context.sendBroadcast()、Context.sendOrderedBroadcast()、Context.sendStickyBroadcast()等。
而在Intent所能描述的資訊分為以下幾大類:
  1. Component Name:指示Intent要到那一個Component所指定的值是該Component的Package Name加上Class Name,也就是該Component的全名(Fully Qualified Name)例如"com.example.project.app.FreneticActivity"。
  2. Action:描述想要做的事情,例如:如果要查看某一個聯絡人的資料或查看網頁,則可以使用ACTION_VIEW(android.intent.action.VIEW),或者想要播打電話可以使用ACTION_CALL(android.intent.action.CALL),想要編輯資料可以使用ACTION_EDIT(android.intent.action.EDIT)等,也可以使用自定義的動作,不一定要使用內建的ACTION,例如: "com.example.project.SHOW_COLOR",以下是內建的ACTION列表:http://developer.android.com/reference/android/content/Intent.html
  3. Category:執行Action時所需的額外描述資料,例如:當設定android.intent.action.MAIN(整個程式的主要進入點),並且增加android.intent.category.LAUNCHER的category資訊時,代表該程式除了為主要進入點之外,也是最上層的程式,意謂會出現在程式選單(Launcher)中;android.intent.category.ALTERNATIVE則代表這個Activity的動作,是會出現在選單上呈現一個替代選項。
  4. Data:描述所要處理的資料,通常以URI的格式進行描述,例如: tel:後面接電話,http:後面接網頁,content:後面接那個Content Provider的存取路徑,file:後面接裝置裡的那個檔案路徑等。
  5. Type: 描述能夠處理的資料類型,例如:同樣是文件,是處理text/plain純文字檔,還是text/html的html檔,又或者是圖檔中的那種檔案,是image/gif、image/jpeg或image/png。
  6. Extra:夾帶額外的資料或物件,讓所接收的元件能夠進判斷或處理,格式為key與value,呈現一對的方式,通常會指定key,但也可以使用內鍵的key夾帶具有特別意義的value,例如:使用ACTION_CALL這個Action,會搭配EXTRA_PHONE_NUMBER指定電話號碼。
  7. Flags:協助Intent如何處理,例如:在Intent描述當啟動Activity時,該如何處理Activity在Task與Back Stage的使用方式,像FLAG_ACTIVITY_NEW_TASK代表該Activity要建立在一個全新的Task中。
Intent Resolution
Intent區分為
  1. Explicit Intent:代表有明確指明Intent是要傳送到那一個Component,也就是有指明Component Name,也可以一併描述其它資料,但不管如何都會將該Intent傳送到所指定Component中進行處理
    例如:
    Intent intent = new Intent();
    intent.setComponent(new ComponentName(this, Main.class));

    其實我們常用來啟動Activity的呼叫方式(如下) ,只是上述的簡便用法,也就是明確啟動某一個Activity來處理工作:
    Intent intent = new Intent(this, Main.class);
  2. Implicit Intent:並不指明Component Name,而是藉由Action、Data (both URI and data type)、Category來判別測試Intent應該要傳送到那些Component,所以通常我們可以發現,當我們點擊某一功能後,會出現很多程式供我們選擇,例如:要觀看某份文檔,則會出現很多可以觀看該文檔格式的應用程式供其選擇。
Intent-Filter
        上述一直談論的是如何將一個Intent進行描述,並且傳送到某一個Component,但是並未說明到,如果在不是使用Explicit Intent,也就是不指明Component Name的情況下,要如何得知那些Component是否符合Intent所描述的內容?這就必須在這些Component建立時,就必須明確告知該Component是適用於那些ACTION、屬於那些Category、可以接受那些Data,這就是Intent-Filter的主要目的,將這些描述記錄在AndroidManifest.xml裡,當程式進行安裝時,Android就可以知道那些Component能適用在那些功能,和接受那些格式的資料等資訊。
基本瞭解:
        這邊所代表該Activity是程式的主要進入點,也就是不需有任何的Intent就可以啟動,並且歸類為最上層的啟動程式。
<intent-filter>
   <action android:name="android.intent.action.MAIN" />
   <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
        而該Activity說明自己主要的動作是預覽和編輯,並且可以接收的資料格式為純文字檔案(text/plain),預設的分類為android.intent.category.DEFAULT,如果該Component沒有歸屬到任何Category,至少要歸類到android.intent.category.DEFAULT,否則便無法讓其他Component使用Intent進行傳遞。
<intent-filter>
   <action android:name="android.intent.action.VIEW" />
   <action android:name="android.intent.action.EDIT" />
   <category android:name="android.intent.category.DEFAULT" />
   <data android:mimeType="text/plain" />
</intent-filter>
        一個Activity也可以有兩個Intent Filter來做為不同的比對條件,只是在這個範例中data及category一樣,當然也可以有自定義的動作:
<intent-filter>
   <action android:name="android.intent.action.VIEW" />
   <action android:name="android.intent.action.EDIT" />
   <category android:name="android.intent.category.DEFAULT" />
   <data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
   <action android:name="android.intent.action.INSERT" />
   <action android:name="com.sabaoth.action.NEW" />
   <category android:name="android.intent.category.DEFAULT" />
   <data android:mimeType="text/plain" />
</intent-filter>


轉貼請註明出處,最好直接使用聯結轉貼!Thanks~
作者: Samuel - 林靖傑
日期:2013/04/18

2 則留言:

  1. 老師今天上課已經三個禮拜了...
    中途我都沒離開過
    您今天給部落格我才敢來留言
    我從第一堂到現在都聽不懂...
    18小時我只聽的懂大概5分鐘(超級糟糕)
    老師我該怎麼辦呢?
    我是星期日早上下午在彰化聯成3樓教室上課的同學

    回覆刪除
    回覆
    1. 在學習Android之前,
      必須要先熟悉Java及物件導向概念,
      就以往的教學經驗發現,
      不明白Java及物件導向, 會造成看不懂語法為何要這樣寫,
      而非是不懂Android的觀念!
      這只是一開始的課程,
      越往後當程式碼越多, 物件導向越切割, 也只更會看不懂!
      建議先學好Java及物件導向,
      不過彰化班之前不是都已經上過別的老師的Java認證課程?
      所以應該好好的熟練之前上過的Java觀念,
      多練習! 看得懂和會寫是兩回事!
      學習是不嫌晚!
      加油!

      刪除