Android游戏开发必不可少是要接触JNI的,除非你什么只是写一些普通的小游戏。特别是用3D、OpenGL等时,JNI是基础。
一、关于NDK
NDK全称是(Native Development Kit),作用就是方便在Android中调用C、C++写的东西,因为C的效率高,底层的东西大都是用C写的。
1、NDK是一系列工具的集合。
* NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。
* NDK集成了交叉编译器,并提供了相应的mk文件隔离平台、CPU、API等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。
* NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。
2、NDK提供了一份稳定、功能有限的API头文件声明。
Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)。
NDK的安装部署等这里就不说了。
NDK写Hello World一般步骤:
按照步骤一步步来,即可实现在Android程序中调用C函数。
程序功能:有两个按钮,分别对应调用两个C函数。
Activity代码部分:
public class MainActivity extends Activity { //静态代码块在类第一次被加载的时候调用 static { System.loadLibrary("hello");//名字还是叫hello } //定义一个本地方法, 在jni目录中的c代码来实现这个方法 public native String helloFromC(); //带下划线, 因为C方法中声明也是下划线. 有区别. public native String hello_c(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //1. 不带下划线的本地函数 Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, helloFromC(), Toast.LENGTH_SHORT).show();//Toast } }); //带下划线的本地函数 Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, hello_c(), Toast.LENGTH_SHORT).show();//Toast } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
本地方法中带下划线时,C代码中的方法名也要进行相应的变化。
C代码部分:
#include<stdio.h> #include<jni.h> #include "com_example_ndkhello_MainActivity.h" #include <android/log.h> #define LOG_TAG "System.out.c" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) /*直接写:类型必须对应, 方法名必须按规定, 参数固定*/ jstring Java_com_example_ndkhello_MainActivity_helloFromC(JNIEnv * env, jobject obj) { LOGI("this is a logcat from c");//在logcat中显示 //不能是中文. (*(*env)).NewStringUTF 是一样的 return (*env)->NewStringUTF(env,"hello , my NDK!"); } /*用javah生成头文件, 然后写. 这个是一般的做法. 注意要引入头文件\写函数参数*/ JNIEXPORT jstring JNICALL Java_com_example_ndkhello_MainActivity_hello_1c (JNIEnv *env, jobject obj) { return (*(*env)).NewStringUTF(env,"hello , my NDK_____!"); }
注意:方法名是固定的,C方法名为Java_包名(以下划线分开)_Activity名_方法名 ,包名与方法名中最好不要包含下划线,一般用Javah工具来生成最好。
以上代码包含了在C代码中使用logcat来进行调试。
Android.mk部分:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello LOCAL_SRC_FILES := hello.c LOCAL_LDLIBS += -llog #引入log库 include $(BUILD_SHARED_LIBRARY)
有关makefile文件的写法,可以看看这里http://zensheno.blog.51cto.com/2712776/501371
源码下载:http://download.csdn.net/detail/xn4545945/5511051
转载请注明出处:http://blog.csdn.net/xn4545945
作者:xn4545945 发表于2013-6-3 21:13:06 原文链接
阅读:40 评论:0 查看评论