JNI demo 手把手教例子

本文详细介绍了一个JNI (Java Native Interface) 的实战案例,包括JNI工程的建立、相关文件的编辑及执行流程等内容。从JNI文件的创建到Java层的调用,再到最终的代码执行结果,一步步引导读者理解JNI的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.sina.com.cn/s/blog_89f592f501013ge3.html

JNI demo 手把手教例子

fe工作室 http://blog.sina.com.cn/u/2314572533  2012-09-26 10:19:11


1 JNI工程建立


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

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

         jnidemo.cpp    //JNI代码文件

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

创建过程如下:

cd android4.1

mkdir jnidemo

cd jnidemo

touch Android.mk

touch jnidemo.cpp

touch onload.cpp



2 编辑jnidemo.cpp


vim jnidemo.cpp

#include "JNIHelp.h"

#include "jni.h"

#include "utils/Log.h"

#include "utils/misc.h"


#define LOG_TAG "Service-JNI"

 

namespace android

{

    static jint nativeOpen(JNIEnv* env,jobject obj){

          ALOGE("JNI test nativeOpen");

          return 10;

    }

    static JNINativeMethod method_table[] = {

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

    };

    int register_android_jnidemo_Service(JNIEnv *env){

         return jniRegisterNativeMethods(env,"com/android/jnidemo/Service",

              method_table,NELEM(method_table));

    }

};

 

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

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

         定义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 namespace android;

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

{

    JNIEnv* env = NULL;

    jint result = -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:= $(call my-dir)

include $(CLEAR_VARS)

 

LOCAL_MODULE_TAGS := eng

 

LOCAL_SRC_FILES:= \

    jnidemo.cpp \

    onload.cpp

 

LOCAL_SHARED_LIBRARIES := \

     libnativehelper \

     liblog

 

LOCAL_MODULE:= libjnitdemo

 

include $(BUILD_SHARED_LIBRARY)

Android.mkandroid下面的makefile文件:

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

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

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

         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());

    }

}

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

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

         声明了native方法nativeOpen()

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

 

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



6 代码执行


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

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

         通过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、付费专栏及课程。

余额充值