shell 是一种脚本语言。
脚本:本质是一个文件,文件里面存放的是 特定格式的指令,系统可以使用脚本解析器 翻译或解析 指令 并执行(它不需要编译)
shell 既是应用程序 又是一种脚本语言(应用程序 解析 脚本语言)
1 | #!/bin/bash |
shell 是一种脚本语言。
脚本:本质是一个文件,文件里面存放的是 特定格式的指令,系统可以使用脚本解析器 翻译或解析 指令 并执行(它不需要编译)
shell 既是应用程序 又是一种脚本语言(应用程序 解析 脚本语言)
1 | #!/bin/bash |
一、Linux环境
1.NDK下载链接:https://github.com/android/ndk/wiki/Unsupported-Downloads(尽量选择R17版本)
2.解压压缩包:unzip xxx.zip
3.配置环境变量:sudo gedit /etc/profile (在最底部配置环境)
1 | NDKRO0T=/root/ndk/android-ndk-r17c //(设置一个ndk变量,解压的目录) |
4.立即生效:source /etc/profile
5.验证是否成功:ndk-build
1 | //出现以下内容说明配置成功 |
【1】生成动态库
动态库在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库。Linux中后缀名为“.so”。
动态库节省空间:如果一个动态库被两个程序调用,那么这个动态库只需要在内存中。
1 | 【1】分步骤生成动态库 |
【2】生成静态库
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。Linux中后缀名为”.a”。
静态库节省时间:不需要再进行动态链接,需要调用的代码直接就在代码内部。
1 | ar -crv libHello.a Hello.o |
【3】链接静态库(生成可执行文件)
1 | g++ Hello.cpp -o Hello -static -L. -l Hello |
【4】-I 添加搜索头文件的路径(大写i)
系统默认头文件搜索路径大致为
1 | 当前目录(如果是双引号包含的话) --> /usr/include --> /usr/local/include |
【5】-L 指定要链接的库所在目录,-l 指定路径寻找库文件
1 | 链接时库搜索路径 /lib --> /usr/lib -->/usr/local/lib |
【6】查看可执行文件符号
1 | nm main |
【7】默认优先使用动态库
1 | gcc main.c -L. -lTest -o main |
【8】强制使用静态库
1 | #-Wl 表示传递给 ld 链接器的参数 |
【9】打包 .a 到so
1 | #打包 .a 到so |
【10】其它命令
–sysroot=XX
使用XX作为这一次编译的头文件与库文件的查找目录,查找下面的 usr/include usr/lib 目录。
1 | g++ --sysroot=C:\Users\94317\AppData\Local\Android\ndk\android-ndk-r20b\sysroot Hello.cpp |
-isysroot XX
头文件查找目录,覆盖–sysroot ,查找 XX/usr/include
-isystem XX
指定头文件查找路径(直接查找根目录)
-IXX
头文件查找目录
优先级:
-I -> -isystem -> sysroot
GCC编译过程:
1 | 1)预处理,C 编译器对各种预处理命令进行处理,包括头文件包含、宏定义的扩 展、条件编译的选择等,后缀是 .i文件。 |
【1】预处理
1 | 不输出文件: |
【2】转换为汇编文件
1 | 不指定预处理文件: |
【3】编译(生成目标文件)
1 | 不指定汇编文件: |
【4】链接(生成可执行文件)
1 | 不指定目标文件: |
【5】执行可执行文件
1 | .\Hello |
同目录多文件的情况下:
1 | gcc Hello.c A.c B.c -o Hello |
1 | 【1】-o FILE: 指定输出文件名,在编译为目标代码时,这一选项不是必须的。 |
【1】ndkBuild配置
1 | android { |
在模块下的 build.gradle 中配置 ndkBuild,确认CPU架构以及Android.mk路径。
【2】将源码编译成动态库
1 | # 每个Android.mk文件必须以定义LOCAL_PATH为开始 |
编译之后,动态库libnative-lib.so会在模块下的 build/intermediates/ndkBuild/
目录下生成。
【3】Android.mk 编译时日志
1 | #输出字符串的方式有如下三种,程度越来越高,有点像Android里面的Log等级 |
【4】c/c++代码日志在AS控制台上现实
1 | # 加载NDK的日志库 |
需要在 include $(BUILD_SHARED_LIBRARY)
前面添加 LOCAL_LDLIBS := -llog
,加载NDK中自带的日志库。
在源代码中定义宏:
1 | #define LOG_TAG "native-lib" |
在源代码中,打印日志到AS控制台:
1 | LOGI("start thread task"); |
【5】Android.mk 生成动态库
1 | LOCAL_PATH := $(call my-dir) |
编译之后, 自动生成动态库,可以在build的以下目录中找到。
【6】使用预先编译好的动态库
编写mk:
1 | # 每个Android.mk文件必须以定义LOCAL_PATH为开始 |
include $(PREBUILT_SHARED_LIBRARY)
预编译动态库,LOCAL_SHARED_LIBRARIES := Test
加载动态库到apk中:
在c++源码中声明libTest.so中的函数
1 | // 如果是C,需要添加 extern "C"{} |
如果调用的是C代码,需要更改为:
1 | extern "C"{ |
【7】变量和宏
定义自己的任意变量。在定义变量时请注意,NDK 构建系统会预留以下变量名称:
LOCAL_
开头的名称,例如 LOCAL_MODULE
。PRIVATE_
、NDK_
或 APP
开头的名称。构建系统在内部使用这些变量。my-dir
。构建系统也是在内部使用这些变量。如果为了方便而需要在 Android.mk
文件中定义自己的变量,建议在名称前附加 MY_
。
【8】其它语法详解
1 | 1、`LOCAL_MODULE` 可以设置模块名称: |
一、Eclipse安装
1.官网地址:https://www.eclipse.org/
2.点击【Download】 ,进入eclispe下载页面,点击【Download x86_64】这个按钮直接下载eclipse软件;
3.下载后安装时选择:Eclipse IDE for Java Developers
4.选择安装路径及jre版本号;
5.Eclipse运行后会弹出一个对话框,提示选择工作空间(Workspace);
二、使用Eclipse进行程序开发
1、创建Java项目,点击“File”→“New”→“Project…”。
2、选择“Java Project”,点击【Next】下一步。
3、在Project name(项目名字)框里取个名字叫”Chapter01”(第一章的意思),其余选项保持默认,然后点击【Finsh】完成。
4、在项目下创建包,找到刚刚创建的Chapter01项目展开找到src文件夹右键打开找到“New”→“Package”。
5、打开“Package”后,在“name”框里取名叫“haha”,“Source folder”意思是项目所在的目录,Chapter01/src就是指这个包在Chapter01项目下的src文件里,然后单击【Finish】完成创建。
6、 在包下面创建类,找到刚刚创建的“haha”包,然后右键打开“New”→“Class”。
7、打开Class后,在Name框里取名叫“HelloWorld”,然后点击【Finsh】。
8、在编写区编写如下代码:
1 | public static void main (String[] args) { |
9、运行程序,右键点击【Run As】→【Java Application】运行;
1、c盘压缩出300M的未分配空间,用于ubuntu系统的efi引导区
2、其它盘符压缩出足够的空间(500G/2T)未分配空间,用于ubuntu系统和存储区
3、下载rufus,下载ubuntu系统镜像iso,制作ubuntu系统u盘
4、插入U盘,bios设置U盘启动(还有个efi啥选项设置为enable还是ture,忘记了)
5、u盘启动,开始安装ubuntu系统
6、安装
1、语言,默认english
2、网络,选择暂时不链接
3、是否安装第三方软件,不安装,选择了安装速度会慢
4、installation type->选择something else(自定义安装,手动分区)
5、选中300M区域,primary/Beginning of this space/EFI System partition
6、再对(500G/2T)空间进行分区,
A:swap交换区,内存大小空间,Logical/Beginning of this space/swap area
B:根目录分区,剩下的全部空间 Logical/Beginning of this space/Ext4 journaling file system/加载点选择根目录(/)
C:最后选择挂载点(Device for boot loader installation),一定要选择上面分的那个300M的EFI分区
7、设置密码等操作即可安装完成
8、设置Windows和Ubuntu双系统切换,预防开机黑屏或花屏
在ubuntu系统,Ctrl + Alt + T打开终端;
在终端输入sudo gedit /etc/default/grub,回车输入用户密码(输入的密码是看不到)然后回车打开grub引导文件;
将grub文件中的GRUB_DEFAULT=0修改为GRUB_DEFAULT=saved;
在下面添加GRUB_SAVEDEFAULT=true,保存文件并退出一个具有注脚的文本5。
修改下图第10行中的参数为”quiet splash nomodeset”。(预防可能出现的花屏黑屏问题)
终端输入 sudo update-grub,回车更新grub文件。
终端输入sudo reboot,回车重启。在启动界面就可以切换想要打开的系统了。不操作默认打开上次打开的系统。
9、同步双系统的时间
双系统的时间不同步是由于,ubuntu会设置主机中的COMS时间为UTC时间,然后加上ip时区计算出本地时间,而windows则是使用CMOS中的时间为本地时间。
终端执行 timedatectl set-local-rtc 1
Logcat 查看日志可选参数
1 | 可选的参数主要有: |
aosp中查看c++版本
1 | //文件路径:build/soong/cc/config/global.go |
java代码跳转natice查找方式
1 | 全局查找:_加java类名 |
搜索/查找文件
1 | cd到framework/system或其他目录,以getevent文件为例 |
查看所有进程的pid
1 | ps -A (查看指定进程的pid:ps -A | grep " packageName") |
adb执行截屏或其他手势
1 | adb shell input keyevent 120 调用截屏命令 |
打印日志调试(这种方法只能查找java层,无法查找到native调用java层的方法,native调用java使用grep搜索)
1 | //查找某个地方从底层调用了哪些,加入下面代码,这种方式不会引起程序崩溃,可以获取到堆栈的调用顺序; |
native端打印堆栈
1 | C++ 中使用android::CallStack将所在线程的调用堆栈打印出来 |
查看当前view对应的具体的是谁
1 | //加上 | grep ResumedActivity 是筛选出当前最top的Activity |
查找系统应用(launcher2)在哪些地方编译的
1 | //cd到~/android-8.1.0_r1/build目录,grep "Launcher2" ./ -rn查找在哪里有用到,注意大小写 |
input dumpsys,打印触摸事件日志到本地文件
1 | # 给触摸事件保存到一个txt中 |
adb shell am stack list查看设备上当前运行的应用程序和任务的信息以及点击坐标,它们之间的关系和顺序等;
AOSP常用编译和查找命令
command | describe |
---|---|
m | 等同于 make ,进行一次完整编译。 |
mm | 在当前目录下编译所有模块,但不包括依赖项。 |
mmm [目录] | 编译指定目录下的所有模块,但不包括依赖项。只编译指定模块:mmm [dir/:target1,target2] |
mma | 在当前目录下编译所有模块,包括依赖项。 |
mmma [目录] | 编译指定目录下的所有模块,包括依赖项。 |
make clean | 删除整个 out/ 目录。 |
make clobber | 用于清除编译缓存。 |
make snod | 当重新编译部分模块完成后,快速生成img文件。 |
cgrep | 对C/C++文件执行 grep (只搜寻C/C++文件类型,也包括.h类型)。 |
jgrep | 只对Java文件执行 grep (只搜寻Java文件类型)。 |
resgrep | 只匹配 /res 目录下的 xml 文件。 |
sepgrep | 只查找sepolicy文件。 |
adb shell dumpsys命令
1 | 命令用于获取Android设备上正在运行的系统服务信息。通过该命令,可以获取到各种设备状态、应用程序信息以及系统服务信息。 |
vscode搜索跳转行号:搜索栏 :加行数;
vscode搜索查询方法:搜索栏 @ 加方法名
monkey简略:
1 | monkey是android下自动化测试比较重要的的一个工具,该工具可以运行在host端或者设备(模拟器或真实设备)。 |
monkey脚本:
1 | 脚本优势:简单、快捷、不需要借助任何工具,可以做简单的性能测试 |
Api | 说明 |
---|---|
LaunchActivity(pkg_name,activity) | 启动应用的Activity |
Tap(x,y,tapDuration) | 模拟单击事件.tapDuration为点击的持续时间,此参数可冒略 |
RotateScreen(rotationDegree,persist) | 旋转屏幕,rotationDegree为旋转角度,1代表90度:persist表示旋转之后是否固定,0表示旋转后恢复,非0则表示固定不变 |
DispatchPress(keyName) | 按键 |
DispatchFlip(true/false) | 打开或者关闭软键盘 |
RunCmd(cmd) | 在设备上运行 shell 命令 |
PressAndHold(x,y,pressDuration) | 模拟长按事件 |
DispatchString(input) | 输入字符串 |
DeviceWakeUp() | 唤醒屏幕 |
UserWait(sleepTime) | 让脚本中断一段时间 |
adb获取系统已安装的apk文件:
1 | 1.第三方app:adb shell /data/app/目录下apk pull出来 |
monkey脚本编写步骤:
1 | 1:确定步骤,如下: |
脚本示例:
1 | //myMonkey.txt文件内容: |
获取手机当前显示的界面的包名:adb shell dumpsys activity | find “mFocusedActivity”
命令帮助:adb shell monkey –help
monke常见参数:
-p:
1 | 用于约束限制,用此参数指定一个或多个包( Package,即App名字)。指定指定包之后Monkey将只允许系统启动指定的APP。如果不指定包,Monkey将允许系统启动设备中的所有APP |
-s:
1 | 用于指定伪随机数生反工seed值,如果seed相同,则两次Monkey测试所产生的事件序列也相同 |
-v
1 | 总共分3个级别日志级别(正常使用3个-v) |
–throttle
1 | 用于指定用户操作( 即事件)间的时延,单位是毫秒 |
–randomize-throttle
1 | 在事件之间插入随机延迟,随机延迟范围为0到throttle设置的时间,单位为毫秒 |
–pkg-whitelist-file
1 | 白名单,后面接txt文件(要执行测试的多个包名,多个包名换行保存即可) |
–pkg-blacklist-file
1 | 黑名单,后面接txt文件 |
日志输出到指定路径
1 | > 后面加输出的路径即可; |
monkey其他常见参数
名称 | 说明 |
---|---|
–pct-touch | 调整点击事件的百分比,down-up,编号为0(100为百分之百) |
-pct-motion | 调整移动事件的百分比,直线滑动,编号为1 |
-pct-pinchzoom | 调整两指缩放压缩手势的百分比,比如放大缩小手势操作,编号为2 |
-pct-trackball | 调整轨迹球时间百分比,不常用,编号为3 现在手机几乎没有滚动球,但滚动球事件中包含曲线滑动事件,在被测程序需要曲线滑动时可以选用此参数 |
-pct-rotation | 调整旋转事件的百分比,横屏竖屏,编号为4 |
-pct-nav | 调整导航事件的百分比,编号为5,包括上下左右,如方向输入设备的输入 )老手机的上下左右键,智能机上没有 |
-pct-majornav | 调整主要导航事件的百分比,编号为6,例如中间键、回退键、菜单键 |
-pct-syskeys | 调整”系统”按键事件的百分比,编号为7,这些按钮一般专供系统使用,如Home, Back,Start Call, End Call,音量控制 |
-pct-appswitch | 调整app切换事件的百分比,编号为8 |
-pct-flip | 调整键盘唤出隐藏的百分比,编号为9 |
-pct-anyevent | 跳转除上面事件外,其它事件的百分比,编号为10,如按键、其他在设备上不常用的按钮等 |
Linux中分析相关代码比较多的话就还是需要找一个比较好的工具进行,其实普遍比较主流的有2种:
1、sourceinsight –这个基本做linux kernel相关使用比较多,基本分析跳转和写代码都还是比较方便,缺点就是只要windows版本,还需要付费
2、VSCode这个是微软的轻量级IDE工具,这个开源,而且可以跨平台windows,mac,linux都可以,对c、c++等语言支持非常好,所以是个比较好的选择,缺点就是对java等支持相比没有as好,导致我们可能主要把它用于native代码阅读编写
因为我们是ubuntu开发,所以这里当然就选vscode进行native源码环境搭建,并且是Ubuntu上面:
步骤
1、下载vscode,这个其实官网有,但是因为实在是网络太卡,建议可以
https://code.visualstudio.com/下载
2、安装下载deb文件,命令如下:
1 | sudo dpkg -i xxxx.deb |
3、启动vscode,直接取Ubuntu应用列表中打开VSCode,刚开始进入建议先
安装vscode的插件,c/c++,c++ intelligent
1 | Android System Tools |
4、然后在file –>open folder打开我们的代码文件夹,我这里是仅仅打开的aosp/frameworks文件夹,没有打开整个aosp源码目录,因为整个aosp代码量太大,运行太卡,基本做完这几个就可以愉快的看到漂亮的native代码了
习惯了eclipse的快捷命令,肯定会不知道怎么操作VSCode类似的场景,这里总结一些快捷键:
1 | 快速文件导航:Ctrl + P |
1、查找当前工程中某个文件:ctl+p
2、查找当前cpp文件中某个方法展示出方法列表 :ctl+shift+o
3、返回上一个操作:在Linux中可以使用快捷键Ctrl+Alt + -
vscode搜索跳转行号:搜索栏 :加行数;
vscode搜索查询方法:搜索栏 @ 加方法名
ps:存在问题写代码时候一些对象等无法有提示,debug进程时候发现无法打断点;