Android(安卓)手动编译jni动态库
- 目的
- 编译环境配置
- 配置环境变量
- 测试简单的例子
- 为什么非要有jni那一层目录
- 编译一个可以允许的文件
目的
能快速,简单(主要是指脱离AndroidStudio)的把c/c++ 源码进行交叉编译成Android上的动态库,静态库,或者可执行文件。从而为逆向分析构建demo节省时间。
编译环境配置
电脑:Mac OS 10.13.4
NDK:官网下载,目前最新的好像android-ndk-r17 我用的是 android-ndk-r14b,ndk不需要安装官网下载后解压就行。
配置环境变量
为了方便使用ndk的命令行工具,我们配置环境变量
在 ~/.bash_profile
文件中添加如下配置
export ANDROID_NDK_HOME=/Users/user01/Development/android-ndk-r14bexport PATH=${PATH}:${ANDROID_NDK_HOME}:${ANDROID_NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin
然后命令行运行如下命令:
$ source ~/.bash_profile
然后命令行运行:
$ ndk-build -h
如果能打印出 ndk-build 这个工具的帮助文档说明环境变量配置成功
测试简单的例子
创建如下目录结构(注意jni这层目录很重要,名字不要随便取):
~/Desktop/test/└── jni/ ├── Android.mk ├── Application.mk └── test.c
主要有三个文件,其中Android.mk和Application.mk 是辅助ndk-build进行编译的,test.c是我们的c测试用例
- Application.mk
主要指定生成哪些cpu架构的动态库,这里只生成armeabi 和armeabi-v7a架构的库
APP_ABI := armeabi armeabi-v7aAPP_PLATFORM := android-14
- Android.mk
具体Android.mk的更详细的配置自行Google
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)# 生成的so库的名字为libdemo.soLOCAL_MODULE := demo# 用于编译的c文件LOCAL_SRC_FILES := test.c# 生成库的类型,是动态库,静态库还是可执行文件,这里先来生成一个动态库include $(BUILD_SHARED_LIBRARY)# 下面这么写是生成可执行文件#include $(BUILD_EXECUTABLE)
- test.c
很简单就是打印一句 hello world!
#include int main(const int argc,const char* args[]){const char* str = "hello world!";printf("%s\n",str);return 0;}
然后命令行进入到test目录下面:
$ cd ~/Desktop/test
$ ndk-build -C ./jni
然后会生成如下目录结构,obj目录下是生成动态库的中间文件,libs里面是最终生成的不同CPU架构的动态库:
test├── jni│ ├── Android.mk│ ├── Application.mk│ └── test.c├── libs│ ├── armeabi│ │ └── libdemo.so│ └── armeabi-v7a│ └── libdemo.so└── obj └── local ├── armeabi │ ├── libdemo.so │ └── objs │ └── demo │ ├── test.o │ └── test.o.d └── armeabi-v7a ├── libdemo.so └── objs └── demo ├── test.o └── test.o.d
为什么非要有jni那一层目录
约定优于配置,没有不行吗?行,但是要改点东西。去掉jni那层目录再编译一次,当前目录结构如下:
test/├── Android.mk├── Application.mk└── test.c
命令行执行
1. $ cd ~/Desktop/test
2. $ ndk-build
结果报错如下:
Android NDK: Could not find application project directory !Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
错误日志上说什么路径找不到错误,需要定义一个xx变量,我们只需要把编译命令改成如下就可以了:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk
编译一个可以允许的文件
修改Android.mk 文件如下:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := demoLOCAL_SRC_FILES := test.c#include $(BUILD_SHARED_LIBRARY)# Android4.4 以后 调用的可执行文件不是基于PIE方式编译的,则无法运行LOCAL_CFLAGS += -pie -fPIELOCAL_LDFLAGS += -pie -fPIE# 编译一个可执行文件include $(BUILD_EXECUTABLE)
这个可执行文件在电脑上是没法执行的,只能放到手机里面执行,执行如下命令,我们把刚生成的文件放到手机上:
- push 文件到手机
$ adb push libs/armeabi-v7a/demo /data/local/tmp
- 为手机中的demo文件添加可执行权限(为了方便直接给予所有权限了)
$ adb shell 'chmod 777 /data/local/tmp/demo'
- 用手机环境运行demo这个文件
$ adb shell '/data/local/tmp/demo'
运行结果会打印一行
hello world!
更多相关文章
- Android(安卓)Studio自定义模板 写页面竟然可以如此轻松
- ADT转AndroidStudio建议
- Android(安卓)StudioV3.2.1的两种模式及签名配置、apk打包混淆
- 【android开发记录片】2.基于Eclipse的JNI开发环境的搭建(cygwin+
- Android模拟器环境中添加和删除apk应用程序
- 转载:Android中如何修改系统时间(应用程序获得系统权限)
- android 5.1.1开机优化(framework层)
- Android(安卓)美化之Toolbar控件使用
- 安装Android(安卓)2.2 SDK时出现的问题