转载请注明出处,谢谢~
这是关于JNI的第一篇文章,讲述的主要是JNI的使用。
欢迎查看我的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); }
方法是首先进入到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; } }执行看结果: