Android studio JNI(NDK) 开发

最近花了一个星期研究NDK,写了一个简要的开发demo,遇到一些问题,在这里简要总结。

JNI是JAVA NATIVE INTERFACE的缩小,它允许Java代码与用其它语言写的代码之间进行交互,例如典型的C或C++语言。Java是上层语言,而C或C++是底层语言(用来实现本地方法),所以JNI是起中间件的作用,将上层(交互层)和下层(驱动层)联系起来。步骤在上层用JAVA申明本地函数,在底层用C或者C++实现本地函数,实现步骤如下。 

 

步骤1.建立native函数,编译生成.class文件

用Java语言,在MainActivity里面建立本地函数 static native String getStringFromC();

编译项目,生成MainActivity.class文件,目录为G:\Android\AndroidStudio\LastPra\app\build\intermediates\classes\debug\com\aiap\lastpra\MainActivity.class,如下图:


 

步骤2.生产.h头文件

进入android studio自带的终端terminal,用以下命令生成头文件

先进入main文件夹 cd app\src\main

命令 javah –d jni–classpathD:\ProgramFiles\Android\sdk\platforms\android-22\android.jar;D:\ProgramFiles\Android\sdk\extras\android\support\v7\appcompat\libs\android-support-v7-appcompat.jar;D:\ProgramFiles\Android\sdk\extras\android\support\v4\ android-support-v4.jar;G:\Android\AndroidStudio\LastPra\app\build\intermediates\classes\debugcom.aiap.lastpra.MainActivity。在app\src\main\jni文件夹下面生成头文件com_aiap_lastpra_MainActivity.h ,如图


 

步骤3.编写本地函数

用c(或c++)语言,在jni文件夹下面新建c文件,如getString.c。在getString.c里面实现头文件com_aiap_lastpra_MainActivity.h里面的函数

JNIEXPORTjstring JNICALL Java_com_aiap_lastpra_MainActivity_getStringFromC (JNIEnv *env, jclass c);

这里的代码为

#include"com_aiap_lastpra_MainActivity.h"

JNIEXPORT jstring JNICALL Java_com_aiap_lastpra_MainActivity_getStringFromC
        (JNIEnv *env, jclass c){
        return(*env)->NewStringUTF(env,"This just a test for Android Studio NDK JNIdeveloper!");
}

 

步骤4.生产.so

执行Build>MakeProject,在目录app\build\intermediates\ndk\debug\lib下生成.so库文件,如图


 

步骤5.调用库文件运行程序

Run app, 结果如下


Successful!

 

 

在开发过程中,遇到很多错误,简要记录如下。

 

Error 1 生成.h文件时,对于javah命令,出现Exceptionin thread “main” java.lang.IllegalArgumentException: not a valid class name,如图


 

解决方案:报错很奇怪,类名是正确的,但是在前面加上操作 –classpath就可以了,如下,(虽然此时出现了其它错误)。


注意 最后的包名一定是 \debug<package>.<activity>, 如这里是……\debugcom.aiap.jni2.MainActivity

 

Error 2  无法访问android.app.Activity  找不到android.app.Activity的类文件,如下


解决方案:

在-classpath 里加上android.jar的路径,如 D:\ProgramFiles\Android\sdk\platforms\android-22\android.jar

 

Error 3无法访问android.support.v7.app.AppCompatActivity,找不到android.support.v7.app.AppCompatActivity的类文件,如下


解决方案:

在-classpath 里加上android-support-v7-appcompat.jar的路径,如

D:\ProgramFiles\Android\sdk\extras\android\support\v7\appcompat\libs\android-support-v7-appcompat.jar

 

Error 4生成.h文件之后,出现了如下错误。

Error:Executionfailed for task ':jni2:compileDebugNdk'.

> Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin. For details,seehttp://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true"in gradle.properties to continue using the current NDK integration. 如下图:


解决方案:

在gradle.properties中加入语句 android.useDeprecatedNdk=true。 gradle.properties的内容如下



Error 5JNI错误之:error: baseoperand of '->' has non-pointer type '_JNIEnv'

解决方案:

写这个代码时报错:pEnv->NewStringUTF(),是因为c和c++对JNIEnv的定义是不同的,从jni.h下面代码看得出来,解决方案为:

  - 使用c++来写代码,文件名就必须.cpp后缀:

 C++ codemust have .cpp extension.,必须cpp后缀,c后缀不行;

  - 使用c来写代码,文件名就必须.c后缀;

 

c语音和c++语言的代码不一样,分别如下:

//return(*env)->NewStringUTF(env, "Hello from JNI !");//C格式

//returnenv->NewStringUTF((char *)"Hello from JNI !");//C++格式

 

Error 6

G:\Android\AndroidStudio\JNItest\jni2\src\main\jni\/com_aiap_jni2_MainActivity.h:2:17: fatal error: jni.h: No such file or directory

解决方案:

将android-ndk-r9d 升级为android-ndk-r10e,将androidstudio1.4升级为androidstudio 1.5

 

Error 7

写好本地函数后,始终无法生成.so动态库文件。

解决方案:

原来是本地函数所在文件夹的位置和命名的问题。Androidstudio 的NDK编译时,默认本地函数在\src\main\jni\的文件下,如果不在这里,或者文件夹命名不是jni(我之前的命名是jnis),系统就找不到,自然就不能生成so文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值