Android如何完全調試framework層代碼

來源:互聯網
上載者:User

1 之前寫過一篇文章:《Android實現開機調試system_process》

2 google的eclipse外掛程式ADT的已經能夠很方便的調試Android的apk了,但是調試的時候應用程式已經進入Activity。

3 如果我們想瞭解一下Activity的啟動過程,只有看代碼+看log輸出了嗎?本文可以告訴你:NO!

4 相信大家比較感興趣的都是代碼,這裡先把代碼再放出來

ZygoteInit.java

public static List readCommandOutput(String command) {

Runtime rt =Runtime.getRuntime();

java.lang.Processproc;

try {

proc =rt.exec(command);

if (proc.waitFor() != 0) {

return null;

}

LinkedListlist = new LinkedList();

InputStreamReaderir = new InputStreamReader(proc.getInputStream());

BufferedReaderin = new BufferedReader(ir);

Stringline = 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";

Listresult = 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){

StringdebugProcess = 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》一樣了:

設定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 (完)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.