您的位置:首页 > 移动开发 > Android开发

Android如何完全调试framework层代码

2014-07-25 09:46 836 查看
from:http://blog.csdn.net/i2cbus/article/details/21739261

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 (完)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: