AS开发JNI步骤

1. 安装配置NDK  
    1). 解压NDK的zip包到非中文目录  
    2). 配置path : 解压后NDK的根目录----->ndk-build  
  
2. 给AS配置关联NDK  
    1). local.properties中添加配置  
     ndk.dir=D\:\\android-ndk\\ndk-bundle
    2). gradle.properties中添加配置 ,若是是最新的ndk,则不须要以下配置
        android.useDeprecatedNdk=true  
  
3. 编写native方法:  
    public class JNIS {  
        public native String helloJNI();  
    }  
  
4. 定义对应的JNI  
    1). 在main下建立jni文件夹  
    2). 生成native方法对应的JNI函数声明头文件: 命令窗口中, 进入java文件夹  
            执行命令: javah com.atguigu.jnitests2.JNIS  
            生成头文件: com_atguigu_jnitests2_JNIS.h  
            函数声明: JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI(JNIEnv *, jobject); 这时生成的.h头文件应该在java文件夹下面。
    著:若是在java目录下编译找不到编译的文件,能够到debug目录下编译,此时生成的.h头文件在debug目录下面。
    3). 将生成的头文件转移到jni文件夹下  
    4). 在jni下定义对应的函数文件: test.c  
        #include "com_atguigu_jnitests2_JNIS.h"  
        JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI  
        (JNIEnv * env, jobject jobj) {  
            return (*env)->NewStringUTF(env, "Hello from C");  
        }  
    5). 在jni文件夹下建立一个空的C文件: util.c  
        说明: 这是AS的bug, 必须至少2个C文件才能经过编译  
  
5. 在该项目下的build.gradle配置生成的so名称和支持的cpu类型  在android中
        defaultConfig {  
            ndk{  
            moduleName "HelloJni" //so文件: lib+moduleName+.so  
            abiFilters "armeabi", "armeabi-v7a", "x86" //cpu的类型  
            }  
        }  
6. 编译生成不一样平台下的动态连接文件  
    1). 执行rebuild, 生成so文件  
    2). so文件目录: build\intermediates\ndk\debug\lib\.....  
7. 调用native方法:  
    1). 在native方法所在的类中加载so文件  
            static {  
            System.loadLibrary("HelloJni");  
            }  
    2). 在Activity中调用native方法:  
            String result = new JNIS().helloJNI();  
        Log.e("TAG", "result="+result);  java

 

步骤如上,下面是经过jni和java交互,java调用jni,而c里面访问java的私有属性,公有属性,静态属性以及公有方法,静态方法和父类的方法。android

代码:ide

package aes.example.com.aesjnidemo.demo;

public class JniOperate extends SuperJni{

    public int num = 100;
    public static String staticField = "staticFiled in java";
    private int age = 20;
    private String test = "java";
    public static int testStatic = 90;

    public native int addNum();
    public native void accessStaticFiled();
    public native void accessPrivateField();
    public native void accessPublicMethod();
    public native void accessStaticMethod();
    public native String accessSuperMethod();

    public void testPublicMethod(String para) {
        this.test = para;
    }

    public static void testStaticMethod() {
        testStatic = 101;
    }

    public int getAge() {
        return age;
    }

    public String getTest() {
        return test;
    }

    static {
        System.loadLibrary("jni_opearte");
    }
}

 

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class aes_example_com_aesjnidemo_demo_JniOperate */

#ifndef _Included_aes_example_com_aesjnidemo_demo_JniOperate
#define _Included_aes_example_com_aesjnidemo_demo_JniOperate
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    addNum
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_addNum
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessStaticFiled
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticFiled
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPrivateField
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPrivateField
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPublicMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPublicMethod
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessStaticMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticMethod
  (JNIEnv *, jobject);

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessSuperMethod
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessSuperMethod
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
#include <string.h>
#include "aes_example_com_aesjnidemo_demo_JniOperate.h"

//在c里面调用java实例的public属性
JNIEXPORT jint JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_addNum
        (JNIEnv *env, jobject obj) {
    jclass jclazz = (*env)->GetObjectClass(env, obj);
    jfieldID fid = (*env)->GetFieldID(env, jclazz, "num", "I");
    jint num = (*env)->GetIntField(env, obj, fid);
    num++;
    return num;
}

//在c里面调用java实例的static属性
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticFiled
  (JNIEnv *env, jobject obj) {
        jclass jclazz = (*env)->GetObjectClass(env, obj);
        jfieldID fid = (*env)->GetStaticFieldID(env, jclazz, "staticField", "Ljava/lang/String;");
        jstring name = (jstring)(*env)->GetStaticObjectField(env, jclazz, fid);
        const char* str = (*env)->GetStringUTFChars(env, name, JNI_FALSE);
        char ch[30] = "C code, ";
        strcat(ch, str);
        jstring new_str = (*env)->NewStringUTF(env, ch);
        (*env)->SetStaticObjectField(env, jclazz, fid, new_str);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPrivateField
 * Signature: ()V
 */
 //在c里面调用java实例的private属性
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPrivateField
  (JNIEnv *env, jobject obj) {
        jclass clazz = (*env)->GetObjectClass(env, obj);
        jfieldID fid = (*env)->GetFieldID(env, clazz, "age", "I");
        jint age = (*env)->GetIntField(env, obj, fid);
        if (age > 18) {
            age = 18;
        } else {
            age--;
        }
        (*env)->SetIntField(env, obj, fid, age);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessPublicMethod
 * Signature: ()V
 */
 //在c里面调用java实例的public方法
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessPublicMethod
  (JNIEnv *env, jobject obj) {
        jclass clazz = (*env)->GetObjectClass(env, obj);
        jmethodID mid = (*env)->GetMethodID(env, clazz, "testPublicMethod", "(Ljava/lang/String;)V");
        char c[10] = "I am C";
        jstring jc = (*env)->NewStringUTF(env, c);
        (*env)->CallVoidMethod(env, obj, mid, jc);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessStaticMethod
 * Signature: ()V
 */
 //在c里面调用java实例的static方法
JNIEXPORT void JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessStaticMethod
  (JNIEnv *env, jobject obj) {
        jclass clazz = (*env)->GetObjectClass(env, obj);
        jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "testStaticMethod", "()V");
        (*env)->CallStaticVoidMethod(env, clazz, mid);
  }

/*
 * Class:     aes_example_com_aesjnidemo_demo_JniOperate
 * Method:    accessSuperMethod
 * Signature: ()Ljava/lang/String;
 */
 //在c里面调用java实例的父类方法
JNIEXPORT jstring JNICALL Java_aes_example_com_aesjnidemo_demo_JniOperate_accessSuperMethod
  (JNIEnv *env, jobject obj) {
        jclass jclazz = (*env)->FindClass(env, "aes/example/com/aesjnidemo/demo/SuperJni");
        if (NULL == jclazz) {
            char c[10] = "error";
            return (*env)->NewStringUTF(env, c);
        }
        jmethodID mid = (*env)->GetMethodID(env, jclazz, "hello", "(Ljava/lang/String;)Ljava/lang/String;");
        char ch[10] = "C call ";
        jstring jstr = (*env)->NewStringUTF(env, ch);
        return (jstring)(*env)->CallNonvirtualObjectMethod(env, obj, jclazz, mid, jstr);
  }

 

测试结果:函数

相关文章
相关标签/搜索