Android Studio开发NDK流程--经验
2016-06-22 09:07
316 查看
最近特意研究了下ndk开发,发现其实android端很简单,难点在于c/c++端的开发。如果真想把ndk开发研究的特别牛,那就得往c/c++方向转了。但是个人感觉没必要,知道native代码如何编译成h文件,如何实现简单的c文件实现,如何打包so文件,以及如何在android中使用即可。查阅了众多资料,实践研究了n牛,总结的经验,也存在一些问题,与大家分享。
一、编写native方法
在android项目中(在app下或者新建一个module都可以,有一些问题后面解释)新建MyName.java类,编写本地方法:public native String getTestName(int a,int b);(类名,本地方法写在哪里都由你)
二、编译成.h文件:
方法一:这种方法是拿.class文件编译h文件
AS菜单栏->Build->Make Project或者Make Module ‘ndklibrary’ 编译java源码成class。
找到.class文件的路径(debug下的也可以):
E:\Android_Studio_Projects\NDK_test2\ndklibrary\build\intermediates\classes\release\com\dk\ndklibrary\MyName.class
cmd进入到目录:E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main>光标
正式编译.h文件:
E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main>javah -d jni -classpath E:\Android_Studio_Projects\NDK_test2\ndklibrary\build\intermediates\classes\release com.dk.ndklibrary.MyName
注意:-d jni
意思是在当前cmd路径下生成jni目录,存放生成的.h头文件。这儿有个-d
jni参数,会在当前路径下生成jni目录,故当前cmd路径进入到main下。
Javah的时候,class文件路径中有个空格,不要忘记
方法二:这种方法是拿.java文件编译h文件
Cmd进入到目录:E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main\java>
正式编译.h文件:
E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main\java>
javah -jni com.dk.ndklibrary.MyName
再,在main下新建jni目录,剪切生成.h文件到jni目录中。
以上两种操作都要确保main下有jni目录,并且.h文件在目录中。
三、在jni目录中新建同名(也可随便取名字)的.c文件,编写.c文件的实现。
Include当前的.h文件,复制.h文件中的方法头到.c文件中,写具体的实现。
还有,在jni目录下新建util.c文件,内容为空即可。
#include "com_dk_ndklibrary_MyName.h"
/*
* Class: com_dk_ndklibrary_MyName
* Method: getTestName
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_dk_ndklibrary_MyName_getTestName
(JNIEnv *env,jobject jobject,jint
a)
{
return(*env)->NewStringUTF(env,"这里是来自c的string");
}
/*
* Class: com_dk_ndklibrary_MyName
* Method: getTestAge
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_dk_ndklibrary_MyName_getTestAge
(JNIEnv *env1,jobject jobject1,jint
a1,jint b1)
{
returna1+b1;
}
四、配置和编译so。
1、在AS中Project Structure选项配置NDK路径,和sdk一样
2、在jni目录所在的module中的build.gradle ->defaultConfig{}内配置
ndk{
moduleName "adbNdkDemo" //生成的so名字
abiFilters "armeabi","armeabi-v7a","x86" //输出指定三种abi体系结构下的so库。目前可有可无。
}
3、在MyName.java类中添加
static {
//中文注释会报错了
//defaultConfig.ndk.moduleName
System.loadLibrary("adbNdkDemo");
}
4、如果报错Error: NDK integration is deprecated in the current plugin在gradle.properties文件中添加android.useDeprecatedNdk=true
5、run或者build或者make,生成文件。
五、查看结果,copy到项目中app中main下面的jniLibs目录里。
生成的so文件路径:
E:\Android_Studio_Projects\NDK_test2\ndklibrary\build\intermediates\ndk\....
遗留问题:在module中编译的so文件和类,移到app module下后无法运行。说是程序在/data/app/...下 , 而native库在/data/app-lib/...下,找不到解决办法.
网上还有些其他大牛的方法,可能需要手动编写android.mk文件,还得研究android.mk文件的语法
一、编写native方法
在android项目中(在app下或者新建一个module都可以,有一些问题后面解释)新建MyName.java类,编写本地方法:public native String getTestName(int a,int b);(类名,本地方法写在哪里都由你)
二、编译成.h文件:
方法一:这种方法是拿.class文件编译h文件
AS菜单栏->Build->Make Project或者Make Module ‘ndklibrary’ 编译java源码成class。
找到.class文件的路径(debug下的也可以):
E:\Android_Studio_Projects\NDK_test2\ndklibrary\build\intermediates\classes\release\com\dk\ndklibrary\MyName.class
cmd进入到目录:E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main>光标
正式编译.h文件:
E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main>javah -d jni -classpath E:\Android_Studio_Projects\NDK_test2\ndklibrary\build\intermediates\classes\release com.dk.ndklibrary.MyName
注意:-d jni
意思是在当前cmd路径下生成jni目录,存放生成的.h头文件。这儿有个-d
jni参数,会在当前路径下生成jni目录,故当前cmd路径进入到main下。
Javah的时候,class文件路径中有个空格,不要忘记
方法二:这种方法是拿.java文件编译h文件
Cmd进入到目录:E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main\java>
正式编译.h文件:
E:\Android_Studio_Projects\NDK_test2\ndklibrary\src\main\java>
javah -jni com.dk.ndklibrary.MyName
再,在main下新建jni目录,剪切生成.h文件到jni目录中。
以上两种操作都要确保main下有jni目录,并且.h文件在目录中。
三、在jni目录中新建同名(也可随便取名字)的.c文件,编写.c文件的实现。
Include当前的.h文件,复制.h文件中的方法头到.c文件中,写具体的实现。
还有,在jni目录下新建util.c文件,内容为空即可。
#include "com_dk_ndklibrary_MyName.h"
/*
* Class: com_dk_ndklibrary_MyName
* Method: getTestName
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_dk_ndklibrary_MyName_getTestName
(JNIEnv *env,jobject jobject,jint
a)
{
return(*env)->NewStringUTF(env,"这里是来自c的string");
}
/*
* Class: com_dk_ndklibrary_MyName
* Method: getTestAge
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_dk_ndklibrary_MyName_getTestAge
(JNIEnv *env1,jobject jobject1,jint
a1,jint b1)
{
returna1+b1;
}
四、配置和编译so。
1、在AS中Project Structure选项配置NDK路径,和sdk一样
2、在jni目录所在的module中的build.gradle ->defaultConfig{}内配置
ndk{
moduleName "adbNdkDemo" //生成的so名字
abiFilters "armeabi","armeabi-v7a","x86" //输出指定三种abi体系结构下的so库。目前可有可无。
}
3、在MyName.java类中添加
static {
//中文注释会报错了
//defaultConfig.ndk.moduleName
System.loadLibrary("adbNdkDemo");
}
4、如果报错Error: NDK integration is deprecated in the current plugin在gradle.properties文件中添加android.useDeprecatedNdk=true
5、run或者build或者make,生成文件。
五、查看结果,copy到项目中app中main下面的jniLibs目录里。
生成的so文件路径:
E:\Android_Studio_Projects\NDK_test2\ndklibrary\build\intermediates\ndk\....
遗留问题:在module中编译的so文件和类,移到app module下后无法运行。说是程序在/data/app/...下 , 而native库在/data/app-lib/...下,找不到解决办法.
网上还有些其他大牛的方法,可能需要手动编写android.mk文件,还得研究android.mk文件的语法
相关文章推荐
- android inflater 用法
- Android N实现分屏
- 记录一些开源项目和一些需要的文章
- Android深度系列—分析Android-Universal-Image-Loader的缓存处理机制
- Android开发中的安全
- Android开发中的安全
- Android开发中的安全
- Android Studio优化技巧
- 笑谈Android图表------MPAndroidChart
- xUtils之FileUtil
- 编译Android源码致命错误解决方案
- android缓存框架ASimpleCache源码分析
- Android--Jsonrpc4j的使用
- xUtils之加载图片
- Android 6.0新特性
- Android studio鼠标提示功能
- Android 总结三
- Android 自定义属性写法
- 高德地图——搜索
- 【黑马Android】(15)cxf 介绍 以及ant 工具的使用/cxf总结