本文轉至http://my.oschina.net/zhangqingcai/blog/42085
需求總是一個接一個。
missed call需要一個單獨的圖標,點擊進入,而missed call 本身在linhone activity中。
思路,使用activity alias。
當然,需要intent啓動activity,也就需要filter
在android的應用程序可以有多個Activity,每個Activity是同級別的,那麼在啓動程序時,最先啓動哪個Activity呢?有些程序可能需要顯示在程序列表裏,有些不需要。怎麼定義呢?
android.intent.action.MAIN 決定應用程序最先啓動的Activity 。
android.intent.category.LAUNCHER決定應用程序是否顯示在程序列表裏。
因爲你的程序可能有很多個activity,
只要xml配置文件中有這麼一個intent-filter,而且裏面有這個launcher,那麼這個activity就是點擊程序時最先運行的那個activity。
隱藏icon實際上就是註釋掉intent-filter中的一句
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<!--
<category android:name="android.intent.category.LAUNCHER" />
-->
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
intent一定要有的3個匹配值, action, category, data.
在某個Activity裏用startActivity()方法發送一個intent,這個intent設定了一些條件,比如用方法setAction(),addCategory()設定了兩個屬性,
發送了這個intent之後,android會去系統裏保存的MainManifest.xml清單(假設這個系統存放全部apk清單的文件爲MainManifest.xml)裏查找符合這兩個屬性的activity,然後啓動它。
當某個Activity用startActivity(intentOther)方法向系統發送了一個intent(假如爲 intentOther),那麼android系統會去查找這個MainManifest.xml裏註冊的<intent-filter >屬性,
查找到符合這個 intentOther 的就啓動這個Activity,如果有多個這樣的Activity符合條件的話,就跳出一個對話框讓用戶選擇究竟要啓動哪一個
以上是理論, 實際代碼如下:
<!-- display missed call -->
<activity-alias
android:name="@string/missedcallactivity"
android:icon="@drawable/missing_icon"
android:label="@string/missedcallactivity"
android:targetActivity=".CustomLinphoneDialer" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
這個代碼 能顯示兩個圖標 ,我們的目的是 能顯示通話記錄, 還得調用target activity, and show call history activity.是不是 需要 多個intent filter? 下面reference a link to explan intent filter.
Intent filter
爲了能支持隱式intent,activity、service和broadcast receiver會包含1到多個intent filter。每個intent filter描述組件的可接收一組intent的能力。在intent filter中,說明了可接受的類型,以及不想要的intent。隱式的intent要想投遞到一個組件,只需通過組件的一個filter即可。
組件把filter分成多個,是爲了針對具體不同的任務。在sample中的Note pad示例中,NoteEditor activity有兩個filter,一個用於啓動並打開指定的note,另一個是爲了打開新的空的note。
一個intent filter是一個IntentFilter類的實例。但是,android系統必須在組件未啓動的情況下就知道它的能力,因此intent filter一般不會在java代碼中設置,而是在應用的manifest文件中作爲<intent-filter>元素的方式聲明。一個例 外是,爲broadcast receiver註冊動態的filter,可以調用Context.registerReceiver()方法,通過直接實例化IntentFilter 對象創建。
filter有三個平等的部分:action、data和category。隱式intent將測試這三個部分。一個intent要想投遞到一個組 件,那麼這三個測試都要通過才行。當然如果組件有多個intent filter,可能一個intent沒有通過,但是通過了另外的一個,這樣也可以把intent投遞到組件。
action測試在intent filter中可以包含多個action,比如:
<intent-filter . . . >
<action android:name="com.example.project.SHOW_CURRENT" />
<action android:name="com.example.project.SHOW_RECENT" />
<action android:name="com.example.project.SHOW_PENDING" />
. . .
</intent-filter>
要想通過測試,intent中的action名稱要匹配其中之一。
如果intent filter中不包含action列表,而intent指定action,那麼intent沒有匹配的action,不通過;intent未指定action,而intent filter指定,會自動通過測試。
category測試在intent filter中可包含category列表:
<intent-filter . . . >
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
. . .
</intent-filter>
intent想通過測試,必須匹配一個intent filter中的category。
原理上講,intent如果沒有category設置,那麼總是可以通過測試。這基本上是正確的,但是有一個例外。Android在爲所有隱式 intent執行startActivity()方法的時候,會認爲它們至少包含了一個 android.intent.category.DEFAULT。因此,如果activity想收到隱式intent,必須加入這個category。
date測試data元素在intent filter元素中,可以重複多次(action和category不允許重複的),也可以根本沒有。比如:
<intent-filter . . . >
<data android:mimeType="video/mpeg" android:scheme="http" . . . />
<data android:mimeType="audio/mpeg" android:scheme="http" . . . />
. . .
</intent-filter>
在data元素中指定uri和數據類型(MIME類型)。uri是被分開表示的:
scheme://host:port/path
其中host和port是關聯的,如果host沒有設置,port也會忽略。
所有這些屬性都是可選的,但是不是獨立的。比如,如果要設置path,那麼也必須設置schema、host和port。
在比較intent中的uri和intent filter中指定的uri時,只會比較intent filter中提及的URL部分。比如,intent filter中只提及了schema,那麼所有url包含這個schema的都匹配。在filter的path部分可以使用通配符做到靈活的匹配。
mimeType屬性,比uri方式更常用。intent和intent filter都可以使用mime通配符的方式,比如,text/*。
如果既有mimeType,又有uri的情況,比較規則如下:
- 如果intent和intent filter都沒有設置任何uri和mimetype,通過;
- intent包含uri但是沒有data type的情況,intent filter的uri部分與之匹配,而且也沒有data type部分,可以通過,比如mailto:和tel:
- intent對象包含數據類型但是沒有uri部分,那麼僅當intent filter也只有數據類型,而沒有uri部分的時候能通過;
- intent對象包括uri和數據類型(或者數據類型在uri中),分兩部分測試,intent對象的數據類型要匹配intent filter,intent對象的uri,或者匹配intent filter中的uri,或者intent filter中沒有uri部分(僅當intent對象的uri是content:或者file:的時候)。
新思路,可以啓動CustomLinphoneDialer界面,然後在跳轉到呼叫記錄view,
如何跳轉呢?
設置全局flag,然後判斷跳轉,這樣的話就需要在manifest中定義feature 的meta data, 保存要跳轉的view, 並在CustomLinphoneDialer.java中判斷。
因此新的manifest 修改爲。
<activity-alias
android:description="@string/history"
android:icon="@drawable/ic_launcher_history"
android:label="@string/history"
android:name="CustomHistoryActivity"
android:targetActivity=".CustomLinphoneDialer" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="dltype"
android:value="@string/dialer_history" >
</meta-data>
</activity-alias>
程序中 判斷處理
在onCreate中判斷出flag值,
private void getlauncherFlag()
{
// get launcher flag
try
{
ActivityInfo info = this.getPackageManager().getActivityInfo( getComponentName(), PackageManager.GET_META_DATA);
launcherType = info.metaData.getString("dltype");
}
catch (Exception e)
{
e.printStackTrace();
}
}
根據flag做跳轉private void applistLoginTransferView()
{
try {
Log.d(TAG, "launcherType=" + launcherType);
if (null != launcherType)
{
if (launcherType.equals(STRING_DIALER_CONTACT))
{
transfer2ContactList();
}
else
{
if (launcherType.equals(STRING_DIALER_HISTORY))
{
transfer2HistoryList();
}
else
{
// do nothing.
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
transfer2HistoryList();
這個transfer2HistoryList是原來的跳轉機制,略過。到此activity-alias實現app另外程序入口並顯示指定view完成。