root@s5p4418_lonbon:/ # ps | grep com.android.settings 说明: 查看应用是否启动PID USER TIME COMMAND 注意:进程ID 用户4856 system 0:00 {ndroid.settings} com.android.settingsroot@s5p4418_lonbon:/ # pm list package | grep com.android.settings 说明:系统中确实有包:com.android.settingspackage:com.android.settingsadb kill-server 和 adb start-serveradb install xxx.apk 安装apkadb install -r xxx.apk 重装apkpm installl xxx.apk 安装apkadb uninstall com.mayday.ethernetdemo 卸载apkpm uninstall com.mayday.ethernetdemo 卸载apk$ adb devicesList of devices attachedemulator-5554 deviceemulator-5555 device$ adb -s emulator-5555 do_your_commandam force-stop com.android.settings 停止apkroot@s5p4418_lonbon:/system/priv-app/Settings # pm path com.android.settings 查看包所对应的apk路径package:/system/priv-app/LBSettings/LBSettings.apk删除与包相关的所有数据,清除数据和缓存:pm clear com.android.settingsam restart 快重启安卓系统intput keyevent --longpress 4 模拟长按返回键intput keyevent 4 模拟短按返回键/system/bin/mount -o rw,remount /system 重挂载system/system/bin/mount -o rw,remount / 重挂载根am restart 快速重启Android快速会杀掉:com.lonbon.launcher, !!com.android.phone,com.android.music,com.iflytek.vflynote:xpushcom.android.keychaincom.android.providers.calendarcom.android.gallery3dcom.google.android.inputmethod.koreancom.estrongs.android.popcom.android.printspoolercom.iflytek.vflynotecom.iflytek.vflynote:tts_serviceandroid.process.acoreandroid.process.mediacom.android.inputmethod.latincom.android.settings 设置com.lonbon.lonbon_app 来邦应用com.android.systemui 系统界面adb -s FA4412DBA4120433 shell 选择指定adb设备的shell对于4418和905x,打开console,如下,因为“start console”依赖于lonbon.debuggable,所以只要在/system/build.prop加入lonbon.debuggable=1,重启即可开启调试on property:lonbon.debuggable=1start consolestart adbd对于905x/4418,只要拦截uboot启动,并输入lonbon登录密码,然后再uboot命令行执行save命令,即会在uboot中增加unlock_con=true到cmdline,android的init进程会解析cmdline,如果获知unlock_con=true,则设置lonbon.debuggable=1,对于3399,s905d3,目前还没有禁止console,所以不需要设置unlock_con=true或者设置lonbon.debuggable=1截图:screencap -p /sdcard/screen.png读取build变量:fjh@lonbon:~/work/platform/s905d3$ . build/envsetup.shfjh@lonbon:~/work/platform/s905d3$ lunch lb905d3-userdebugfjh@lonbon:~/work/platform/s905d3$ get_build_var OUT_DIRoutfjh@lonbon:~/work/platform/s905d3$ get_build_var TARGET_OUTout/target/product/lb905d3/systemhide用法:Makefile在执行@后面的命令时,不回显将要执行的命令,如果删掉 @,则可以看到命令执行的详细过程$ grep -rnHI "hide" build/make/core/config.mkbuild/make/core/config.mk:169:hide := @可用命令的完整列表:hmm (要先执行:. build/envsetup.sh)查看编译帮助文件fjh@lonbon:/work/platform/s905d3$ ./build/make/help.shOSD截图:screencap -p /storage/sdcard/tes1t.pngstart media 启动media服务,执行/system/bin/mediaservermediastart surfaceflinger 启动surfaceflinger 服务,执行/system/bin/surfaceflingerstop surfaceflinger
Android Studio 快捷键
Ctrl+Alt+ left/right 返回至上次浏览的位置
快速调试Java代码
库依赖:部分人说需要加入rdynamic ,可视编译情况而定,本人编译没有加可以通过android 系统 C++部分:#include <utils/CallStack.h>using namespace android;void print_stackframe(void){CallStack stack;stack.update();stack.log(printTag);}库依赖:android8及以下:libcutilsandroid9及以上libutilscallstack
打印调用栈
基本分两大类,一类是静态的,要把打印语句插入到代码中,一类是动态的,需要看的时候,查看一下,实时观测各线程调用栈情况。
Andoird 命令
am stack start
am stack movetask [true|false]
am stack resize
am stack list
am stack info
静态方法
1. Java中打印调用栈
导入的包是:import android.util.Log;Java 主动抛出异常来获得调试信息:try { 这种方法在普通签名或者平台签名的app可行,应用不会崩throw new Exception();} catch (Exception e) {Log.e(TAG, "Exception: ~~~~~~~~~~ ~~~~~~~~~~", e);}或者:StackTraceElement[] ste = new Throwable().getStackTrace(); 这种方法在普通签名或者平台签名的app可行,应用不会崩if(ste.length >=1){for(int i = 1; i < ste.length; i++){Log.d(TAG, "File:" + ste[i].getFileName() + ", Line: " + ste[i].getLineNumber() + ", MethodName:" + ste[i].getMethodName());}}或者如果只是想在文件中添加一些输出,譬如想输出当前哪一行,在哪个文件中,用下面的测试代码就可以了public class Test{public static void main(String args[]){System.out.println("This is " + getLineInfo());}public static String getLineInfo(){StackTraceElement ste = new Throwable().getStackTrace()[1];return ste.getFileName() + ": Line " + ste.getLineNumber();}}或者:android 系统 java部分:Log.d(TAG,Log.getStackTraceString(new Throwable())); 这种方法在普通签名或者平台签名的app可行,应用不会崩报错1:Can't write: system_app_crash
2. C++中打印调用栈
也是比较简单,直接利用CallStack类
#include <utils/CallStack.h>...CallStack stack("FUCK");...
CallStack从4.3开始,重写了下,现在使用比较简单了,实例化的地方就直接打印了。
成功的案例:
status_t AudioFlinger::ThreadBase::readyToRun(){CallStack stack("FUCK"); 这是我加的status_t status = initCheck();if (status == NO_ERROR) {ALOGI("AudioFlinger's thread %p ready to run", this);} else {ALOGE("No working audio driver found.");}return status;}
3. C中打印调用栈 (测试:在4418能编译通过)
以前写的方法,又复杂又不好用(版本更新,很多库和接口都变了)。其实,在C中打印调用栈,也是超级简单。只要随便找一个C++的源文件,实现一个函数就可以了:
#include <utils/CallStack.h>using namespace android;extern "C" void printCallStack();void printCallStack() {CallStack stk("Fuck");}
这可以添加在android现有code中,也可以自己新增一个cpp的文件编进来。 想要打印的地方,直接调用即可:
...extern void printCallStack();void test_c_code() {...printCallStack();...}...
注意:
- C++代码的printCallStack声明一定要有extern “C”,否则c++的mangle后的符号,C中是不认的
- 添加后注意库的链接,还有命名空间别搞错了。
另外,以上方法实际上也就适用在汇编中打印CallStack,都一样的~~
以上CallStack方法, NDK中不好用,而且旧版本可能有兼容性问题,NDK想用的话,需要处理一下,不过不保证每家做出来的都一样(理论上google没统一的,可能都可能不保险..),应用包进去的话,估计要小心点。
4. 内核态代码中打印调用栈
内核看调用栈,也是比较简单的,直接在要看的地方,加入下面一行代码:s905d3,3516e,3516d,4418,3399,3536,4412都支持
WARN_ON(1);
静态打印的问题:
- 静态打印调用栈,需要修改代码,重新编译运行
- 对于底层函数,或者调用次数很多的函数,会出现海量流氓log,没法真正分析了。
解决方法,改代码这个没法解决,针对流氓log,可以想一些办法:
- callStack的地方,条件触发,根据上下文,设置条件触发
- 不好以上下文设条件的,可以根据进程名/uid等设置触发条件
- 可以用大绝招:自己定义property设条件,可以在shell串口通过改变property值来toggle log开关。
动态方法
动态的话,其实ADB连上DDMS后,查看更方便,java堆栈查看起来特别顺手,这里只看shell命令的几种方式:
1. Dump Java调用栈
java调用栈实际也包含了native的栈和内核栈,比较全一些,看的也更清晰。使用方式也很简单:
kill -3 <pid>
由于是虚拟机帮忙的,目前只适用于虚拟机进程(即java进程)<br />2. Dump native栈<br /> 用Debuggerd很容易获取native栈信息,这个可以当采样或者分析卡住或死锁问题。
debuggerd -b <pid>
注意这个对java进程,是得不到java调用栈的,不过得到的是虚拟机执行java指令时的虚拟机调用栈,debugger 虚拟机必用。<br />3. 查看内核栈<br /> 比较难,大多系统没有开放,看不到,不过调试版本可以。<br /> 查看方法是:
cat /proc/<pid>/task/<tid>/stack
不过最新Naugot上的调用栈,看起来最新的不做demangle了:
"main" prio=5 tid=1 Native| group="main" sCount=1 dsCount=0 obj=0x748ef6b8 self=0xa638b400| sysTid=1774 nice=0 cgrp=default sched=0/0 handle=0xaa74b534| state=S schedstat=( 0 0 0 ) utm=18 stm=193 core=0 HZ=100| stack=0xbf403000-0xbf405000 stackSize=8MB| held mutexes=kernel: SyS_epoll_wait+0x23c/0x2d1kernel: SyS_epoll_pwait+0x70/0xe1kernel: sysenter_do_call+0x12/0x22native: #00 pc ffffe424 [vdso] (__kernel_vsyscall+16)native: #01 pc 000779ab /system/lib/libc.so (__epoll_pwait+43)native: #02 pc 00020cb0 /system/lib/libc.so (epoll_pwait+112)native: #03 pc 00020d0e /system/lib/libc.so (epoll_wait+62)native: #04 pc 00018f1b /system/lib/libutils.so (_ZN7android6Looper9pollInnerEi+203)native: #05 pc 00018d84 /system/lib/libutils.so (_ZN7android6Looper8pollOnceEiPiS1_PPv+68)native: #06 pc 000d38c3 /system/lib/libandroid_runtime.so (_ZN7android18NativeMessageQueue8pollOnceEP7_JNIEnvP8_jobjecti+77)native: #07 pc 000d3934 /system/lib/libandroid_runtime.so (???)native: #08 pc 007b1c0c /system/framework/x86/boot-framework.oat (Java_android_os_MessageQueue_nativePollOnce__JI+136)at android.os.MessageQueue.nativePollOnce(Native method)at android.os.MessageQueue.next(MessageQueue.java:323)at android.os.Looper.loop(Looper.java:136)at android.app.ActivityThread.main(ActivityThread.java:6119)at java.lang.reflect.Method.invoke!(Native method)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
这有点蛋疼,读起来有点难受,看提交记录,是为了绕某个bug:
commit 7c903fbacfaf449fb4f7a9fa2f1a1b6ba2db5330Author: Josh Gao <jmgao@google.com>Date: Tue Mar 22 11:29:17 2016 -0700Don't demangle symbol names.Bug: http://b/27299236Change-Id: I3a698c6d93e262fd78e743c1e6e946b054b9dcd1
当然,这些动态看的调用栈,通过adb bugreport或dumpstate命令,都能得到。如果有bug的话,可以先保存一份bugreport,存下了放在后面慢慢看,然后再来解刨场景分析。
Android Studio技巧
Ctrl+Q :把光标移至方法处,按此组合键可快速查看方法的说明文档
Ctrl +Alt + ← :返回
实现接口:Ctrl+I
Android java代码技巧
{@link}与@see
写代码的时候,有时候,你需要写一些注释,把内容相互关联起来,方便自己或别人看的时候,可以直接找到你关联的代码类或者啥的。
这个时候,{@link}与@see,这2个javadoc注解就派上用场了,
不管他具体有什么功能,咱就只管一个,他可以链接代码,让注释看的更清楚易懂。方便你我他。
@see 标签允许用户引用其他类的文档。具体使用方式如下:
@see classname
@see fully-qualified-classname
@see fully-qualified-classname#方法名称
@see fully-qualified-classname#属性名称
我在使用的时候,发现这个只能单独一行顶头写,如果不顶头写就不管用了,没了链接的效果。
但是,{@link}这个却可以随便放。
具体使用方法和上面那个@see是一样的。
实际效果,看下面的图吧。
Tips:{@link}指定的链接,可以“Ctrl + 鼠标左键”跳转
@Deprecated注解的使用
被注解@Deprecated标记的程序元素是不鼓励使用的程序元素,通常是因为它很危险,或者是因为存在更好的替代方案。
方法被画了删除线,以为这个方法是不赞成使用的
