Android如何完全調試framework層代碼,androidframework
1 之前寫過一篇文章:《Android實現開機調試system_process》
2 google的eclipse外掛程式ADT的已經能夠很方便的調試Android的apk了,但是調試的時候應用程式已經進入Activity。
3 如果我們想瞭解一下Activity的啟動過程,只有看代碼+看log輸出了嗎?本文可以告訴你:NO!
4 相信大家比較感興趣的都是代碼,這裡先把代碼再放出來
ZygoteInit.java
[java] view plaincopy
- public static List<String> readCommandOutput(String command) {
-
- Runtime rt =Runtime.getRuntime();
-
- java.lang.Processproc;
-
- try {
-
- proc =rt.exec(command);
-
-
-
- if (proc.waitFor() != 0) {
-
- return null;
-
- }
-
- LinkedList<String>list = new LinkedList<String>();
-
- InputStreamReader ir = new InputStreamReader(proc.getInputStream());
-
- BufferedReader in = new BufferedReader(ir);
-
- String line = null;
-
- while ((line = in.readLine()) != null) {
-
- list.add(line);
-
- }
-
- return list;
-
- } catch (InterruptedException e) {
-
- e.printStackTrace();
-
- } catch (IOException e) {
-
- e.printStackTrace();
-
- }
-
- return null;
-
- }
-
-
-
- public static String getPackageName(){
-
- String strPid =Integer.toString(android.os.Process.myPid());
-
- String cmd = "ps";
-
-
-
- List<String>result = readCommandOutput(cmd);
-
- if(result == null){
-
- return "";
-
- }
-
-
-
- for(String info:result){
-
- if(info.contains(strPid)){
-
- int index = info.lastIndexOf(" ");
-
- if(index >=0){
-
- StringsubStr = info.substring(index+1);
-
- Log.i(TAG,subStr);
-
- return subStr;
-
- }
-
- }
-
- }
-
- return "";
-
- }
-
-
-
- public static boolean needDebug(String packageName){
-
- String debugProcess = android.os.SystemProperties.get("persist.sys.debug");
-
- Log.i(TAG,debugProcess);
-
-
-
- if(debugProcess.equals(packageName)){
-
- return true;
-
- }
-
- return false;
-
- }
-
-
-
- public static void main(Stringargv[]) {
-
-
-
- try {
-
- // Start profiling the zygote initialization.
-
- SamplingProfilerIntegration.start();
-
-
-
- registerZygoteSocket();
-
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
-
- SystemClock.uptimeMillis());
-
- preload();
-
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
-
- SystemClock.uptimeMillis());
-
-
-
- // Finish profiling the zygote initialization.
-
- SamplingProfilerIntegration.writeZygoteSnapshot();
-
-
-
- // Do an initial gc to cleanup after startup
-
- gc();
-
-
-
- // If requested, start system server directlyfrom Zygote
-
- if (argv.length != 2) {
-
- throw new RuntimeException(argv[0] + USAGE_STRING);
-
- }
-
-
-
- if (argv[1].equals("start-system-server")) {
-
- startSystemServer();
-
- } else if (!argv[1].equals("")) {
-
- throw new RuntimeException(argv[0] + USAGE_STRING);
-
- }
-
-
-
- Log.i(TAG, "Accepting command socket connections");
-
-
-
- if (ZYGOTE_FORK_MODE) {
-
- runForkMode();
-
- } else {
-
- runSelectLoopMode();
-
- }
-
-
-
- closeServerSocket();
-
- } catch (MethodAndArgsCaller caller) {
-
- String packageName = getPackageName();
-
- if(needDebug(packageName)){
-
- android.ddm.DdmHandleAppName.setAppName(packageName,UserHandle.myUserId());
-
- android.os.Debug.waitForDebugger();
-
- }
-
- caller.run();
-
- } catch (RuntimeException ex) {
-
- Log.e(TAG, "Zygote died with exception", ex);
-
- closeServerSocket();
-
- throw ex;
-
- }
-
- }
5 如果有興趣,繼續往下看!
6 readCommandOutput:用於執行命令並擷取命令的輸出
7 getPackageName()有於擷取當前進程的包名
這裡預設進程名稱即為包名
擷取ps的輸出
然後通過pid找到本程式所在的輸出行。
提取出本程式所在的輸出行包名
8 needDebug()用於判斷當前進程是否需要調試,原理是這樣的:
使用者通過setprop persist.sys.debug 包名來設定包的名稱
needDebug擷取 persist.sys.debug
再與本進程的包名進行比較,以判斷是否要調試
9 接下來的動作就和《Android實現開機調試system_process》一樣了:
設定App在DDM中的名稱:
android.ddm.DdmHandleAppName.setAppName(packageName,UserHandle.myUserId());
等待調試器來串連:
android.os.Debug.waitForDebugger();
10 接下來重新編譯和燒錄,mmm...,一個漫長的過程,但是結果將會證明一確都是值得的。
11 接下來,建立一個偽工程,修改Manifest中的package為需要調試的程式包名
12 再在工程中將需要調試的framework層代碼引進來
13 接下來,adb shell串連到android,進行命令列
14 執行命令:
setprop persist.sys.debug 包名
15 在需要調試的代碼上設定斷點
16 接下來,啟動應用程式,注意,是直接啟動程式,而不是通過eclipse啟動調試!
17 enjoy it!
18 (完)
android中更改framework層代碼後怎操作才可以看到更改後的效果?
1.下面方法適合真機:下載android源碼,然後編譯你修改的framwork的代碼,會產生framework.jar,然後push到system/framework目錄下,重啟機器!ok
2,下面方法適合模擬器:
(1):用unyaffs解壓,你下載的sdk目錄下system.img,然後替換其中的framework.jar,然後再壓縮成新的system.img;然後啟動模擬器就ok
(2):或者用直接全編譯源碼,用產生system.img去替換模擬器下面system.img也ok
怎調試android官方代碼
如果指的是Framework層的(比如控制項、系統服務那些),在SDK Manager中下載下來,再Eclipse重關聯一下就能看到了。具體關聯方法是按住Ctrl點Button、TextView,在彈出新頁面中,點擊左上方的Change Attached Source按鈕,再點擊External Folder,找到sdk目錄,點擊sources目錄,選擇你想看的下載過系統版本檔案夾,點確定就能看到了。
如果是想看android底層原始碼,就需要Linux系統內容了,這個我沒有實踐過,具體過程不是很清楚,你還是百度“android原始碼”看看吧,連結就不給了,免得又被屏蔽了……