Android NDK 初探
说到Android NDK,其实我也是前几个月才有所了解,当时在开发了一些应用程序后,萌生了想做游戏的想法。后来到网上查资料,就接触了《Android游戏开发》这本书,写于2009吧,书上一开始说的很神秘,就是向开发者介绍一种秘密武器,其实说白了,就是移植游戏的方法,更直白些,就是教你怎么样把用c或者cpp写的程序移植到java开发的应用中。看到这,有些同学可能就不明白了,为什么要移植程序。原因其实很简单,有很多的游戏代码都是基于c语言的,还有游戏引擎,都是基于c开发的,你要想用人家的代码或者引擎,你就得了解JNI(Java Native Interface),在写书的那时候,google其实不推荐这种编程方式,即便android平台从刚开始就支持JNI编程,只不过官方没有出相应的开发工具,所以书里面用的工具还是Mentor Graphics 家的的东西,其实我也能理解google的用心,本来做出这么个混合架构就是想把层次分清,我们用java开发应用层,对于普通的开发者,更低层次的东西一般碰不到。但什么事都有好有坏吧,成也萧何败萧何,c语言有那么多现成的资源,不用岂不可惜,况且java比较容易反编译,你写的应用不说被别人完全盗用吧,最起码别人可以在你不同意或者不知道的情况下,借用部分代码等等。当然我觉得这不是主因,而且你也不可能完全用c写android应用,毕竟java是王道。最终google妥协了,NDK就诞生了,这就是官方出的一套进行原生语言编译开发的工具,他和android平台结合的更紧密,使用起来也非常方便。
网上有很多搭建NDK平台的教程,在这就不赘言,最好是在linux或者mac os 的开发环境下,用着方便。
开发包里面有很多sample程序,那我们熟悉这个开发环境以及工具,当然就从那个hello-jni开始,这名字起的,多亲切。
ndk的程序,大的方面和平常的一样,我们要干的就是把自己写的c或者cpp程序,通过ndk编译出来一个so文件,打包进apk,以使它能够在arm上面运行。
先看HelloJni.java这个文件
package com.example.hellojni;
import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
public class HelloJni extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/* Create a TextView and set its content.
* the text is retrieved by calling a native
* function.
*/
TextView tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
}
/* A native method that is implemented by the
* 'hello-jni' native library, which is packaged
* with this application.
*/
public native String stringFromJNI();
/* This is another native method declaration that is *not*
* implemented by 'hello-jni'. This is simply to show that
* you can declare as many native methods in your Java code
* as you want, their implementation is searched in the
* currently loaded native libraries only the first time
* you call them.
*
* Trying to call this function will result in a
* java.lang.UnsatisfiedLinkError exception !
*/
public native String unimplementedStringFromJNI();
/* this is used to load the 'hello-jni' library on application
* startup. The library has already been unpacked into
* /data/data/com.example.HelloJni/lib/libhello-jni.so at
* installation time by the package manager.
*/
static {
System.loadLibrary("hello-jni");
}
}
没什么复杂的,onCreate函数我们熟悉,程序启动就会加载,我们自己写了一个TextView,让他的内容等于stringFromJNI()这个函数的返回值,那我们就看这个函数。
/* A native method that is implemented by the
* 'hello-jni' native library, which is packaged
* with this application.
*/
public native String stringFromJNI();
native这个关键字,就是声明这个函数要用到原生语言,具体实现方法要到原生语言里面去看,当然 下面那个函数也一样,在java中只要声明这些要实现的方法就行了。
static {
System.loadLibrary("hello-jni");
}
最后,这个方法别忘了,static方法就是要在onCreate之前载入编译好的文件。
再看jni目录下的hello-jni.c
#include <string.h>
#include <jni.h>
/* This is a trivial JNI example where we use a native method
// * to return a new VM String. See the corresponding Java source
* file located at:
*
* apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
*/
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
头文件,jni.h必须要有,这没啥说的,下面这个函数,看着复杂,其实也有规律可循,jstring就是指java 中的String, 这是返回值, 下来是包的名字,下来是类的名字,最后是类里面的方法名字,函数里的 JNIEnv 以及jobject都是必须的。下来再看实现函数的语句就是返回一个字符串“Hello from JNI !”。 很好理解。
最后一步就是把这个c文件编译成so文件,这步也不难。打开terminal进入到你的project目录下,用ndk-build命令,就会自动执行Android.mk文件中的语言来编译,你最终会在当前目录下看到新的libs目录,里面就有已经生产好的so文件,现在你可run你的android project了,看看效果。
当然,这是最简单的ndk程序,但万事开头难,自己动手做了才会有最真实的感受,才能慢慢理解。

浙公网安备 33010602011771号