编写HelloWorld JNI
新建Android项目,编写一个native方法,一个native方法是一个java调用非java代码的接口,native方法可以由c来实现
package tu.bb.ndk; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { //本地方法 public native String sayHello(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
用JNI协议来进行Java和C代码的相互调用、通信,Java的本地方法由C来实现,需要符合一套JNI的命名规则和数据类型的转换,我们可以借助jdk提供的 (javah 类全名) 命令来生成C语言的头文件,cd到工程目录下的src文件下,执行javah命令就会在src目录下生成一个头文件了
在工程目录下创建jni目录,拷贝刚才生成的头文件、创建Java native 方法C语言实现文件、Android.mk文件,Android.mk文件是交叉编译c/c++代码时依赖的配置文件,是linux下makefile语法的子集
#获取当前Android.mk文件路径 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #指定C库文件的名字 LOCAL_MODULE := libHelloWorld #指定C语言实现的源文件 LOCAL_SRC_FILES := tu_bb_ndk_MainActivity.c \ include $(BUILD_SHARED_LIBRARY)
至于Android.mk要如何编写,大家可以到android-ndk-r7b/docs/ANDROID-MK.html去拷贝
现在我们就可以来实现头文件中的函数了
#include <stdio.h> #include <jni.h> #include "tu_bb_ndk_MainActivity.h" //env代表的是jvm C语言实现的结构体指针,obj代表的是当前调用Java native方法的对象 JNIEXPORT jstring JNICALL Java_tu_bb_ndk_MainActivity_sayHello (JNIEnv * env, jobject obj) { return (*env)->NewStringUTF(env,"Hello World"); }
利用cygwin工具进行交叉编译,生成库文件,位于libs\armeabi目录下,生成libHelloWorld.so库文件
编写Java测试代码,需要注意的是,使用本地方法之前需事先把库文件加载入jvm中,指定要加载的库文件名
package tu.bb.ndk; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.view.Menu; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { private Context mContext; static{ //事先把库文件加载进jvm,HelloWorld为库文件名字 System.loadLibrary("HelloWorld"); } //本地方法 public native String sayHello(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; View bt_hw = findViewById(R.id.bt_hw); bt_hw.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, sayHello(), Toast.LENGTH_LONG).show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
好了,HelloWorld就此完成