Android-JNI搭建以及调用

转载请注明出处,谢谢~


这是关于JNI的第一篇文章,讲述的主要是JNI的使用。

欢迎查看我的JNI的第二篇文章,讲述的是JNI机制以及实现,是第一篇的升华版。

JNI(二):JNI机制与实现


首先要新建一个工程,起名HelloJni。然后在工程目录下新建文件夹jni。如图:

我用的是eclipse

Android-JNI搭建以及调用_第1张图片

然后我们用快捷键Alt+Enter进入工程属性选项,选择左边栏的builder,然后点击new:

Android-JNI搭建以及调用_第2张图片

之后我们选择program,然后会有一个弹出窗口:

Android-JNI搭建以及调用_第3张图片

在main选项中设置好两个路径,第一个是ndk里ndk-build.cmd的路径,我这里用的是ndk-r9,第二个是工程路径,就是我们的HelloJni工程,然后再看refresh选项:

Android-JNI搭建以及调用_第4张图片

把如图所示的勾选上,然后看options选项:

Android-JNI搭建以及调用_第5张图片

把如图所示勾选上之后会报个错,此时ok不能点,然后我们点Specify Resources...选项,进入另一个界面:

Android-JNI搭建以及调用_第6张图片

在这里我们选择HelloJni项目的jni目录,点击finish完成。然后点击ok设置完成。

之后我们写我们的jni的头文件:

我们要在src中新建一个类,类里写上我们要用到的native方法:

package com.ocean.hellojni.jni;

public class JniClient {
	
	public static native String getString(String a,String b);
	public static native int getInt(int a,int b);
}

然后如果是用eclipse,会自动生成classes文件,其他的可能需要手动生成一下,然后我们用cmd命令行生成头文件:

Android-JNI搭建以及调用_第7张图片

方法是首先进入到HelloJni工程的目录下,然后进入bin的classes目录,之后执行语句javah path。path是你写的native本地方法那个类的全路径,就是包名,路径加上方法名,不需要后缀名,之后就生成好了.h的头文件,然后将它拷贝到jni目录,打开:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_ocean_hellojni_jni_JniClient */

#ifndef _Included_com_ocean_hellojni_jni_JniClient
#define _Included_com_ocean_hellojni_jni_JniClient
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_ocean_hellojni_jni_JniClient
 * Method:    getString
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_ocean_hellojni_jni_JniClient_getString
  (JNIEnv *, jclass, jstring, jstring);

/*
 * Class:     com_ocean_hellojni_jni_JniClient
 * Method:    getInt
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_ocean_hellojni_jni_JniClient_getInt
  (JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif
根据它写我们的C/C++文件:

#include "com_ocean_hellojni_jni_JniClient.h"
#include <stdio.h>
#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_ocean_hellojni_jni_JniClient
 * Method:    getString
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_ocean_hellojni_jni_JniClient_getString
  (JNIEnv *env, jclass arg, jstring strA , jstring strB) {
	jstring str = (*env)->NewStringUTF(env,"Hello Jni!");
	return str;
}

/*
 * Class:     com_ocean_hellojni_jni_JniClient
 * Method:    getInt
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_ocean_hellojni_jni_JniClient_getInt
  (JNIEnv *env, jclass arg, jint a , jint b){
	return a+b;
}

#ifdef __cplusplus
}
#endif

此处应注意方法名要和头文件的一致。

然后我们写.mk文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := HelloJni
LOCAL_SRC_FILES := com_ocean_hellojni_jni_JniClient.c
include $(BUILD_SHARED_LIBRARY)
C和C++的.mk文件可能略有不同,但大致都是这样,详情以后的博文里也许会提到。

然后再java类中调用我们写的本地方法:

package com.ocean.hellojni;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;

import com.ocean.hellojni.jni.JniClient;

public class MainActivity extends Activity {

	private TextView show;
	private TextView answer;
	private EditText one;
	private EditText two;
	
	static{
		System.loadLibrary("HelloJni");
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		show = (TextView) findViewById(R.id.show);
		answer = (TextView) findViewById(R.id.answer);
		one = (EditText) findViewById(R.id.et_one);
		two = (EditText) findViewById(R.id.et_two);
		String string = JniClient.getString("1","2");
		show.setText(string);
		
		answer.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				if (one.getText().toString() != null && two.getText().toString() != null
						&& !one.getText().toString().equals("") && !two.getText().toString().equals("")) {
					int i = JniClient.getInt(Integer.valueOf(one.getText().toString()),
							Integer.valueOf(two.getText().toString()));
					answer.setText("result : "+i);
				}
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}
执行看结果:

Android-JNI搭建以及调用_第8张图片


OK!此处应该有掌声~~


你可能感兴趣的:(eclipse,android,jni,native)