2010年1月23日 星期六

淺談Intent

(Origin 1/6 Tweets)

Android上的Intent其實是個簡單而強大的機制, 不同的應用程式可以利用它互相的傳遞資訊
從這機制可以來延伸思考, 不同軟體間的各自為政將會是種錯誤的事, 軟體與軟體間應該能盡量建立connection, 打破藩籬, 一直在單一軟體增加功能會是死路一條吧

舉個簡單的例子, Camera軟體拍照完, 可以直接將照片分享到e-mail, mms, 網路上, 也可以直接送到後處理軟體後製(例如說PicSays), 一個Camera軟體不需要自己提供所有的功能, 只要把成品送至有適當接口的軟體, 它只要專心把拍照功能做好, 其他就交給別人去加強它

當然後製軟體也可以在做完後製後交接給下一棒, 比如說還是可以在這邊做分享的動作, 這樣各種模組的組合下, 就有不同的可能性, 使用者也可以選擇對他來說比較方便的軟體當成其中的模組不需要受限於某種特定軟體之中

這種模式可以把一個大型的軟體應用拆裝成不同的積木, 開發者可以各自開發自己擅長的部份, 使用者也可以依自己喜好組合

Intent的使用上相當的簡易, 最基本的組成是: action, data



  • action 代表的是要被處理的動作, 舉個簡單的例子, Intent.ACTION_VIEW , 如同字面上的意思, 這個動作就是用來"檢視"(View)某種資料 , 處理這個Intent的Component(Activity, BroadcastRecevier)就要去針對對應的action實作動作

  • data 是個uri, uri指向資料實際的位置(可以是實體檔案, 也可以是一個provider, 也可以是個contact) , 處理這個Intent的Component(Activity, BroadcastRecevier)必須要提供處理這個data的能力


除了這兩樣東西外, 其他還可以帶的資訊是: category, type, component, extras



  • category 藉由category可以把一系列相關的intents給grouping起來, 最常見也一定會見到的intent category就是CATEGORY_LAUNCHER , 如果某個Activity的intent filter含有這個category, 表示這個Activity會在Home的Launcher(啟動程式區)裡看到, 如果某個Activity標上了android.intent.category.SAMPLE_CODE , 那你就會在SDK裡面的ApiDemos 找到它的入口

  • type 指的是資料的mime type, 這在某些Action 是相當有用的, 比如說ACTION_SEND, Camera拍照後Share相片, 是透過這個action, Browser share link也是透過這action, 但一個AP未必支援兩種資料, 這時候就是透過mime type來區分的, 基本上Camera , Browser都是會直接叫ACTION_SEND, 但一個會指定mine type是image/*一個會指定text/plain , 所以, 雖然是同一種intent action, 帶出來的menu裡的items也會不同

  • component 用來指定某一特定的component (Activity, BroadcastReceiver), 註冊同一種intent的components有可能不只一個 , 透過指定component name, 可以直接呼叫特定的component

  • extras 用來帶額外的資料, 比如說Browser call ACTION_SEND, 就會額外帶EXTRA_TEXT, EXTRA_SUBJECT



一個activity能處理的intent是定義在AndroidManifest裡的intent-filter section, 如

<activity android:name=".app.HelloWorld" android:label="@string/activity_hello_world">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>


(寫到這邊有點懶得寫了, 直接寫應用, 因為很多都可以看SDK doc)




如何取出support某個intent的activities?

可以使用 PackageManager.queryIntentActivities(Intent intent, int flags)

這個還有個應用, 可以用來得知某個程式有沒被安裝

拓展Browser的應用

其實Browser會把Uri forward給可以處理它的Activities, 比如說"market://" , 碰到這種連結就會直接給Market , 當然, Browser本身也是處理"scheme: http及https"類型intent的application, 所以就可以有以下這樣的應用:



  • OAuth callback, 這是我看來的用法不是我發明的, 挺高明的, 在寫OAuth時, 如果沒有call back url, 就變成要user輸入一個verifier, 這種在使用上蠻討厭的, 但其實call back url也是可以是個Uri的, 比如說"myapp://xxxx" , 只要實作一個處理這Uri的Activity就可以處理掉這問題了

  • 續上, 延伸應用, form action其實應該也可以套用同樣的作法, 因此可以寫一個web form call local app來處理data

  • Remote image viewer 如果 http://xxx/xxx.jpg這類的圖檔連結可以用自己的image view開啟, 那可以提供不同於Brower的使用體驗, 要達到這樣也很簡單, 以下就是用來處理Flickr圖檔連結的intent filter
    <intent-filter><action android:name="android.intent.action.VIEW"></action>
    <data android:scheme="http" ></data>
    <data android:host="*.flickr.com"></data>

    <category android:name="android.intent.category.DEFAULT"></category>
    <category android:name="android.intent.category.BROWSABLE"></category>
    <data android:pathPattern=".*\.jpg"></data>
    </intent-filter>


寫這麼多字, 後面越來越文句不通暢, 懶得寫了, 有空在來整理