【Android学习笔记】如何使用Eclipse在Android项目中调用C/C++代码,及遇到的错误解决方法
2013-11-07 11:35
567 查看
首先,我们创建一个工程,这里名叫“DemoJNI”,包名按照自己习惯改好,然后各种next最后finish。
为了条理清晰,我在主Activity之外创建了一个JniInterface类,专门作为JAVA和C/C++之间的接口。在这个类中,我们写几个native方法,就是要通过C/C++代码来实现的方法。完整的JniInterface类如下:
保存
注意!native方法不能在JAVA中添加实现,必须在C/C++代码中实现!
下面我们使用javah命令生成JNI头文件
点击Run->External Tools->External Tools Configuration,选中左侧的“Program”,点左上角的新建按钮,建立一条控制台指令。右边的name是你给这个指令起的代号,我们就叫javah;location是你的javah二进制文件的路径,一般就实在JAVA_HOME的bin目录下;working directory是你的java代码生成的.class文件的路径,你只需要设置到classes这一层就可以了,如图。
解释一下Arguments,这里的参数就相当于我们在终端输入的指令的参数。javah的参数中
-classpath [类文件的路径] ;-d [输出的头文件的位置] 。参考下图的例子设置好后Apply,然后RUN!
好的,我们成功地遇到了问题!这是什么鸟?
很不幸,我不知道问题出在哪,希望哪位明白的能告诉我解决办法。
不过这条路走不通,我们就绕路,也能走的过去。我直接打开linux的终端,进入上面Working directroy设置的那个路径,直接输入 javah com.startsi.demojni.JniInterface 注意参数一定要按照此格式输入完整的包名.类名。然后我们发现在当前目录下出现了一个新的头文件 。先不着急,再打开eclipse,在左侧工程列表栏中右击你的工程,选择Android Tools -> Add Native Support
直接Finish就可以了。然后刷新你的工程,发现多了一个JNI文件夹。现在把刚才生成的头文件拷贝到这个JNI文件夹中,然后刷新你的工程,看是否成功添加进来了。如下图示:
打开这个头文件,发现包含jni.h的一行报错 Unresolved inclusion: <jni.h>
解决方法:右击工程,-> properties 左侧选择 C/C++ General -> Paths and symbols
添加jni.h的路径,顺便把jni_md.h的路径也添加进来,不然待会声明函数的部分依然报错。如下图
C++的头文件之后要用到的话,路径位置也在这里添加上。
应用后重新编译,发现错误没有了,好,下一步。
打开jni中生成的cpp文件,把我们弄出来的头文件包含进去。然后把头文件中声明的函数挨个实现。先上代码吧。
在这里,JNI中C/C++与JAVA之间的参数传递不做重点,想要了解有关内容,请参阅
http://www.20864.com/201258/221.html
然后进入我们之前设置javah指令的地方,再新建一个ndk_build指令,location中设置到你的ndk-build所在的位置,working directory设置为工程下的jni目录。如图
注意路径最后是ndk-build,不是ndk-build.cmd。设置好后apply,之后Run。可以看到 .so的库文件已经生成了,你可以在工程的 libs/armeabi/ 目录下找到库文件。
对了,这里要说一下Android.mk文件的写法。这个脚本文件在你的jni目录下,ndk在编译生成库文件时会按照该文件的说明进行编译。某些工程还需要添加一个Application.mk的文件,和Android.mk共同作用。Android.mk的写法请参照/article/1948410.html
我们已经在JniInterface类中声明了几个本地方法,并且在C/C++代码中实现了这写本地方法,也编译生成了.so的库文件。下面我们只要在想要调用本地代码的时候调用JniInterface中的方法就可以了。
首先要在MainActivity中加载库
痛苦啊!找了各种资料都没有有效的解决这个问题的办法。求解救啊!
之前明明可以成功的啊?这下连之前写好的工程都不能运行了,也是报这个错。求路过的大牛解救!!
为了条理清晰,我在主Activity之外创建了一个JniInterface类,专门作为JAVA和C/C++之间的接口。在这个类中,我们写几个native方法,就是要通过C/C++代码来实现的方法。完整的JniInterface类如下:
package com.startsi.demojni; public class JniInterface { public native int intMethod(int x,int y); public native String stringMethod(String str); public native byte byteMethod(byte b); }
保存
注意!native方法不能在JAVA中添加实现,必须在C/C++代码中实现!
下面我们使用javah命令生成JNI头文件
点击Run->External Tools->External Tools Configuration,选中左侧的“Program”,点左上角的新建按钮,建立一条控制台指令。右边的name是你给这个指令起的代号,我们就叫javah;location是你的javah二进制文件的路径,一般就实在JAVA_HOME的bin目录下;working directory是你的java代码生成的.class文件的路径,你只需要设置到classes这一层就可以了,如图。
解释一下Arguments,这里的参数就相当于我们在终端输入的指令的参数。javah的参数中
-classpath [类文件的路径] ;-d [输出的头文件的位置] 。参考下图的例子设置好后Apply,然后RUN!
好的,我们成功地遇到了问题!这是什么鸟?
很不幸,我不知道问题出在哪,希望哪位明白的能告诉我解决办法。
不过这条路走不通,我们就绕路,也能走的过去。我直接打开linux的终端,进入上面Working directroy设置的那个路径,直接输入 javah com.startsi.demojni.JniInterface 注意参数一定要按照此格式输入完整的包名.类名。然后我们发现在当前目录下出现了一个新的头文件 。先不着急,再打开eclipse,在左侧工程列表栏中右击你的工程,选择Android Tools -> Add Native Support
直接Finish就可以了。然后刷新你的工程,发现多了一个JNI文件夹。现在把刚才生成的头文件拷贝到这个JNI文件夹中,然后刷新你的工程,看是否成功添加进来了。如下图示:
打开这个头文件,发现包含jni.h的一行报错 Unresolved inclusion: <jni.h>
解决方法:右击工程,-> properties 左侧选择 C/C++ General -> Paths and symbols
添加jni.h的路径,顺便把jni_md.h的路径也添加进来,不然待会声明函数的部分依然报错。如下图
C++的头文件之后要用到的话,路径位置也在这里添加上。
应用后重新编译,发现错误没有了,好,下一步。
打开jni中生成的cpp文件,把我们弄出来的头文件包含进去。然后把头文件中声明的函数挨个实现。先上代码吧。
//DemoJNI.cpp #include <jni.h> #include "com_startsi_demojni_JniInterface.h" #include <string> /* * Class: com_startsi_demojni_JniInterface * Method: intMethod * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_startsi_demojni_JniInterface_intMethod (JNIEnv *env, jobject obj, jint x, jint y){ return x*y; } /* * Class: com_startsi_demojni_JniInterface * Method: stringMethod * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_startsi_demojni_JniInterface_stringMethod (JNIEnv *env, jobject obj, jstring str){ const char* ptr = env->GetStringUTFChars(str,0); return env->NewStringUTF(ptr); } /* * Class: com_startsi_demojni_JniInterface * Method: byteMethod * Signature: (B)B */ JNIEXPORT jbyte JNICALL Java_com_startsi_demojni_JniInterface_byteMethod (JNIEnv *env, jobject obj, jbyte b){ char byte = (char)b; byte += 1; return (jbyte)byte; }
在这里,JNI中C/C++与JAVA之间的参数传递不做重点,想要了解有关内容,请参阅
http://www.20864.com/201258/221.html
然后进入我们之前设置javah指令的地方,再新建一个ndk_build指令,location中设置到你的ndk-build所在的位置,working directory设置为工程下的jni目录。如图
注意路径最后是ndk-build,不是ndk-build.cmd。设置好后apply,之后Run。可以看到 .so的库文件已经生成了,你可以在工程的 libs/armeabi/ 目录下找到库文件。
对了,这里要说一下Android.mk文件的写法。这个脚本文件在你的jni目录下,ndk在编译生成库文件时会按照该文件的说明进行编译。某些工程还需要添加一个Application.mk的文件,和Android.mk共同作用。Android.mk的写法请参照/article/1948410.html
我们已经在JniInterface类中声明了几个本地方法,并且在C/C++代码中实现了这写本地方法,也编译生成了.so的库文件。下面我们只要在想要调用本地代码的时候调用JniInterface中的方法就可以了。
首先要在MainActivity中加载库
//Load Native Library static System.loadLibrary("DemoJNI"); }然后给MainActivity添加一个TextView,这里我们直接使用HelloWorld那个Textview。不罗嗦了,直接看代码吧。
TextView rtv; JniInterface jn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); rtv = (TextView)findViewById(R.id.returnTextView); rtv.setText("intMethod return : " + jn.intMethod(5, 5) + "\n" + "stringMethod return : " + jn.stringMethod("success !") + "\n" + "byteMethod return : " + jn.byteMethod((byte)'a')); }然后运行一下程序,诶,出错了
痛苦啊!找了各种资料都没有有效的解决这个问题的办法。求解救啊!
之前明明可以成功的啊?这下连之前写好的工程都不能运行了,也是报这个错。求路过的大牛解救!!
相关文章推荐
- Android apk系列2-------系统签名(生成release版本的系统)
- Android Fragment完全解析,关于碎片你所需知道的一切
- android中给TextView或者Button的文字添加阴影效果
- Android入门-MMS-短信/彩信发送流程+代码分析
- android中使用smack库时,遇到错误:java.lang.NullPointerException
- Android如何获取其他应用程序的context
- Android apk系列1-------APK签名
- Android拍照和取相册并裁切
- Android的数据库SQLiteDatabase基础讲解
- Android 加载网页进度条
- Android中BindService方式使用的理解
- 创建一个AlertDialog对话框,必须按确定或取消按钮才能关闭对话框
- ANDROID 学习笔记
- android 开发 屏幕适配 概念
- android.os.NetworkOnMainThreadException exception
- Android基础——Activity生命周期
- android:layout_weight详解
- android4.0触摸屏滑鼠模式解决方法-添加idc文件
- 我的android 第一天-电话拨号器
- [Android实例] android json