为APP开发JNI接口以及NDK动态库的时候,需要频繁修改和调试C/C++代码,如果在eclipse或AndroidStudio开发的话,需要1)clean项目,2)ndk build 3)生成APK,启动调试,实际会卸载已安装APK再装一遍,这个过程相当耗时,快则7秒左右,慢则十几秒以上,有没有可能不需要重新安装APK,只需要替换它的so库,重启APP就能自动加载生效?即:
执行ndk-build生成so
替换APP在手机上已安装的so库
重启APP
经过摸索发现可以,整个过程时间缩短为3秒左右。但替换so需要root权限,如果没有root权限怎么办?以下介绍在不需要root权限的环境下实现的方法。
第一步:先将so文件push到sdcard上:
adb push libkplayer.so /sdcard/
第二步:进入shell,并且换APP的身份:
adb shell
run-as com.xxx.jkplayer #APP包名
这时shell自动切换到/data/data/com.xxx.jkplayer目录下,此目录是可写的,而原来打包在APP里的so库存放在/data/data/com.xxx.jkplayer/lib/下是不可写,所以解决的方法是将修改好的so库copy到/data/data/com.xxx.jkplayer,这需要在JAVA层稍为修改一下加载库的方法:
//System.loadLibrary("jkplayer");
System.load("/data/data/com.xxx.jkplayer/libjkplayer.so");
重新编译和安装APK,这时启动时会提示loadLibrary失败,没关系,做完下一步就可以了。
第三步:从/sdcard上copy过来并赋予可执行权限:
cp /sdcard/libjkplayer.so . #当前目录在/data/data/com.xxx.jkplayer
chmod 0755 libjkplayer.so
现在重新启动APP,就可以成功把/data/data/com.xxx.jkplayer/libjkplayer.so load起来,下次我们只需要替换掉这个so,重启APP就可以了,而不需要点AndroidStudio调试按钮了。
我们当然希望写一个脚本来自动实现替换so并重启APP的动作,启动APP:
adb shell am start -n com.xxx.jkplayer/com.xxx.jkplayer.MainActivity
重启之前,可以先强行停止APP:
adb shell am force-stop com.xxx.jkplayer
将这些脚本和ndk-build等组合在一起,每次修改完C/C++代码后,执行脚本,只需要3秒左右APP已经重启就绪。下面我介绍如何为QtCreator IDE配置这些脚本,并且只需要点一个run按钮或ctrl+r就能直接跑起这个脚本,还能显示编译错误和点击定位错误,还能在QtCreator中看到Android的log输出。
为什么使用QtCreator(不需要装QtSDK)?
因为它用来写C/C++代码,轻量级跨平台,代码补全高亮不在话下,书签、代码大纲、编辑器分栏、快捷键都挺好使。 好吧,真正是因为我一直用它,所以觉得顺手。
ndk-build的编译输出窗口,也可以通过配置将logcat的日志显示到此窗口来。
经常与JNI打资产,如果靠手工查手册就欲哭无泪了-_-~~
也可以配置使得NDK里的库函数和头文件都可以补全,代码阅读时点击跳转。
下面介绍配置过程。
第一步:import jni目录,完成后,保存所有,QtCreator的工程文件也会保存在import目录下
第二步:进入项目属性,删除默认的构建步骤(ctrl+b时调用),添加自己的:
其中的%{buildDir}\build.bat
指的是Qt工程(xxxx.qtcreator)所在目录下的build.bat脚本,内容为:
$NDK\ndk-build -c jni
NDK为指向ndk sdk根目录的环境变量,-c
参数指向你jni工程目录,即里面存放c/c++/Android.mk等,如果Qt工程建在jni目录下,-c jni
不需要。
clear.bat的内容:
$NDK\ndk-build -c jni clear
run.bat:
adb shell am force-stop com.xxx.jkplayer
adb push libs\armeabi-v7a\libjkplayer.so /sdcard/
&& adb shell "run-as com.xxx.jkplayer cp -v /sdcard/libjkplayer.so ."
&& adb shell "run-as com.xxx.jkplayer chmod 0755 libjkplayer.so"
&& adb shell am start -n com.xxx.jkplayer/com.xxx.jkplayer.MainActivity
executable.bat:
adb shell "logcat -c && logcat -v time | grep -i xxx" #将logcat输出到QtCreator上来
实际使用发现这样打印出来的每行log都被追加了一个空行。当然,你也可以使用AndroidStudio的日志查看器。
OK,现在已经可以用了,编写代码,ctrl+r一下,编译、部署so、重启APP,一步到位。
最后附上代码补全设置:
保存后,QtCreator会自动reload,编辑器就立刻高亮JNI和NDK函数,按住ctrl键,将鼠标移到符号上点击就可以跳转,alt+左箭头返回。