Android+NDK 入门备忘 Ubuntu 11.10


开始使用 Android NDK 进行开发,NDK 的主要原理还是 JNI 技术,这一技术实现了 Java代码和 C/C++代码间的相互调用,这样做的好处是:首先,将一些比较耗时的操作放到底层来实现,毕竟C和C++的效率高比Java高,并且指针是可以加快程序的运行速度;其次. 在C语言领域,已经有很多成熟的类库和框架,使用NDK后,可以直接使用他们,因而避免再用Java去重复制造轮子。

Android NDK的开发,需要Linux的编译环境,所以建议直接装个Linux系统,在上面进行Android开发,当然也可以使用虚拟机来代替,不过个人觉得虚拟机始终不伦不类,还是真正的Linux环境比较顺手。

使用NDK时的大致步骤如下:

1.  新建一个Android 工程,在里面新建一个jni 文件夹,专门用来存放 C 语言程序和Android.mk 文件;

2.  在java文件中编写一个 native 函数:

 
  1. package tangyuchun.ndk.hellojni;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.widget.TextView;  
  6.   
  7. public class HellojniActivity extends Activity {  
  8.     static {  
  9.         System.loadLibrary("hello-jni");  
  10.     }  
  11.   
  12.     public void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.   
  15.         TextView tv = new TextView(this);  
  16.         tv.setText(getString());// 调用了native方法   
  17.         setContentView(tv);  
  18.     }  
  19.   
  20.     public native static String getString();  

这里是一个简单的Activity界面,里面定义了一个 getString()方法,用来获取一个字符串。
 
3.  打开终端,使用 javah -classpath 命令编译 bin/classes 下生成的 .class文件。我的命令如下:

javah -classpath /home/administrator/android_code/hello-jni/bin/classes tangyuchun.ndk.hellojni.HellojniActivity 

也可以在src的 .java 源代码中使用同样的命令:

 javah -classpath /home/administrator/android_code/hello-jni/src tangyuchun.ndk.hellojni.HellojniActivity  

记得在前面要加上包名(我的是在tangyuchun.ndk.hellojni 这个包下面)。

4.  经过第3步后,就会在该类目录下生成一个 .h 的头文件(Ubuntu也有可能生成在主文件夹下面),名字为

tangyuchun_ndk_hellojni_HellojniActivity.h,打开这个头文件,内容如下:

 
  1. #include <jni.h>   
  2. /* Header for class tangyuchun_ndk_hellojni_HellojniActivity */  
  3.   
  4. #ifndef _Included_tangyuchun_ndk_hellojni_HellojniActivity   
  5. #define _Included_tangyuchun_ndk_hellojni_HellojniActivity   
  6. #ifdef __cplusplus   
  7. extern "C" {  
  8. #endif   
  9. /* 
  10.  * Class:     tangyuchun_ndk_hellojni_HellojniActivity 
  11.  * Method:    getString 
  12.  * Signature: ()Ljava/lang/String; 
  13.  */  
  14. JNIEXPORT jstring JNICALL Java_tangyuchun_ndk_hellojni_HellojniActivity_getString  
  15.   (JNIEnv *, jclass);  
  16.   
  17. #ifdef __cplusplus   
  18. }  
  19. #endif   
  20. #endif 

5.  看到里面有一个函数: JNIEXPORT jstring JNICALL Java_tangyuchun_ndk_hellojni_HellojniActivity_getString(JNIEnv *, jclass);

这个方法就与第2步的getString()对应。

6.  在jni 文件夹中新建一个 c语言文件,我的是 hello-jni.c ,include相应的头文件,然后将第4步中的那个方法复制,完成该方法:

 
  1. #include <string.h>   
  2. #include <stdio.h>   
  3. #include <android/log.h>   
  4. #include <stdlib.h>   
  5. #include <jni.h>   
  6.   
  7. JNIEXPORT jstring JNICALL Java_tangyuchun_ndk_hellojni_HellojniActivity_getString(  
  8.   JNIEnv *env, jclass thiz) {  
  9.  return (*env)->NewStringUTF(env, "Some say love");  
  10.         //这里只是做个样例,所以只让他返回一段字符串 "Some say love"   

注意,要给方法添加参数,头文件中只是声明,并没有实参。
 
7.  同样,在 jni 文件夹下面新建一个 Android.mk 文件,内容如下:

 
  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_MODULE    := hello-jni  
  6. LOCAL_SRC_FILES := hello-jni.c  
  7.   
  8. include $(BUILD_SHARED_LIBRARY)  

那个LOCAL_MODULE 就是将要生成的.so 文件名,LOCAL_SRC_FILES就是第6步中编写的 .c 文件。

8.  保存上述文件,打开终端,定位到工程的目录下的jni 文件夹,在终端输入: ndk-build 命令,回车。

9.  返回到工程文件夹下,就会看到生成了两个文件夹 libs 和 obj,其中 libs/armeabi/ 文件夹下面就有 一个libhello-jni.so文件,这

个.so文件其实就是用来在android中调用C语言的类库;

10. 在Android虚拟机上运行上面建立的工程,如下所示:

相关内容