Android之从零开始JNI研发
2017-02-15 14:45
197 查看
转载注明出处:http://blog.csdn.net/xiaohanluo/article/details/55193157
本文是基于Mac端Android Studio的JNI开发介绍。
Andorid官方JNI文档
Android官方JNI实例文档
JNI维基百科
JNI手册英文版
JNI手册中文版
Oracleg官方JNI文档
Getting Started with the NDK
MAC端手撕NDK环境搭建
选择NDK版本下载 NDK Downloads
解压下载文件
设置环境,到用户的根目录,打开.bash_profile文件,设置NDK环境,参考文章Mac OS X配置环境变量
Windows手撕NDK环境搭建,因为C/C++在GCC的环境下编译、运行,所以Windows环境下需要Cygwin模拟Linux编译环境,参考http://www.jb51.net/softjc/159272.html
环境配置完成后,使用ndk-build指令查看一下是否配置成功。
mac下执行效果:
ndk环境搭建好后就可以开始动手了。
图-1 class目录结构图
例如,
图-2 h文件目录图
放在工程的根目录jni中
放在工程的内部子文件中
放在
图-3 根目录生成so
新建mk文件,设置一些属性。
进入jni目录,使用
图-4 运行结果图
注意:只有C/C++把放在工程根目录中的jni才可以使用ndk-build指令编译
图-5 非根目录接结构图
在工程根目录新建Application.mk文件。
在C/CC++代码目录新建Android.mk文件
在工程的根目录下执行以下指令(可以直接进入C/C++源代码目录执行
指令运行结果图:
图-6 运行结果图
Application.mk指定了编译的mk,而Android.mk指定了编译的一些属性,包括编译源文件等等,这些都可以灵活变化
6.3 C/C++放在
图-7 自动生成so目录图
在
在壳工程(通常是app/build.gradle)的build.gradle配置生成的so库名,找到defaultConfig这个节点,添加如下内容。
在
然后rebuild项目,会自动生成so动态库,在
图-8 自动生成so的目录
同时在
运行结果图:
图-9 运行结果图
确认loadLibrary时候库的名字是否正确
so目录有问题,[点这里看设置]http://blog.csdn.net/yy1300326388/article/details/46291417
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
使用以下指令编译
附上demo地址:https://github.com/Kyogirante/JNIDemo
本文是基于Mac端Android Studio的JNI开发介绍。
Andorid官方JNI文档
Android官方JNI实例文档
JNI维基百科
JNI手册英文版
JNI手册中文版
Oracleg官方JNI文档
1. NDK安装以及环境配置
Android Studio 2.2及以上参考链接Getting Started with the NDK
MAC端手撕NDK环境搭建
选择NDK版本下载 NDK Downloads
解压下载文件
设置环境,到用户的根目录,打开.bash_profile文件,设置NDK环境,参考文章Mac OS X配置环境变量
Windows手撕NDK环境搭建,因为C/C++在GCC的环境下编译、运行,所以Windows环境下需要Cygwin模拟Linux编译环境,参考http://www.jb51.net/softjc/159272.html
环境配置完成后,使用ndk-build指令查看一下是否配置成功。
mac下执行效果:
> ndk-build Android NDK: Could not find application project directory ! Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
ndk环境搭建好后就可以开始动手了。
2. 定义带有本地方法Java类
public class JNIDemoUtil { private native String getString(String input); }
3. 生成class文件
build -> rebuild重新构建项目,生成class文件,class文件在
<壳工程>/build/classes/debug目录下。
图-1 class目录结构图
4. 生成.h头文件
进入到<壳工程>/build/classes/debug目录下执行以下指令
# -classpath指定类的路径 javah -classpath . -jni {包名.类名}
例如,
javah -classpath . -jni com.kyo.jnidemo.jni.JNIDemoUtil,会生成.h文件。
图-2 h文件目录图
5. 编写c/c++文件
native的具体实现#include <stdlib.h> #include <jni.h> #include "com_kyo_jnidemo_jni_JNIDemoUtil.h" #ifdef __cplusplus extern "C" { #endif jstring Java_com_kyo_jnidemo_jni_JNIDemoUtil_getString(JNIEnv *env, jclass obj) { return (*env)->NewStringUTF(env, "hello world"); } #ifdef __cplusplus } #endif
6. 生成.so动态库
上面拿到了h头文件和具体实现的c/c++文件,接下来是生成.so动态库,根据放的目录不同有三种方式。放在工程的根目录jni中
放在工程的内部子文件中
放在
/src/main/jni目录中
6.1 C/C++代码在根目录jni
图-3 根目录生成so
新建mk文件,设置一些属性。
LOCAL_MODULE := ${call my-dir}/ include ${CLEAR_VARS} LOCAL_SRC_FILES := /Users/wang/WorkPlace/MyWork/JNIDemo/jni/JNIDemoUtil.c LOCAL_MODULE = libJNIDemo include ${BUILD_SHARED_LIBRARY}
进入jni目录,使用
ndk-build指令,会在工程根目录中自动生成
libs、
obj两个目录,其中libs,目录下就有so库。
图-4 运行结果图
注意:只有C/C++把放在工程根目录中的jni才可以使用ndk-build指令编译
6.2 C/CC++代码在工程内部其他目录
图-5 非根目录接结构图
在工程根目录新建Application.mk文件。
APP_BUILD_SCRIPT := /Users/wang/WorkPlace/MyWork/JNIDemo/jni_c/src/Android.mk # 因为针对多个CPU架构会生成多个so库,使用APP_ABI限定生成支持某种CPU架构的so库 APP_ABI := armeabi
在C/CC++代码目录新建Android.mk文件
LOCAL_MODULE := ${call my-dir}/ include ${CLEAR_VARS} LOCAL_SRC_FILES := /Users/wang/WorkPlace/MyWork/JNIDemo/jni_c/src/JNIDemoUtil.c LOCAL_MODULE = libJNIDemo include ${BUILD_SHARED_LIBRARY}
在工程的根目录下执行以下指令(可以直接进入C/C++源代码目录执行
ndk-build生成so库),会在工程根目录中自动生成
libs、
obj两个目录,其中libs,目录下就有so库。
ndk-build NDK_PROJECT_PATH={工程目录} NDK_APPLICATION_MK={工程的Applicaion.mk目录}
指令运行结果图:
图-6 运行结果图
Application.mk指定了编译的mk,而Android.mk指定了编译的一些属性,包括编译源文件等等,这些都可以灵活变化
6.3 C/C++放在src/main/jni
目录下
图-7 自动生成so目录图
在
local.properties中添加ndk路径,我的如下。
sdk.dir=/Users/wang/Android/Android_SDK ndk.dir=/Users/wang/Android/Android_NDK_r13b
在壳工程(通常是app/build.gradle)的build.gradle配置生成的so库名,找到defaultConfig这个节点,添加如下内容。
defaultConfig { ... ndk { moduleName "libJNIDemoJni" // so库名 abiFilters "armeabi" // 指定生成的CPU架构对应的so库 } }
在
gradle.properties文件中添加.
android.useDeprecatedNdk=true
然后rebuild项目,会自动生成so动态库,在
<壳工程>/build/intermedistes/ndk目录下面,目录如下图:
图-8 自动生成so的目录
7. 载入so库
将生成的so库在<壳工程>/src/main/jniLibs目录下。
同时在
JNIDemoUtil中载入so库代码。
public class JNIDemoUtil { // 注意库的名字前面没有lib static { System.loadLibrary("JNIDemo"); } public native static String getString(); }
8. 编译运行
准备工作做完后,可以直接运行啦。public void onClick(View v) { int id = v.getId(); if(id == R.id.jni_demo_btn){ mInfoTv.setText(JNIDemoUtil.getString()); } }
运行结果图:
图-9 运行结果图
9. 问题解答
java.lang.UnsatisfiedLinkError: Couldn’t load XXX indLibrary确认loadLibrary时候库的名字是否正确
so目录有问题,[点这里看设置]http://blog.csdn.net/yy1300326388/article/details/46291417
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
使用以下指令编译
ndk-build NDK_PROJECT_PATH={工程目录} NDK_APPLICATION_MK={工程的Applicaion.mk目录}
附上demo地址:https://github.com/Kyogirante/JNIDemo
10. 结束语
本篇几乎没有涉及C/C++与java之间变量以及语法等等一些知识点,这些会在下篇来介绍。本人也是在学习探索过程中,如果有错误希望大家指出来。相关文章推荐
- [从零开始系列]AndroidApp研发之路-<楼外篇>Retrofit的刨根问底篇
- Android分享SDK 从零开始自主研发
- [从零开始系列]AndroidApp研发之路(一) 网络请求的封装(一)
- 浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power电源控制
- 浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power电源控制
- android JNI编程 一些技巧(整理)
- Android JNI 实例
- 兼容Android平台的JNI调用
- Android JNI实例
- Android JNI实例
- Android jni 实例
- JNI: native bindings to java within android
- 谷歌为Android 2.0操作系统研发出“手势搜索”
- 浅析android通过jni控制service服务程序的简易流程
- Android JNI实例
- jni / C for android 技术总揽
- Android JNI实例
- Android JNI
- 从零开始学Android
- Android JNI