转载请注明出处,谢谢~
这是关于JNI的第一篇文章,讲述的主要是JNI的使用。
欢迎查看我的JNI的第二篇文章,讲述的是JNI机制以及实现,是第一篇的升华版。
首先要新建一个工程,起名HelloJni。然后在工程目录下新建文件夹jni。如图:
我用的是eclipse
然后我们用快捷键Alt+Enter进入工程属性选项,选择左边栏的builder,然后点击new:
之后我们选择program,然后会有一个弹出窗口:
在main选项中设置好两个路径,第一个是ndk里ndk-build.cmd的路径,我这里用的是ndk-r9,第二个是工程路径,就是我们的HelloJni工程,然后再看refresh选项:
把如图所示的勾选上,然后看options选项:
把如图所示勾选上之后会报个错,此时ok不能点,然后我们点Specify Resources...选项,进入另一个界面:
在这里我们选择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命令行生成头文件:
方法是首先进入到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;
}
}
执行看结果:
OK!此处应该有掌声~~