您的位置:首页 > 移动开发 > Android开发

Android游戏开发----JNI小结

2014-03-08 12:46 405 查看
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写Hello World

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文件的写法,可以看看这里/article/6935822.html

源码下载http://download.csdn.net/detail/xn4545945/5511051

出处:http://blog.csdn.net/xn4545945
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