編輯:關於Android編程
今天主要分析下ActivityManagerService(服務端) 與應用程序(客戶端)之間的通信模型,在介紹這個通信模型的基礎上,再簡單介紹實現這個模型所需要數據類型。
本文所介紹內容基於android2.2版本。由於Android版本的不同,本文所包含的一些類可能在命名等細節上做了一些更改,但萬變不離其宗,整個核心思想和通信流程依舊如下。
例如,①、在android2.3上就將android2.2中ActivityManagerService的很多處理邏輯提煉出來,形成了一個單獨的ActivityStack類,因而顯得更“高級”;
②、將後文講解到的HistoryRecord.Java直接重名名為ActivityRecord.java等。
很多不同點我也就不在細說了。大家在研究源碼的過程裡,注意差異就成。
Android的三大核心功能有如下三個:
1、View.java 關於View工作原理,《Android中View繪制流程以及invalidate()等相關方法分析》分析過。
功能有: 繪制圖形、處理觸摸、按鍵事件等;
2、ActivityManagerService.java簡稱為 AMS
功能有:管理所有應用程序的Activity 、內存管理等 。
3、WindowManagerService.java簡稱為WMS
功能有:為所有應用程序分配窗口,並管理這些窗口。
從上可知,AMS作為一種系統級服務管理所有Activity,當操作某個Activity時,例如: 啟動一個新的Activity、停止當前Activity,必須報告給AMS,而不能“擅自處理”。當AMS接受到具體通知時,會根據該通知的類型,首先會更新內部記,然後在通知相應客戶進程去運行一個新的Activity或者停止指定的Activity。另外,由於AMS記錄了所有Activity的信息,當然能夠主動的調度這些Activity,甚至在內存不足時,主動殺死後台的Activity。
首先對模型中可能運到的類做一個介紹:
ActivityThread.java路徑位於:\frameworks\base\core\java\android\app\ActivityThread.java
說明: 該類為應用程序(即APK包)所對應進程(一個進程裡可能有多個應用程序)的主線程類,即我們通常所說的UI線程。
一個ActivityThread類對應於一個進程。最重要的是,每個應用程序的入口是該類中的static main()函數 。
Activity.java 路徑位於:\frameworks\base\core\java\android\app\Activity.java
說明:該類是與用戶交互的對象,同時也是APK應用程序運行的最小單元。ActivityThread類會根據用戶的操作選擇運行哪個Activity。當前運行的Activity是出於resume狀態(有且僅有一個),其他Activity出於pause或stop狀態。
Instrumentation.java路徑位於 :\frameworks\base\core\java\android\app\ActivityThread.java
說明: 該類用於具體操作某個Activity的功能----單向(oneway)調用AMS以及統計、測量該應用程序的所有開銷。
一個Instrumentation類對應於一個進程。每個Activity內部都有一個該Instrumentation對象的引用。
舉個例子吧。
我們將我們應用程序比作一個四合院,那麼Activity對應於四合院的人,ActivithThread對應於院子的主人----管理所有人,Instrumentation對應於管家------受氣的命,接受來自人(Activity/ActivithThread)的命令 ,去單向(oneway)調用AMS 。
ApplicationThread類是ActivityThread的內部類:
說明:該類是一個Binder類,即可實現跨進程通信。主要用於接受從AMS傳遞過來的消息,繼而做相應處理。
ActivityManagerService.java路徑位於:
\frameworks\base\services\java\com\android\server\am\ActivityManagerService.java
說明:該類是一個Binder類,即可實現跨進程通信。因此可以接受從客戶端,例如Instrumentation、Context等調用過來的
信息。ActivityManagerService提供了全局的代理對象,供IPC調用。
AMS與ActivityThread的通信模型圖如下:
從該模型圖我們得知以下知識點:
第一、 引起調用AMS的對象通常有Context 、 Instrumentatio、ActivityThread等 。
第二、當AMS接受到來自某個應用程序傳來的消息後,在AMS內部處理完畢後,會通過Binder機制回調回該應用程序
所在ApplicationThread服務端類,即ActivityThread.java類。
第三、當ActivityThread接受到AMS傳遞過來的消息後,進行內部處理。如果需要的話,會繼續與AMS通信。
最後,當整個通信完成時,ActivityThread會選擇合適的對象,例如Service、Activity、BroadcastReceiver等去做相應的
處理。
最後,對通信模型設計到的設計到的數據類進行介紹:
ProcessRecord.java路徑:\frameworks\base\services\java\com\android\server\am\ ProcessRecord.java
說明: 記錄每個進程的裡的全部信息 。 主要信息包括該進程中包含的Activity、Provider、Service等信息、進程文件信息、該進程的內存狀態信息。
源代碼(部分)如下:
class ProcessRecord implements Watchdog.PssRequestor { // 第一個應用程序的ApplicationInfo對象 final ApplicationInfo info; // all about the first app in the process final String processName; // name of the process 進程名 // List of packages running in the process final HashSetpkgList = new HashSet(); // 該進程裡運行的應用程序包名 // contains HistoryRecord objects final ArrayList activities = new ArrayList(); // 保存該進程下所有Activity的信息 AndroidManifest.xml // all ServiceRecord running in this process final HashSet services = new HashSet(); // 保存該進程下所有Service的信息 }
HistoryRecord.java路徑:\frameworks\base\services\java\com\android\server\am\HistoryRecord.java
說明: 記錄每個Activity的全部信息,因為AMS不知道客戶端Activity的存在,因此在服務端用HistroyRecord對象來方便管理和統計對應客戶端Activity的信息。而且該類也是一個Binder類,因此可以跨進程調用。在客戶端中,ActivityThread同樣用HistroyRecord的“代理“ Proxy對象去標記對應的Activity。
源代碼(部分)如下:
** * An entry in the history stack, representing an activity. */ class HistoryRecord extends IApplicationToken.Stub { final ActivityInfo info; // all about me final Intent intent; // the original intent that generated us final String shortComponentName; // the short component name of the intent TaskRecord task; // the task this is in. 該Activity對應Task的信息 ProcessRecord app; // if non-null, hosting application 該Activity所在的進程信息 boolean stopped; // is activity pause finished? 該Activity是否已經停止 即onStop(); boolean delayedResume; // not yet resumed because of stopped app switches? 是否需要暫時停止啟動 boolean finishing; // activity in pending finish list? 是否正在finish 即殺死該Activity ... }
TaskRecord.java路徑:\frameworks\base\services\java\com\android\server\am\TaskRecord.java
說明: 記錄每個任務 Task的信息。 Activity可以運行在不同的Task中。
源代碼(部分)如下:
class TaskRecord { // id final int taskId; // Unique identifier for this task. final String affinity; // The affinity name for this task, or null. final boolean clearOnBackground; // As per the original activity. //啟動一個新的Task的的Intent信息 Intent intent; // The original intent that started the task. Intent affinityIntent; // Intent of affinity-moved activity that started this task. ComponentName origActivity; // The non-alias activity component of the intent. ComponentName realActivity; // The actual activity component that started the task. //運行在該Task的Activity數目 int numActivities; // Current number of activities in this task. }
ActivityManagerService.java
PS:該類還是相當龐大的,有著琳琅滿目的數據對象,稍不注意,就給迷失了。
源代碼(部分)如下:
class ActivityManagerService extends ActivityManagerNative implements xxx { // This is the maximum number of activities that we would like to have // running at a given time. static final int MAX_ACTIVITIES = 20; //系統中正在運行的Activity數目,最大為20 // Maximum number of recent tasks that we can remember. static final int MAX_RECENT_TASKS = 20; //最大的Task數目為20 /** * The back history of all previous (and possibly still * running) activities. It contains HistoryRecord objects. */ //當前系統中正在運行的Activity信息,即處於onPause、onStop、onResume狀態的Activity信息 final ArrayList mHistory = new ArrayList(); /** * Current activity that is resumed, or null if there is none. */ HistoryRecord mResumedActivity = null; //當前正在於用戶交互的Activity信息,即處於onResume狀態。 /** * When we are in the process of pausing an activity, before starting the * next one, this variable holds the activity that is currently being paused. */ HistoryRecord mPausingActivity = null; //當前正在暫停的Activity信息,即正在onPause(); /** * All of the applications we currently have running organized by name. * The keys are strings of the application package name (as * returned by the package manager), and the keys are ApplicationRecord * objects. */ //當前正在運行的Process信息 final ProcessMapmProcessNames = new ProcessMap (); //開始啟動一個Activity public final int startActivity(){ ...} }
基本對象都已在開篇介紹過,ActivityThread 、ApplicationThread 類。
ActivityThread .java
源代碼(部分)如下:
/** * This manages the execution of the main thread in an * application process, scheduling and executing activities, * broadcasts, and other operations on it as the activity * manager requests. * * {@hide} */ public final class ActivityThread { //保存了該進程裡所有正在運行的Activity信息 , 即沒有onDestroy()的Activity //IBinder對象是HistoryRecord的代理對象,在客戶端已IBinder標記每個Activity信息 final HashMapmActivities = new HashMap (); final H mH = new H(); // H對象 ,Handler子類 Instrumentation mInstrumentation; ... }
ApplicationThread是ActivityThread的內部類
源代碼(部分)如下:
public final class ActivityThread { ... //Binder類 主用功能是接受從AMS傳遞過來的消息,做處理後轉發給H類去進一步處理。 private final class ApplicationThread extends ApplicationThreadNative{ public final void schedulePauseActivity(){...} public final void scheduleSendResult{...} public final void scheduleSendResult(){...} } }
最後介紹一下ActivityThread的兩個內部類。
H類 是ActivityThread的內部類
說明 :H類是一個Hander子類 ,該類僅僅是為了異步調用而設計的,使用方法同Hander類一樣。
源代碼(部分)如下:
public final class ActivityThread { ... private final class H extends Handler { private H() { SamplingProfiler.getInstance().setEventThread(mLooper.getThread()); } //處理消息 public void handleMessage(Message msg){ switch (msg.what) { case LAUNCH_ACTIVITY: { //啟動一個Activity ActivityRecord r = (ActivityRecord)msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo); handleLaunchActivity(r, null); } ... } } } }
ActivityRecord類同樣是ActivityThread的內部類
說明:在客戶端保存當前Activity的相關信息,方便ActivityThread管理維護Activity。這個類在實現和功能上對應於AMS的
HistoryRecord類。
源代碼(部分)如下:
public final class ActivityThread{ ... //記錄了客戶端Activity的信息 private static final class ActivityRecord { IBinder token; //該變量對應於AMS服務端HistoryRecord對象 Intent intent; //啟動該Activity對應的intent信息 Bundle state; //保存一些信息 onCreate(state) Activity activity; //對應於Activity類 ActivityInfo activityInfo; //對應的ActivityInfo對象 ... } }
另外我再對客戶端Activity、ActivityRecord、ActivityThread 類包含的IBinder token屬性進行一下說明:該token變量
實際上指向的的ActivityManagerService的HistoryRecord對象,他們是一一對應的。在應用程序內部和AMS都通過該token
變量來標記我們實際需要的Activity信息。 如下圖所示:
對ActivityManagerService通信模型以及數據類有一定認識後,那麼現在你就可以具體去接觸每個操作是怎麼實現的了。 例如startActivity()、 registerReceiver()等。 後面我也會慢慢講解到的,有興趣的可以先看如下兩篇吧。講解的都挺詳細的,反正我是偷了不少經。 O(∩_∩)O~
項目使用的技術呢,說白了,就是將要傳遞的event(一個Object對象,可任意自定義),發送到公共的組件EventBus中進行存儲, 在通過
喜歡K歌的小伙伴注意啦啦!萬眾期待的酷狗ktv手機版終於上線啦!現在,只要下載了酷狗ktv的手機版,不用去K房,在家也一樣可以開啟唱K模式!那麼,作為酷狗旗
優點:擺脫原始的Crash界面處理缺點:無法自定義界面實現自定義Ui介紹:“Recovery”幫助你自動處理程序在運行時的Crash,它含有以下幾
一、簡介這個題目是別人面試UC優視集團Android逆向工程師一職位的面試題,相比較前面的面試題1,增加了一些難度。 二、題目分析1.使