您的位置:首页 > 编程语言 > Java开发

第一个NDK程序

2011-03-04 11:36 183 查看

一、概述

【 为什么要使用JNI】

重用已有的代码,这些代码用C/C++编写

提供程序运行效率

通常会在与硬件、操作平台交互时, 或者使用一些与Android平台无关的算法时用到JNI。

 

【文章目标】

认识如何为Native Code编写Java接口。

认识在JAVA程序中是如何访问C/C++代码的。

二、实例

Native Code实现了一个返回字符串"Hello world JNI!!!"的功能,JAVA调用了该方法,并将它打印到屏幕上。

【效果图】
 


 

【实现步骤】

(1)编写带有native声明的方法的java类。
package enleo.jni;
public class Jni {
public native int add();
public native String getString();
}
 

 

(2)使用javac命令编译所编写的java类,生成Jni.class.


 

 

(3)使用javah-jni java类名生成扩展名为h的头文件
 


 

 打开enleo_jni_Jni.h文件,自动生成了以下内容:
#ifndef _Included_enleo_jni_Jni
#define _Included_enleo_jni_Jni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     enleo_jni_Jni
* Method:    add
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_enleo_jni_Jni_add
(JNIEnv *, jobject);
/*
* Class:     enleo_jni_Jni
* Method:    getString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_enleo_jni_Jni_getString
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
  
注意:这个文件是C/C++的头文件声明,它是(1)中建立的Java类的一个映射。当然,这个文件也可以通过手动生成,这不是好方法! 因为你不知道Java的数据类型与C/C++数据类型之间的映射关系。另外,在C/C++的实现文件里面的方法必须与.h文件所声明的一致。

 

(4)使用C/C++(或者其他编程想语言)实现本地方法。
enleo_jni_Jni.c 

#include <stdio.h>
#include <stdlib.h>
#include "enleo_jni_Jni.h"
int add(){
int x,y;
x =100;
y =100;
return x+y;
}
JNIEXPORT jint JNICALL Java_enleo_jni_Jni_add(JNIEnv *env, jobject thiz)
{
return add();
}
JNIEXPORT jstring JNICALL Java_enleo_jni_Jni_getString(JNIEnv *env, jobject thiz)
{
(*env)->NewStringUTF(env,"Hello world JNI!!!");
}
 

(5)将C/C++编写的文件生成动态连接库

1.编写Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := NewJNI
LOCAL_SRC_FILES := enleo_jni_Jni.c
include $(BUILD_SHARED_LIBRARY)
 

2.编写Application.mk

APP_PROJECT_PATH :=$(call my-dir)/project
APP_MODULES := NewJNI
 

3.编译C/C++代码



 

【可能出现的问题】如果NDK的版本与SDK版本不兼容,会出现下面的提示



我的解决方法是修改了default.properties,将版本从7改为4,骗过了cygwin。
不过这种方法不推荐使用,大家最好还是下载合适的版本。

 

(6)调用动态库

调用System.loadLibrary("NewJNI");函数加载libNewJNI.so。
package enleo.HelloWorldJNI;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import enleo.jni.Jni;
public class eHelloWorldJNI extends Activity {
private TextView textView;
static{
System.loadLibrary("NewJNI");
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Jni jni = new Jni();
int result = jni.add();

textView = (TextView)findViewById(R.id.tv);
textView.setText(jni.getString());
}
}
 

【可能出现的问题】UnsatisfiedLinkError
导致这种错误的原因是找不到库,或者找不到库函数。请检查修正后重新运行。
 


四、扩展

Java和NativeCode数据类型映射表

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息