Hyun Chul's Utopia

NDK 개발환경 구축 및 간단한 예제 본문

프로그래밍/Android

NDK 개발환경 구축 및 간단한 예제

디프시다루핀 2014. 4. 24. 13:58

 NDK를 사용해 보려고 했으나.. 개발환경 구축조차 안했더군요.. 그래서 많은 분들의 블로그 및 게시물들을 참고하여 개발환경 구축이 완료 되었고.. 간단히 정리해 보았습니다.


개발환경 구축하기..


1. 기본적인 Android개발환경 구축 

  - Eclipse, ADT 등등.. 의 기본적인 항목이 구축 되어 있어햐 합니다.


2. NDK 다운로드.

 - 구글 개발자 페이지에서 다운 받습니다. (r9 버젼의 경우.. 450 MB 정도 되었던것 같음..)

 - http://developer.android.com/tools/sdk/ndk/index.html#Downloads

 - 다운속도.. 쫌 느립니다..

 - 다운로드 완료후 적당한 경로에 압축 해제해 줍니다.. (가능하면 한글 & 공백이 포함되지 않은 경로를 추천합니다.)

 - 압축 해제한 경로를 환경변수에 등록해 줍니다.


3. Cygwin 다운로드

 - Windows환경에서 Linux처럼 사용할 수 있는 가상의(?) 환경을 만들어 주는 프로그램 입니다.

 - 설치파일을 다운로드 받습니다.

 - http://cygwin.com/

 - 설치 파일은 용량이 매우 작지만.. 실제 설치는.. 엄청나게 오래 걸립니다.


4. Cygwin 설치

 - 구지 설치 항목을 따로 둔것은.. 좀.. 까다로운(?)게 있어서... 입니다..

 - 설치될 경로, 다운로드 받을 경로 등을 정하고 '다음'버튼을 눌러 줍니다.

 - 실제 설치는 인터넷을 통해 파일을 다운로드 받으면서 진행되도록 되어 있습니다.

   - 이 과정에서 Download받을 사이트를 정하게 되어 있는데요.. KAIST쪽은.. 잘 안되는것 같고.. JAIST(일본)이쪽은 되긴 되는데 좀 느리고.. 그래서 찾은게 Daum 입니다.

   - 다운받을 미러 서버 (다음)  : http://ftp.daum.net/cygwin

   - 항상 오픈소스 배포에 힘써주는 Daum형님 감사합니당.. 

 - 패키지 선택하는 항목이 전부 'Default'로 되어 있으나.. 편의를 위해 Debug, Devel, Editors의 모든 파일은 Install로 설정 합니다.

 - 설치는 진심.. 개.. 느립니다.. 인내를 가지셔야 합니다.. (설치된 경로를.. 보니.. 사용된 공간은.. 약 17.7 GB이고.. 파일 갯수는 24만개 정도 됩니다..;;;)

 - 설치가 완료후 실행 시키면 대략 이런 화면을 확인할 수 있습니다.




예제 만들어 보기


예제는 Eclipse에서 진행


1. Android 프로젝트 생성

 - 새로운 Android 프로젝트를 생성 합니다.


2. JNI코드 작성.

 - NDK를 이용하기 위한 코드를 작성합니다.

 - 해당 프로젝트 내의 src쪽에 작성하면 될듯 합니다.

 - 간단 코드 예제..


JNITest.java

public class JNITest {
    static{System.loadLibrary("testlib");}
	
    private native void ndk_test();
    private native int add(int first, int second);

    public int addNumber(int first, int second){
        return add(first, second);
    }
}


3. JNI코드 컴파일

 - 앞서 설치한 Cygwin을 실행 합니다.

 - 방금 작성한 예제파일 (JNITest.java)가 있는 경로로 진입 합니다.

   - 기본적으로 Cygwin을 실행하면 기본 경로가 User의 Home 경로로 되어 있습니다. 

   - 만약 이 밖의 경로에 진입하고 싶을 경우.. root경로에서 '/cygdrive/드라이브명' 으로 진입하시면 됩니다.

 - 'javac JNITest.java' 명령어 실행 --> 결과물로 'JNITest.class' 파일이 생성됨.

 - src 경로에서 'javah -d ../jni 패키지명.JNITest' 명령어 실행 --> 결과물로 해당 ../jni 경로에 해당 JNITest의 .h 헤더파일이 생성됩니다.

 - 생성된 헤더 파일의 내용..



 - 생성된 .h 헤더파일에 대한 코드를 작성 합니다.

   - 헤더파일이 있는 곳에 jni_test.c 파일 생성.

   - jni_test.c

// jni_test.c
#include
#include "com_tistory_darphin_ndktest_JNITest.h"

JNIEXPORT void JNICALL Java_com_tistory_darphin_ndktest_JNITest_ndk_1test 
(JNIEnv *pEnv, jobject pThis)
{
	return 10;
}

JNIEXPORT jint JNICALL Java_com_tistory_darphin_ndktest_JNITest_add 
(JNIEnv *pEnv, jobject pThis, jint n_first, jint n_second)
{
	return n_first + n_second;
}

 - 생성된 jni폴더에 'Android.mk' 파일 생성

- Android.mk

LOCAL_PATH	:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE	:= testlib
LOCAL_SRC_FILES	:= jni_test.c

include $(BUILD_SHARED_LIBRARY)

 - 'Android.mk' 파일의 작성이 끝나면.. 해당 경로에서 'ndk-build' 명령어 실행

 - 대충.. 이런 메세지들이 출력되면서 컴파일이 진행됨.

$ ndk-build

Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 8 in /cygdriveXXXXXXXXXX/Workspace/NdkTest/AndroidManifest.xml

[armeabi] Compile thumb  : testlib <= jni_test.c

D:/XXXXXXXXXX/Workspace/NdkTest/jni/jni_test.c: In ndktest_JNITest_ndk_1test':

D:/XXXXXXXXXX/Workspace/NdkTest/jni/jni_test.c:6:2: function returning void [enabled by default]

[armeabi] SharedLibrary  : libtestlib.so

[armeabi] Install        : libtestlib.so => libs/armeabi/libtestlib.so


 - 위의 과정을 거치고 나면 대략 이런 상태의 파일들이 존재 합니다.



4. 1번 과정에서 만들었던 Android 프로젝트에.. 간단히 코드를 작성합니다.

- JNITest 클래스를 통해서.. 방금 만든 libtestlib.so파일을 사용할 수 있습니다.

 - MainActivity.java


import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {
	
    TextView tvMain;
    JNITest myJni;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
	
        tvMain = (TextView)findViewById(R.id.tv_main);
	
        myJni = new JNITest();
        String strText = "Add Result : " + myJni.addNumber(500, 10000);
        tvMain.setText(strText);
    }
}


Comments