[Android应用开发]-(14)JNI----经典实例分析
接下来几篇文章,学习JNI开发,主要是学习《JNI详解》,将里面的实例通过Android平台实现,首先由一个经典实例引出 – HelloWorld!!HelloWorld是经典的,一想起学编程,就想起那些年我们一起写过的HelloWorld。这里用HelloWorld来讲解JNI的开发过程。这个过程大致可通过下图来说明:
1) 新建一个HelloWorld工程;
2) 创建一个带有native方法的类Helloworld.java;
[java]
package org.winplus.helloworld;
public class HelloWorld {
public native void print();
private void stitic() {
System.loadLibrary("helloworld");
}
}
package org.winplus.helloworld;
public class HelloWorld {
public native void print();
private void stitic() {
System.loadLibrary("helloworld");
}
}
HelloWorld类首先声明了一个publicnativevoid print()方法。Static包含的是本地库。在java代码中声明为native的本地方法只作为声明存在。在调用本地方法之前,必须先装载含有该方法的本地库,如HelloWorld中所示,置于static中,在JavaVM初始化一个类时,首先会执行这段代码,这可保证调用本地方法之前装载了本地库。转载的机制请看后文…
3) 使用javac编译Helloworld.java
使用Eclipse的同学不需要做此动作,都自动编译了。进入Class目录。
4) 使用javah –jni 编译Helloworld.class 生成头文件 Helloworld.h;Javah –jni org.winplus.helloworld.HelloWorld会生成一个名为:org_winplus_helloworld_ HelloWorld.h的头文件。生成的代码如下:
[cpp]
<SPAN style="FONT-SIZE: 16px">/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_winplus_helloworld_HelloWorld */
#ifndef _Included_org_winplus_helloworld_HelloWorld
#define _Included_org_winplus_helloworld_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_winplus_helloworld_HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_winplus_helloworld_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif</SPAN>
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_winplus_helloworld_HelloWorld */
#ifndef _Included_org_winplus_helloworld_HelloWorld
#define _Included_org_winplus_helloworld_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_winplus_helloworld_HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_winplus_helloworld_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
我们注意到JNIEXPORTvoid JNICALL Java_org_winplus_helloworld_HelloWorld_print(JNIEnv *,jobject);这里我们注意到JNIEXPORT和JNICALL两个宏,我们看到这个函数声明接收两个参数而对应的Java代码中并没有参数。第一个参数是指向JNIEnv结构的指针;第二个参数,为HelloWorld对象自身,即this指针。
5) 使用C实现头文件中的函数
[cpp]
<SPAN style="FONT-SIZE: 16px">#include <jni.h>
#include <stdio.h>
#include "android/log.h"
#include "HelloWorld.h"
static const char *TAG="HelloWorld";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
JNIEXPORT void JNICALL Java_org_winplus_helloworld_HelloWorld_print
(JNIEnv *env, jobject obj){
LOGI("Hello World");
return;
}
</SPAN>
#include <jni.h>
#include <stdio.h>
#include "android/log.h"
#include "HelloWorld.h"
static const char *TAG="HelloWorld";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
JNIEXPORT void JNICALL Java_org_winplus_helloworld_HelloWorld_print
(JNIEnv *env, jobject obj){
LOGI("Hello World");
return;
}
这里为了方便看到打印信息,使用了jni中的log.h头文件和ANDROID_LOG_INFO宏。
6) 编译C文件生成本地库。这一步比较繁琐,请下载源码看吧。具体步骤
a) 将头文件及C文件拷贝到jni目录,并编写Android.mk和Application.mk文件
b) 通过ndk或者在Ubuntu下编译,生成helloworld.so文件 www.zzzyk.com
c) 将生成的文件拷贝到libs/armeabi目录下,并更改名字为:libhelloworld.so
7) 运行程序,查看结果。
作者:tangcheng_ok
补充:移动开发 , Android ,