Android Studio上编译JNI程序

来源:互联网 发布:淘宝香港代购 编辑:程序博客网 时间:2024/05/19 03:43

1. 添加native接口

在需要使用Jni的类中添加native接口。

public class JniActivity extends Activity {    private TextView tvJniTest = null;    static{        System.loadLibrary("JniTest");    }    public native String getStringFromNative();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_jni);        tvJniTest = (TextView) findViewById(R.id.tv_jni_test);        tvJniTest.setText(getStringFromNative());    }}

2. 利用javah生成h头文件

点击Build–>Rebuild Project,生成.class文件。
编译OK后生成的class文件在AS工程的如下目录:

工程目录\moudle名\build\intermediates\classes\debug\

利用.class文件生成.h文件:
打开AS的命令控制台:View–>Tool Windows–>Terminal,进入工程class的目录,如:

cd exampletovey\build\intermediates\classes\debug

输入编译命令:

javah -d jni -classpath D:\eclipse_sdk\sdk\platforms\android-19\android.jar; com.genepoint.jni.JniActivity

回车后,会在debug\jni目录下生成对应的文件com_genepoint_jni_JniActivity.h,将该文件拷贝到模块的src\main\jni\目录下,整理改h文件如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_genepoint_jni_JniActivity */#ifndef _Included_com_genepoint_jni_JniActivity#define _Included_com_genepoint_jni_JniActivity#ifdef __cplusplusextern "C" {#endif/* * Class:     com_genepoint_jni_JniActivity * Method:    getStringFromNative * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_genepoint_jni_JniActivity_getStringFromNative  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

新建文件,com_genepoint_jni_JniActivity.c,实现如下:

#include "com_genepoint_jni_JniActivity.h"/* * Class:     com_genepoint_jni_JniActivity * Method:    getStringFromNative * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_genepoint_jni_JniActivity_getStringFromNative  (JNIEnv *env, jobject jObj){    return (*env)->NewStringUTF(env,"Hello From JNI!");}

执行Build–>Make Project,会报错误:

NDK not configured.

提示未配置NDK,需要在工程的local.properties文件中配置NDK路径。

3. 配置NDK

在项目的local.properties文件中,加入如下配置:

sdk.dir=D:\eclipse_sdk\sdk
ndk.dir=D:\eclipse_sdk\ndk

并在gradle.properties中加入如下语句:

android.useDeprecatedNdk=true

在当前Module中的build.gradle中的defaultConfig分支中加入如下语句:

ndk {    moduleName "JniTest"        // so文件的名字    abiFilters "armeabi","armeabi-v7a","x86"  // 需要编译的平台}

在Windows下NDK存在一个bug,当仅仅编译一个文件时出现会出现此问题,解决方法就是再往jni文件夹加入一个空util.c文件即可。

4. 进行编译so文件

执行Build–>Rebuild Project,就可以编译出so文件。
生成的so文件在build/intermediates/ndk/lib/目录下。
运行该模块,即可在app中加载并调用该so文件了,生成的apk直接将so打包好了,不需要进行第5步。

5. 在AS项目中,调用so文件

. 首先,将so文件拷贝到模块的libs目录下
. 编写模块的build.gradle文件,在android块下,增加如下内容(与 defaultConfig同一级):

    task nativeLibsToJar(type: Zip, description: "create a jar archive of the native libs") {          destinationDir file("$projectDir/libs")          baseName "Native_Libs2"          extension "jar"          from fileTree(dir: "libs", include: "**/*.so")          into "lib"      }      tasks.withType(JavaCompile) {          compileTask -> compileTask.dependsOn(nativeLibsToJar)      }  

. 直接运行该模块,即可直接运行生成apk
. 第5步直接使用so文件的方法与之前的编译so方法不能共存

遇到的部分问题及解决方法

.1、 c及.h文件中,显示Cannot find jni.h文件,导致代码中与JNI C有关的关键字全部为红色。
参考资料:http://stackoverflow.com/questions/21096819/jni-and-gradle-in-android-studio
解决方法:在程序的build.gradle中,android{defaultConfig{***}}defaultConfig中添加如下代码:

sourceSets.main{            jni.srcDirs = []            jniLIbs.srcDir 'src/main/libs'        }

但是添加该代码后,会在.c和.h文件上部一直提示Sync Now,同步后也没有效果,一直没有去掉,重启也不能去掉。

1 0