Android

NDK 테스트하기

top2blue 2016. 3. 7. 16:18

1. JNI에서 사용할 java쪽 native method를 생성한다.

   사용하는 클래스에 넣어도 상관없고, 아예 JNI전용 클래스를 만들어도 상관없는데,

   중요한건 메소드에 달린 native 키워드.

package kr.example.admin.myndktest2;

public class MyNDKModule {

public native String getMessage();

}


2. Ctrl+F9나 메뉴의 Build-Make Project를 눌러 빌드를 한번 진행해둔다.

   빌드를 한번 하는 이유는, 자바 클래스 파일에서 C 헤더를 뽑아주는 

   javah가 .java 소스파일이 아닌 .class 바이트코드 파일을 참조하기 때문.


3. 소스쪽 디렉토리에 jni 디렉토리를 생성하고,

   우측버튼 - New - Folder - JNI Folder


4. 생성된 jni 디렉토리에 javah와 class파일을 이용해서 JNI .h 헤더파일을 생성한다.

   javah 명령은,

   javah -classpath 클래스패스 클래스명

   구조이다.

   

   터미널에서 

   cd app\src\main\jni

   javah.exe -classpath ..\..\..\build\intermediates\classes\debug\ kr.example.admin.myndktest2.MyNDKModule


   위와 같이 하면 jni폴더에 "kr_example_admin_myndktest2_MyNDKModule.h"파일이 생성된다.


   이제 C/C++ 파일을 만들어서 코딩한다.

   main.c

   ======================================

   #include "kr_example_admin_myndktest2_MyNDKModule.h"

   JNIEXPORT jstring JNICALL Java_kr_example_admin_myndktest2_MyNDKModule_getMessage (JNIEnv *env, jobject obj){

return (*env)->NewStringUTF(env, "Hello World - 안녕~~~");

   }


5. Build 메뉴의 Make Module 'app'를 눌러 모듈을 빌드한다.

   이 상태에서 빌드를 하면 ndk를 찾을 수 없다고 오류가 발생한다.

   

   local.properties파일의 NDK경로를 확인한다

   ndk.dir=C\:\\Users\\Administrator\\AppData\\Local\\Android\\sdk\\ndk-bundle

   sdk.dir=C\:\\Users\\Administrator\\AppData\\Local\\Android\\sdk


   gradle.properties파일을 열어 아래의 내용을 마지막줄에 추가한다.

   android.useDeprecatedNdk=true


6. Build 메뉴의 Make Module 'app'를 눌러 모듈을 다시 빌드한다.


7. 1번에서 만든 class파일을 열어 아래와 같이 수정한다.

   System.loadLibrary에서 사용되는 이름은 기본적으로 모듈 이름이다. 


package kr.example.admin.myndktest2;

public class MyNDKModule {

   static {

System.loadLibrary("app");

   }

   public native String getMessage();

}


8. 라이브러리 명 (.so파일명)을 변경하고 싶다면,

   모듈의 build.gradle 파일을 열어 moduleName을 정의해준다.


    defaultConfig {

        applicationId "kr.example.admin.myndktest2"

        minSdkVersion 16

        targetSdkVersion 23

        versionCode 1

        versionName "1.0"


        ndk{

            moduleName "MyNDKModule"

        }

    }


   moduleName을 변경하면 .so파일명도 변경되고, 

   System.loadLibrary()에 사용되는 이름도 변경해주어야 한다.


9. C에서 __android_log_print()를 사용했는데 빌드 중 오류가 발생한다면,

   android log library를 빌드에 추가해주어야 한다.

   모듈별 build.gradle에 ldLibs "log" 를 추가해 준다.

   정상적으로 로그가 출력되는것을 확인할 수 있다.


ndk{

            moduleName "MyNDKModule"

   ldLibs "log"

        }


   각 c/cpp 파일에 head 추가하고

   #include <android/log.h>


  아래의 함수를 이용하여 로그를 출력한다.

   __android_log_print("로그 타입", "로그 명", "로그 내용 및 변수 타입", 변수);


   예)

#include "NativeModule.c.h"

#include <android/log.h>

JNIEXPORT jstring JNICALL Java_kr_example_admin_myndktest2_MyNDKModule_getMessage (JNIEnv *env, jobject obj){

   __android_log_print(ANDROID_LOG_DEBUG, "JNI TEST","로그를 출력해보자");

   return (*env)->NewStringUTF(env, "Hello World - 안녕~~~");

}


10.  MainActivity를 열어 사용하는 코드를 추가한다.


        textView = (TextView)findViewById(R.id.textView);

        MyNDKModule jni = new MyNDKModule();

        textView.setText(jni.getMessage());


11. 실행한다.....


//==========================================================================================

// 위의 4번에서 터미널을 사용하는 방법이 어렵다면

  File 메뉴의 Setting으로 들어가서

  Tools의 External Tools 를 선택하고 + 기호를 눌러 외부 툴을 등록한다.

  Name : javah

  Program : 은 버튼을 눌러 JDK\bin안의 javah.exe를 선택한다.

  Parameters : -classpath $OutputPath$\ 클래스전체이름

              예) -classpath $OutputPath$\ kr.example.admin.myndktest2.MyNDKModule

  Working Directory : $ProjectFileDir$\app\src\main\jni


  위와 같이 설정하고

  프로젝트명 위에서 우측버튼 - External Tools - javah를 선택하면 헤더파일이 자동으로 생성된다.



Ndktest하기.txt


JNI JAVA와 C 의 연동.pdf