Menu Home

android程序调用JNI

OS: 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程序 。1

Categories: android应用 C/C++ java

Tagged as:

lnmcc

Leave a Reply

Your email address will not be published.