在Android开发过程中难免和JNI NDK打交道做混合开发,按一般方式当交叉编译完成得到so库后,我们将so库集成到Android项目里,打包成apk安装到手机上验证运行效果。但当我们想快速在手机上验证so的功能与性能时,上面提到的传统方式就过于繁琐了。那我们能不能在Android设备上直接运行C/C++程序来直接调用so库呢?
答案是肯定的,因为我们在linux系统就可以直接运行C/C++程序,而Android系统与Linux系统的关系大家也都了解。下面来看一下具体的实现流程:
首先展示一下此demo需要用到的文件
- libs:存放so库
- log.txt: 程序运行后打印的日志
- models_sheet_phone: 模型资源文件
- pictures: 图片资源
- sheet_phone_test: c++运行程序
- testOnAndroid.sh: 运行脚本
文件准备好开始操作:
1.电脑手机连接好,需要自行安装adb环境
# 查看连接的设备
adb devices
2.将准备好的文件push到手机
#将文件复制到Android设备目录下,选择这个路径是因为可以设置文件读写执行权限
adb push /Users/kaka/Desktop/ceshi/ /data/local/tmp
可以看到文件已经成功导入。
3.给c++可运行程序设置权限
chmod 777 /data/local/tmp/ceshi/sheet_phone_test
4.设置查找so库路径的环境变量
export LD_LIBRARY_PATH=/data/local/tmp/ceshi/libs
如果不设置的话,会提示找不到so库的错误:
也看到过一些文章说将自己的so文件放到系统的so默认查找路径,但此操作需要root设备,而通常我们是不想进行root操作的,因此设置环境变量就很好的解决了这个问题。
5.现在可以执行C++程序了
#第一个是c++程序,后几个是我这个执行程序所需传的参数(即 main(int argc, char** argv) 方法中的argv)
/data/local/tmp/ceshi/sheet_phone_test /data/local/tmp/ceshi/pictures/ /data/local/tmp/ceshi/models_sheet_phone 4 1080 1920
最后就是我运行程序打印出的日志信息了。
6.为了简化操作,可以将上述命令写成脚本。
#!/bin/bash
# 运行程序,so库,模型,图片等文件路径
DATA_DIR=/Users/kaka/Desktop/ceshi/
# 复制到Android系统的路径
ANDROID_DIR=/data/local/tmp
function runInAndroidEnv(){
#将准备好的文件push到Android
adb push $DATA_DIR $ANDROID_DIR
adb shell chmod 777 $ANDROID_DIR/ceshi/sheet_phone_test
#LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径
#执行测试程序
adb shell "LD_LIBRARY_PATH=$ANDROID_DIR/ceshi/libs ${ANDROID_DIR}/ceshi/sheet_phone_test ${ANDROID_DIR}/ceshi/pictures/ ${ANDROID_DIR}/ceshi/models_sheet_phone 4 1080 1920 > $ANDROID_DIR/ceshi/log.txt"
#导出运行日志
adb pull $ANDROID_DIR/ceshi/log.txt $DATA_DIR
}
runInAndroidEnv
这样只要直接运行脚本,就可以直接得到程序执行输出的log日志文件了。
此种方案比较适合去做一些自动化测试,可以简便直观的看到我们的sdk(c/c++层)在不同机型(不同cpu)上的性能表现。