Android程序调用JNI
27 Aug 2013OS: MAC OS 10.7.5 Android: 4.3 NDK: android-ndk-r7c java: 1.6.0_51
使用JNI
在Eclipse中新建一个Android工程,假设项目目录为project,修改activity_main.xml 如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView android:id="@+id/showText"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
MainActivity.java:
package net.lnmcc.usejni;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
// 加载JNI库
static {
System.loadLibrary("useJNI");
}
// 定义JNI方法
public native String getStringFromNative();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 调用JNI方法
String strResult = getStringFromNative();
TextView tv = (TextView)findViewById(R.id.showText);
tv.setText(strResult);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
创建Application.mk
在项目根目录中创建Application.mk:
APP_PROJECT_PATH:=$(call my-dir) #项目所在目录
APP_MODULES:=useJNI #应用程序的名字
编译上面的代码,在 bin/classes/net/lnmcc/usejni下生成了相应的class文件。
实现JNI
JNI头文件的生成
在项目根目录下新建jni文件夹,用来放置jni相关的文件。 JNI头文件可以使用javah来自动生成,这里的关键是路径一定要正确,:
$ cd project
$ javah -classpath bin/classes/ \
> -d jni \
> com.lnmcc.usejni.MainActivity #前缀一定是你的包名,否则找不到class文件
如果没有错误,javah就会自动生成net_lnmcc_usejni_MainActivity.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class net_lnmcc_usejni_MainActivity */
#ifndef _Included_net_lnmcc_usejni_MainActivity
#define _Included_net_lnmcc_usejni_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: net_lnmcc_usejni_MainActivity
* Method: getStringFromNative
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_net_lnmcc_usejni_MainActivity_getStringFromNative
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
实现JNI函数
在project/jni文件夹中新建C源代码文件,JNI函数的命名规则为:
JAVA_包名_类名_函数名
useJNI.c:
#include "net_lnmcc_usejni_MainActivity.h"
JNIEXPORT jstring JNICALL Java_net_lnmcc_usejni_MainActivity_getStringFromNative
(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, (char*)"Hello, World");
}
创建Android.mk
在project/jni/文件夹中创建Android.mk文件:
LOCAL_PATH:=$(call my-dir) #项目根目录
include $(CLEAR_VARS) #除了LOCAL_PATH,清除其它LOCAL_变量的值
LOCAL_MODULE:=useJNI
LOCAL_SRC_FILES:=useJNI.c
include $(BUILD_SHARED_LIBRARY) # 编译成动态库
编译JNI库
$ cd project/jni
$ ndk-build #这是NDK-r7c提供的工具,确保在环境变量中
如果没有错误,输出:
Compile thumb : useJNI <= useJNI.c
SharedLibrary : libuseJNI.so
Install : libuseJNI.so => libs/armeabi/libuseJNI.so
测试程序
在Eclipse中刷新项目,使在project/libs/armeabi/下出现libuseJNI.so,然后Run程序 。