最近看了下Jni的配置与使用,因此写个Demo练习一下。在Android Studio里面,编写Jni,使用so还是非常方便的。参考文章:http://www.jianshu.com/p/d8cde65cb4f7,感谢作者的分享~

NDK下载配置

1、在Android Studio里面先下载NDK。可能需要翻墙,如果下载失败,可以尝试去网络上找找。

pic

2、配置NDK环境

pic

pic

好啦,这样,NDK环境就算配置完成了。

建立NdkJniDemo项目

1、新建立工程NdkJniDemo。

2、建立一个JniUtil.java类:

package com.xyzlf.jni.demo;

/**
 * Created by zhanglifeng on 2016/7/17
 */

public class JniUtil {

    public static native String getStringFromJni();
 
}

然后Clean Project,Rebuild Project,之后,你就能在项目的路径:app/build/intermediates/classes/debug 看到 com.xyzlf.jni.demo.JniUtil.class

cd app/build/intermediates/classes/debug

javah -jni com.xyzlf.jni.demo.JniUtil

pic

以上操作如果没有问题的话,就会生成com_xyzlf_jni_demo_JniUtil.h文件。在项目的src/main下面建立一个jni文件夹,将生成的com_xyzlf_jni_demo_JniUtil.h文件拷贝进去。

在jni文件夹里面,新建一个与.h对应的.c文件,名字可以随便,我取得名字为:JniUtil.c,加入以下代码:

//
// Created by zhanglifeng on 2016/7/17.
//

#include "com_xyzlf_jni_demo_JniUtil.h"
/*
* Class:     com_xyzlf_jni_demo_JniUtil
* Method:    getStringFromJni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_xyzlf_jni_demo_JniUtil_getStringFromJni
        (JNIEnv *env, jobject obj) {
   return (*env)->NewStringUTF(env, "这里是来自c的string");
}

3、Jni类的配置及引用

在项目app下的build.gradle下面配置ndk:

ndk {
	moduleName "NdkJniDemo"          //生成的so名字
	abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库,目前可有可无。
}

pic

在JniUtil里面引用”NdkJniDemo”,记住需要跟上面gradle里面配置的名字一致,否则会找不到,完整代码如下:

package com.xyzlf.jni.demo;

/**
 * Created by zhanglifeng on 2016/7/17
 */

public class JniUtil {

    static {
        System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
    }

    public static native String getStringFromJni();

}

在MainActivity中调用:

package com.xyzlf.jni.demo;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = (TextView) findViewById(R.id.ndk_text);
        textView.setText(JniUtil.getStringFromJni());
    }
}

如果build过程中失败的话,在gradle.properties加入配置

android.useDeprecatedNdk=true

以下是运行效果图:

pic

工程目录结构:

pic

至此就完成了。

项目中引用so

以上项目编译完后,可以在app/build/intermediates/ndk/debug/lib下面找到生成的so:

pic

将这几个so,拷贝至app/src/main/jniLibs目录下:(如果没有jniLibs目录,新建一个),这样就直接引用so,可以将,jni文件下面的.h,.c文件删除了。

pic

ERROR

Error:(36) undefined reference to '__android_log_print'

解决方案,在buil.gradle里面添加:ldLibs “log”//实现__android_log_print

完整的build.gradle如下:

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"
    defaultConfig {
        applicationId "com.xyzlf.jni.demo"
        minSdkVersion 8
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        ndk {
            moduleName "NdkJniDemo"          //生成的so名字
            ldLibs "log"//实现__android_log_print
            abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库,目前可有可无。
        }

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

完整项目地址

完整的项目地址:https://github.com/xyzlf/JniDemo


分享到