閱讀353 返回首頁    go 阿裏雲 go 技術社區[雲棲]


一個app,多個入口圖標,activity-alias實現多程序入口並顯示指定view完成

https://blog.csdn.net/black0591/article/details/8264168

需求總是一個接一個。
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。

如果隻有一個Activity,沒有這兩句也可以。

隱藏icon實際上就是注釋掉intent-filter中的一句

[html] view plaincopy
  1. <intent-filter>  
  2.     <action android:name="android.intent.action.MAIN" />  
  3.     <category android:name="android.intent.category.DEFAULT" />  
  4.     <!--    
  5.     <category android:name="android.intent.category.LAUNCHER" /> 
  6.     -->  
  7.     <category android:name="android.intent.category.BROWSABLE" />  
  8. </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符合條件的話,就跳出一個對話框讓用戶選擇究竟要啟動哪一個

以上是理論, 實際代碼如下:

[java] view plaincopy
  1. <!-- display missed call -->  
  2. <activity-alias  
  3.     android:name="@string/missedcallactivity"  
  4.     android:icon="@drawable/missing_icon"  
  5.     android:label="@string/missedcallactivity"  
  6.     android:targetActivity=".CustomLinphoneDialer" >  
  7.     <intent-filter>  
  8.         <action android:name="android.intent.action.MAIN" />  
  9.    
  10.         <category android:name="android.intent.category.LAUNCHER" />  
  11.     </intent-filter>  
  12. </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,比如:

[html] view plaincopy
  1. <intent-filter . . . >  
  2.     <action android:name="com.example.project.SHOW_CURRENT" />  
  3.     <action android:name="com.example.project.SHOW_RECENT" />  
  4.     <action android:name="com.example.project.SHOW_PENDING" />  
  5.     . . .  
  6. </intent-filter>  

要想通過測試,intent中的action名稱要匹配其中之一。

如果intent filter中不包含action列表,而intent指定action,那麼intent沒有匹配的action,不通過;intent未指定action,而intent filter指定,會自動通過測試。

category測試

在intent filter中可包含category列表:

[html] view plaincopy
  1. <intent-filter . . . >  
  2.     <category android:name="android.intent.category.DEFAULT" />  
  3.     <category android:name="android.intent.category.BROWSABLE" />  
  4.     . . .  
  5. </intent-filter>  

intent想通過測試,必須匹配一個intent filter中的category。

原理上講,intent如果沒有category設置,那麼總是可以通過測試。這基本上是正確的,但是有一個例外。Android在為所有隱式 intent執行startActivity()方法的時候,會認為它們至少包含了一個 android.intent.category.DEFAULT。因此,如果activity想收到隱式intent,必須加入這個category。

date測試

data元素在intent filter元素中,可以重複多次(action和category不允許重複的),也可以根本沒有。比如:

[html] view plaincopy
  1. <intent-filter . . . >  
  2.     <data android:mimeType="video/mpeg" android:scheme="http" . . . />  
  3.     <data android:mimeType="audio/mpeg" android:scheme="http" . . . />  
  4.     . . .  
  5. </intent-filter>  

在data元素中指定uri和數據類型(MIME類型)。uri是被分開表示的:

[html] view plaincopy
  1. 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 修改為。

[html] view plaincopy
  1. <activity-alias  
  2.     android:description="@string/history"  
  3.     android:icon="@drawable/ic_launcher_history"  
  4.     android:label="@string/history"  
  5.     android:name="CustomHistoryActivity"  
  6.     android:targetActivity=".CustomLinphoneDialer" >  
  7.     <intent-filter >  
  8.         <action android:name="android.intent.action.MAIN" />  
  9.   
  10.         <category android:name="android.intent.category.LAUNCHER" />  
  11.     </intent-filter>  
  12.   
  13.     <meta-data  
  14.         android:name="dltype"  
  15.         android:value="@string/dialer_history" >  
  16.     </meta-data>  
  17. </activity-alias>  

程序中 判斷處理
在onCreate中判斷出flag值,

[java] view plaincopy
  1. private void getlauncherFlag()   
  2. {  
  3.     // get launcher flag  
  4.     try   
  5.     {  
  6.         ActivityInfo info = this.getPackageManager().getActivityInfo( getComponentName(), PackageManager.GET_META_DATA);  
  7.         launcherType = info.metaData.getString("dltype");  
  8.     }   
  9.     catch (Exception e)   
  10.     {  
  11.         e.printStackTrace();  
  12.     }      
  13. }  
