转载请注明出处:http://blog.csdn.net/htwhtw123/article/details/71057314
最近开始学习NDK,发现网上的大多数博客都不实用,有各种bug,折腾了一天,终于成功的将c语言代码信息与java代码部分相互传递信息了。该项目实际实现,字符串msg1:c向java传,字符串msg2:java向c传,c将自己的一段字符串加在java传的字符串上,再传给java。我使用的是Android Studio2.3.1
我把源码发在github上了,这里是链接NDKTest
1.NDK下载与配置:
使用Android Studio直接下载:
点击:SDK Manager
然后选择SDK Tools标签,选择LLDB和NDK 然后点击OK,这个过程是非常费时的
2.如果没有配置好java环境变量请:点击此处(否则后面使用javah命令会报错)
3.实际上Android Studio在创建项目的时候直接完成ndk配置,只要在创建项目最开始的地方勾选include C++support就可以了。
当然,这里叙述的是没有选此项的情况,适用于项目中途需要加入c语言代码的情况,或者说更适用于一般情况。
4.创建一个一般的项目(不要勾选include C++support)
创建类NdkJniUtils ,MyTestJniLib是必不可少的,当然可以定义成自己喜欢的情况,但后面ndk{}中代码会需要与此一致
public class NdkJniUtils {
String msg;
static {
System.loadLibrary("MyTestJniLib"); //defaultConfig.ndk.moduleName
}
public native String getCLanguageString();
public native String setCLanguageString(String str);
}
5.点击Build->Make Module ‘app’,生成相应的.class文件,在如下图的位置(我的包全名为com.ndkreport)
注意:如果clean Project项目或Rebuild可能出现以下错误:
Error:Execution failed for task ':app:clean'.
> Unable to delete directory: C:\Users\asus\Downloads\NDKReport\app\build\intermediates\classes\debug
解决方法:
Tools->Android->Sync project with Gradle Files
如果依旧有此错误,请手动删除app\build\intermediates\classes\debug文件夹,然后Tools->Rebuid Project
6.点击Terminal,就是在左下角位置,准备生成.h文件
7.在Terminal命令行中输入
cd app/build/intermediates/classes/debug
javah -jni com.ndkreport.NdkJniUtils
如果出现javah不是执行命令的情况,点击链接:配置java环境变量
.h文件将出现在debug目录下(从此以下均在Projec视图的情况):
8.为了使c++/c文件可用(以及编写时自动生成代码省事),现在先去gradl.properties文件下添加一句:
android.useDeprecatedNdk=true
再点击右上角的Sync now
9.在src/main文件夹下创建文件夹jni,并将刚刚得到的.h文件剪切到jni文件夹下,创建任意名的.c文件与jni之下(但请使用小写字母,否则在编写时无法自动生成代码),我的是jnitest.c,
在jnitest.c中加入如下代码,这里的Java_com_ndkreport_NdkJniUtils_getCLanguageString和Java_com_ndkreport_NdkJniUtils_setCLanguageString从.h文件复制的函数名,com_ndkreport_NdkJniUtils.h是刚刚剪切的.h文件:
#include "com_ndkreport_NdkJniUtils.h"
#include <string.h>
#include <stdio.h>
JNIEXPORT jstring JNICALL Java_com_ndkreport_NdkJniUtils_getCLanguageString
(JNIEnv *env, jobject object){
return (*env)->NewStringUTF(env,"你好,Java!");
}
JNIEXPORT jstring JNICALL Java_com_ndkreport_NdkJniUtils_setCLanguageString
(JNIEnv *env, jobject object, jstring string) {
const char *ch;
//获取由java传过来的字符串
ch = (*env)->GetStringUTFChars(env, string, NULL);
strcat(ch,"c传出去的句子");
return (*env)->NewStringUTF(env,ch);
}
在build.gradle文件下的defaultConfig{}之内,加入如下代码这里的MyTestJniLib与前面NdkJniUtils 类中的一致。
ndk {
moduleName "MyTestJniLib" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库,目前可有可无。
}
}
以下代码写在android{}之内,是ndk文件夹路径:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
然后,点击Sync now
接着,在app\build\intermediates\ndk\debug\lib下,的那些文件夹内,会生成不同类型的.os文件,Android.mk也出现了
10。在MainActivity中把得到的结果显示出来,代码如下:
public class MainActivity extends AppCompatActivity {
String msg="";
String msg2="";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView=(TextView) findViewById(R.id.textView);
NdkJniUtils n=new NdkJniUtils();
msg=n.getCLanguageString();
msg2=n.setCLanguageString("这是java传出去的句子");
textView.setText("msg="+msg+"\n"+"msg2="+msg2);
}
}
11.结果:打开APP时: