Android如何完全调试framework层代码
1 之前写过一篇文章:《Android实现开机调试system_process》
2 google的eclipse插件ADT的已经能够很方便的调试Android的apk了,但是调试的时候应用程序已经进入Activity。
3 如果我们想了解一下Activity的启动过程,只有看代码+看log输出了吗?本文可以告诉你:NO!
4 相信大家比较感兴趣的都是代码,这里先把代码再放出来
ZygoteInit.java
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中的Audio播放:控制Audio输出通道切换
- Android实现图表绘制和展示
- Android入门第十六篇之Style与Theme
- 如何创建QuickAction在Android对话 类似于苹果的效果
- 利用任务调度特性检测Android模拟器
- Android高手进阶教程(八)之----Android(安卓)Widget开发案例(世
- OpenCore的代码结构
- Android上使用ASIFT实现对视角变化更鲁棒的特征匹配
- MVC架构设计与三层模型 & MVP思想精髓与解耦