OSX上Android NDK的安装与使用

安装

在OS X上安装是格外简单的,在配置好ADT之后,只要在http://developer.android.com/tools/sdk/ndk/index.html下载mac对应版本就可以了。

之后为了省事,记得在$PATH里面添加ndk的安装路径。

使用

编译

这里采用一个最傻瓜的作法,先创建一个类,标明你要使用的api。例如:

1
2
3
4
5
package la.tietie.helloworld;

public class LabelText {   
  public static native String getText();
}

然后不要添加任何内容了。

在命令行下,cd到 project/src, 输入

1
javac la/tietie/helloworld/LabelText.java

这时候就会生成一个 与 LabelText.java 同名的 class文件

然后输入

1
javah -jni la.tietie.helloworld.LabelText

之后在src 目录下可以看到一个.h文件, 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class la_tietie_helloworld_LabelText */

#ifndef _Included_la_tietie_helloworld_LabelText
#define _Included_la_tietie_helloworld_LabelText
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     la_tietie_helloworld_LabelText
 * Method:    getText
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_la_tietie_helloworld_LabelText_getText
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

在工程目录下,建立jni文件夹,将头文件拖进去。 然后新建一个叫做Android.mk的文件,此文件是NDK的makefile 文件。

里面填入

1
2
3
4
5
6
7
8
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := LabelText
LOCAL_SRC_FILES := LabelText.cpp

include $(BUILD_SHARED_LIBRARY)

之后在 cpp 里面填上代码 就可以了。可以这样:

1
2
3
4
5
6
7
8
9
10
#include <LabelText.h>
#include <jni.h>
#include <stdlib.h>
#include <string.h>

JNIEXPORT jstring JNICALL Java_la_tietie_helloworld_LabelText_getText
  (JNIEnv* env, jclass)
{
  return env -> NewStringUTF("hello world");
}

最后cd到工程目录下,输入ndk-build,如果代码正确的话,就会在工程的libs/armeabi/下出现你的so文件。

使用

在原来的那个类上添加代码到如下所示

1
2
3
4
5
6
7
8
9
10
package la.tietie.helloworld;

public class LabelText {
  static
  {
      System.loadLibrary("LabelText");
  }
  
  public static native String getText();
}

然后直接用那个写好的类就好了。

注意

  1. 用编译的class文件生成cpp文件有个不足的地方,如果文件依赖于 android的一些库文件,那么你就要自己手动在javac后面链接它。其实无所谓,不管传入什么类,ndk都会解析为jobject。

  2. 如果在ndk内部使用了Android 的库 例如 图像库,例如 log 库 需要在mk文件中声明。例如添加

    LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog -ljnigraphics

    即可调用Android/log.h 和 Android/Bitmap.h

  3. 如果头文件是手写的,没有用生成且是cpp语言的话,记得在头文件中加上标记 extern “C” {}。

  4. 调用的c的函数名,一定要与包名类名一致!否则会报找不到函数名的问题
  5. ndk下崩溃了是没有任何exception的,要勤写log。

Comments