JNI demo 手把手教例子


1 JNI工程建立

Android目录下创一个目录jnidemo,并在该目录下创建三个文件

n        Android.mk   //用于编译JNI工程的makefile文件

n        jnidemo.cpp   //JNI代码文件

n        onload.cpp    //用于注册JNI方法的文件

创建过程如下:

cd android4.1

mkdir jnidemo

cd jnidemo

touch Android.mk

touch jnidemo.cpp

onload.cpp

2 编辑jnidemo.cpp

vim jnidemo.cpp

#include"JNIHelp.h"

#include "jni.h"

#define LOG_TAG"Service-JNI"

 

namespace android

{

 staticjint nativeOpen(JNIEnv* env,jobjectobj){

     ALOGE("JNI test nativeOpen");

          return10;

}

static JNINativeMethod method_table[] = {

      {"nativeOpen","()I",(void*)nativeOpen }

      };

int register_android_jnidemo_Service(JNIEnv*env){

     returnjniRegisterNativeMethods(env,"com/android/jnidemo/Service",

            method_table,NELEM(method_table));

}

};

 

n        这里我们提供了一个接口给Java层序调用,即nativeOpen(),我们是静态定义的,所以不需要的.h文件中声明。

n        静态初始化JNINativeMethod结构体,里面对nativeOpen()方法的描述

n        定义register_android_jnidemo_Service()方法,用于注册JNI文件,在该方法中,用到了两个关键的参数,一个是"com/android/jnidemo/Service",对应着java代码的包名,即调用JNIjava代码所在的包是“com.android.jnidemo,类名是Service,另一个是method_table,即是上面初始化的JNINativeMethod结构体。那么register_android_jnidemo_Service()是在哪里被调用的呢?那么请看onload.cpp

3 编辑onload.cpp

#include"JNIHelp.h"

#include "jni.h"

#include"utils/Log.h"

#include"utils/misc.h"

 

namespace android{

int register_android_jnidemo_Service(JNIEnv*env);

};

using namespaceandroid;

extern "C" jint JNI_OnLoad(JavaVM* vm, void*reserved)

{

   JNIEnv* env = NULL;

    jintresult = -1;

 

    if(vm->GetEnv((void**) &env,JNI_VERSION_1_4) != JNI_OK) {

       ALOGE("GetEnv failed!");

       return result;

   }

   ALOG_ASSERT(env, "Could not retrieve the env!");

 

   register_android_jnidemo_Service(env);

   return JNI_VERSION_1_4;

}

java代码调用System.loadLibrary()加载JNI库的时候,将调用到onload.cppJNI_OnLoad()方法,然后将调用在jnidemo.cpp文件中定义的方法register_android_jnidemo_Service(env)JNI进行注册。其实很简单吧,onload.cpp就是完成注册功能的。

4 编辑Android.mk

LOCAL_PATH:= $(callmy-dir)

include$(CLEAR_VARS)

 

LOCAL_MODULE_TAGS :=eng

 

LOCAL_SRC_FILES:=\

   jnitest.cpp \

   onload.cpp

 

LOCAL_SHARED_LIBRARIES :=\

    libnativehelper \

    liblog

 

LOCAL_MODULE:=libjnitdemo

 

include$(BUILD_SHARED_LIBRARY)

Android.mkandroid下面的makefile文件:

n        LOCAL_MODULE_TAGS,编译的模式,这里我们选择eng模式

n        LOCAL_SRC_FILES编译的源文件,这里的源文件就是前面定义的两个cpp文件

n        LOCAL_SHARED_LIBRARIES用到的共享库,libnativehelper是用于注册JNI用到的共享库,liblog是用于打印log用到的共享库,即ALOGD()方法需要的。

n        LOCAL_MODULE编译输出模块的名称,编译之后将生成libjnidemo.so文件

 

jnidemo目录下执行mm命令(前提是构建好Android的环境),编译当前目录下,之后将在out产品目录下的system/lib/目录下生成libjnidemo.so文件

5 编辑java代码

package com.android.jnidemo;

import android.util.Log;

public class Service {

String TAG="Service";

   static {

      System.loadLibrary("jnidemo");

   }

   public native int nativeOpen();

   public Service(){

      Log.v(TAG,"get from jni = "+nativeOpen());

   }

}

n        这里是java很简单的一个类,包名是com.android.jnidemo,类名是Service,这里我们看到了,在jnidemo.cpp文件中注册JNI的时候于此对应"com/android/jnidemo/Service"

n        定义了一个静态模块,用于加载JNI库文件libjnidemo.ko

n        声明了native方法nativeOpen()

n        Service类的构造函数中,调用了nativeOpen()方法。

 

我是在eclipse下面创建了一个Android apk的工程,在ActivityonCreate()方法中创建了Service的实例,即new Service(),这里就不写出来了。

6 代码执行

n        首先需要将libjnidemo.ko文件推送到小机的system/lib目录下

out的产品目录的system/lib下执行adb pushlibjnidemo.ko  /system/lib

n        通过eclipse在小机中运行apk,在logcat中我们将看到如下打印:

com.android.jnidemo  Service-JNI    JNI test nativeOpen

com.android.jnidemo  service        get from jni = 10

第一条是在JNInativeOpen方法中打印的,第二条是在Java代码中打印的。

看到这个结果,说明JNI已经ok了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值