根據flag做跳轉

[java] view plaincopy
  1. private void applistLoginTransferView()   
  2. {  
  3.     try {  
  4.         Log.d(TAG, "launcherType=" + launcherType);  
  5.         if (null != launcherType)  
  6.         {  
  7.             if (launcherType.equals(STRING_DIALER_CONTACT))   
  8.             {  
  9.                 transfer2ContactList();  
  10.             }   
  11.             else   
  12.             {  
  13.                 if (launcherType.equals(STRING_DIALER_HISTORY))   
  14.                 {  
  15.                     transfer2HistoryList();  
  16.                 }   
  17.                 else   
  18.                 {  
  19.                     // do nothing.  
  20.                 }  
  21.             }  
  22.         }  
  23.     }  
  24.     catch (Exception e)  
  25.     {  
  26.         e.printStackTrace();  
  27.     }  
  28. }   

[java] view plaincopy
  1. transfer2HistoryList();  
這個transfer2HistoryList是原來的跳轉機製,略過。
到此activity-alias實現app另外程序入口並顯示指定view完成。

https://blog.csdn.net/sam_zhang1984/article/details/7278470

一個工程對應一個AndroidManifest.xml文件,這個文件中包含有該項目的一些設置,如權限、SDk版Activity、Service信息等。一般而言,這個文件中會有且僅有一個application節點,這個節點表示這是一個應用程序,不管它下麵還有多少子節點如Activity、Service等等。形象的說,就是這個項目生成的apk安裝到Android設備後,應用程序列表中會出現一個ICON,這個ICON就是這個程序的執行入口了。

 

但是,某些情況下,我們需要為我們的apk設置多個執行入口,也就是安裝後在應用程序列表中出現多個ICON圖標,各個ICON是APP不同模塊的入口點,並且各個模塊運行在不同的進程中。

可能這種需求很少見,但還是有一個現實的例子:係統中的聯係人和電話這兩個程序。表麵看來這是兩個獨立的應用程序,但實際上它們隻是一個應用程序的兩個執行入口而已,點擊聯係人圖標就會進入聯係人界麵,點擊電話圖標就會進入撥號界麵,這都是通過設置該項目下Activity的屬性來實現的。

Activity有一個重要的屬性process,這個屬性是指定Activity運行時所在的進程。沒有指定此屬性的話,所有程序組件運行在應用程序默認的進程中,這個進程名跟應用程序的包名一致。中所有組建元素的process屬性能夠為該組件設定一個新的默認值。但是任何組件都可以覆蓋這個默認值,允許你將你的程序放在多進程中運行。如果這個屬性被分配的名字以:開頭, 當這個activity運行時, 一個新的專屬於這個程序的進程將會被創建。

以下麵的代碼為例,項目中有兩個Activity,其中一個采用默認屬性,另一個為其指定process屬性以及新的ICON,這樣該項目安裝到設備上之後可以發現多了兩個應用程序圖標,一個是應用程序默認的圖標,點擊後進入HelloWorldActivity;另一個是手動指定的ICON,點擊後進入NextPageActivity。這時使用adb shell查看進程可以發現,兩個Activity是運行在不同的進程中的。

AndroidManifest.xml的主要內容如下:

[html] view plaincopy
  1. <activity android:name=".HelloWorldActivity"    
  2.           android:label="@string/app_name"    
  3.           android:process=":process.main">    
  4.          <intent-filter>    
  5.                 <action android:name="android.intent.action.MAIN" />    
  6.                 <category android:name="android.intent.category.LAUNCHER" />    
  7.          </intent-filter>    
  8. </activity>    
  9.      
  10. <activity android:name="cn.ian.NextPageActivity"    
  11.       android:label="@string/nextpage"    
  12.       android:process=":process.sub"    
  13.       android:icon="@drawable/icon1"    
  14.       android:launchMode ="singleInstance">    
  15.      <intent-filter>    
  16.                 <action android:name="android.intent.action.MAIN" />    
  17.                 <category android:name="android.intent.category.LAUNCHER" />    
  18.          </intent-filter>    
  19. </activity>    


通過上麵的方式,為App的各個組件指定process和icon屬性,便能夠達到類似於一個apk中打包多個程序(模塊)的目的。

ps:要特別注意,為Activity指定process屬性後,還必須為其指定launchMode為singleInstance,這樣才有效。


最後更新:2017-04-04 07:03:40

  上一篇:go IOS開發網站匯總
  下一篇:go eclipse如何導入javax.servlet.*