android jni的使用

来源:互联网 发布:电脑摄像头监控软件 编辑:程序博客网 时间:2024/05/18 02:43

android中的jni,可以方便java与本地native的代码互相访问,上一篇文章是java访问本地方法的介绍,有人说上一篇的做法是老版本jdk1.4之前的格式,新版本jdk1.6之后的格式是使用映射,本篇就是使用映射来实现java与native互相访问的一个实例,就是自己的一个笔记,如有不足之处,还请不吝赐教!

一,首先,还是通过eclipse新建一个app,关键代码如下,

一个MainActivity.java :

package com.nativedemo.hellonativedemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.util.Log;

public class MainActivity extends Activity {

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

NewHelloJni mNewHelloJni = new NewHelloJni();
mNewHelloJni.displayNativeStr();
mNewHelloJni.printJaveStrFromNative();

int sum = mNewHelloJni.getAddSumFromNative(10000,500);
String mStr = mNewHelloJni.getStrFromNative();
Log.d("Hellojni","jni native ,getAddSumFromNative= "+sum+",mStr="+mStr);
}

    static {
        Log.d("hellonative","Loading JNI jni Library");
        System.loadLibrary("newhellojni");
    }

。。。。。。

}

一个 NewHelloJni.java 这里声明了本地方法,和native中想要访问的java中的方法

package com.nativedemo.hellonativedemo;
import android.util.Log;

public class NewHelloJni{
String fromNativeStr ="It is from jave!";
        int mInt =20000;


public NewHelloJni(){
fromNativeStr= "init...";
}


void setJaveStrFromNative(String str){
fromNativeStr = str;
}
void setJaveintFromNative(int mI){
mInt = mI;
}

void printJaveStrFromNative(){
Log.d("hellojni","from native str:"+fromNativeStr+",mInt="+mInt+",but show in jave!");
}


native void displayNativeStr(); //需要本地实现的方法,前面都有个native关键字
native String getStrFromNative();
native int getAddSumFromNative(int num1,int num2);
}

二,在app的根目录,新建一个文件夹 newjni,里面放的文件有:Android.mk,com_nativedemo_hellonativedemo_NewHelloJni.cpp(本地方法的实现类),内容如下:

Android.mk的内容:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_LDLIBS := -llog

LOCAL_SRC_FILES := \
com_nativedemo_hellonativedemo_NewHelloJni.cpp

LOCAL_C_INCLUDES := \
    $(JNI_H_INCLUDE)

LOCAL_SHARED_LIBRARIES := \
    libandroid_runtime \
    libnativehelper \
    libutils \
    libcutils \
    liblog

#LOCAL_PRELINK_MODULE := false

LOCAL_MULTILIB := 32
LOCAL_MODULE:= libnewhellojni
LOCAL_MODULE_TAGS := optional

include $(BUILD_SHARED_LIBRARY) 

com_nativedemo_hellonativedemo_NewHelloJni.cpp的内容:

#include <jni.h>
#include "JNIHelp.h"
#include "utils/Log.h"
#include <string.h>
#include <pthread.h>
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"


