Android NDK

Android Native Development Kit

Java에서 C나 C++로 만든 Native 코드를 호출하기 위한 방법 중 JNI ( Java Native Interface )라고 있다.

안드로이드에서는 Native 코드를 사용하기 위해 NDK를 제공한다.

일반적인 순서는

1. Java로 Android 코드 작성(호출하고자 하는 native 함수의 signature 작성)
2. 위 자바코드를 컴파일
3. 결과물로 나온 *.class 파일을 javah 를 이용해 header 파일 생성
4. 생성된 *.h 를 이용해 *.c 나 *.cpp 로 native 코드 작성.
5. Android.mk 작성
6. ndk 에 있는 ndk-build 를 실행
7. *.so 를 포함해서 패키징(*.apk)
8. 디바이스에 설치 및 실행


그럼, 이제 환경을 구성하자.

자바를 설치한다.

구글에서 Android SDK를 검색하면 첫번째 검색되는 링크를 클릭하여 SDK를 다운로드 한다.
다운로드한 파일을 적당한 곳에 푼다.(c: 드라이브 d: 드라이브 linux라면 /home 아래든)
여기선 c:아래 압축을 풀어놓는다.

구글에서 ndk를 검색하면 제일 처음 검색되는 구글 개발자 사이트에서 ndk를 받을수 있다.
여기서 자신의 플랫폼에 맞는 kit을 다운받아야 한다.
적당한 곳에 압축을 푼다.(마찬가지로 c:에 압축을 해제)

이제 컴파일러가 필요하다. 대부분 linux를 사용하는 user는 gcc를 설치했으리라 생각한다.
윈도우에서는 cygwin 설치를 추천한다.
cygwin을 다운로드하고 develop 부분을 그냥 다 설치한다.(귀차니즘)

환경변수에서 NDK홈을 지정해준다.
보통 윈도우에서는 시스템-고급 시스템 설정(시스템 속성)-환경변수 에서 설정한다.

NDK=c:\android-ndk-r8e

cygwin 을 실행하여 프롬프트에서

echo $NDK 또는 $NDK/ndk-build  해서 잘 설정 되었는지 확인한다.

SDK에 포함되어있는 eclipse를 실행
이제 젤 위에 설명했던 1번

1. 새로운 프로젝트(myfirstndk) 생성(가상 디바이스를 사용할려면 미리 생성해둔다.)

패키지명은 com.example.mmyfirstndk

프로젝트 홈-src-com.example 등 패키지 명 아래 TestJNI.java 를 생성


package com.example.myfirstndk;

public class TestJNI {

static {
System.loadLibrary("testjni");
}
private native int testSuByJNI();

public int getSu(){
return testSuByJNI();
}
}

MainActivity 에서는 해당 클래스의 함수를 호출해준다.

TestJNI jni;
jni = new TestJNI();
jni.getSu();


2. 저장.(eclipse에서 자동으로 컴파일. bin 아래 classes 아래 패키지에 맞게 들어간다.)

3. 프로젝트 홈아래 jni 폴더를 만든다.

cygwin으로 프로젝트 홈 아래 jni 폴더로 이동한다.
(참고로 c드라이브는 /cygdrive/c 에 가상으로 마운트되있다.)

native코드를 호출하는 class파일을 복사해온다.

$ cp ../bin/classes/com/example/myfirstndk/TestJNI.class .

지금은 조금 불편하지만 패키지명에 맞도록 경로를 만들어준다.
$ mkdir -p com/example/myfirstndk

해당 경로로 class를 넣어준다.
$ mv TestJNI.class com/example/myfirstndk

이제 헤더파일을 생성하자.
$ javah com.example.myfirstndk.TestJNI

오류가 날 경우 오타, 디렉토리명을 꼭 확인하자.
$ ls
해보면 com_example_myfirstndk_TestJNI.h 를 볼수 있다.

4. 이제 native 코드를 만들자.
적당한 에디터로 (연습이니 노트패드 등 으로) c 코드를 작성한다.
(여기선 cat으로 ... 귀차니즘)
$ cat > testjni.c

#include "com_example_myfirstndk_TestJNI.h"
#include <android/log.h>
#include <unistd.h>

JNIEXPORT jint JNICALL Java_com_example_myfirstndk_TestJNI_testSuByJNI
  (JNIEnv *env, jobject jobj){
        int rs = 0;
        uid_t id;
        id = 0;

        __android_log_print(ANDROID_LOG_INFO, "-----", "AAAAA");

        rs = setuid(id);
        __android_log_print(ANDROID_LOG_INFO, "ndk", "rs: %d",rs);

        id = getuid();
                __android_log_print(ANDROID_LOG_INFO, "ndk", "uid: %d",id);

        id = getpid();
        __android_log_print(ANDROID_LOG_INFO, "ndk", "pid: %d",id);

        id = getppid();
        __android_log_print(ANDROID_LOG_INFO, "ndk", "ppid: %d",id);


        return 1;
  }

별 내용은 없다. logcat으로 로그확인을 해보자는 거다. 


5. Android.mk 를 작성한다. ( ndk에서 사용하는 Makefile 이다.)
$ cat > Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_LDLIBS      := -llog
LOCAL_MODULE    := testjni
LOCAL_SRC_FILES := testjni.c

include $(BUILD_SHARED_LIBRARY)

위 내용중 로그를 사용하지 않는다면 LOCAL_LDLIBS는 지워도 무관하다. 

6. 빌드하자. 
$ $NDK/ndk-build
Cygwin         : Generating dependency file converter script
Compile thumb  : testjni <= testjni.c
SharedLibrary  : libtestjni.so
Install        : libtestjni.so => libs/armeabi/libtestjni.so

※ 여기서 중요한 점은 이클립스의 안드로이드 프로젝트 폴더 아래에서 했다는 점이다.

7. 이클립스로 가서 프로젝트 익스플로러에서 새로고침을 해준다. 
  프로젝트의 libs 폴더에 가면 libtestjni.so 파일이 있을 것이다.

8. 디바이스를 연결하고(또는 구동하고) Run as ... Android Application 하면 끝.

이클립스의 logcat에서 로그를 확인한다.

댓글

이 블로그의 인기 게시물

C#에서 포인터 사용

WPF RichTextBox 와 Document의 바인딩

WPF 이미지위에 라인 그리기(WPF DrawLine on exist Image)