namespace android{
jobject objGlobal = NULL;
    JNIEnv* envGlobal =NULL;
    jclass jniClass =NULL;

jobject instanceObj =NULL;
    jmethodID constuctorId =0;
jfieldID fidInt =0;
jfieldID fidStr =0;
jmethodID jMIdNoArgs =0;
jmethodID jMIdIArgs =0;


static void displayNativeStr(JNIEnv* env, jobject obj){
   env = AndroidRuntime::getJNIEnv();
   jstring jStrJave=NULL;
const char* cStrJave = NULL;
       
   const char* str= "set native string in native";
   jstring jStr = env->NewStringUTF(str);//实例化一个字符串


   jniClass = env->FindClass("com/nativedemo/hellonativedemo/NewHelloJni");
jniClass = env->GetObjectClass(obj);
   constuctorId = env->GetMethodID(jniClass,"<init>","()V"); //获取构造函数id
if(instanceObj == NULL){
    instanceObj = env->NewObject(jniClass,constuctorId);
}
if(objGlobal == NULL){
//objGlobal = env->NewGlobalRef(instanceObj); //实例化一个全局的引用
objGlobal = env->NewGlobalRef(obj);
}
   

   fidInt = env->GetFieldID(jniClass,"mInt","I");   //访问java中的属性
        int javeInt = env->GetIntField(objGlobal,fidInt);
        env->SetIntField(objGlobal,fidInt,99990);


fidStr = env->GetFieldID(jniClass,"fromNativeStr","Ljava/lang/String;");//访问java中的字符串属性
//jStrJave = (jstring)env->GetObjectField(objGlobal,fidStr);
        //cStrJave = env->GetStringUTFChars(jStrJave,NULL);   
        //env->ReleaseStringUTFChars(jStrJave,cStrJave);
        env->SetObjectField(objGlobal,fidStr,jStr);


   jMIdNoArgs = env->GetMethodID(jniClass, "printJaveStrFromNative", "()V");//访问java中的方法
   if(jMIdNoArgs !=0){
    env->CallVoidMethod(objGlobal, jMIdNoArgs);
   } 


   jMIdIArgs = env->GetMethodID(jniClass, "setJaveintFromNative", "(I)V");
ALOGD("native jni code,constuctorId=%d,fidInt=%d,javeInt=%s,,fidStr=%d,jStrJave=%s,jMIdJave=%d,jMIdIArgs=%d \n",
constuctorId,fidInt,javeInt,fidStr,jStrJave,jMIdNoArgs,jMIdIArgs);
   if(jMIdIArgs!=0){
env->CallVoidMethod(objGlobal, jMIdIArgs,350000);
   }
}


 //本地代码的实现,无参数的函数
static jstring getStrFromNative(JNIEnv* env, jobject obj){
   const char* str= "from jni native string";
   jstring jStr = env->NewStringUTF(str);
   return jStr;
}
//本地代码的实现,有参数的函数
static int getAddSumFromNative(JNIEnv* env, jobject obj,jint num1,jint num2){
   return num1+num2;
}
//java中的方法,跟本地方法的映射,
static JNINativeMethod sMethods[] = {
   /* name, signature, funcPtr */
   {"displayNativeStr","()V",(void *) displayNativeStr},
   {"getStrFromNative","()Ljava/lang/String;",(void *) getStrFromNative},
   {"getAddSumFromNative","(II)I",(void *) getAddSumFromNative}
};


int register_com_nativedemo_hellonativedemo_NewHelloJni(JNIEnv* env)
{
   return jniRegisterNativeMethods(env, "com/nativedemo/hellonativedemo/NewHelloJni",
                           sMethods, NELEM(sMethods));
}
}//end namespace android


/*
* JNI Initialization
*/
jint JNI_OnLoad(JavaVM *jvm, void *reserved)
{
   JNIEnv *e;
   int status;


   ALOGV("Hello jni native : loading JNI\n");


   // Check JNI version
   if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
ALOGE("JNI version mismatch error");
return JNI_ERR;
   }


   if ((status = android::register_com_nativedemo_hellonativedemo_NewHelloJni(e)) < 0) {
ALOGE("jni hello native registration failure, status: %d", status);
return JNI_ERR;
   }


   return JNI_VERSION_1_6;
}
这个函数中的JNI_OnLoad,在jvm加载动态库时会被调用,然后扎个方法里调用了注册本地方法的函数,jniRegisterNativeMethods(env, "com/nativedemo/hellonativedemo/NewHelloJni",sMethods, NELEM(sMethods));第一个参数是包含有需要本地实现方法的jave类,第二个参数是一个映射数组,,第三个参数是有多少个这样的映射,在JNINativeMethod sMethods[]这个数组里面,第一个元素是java中的方法,第二个是Signature签名,第三个是本地实现方法。

mainactivity.java中,有使用的代码,比较容易看懂,不做解释了。


0 0
原创粉丝点击