NDK는 아래 링크에서 다운로드해서 설치하면 된다.

 

developer.android.com/ndk/downloads

 

NDK 다운로드  |  Android NDK  |  Android Developers

개발 플랫폼에 맞는 NDK 패키지를 선택합니다. NDK 최신 버전 및 이전 버전의 변경사항에 관한 정보는 NDK 버전 기록을 참조하세요. macOS용 공증된 NDK가 필요하다면 ZIP 파일이 아닌 App Bundle을 다운

developer.android.com

프로젝트의 local.properties에 경로를 설정해주면 된다. 

 

ndk.dir=/Users/계정/Library/Android/sdk/ndk
sdk.dir=/Users/계정/Library/Android/sdk

 

NDK 모듈은 보통 c++로 작성된 라이브러리를 사용하거나 보안을 위해서 사용하곤 한다.

JNI(Java Native Interface)는 자바기반의 클래스에서 Native 코드에 접근하기 위한 인터페이스이다.

 

Java <-> JNI <-> C/C++


이제 NDK 모듈을 추가해보자.

 

스튜디오의 File -> New -> New Module ... 메뉴를 선택한다.

 

 

모듈 타입을 정하는 화면이 나오는데 Android Library 를 선택하고 Next 버튼을 클릭한다.

모듈명, 패키지명을 적절히 입력하고 Finish를 클릭하면 모듈이 생성된다.

 

모듈의 main 폴더를 우클릭하고 신규 디렉토리를 생성한다.

 

새 디렉토리 이름은 jni를 입력하고 Enter 키를 누른다. 보통 jni 폴더를 생성해서 cpp나 mk 파일을 그 폴더 내부에 넣는다.

 

이제 make 파일을 생성하자.

jni 폴더를 우클릭하고 새 파일을 생성한다. 

 

 

 

Android.mk 내용

#소스파일 위치: 현재 디렉터리
LOCAL_PATH := $(call my-dir)

#동일한 변수가 중복 사용되는 것을 방지
include $(CLEAR_VARS)

#모듈 이름
LOCAL_MODULE    := crypto
#소스파일 목록(c, cpp)
LOCAL_SRC_FILES := crypto.cpp

#LOCAL_CPPFLAGS := -fexceptions
#LOCAL_DEFAULT_CPP_EXTENSION := cpp
#LOCAL_LDLIBS += -llog

#빌드적용. 이게 정의 안되면 빌드할 모듈이 없다고 함
include $(BUILD_SHARED_LIBRARY)

아래 파일은 컴파일시 추가적으로 설정이 필요할때 사용한다. 없어도 무관..

Application.mk

#NDK 프로젝트 위치
#APP_PROJECT_PATH
#모듈이름
#APP_MODULES

#debug, release(기본)
APP_OPTIM := debug

#C소스 컴파일 플래그
#APP_CFLAGS
#C++소스 컴파일 플래그
#APP_CXXFLAGS
#C/C++ 컴파일 플래그
APP_CPPFLAGS := -frtti -fexceptions

#지원할 ABI, 모두는 all
APP_ABI := arm64-v8a armeabi-v7a

#사용할 library
APP_STL := c++_static

#APP_PLATFORM := android-29
NDK_TOOLCHAIN_VERSION := clang

#특정 Android.mk를 지정. 기본은 jni 밑에 Android.mk 파일 사용.
#APP_BUID_SCRIPT

 

자바 클래스를 생성한다.

public class Crypto {

	//crypto.cpp 에 정의할 함수, native 키워드가 붙는다.
    public static native byte[] getKey();

    static {
    //라이브러리 로딩, LOCAL_MODULE에 작성한 이름(so 파일명 앞에 lib만 제거된 이름과 동일)
        System.loadLibrary("crypto");
    }
}

 

이제 c/c++ 함수를 작성할 소스파일( cpp) 파일을 생성한다.

jni 폴더를 우클릭하고 C/C++ Source File을 클릭한다.

 

cpp 소스파일에 테스트할 코드를 간단히 작성한다.

 

함수명 작성 규칙은 JNIEXPORT $리턴타입 JNICALL Java_$패키지명_$클래스명_$함수명 이다.

리턴타입은 JNI 타입인데 자바에서 사용하는 데이터 타입 앞에 j를 붙인다.

byte -> jbyte

배열은 뒤에 Array를 붙인다. jbyteArray

 

패키지명은 현재 NDK 모듈의 패키지명이다. 

클래스명은 위에서 생성한 자바 클래스 명이다. 함수명은 자바 클래스에 정의된 함수명이다.

자바클래스와 cpp 함수간에 규약이 맞지 않으면 오류로 표시된다.

#include <jni.h>
  
  const char key[] = {
		0x10, 0x12, 0x49, 0x51,
		0x55, 0x48, 0x76, 0x5F,
		0x65, 0x6A, 0x6C, 0x33,
		0x6E, 0x6K, 0x77, 0x44
	};
    
  extern "C"
  
  JNIEXPORT jbyteArray JNICALL Java_com_test_cryptolib_Crypto_getKey(
		JNIEnv* env, jobject){
    jbyteArray array = env->NewByteArray(16);

    jbyte *bytes = env->GetByteArrayElements(array, 0);
    for(int i =0; i < sizeof(key); i++){
        bytes[i] = key[i];
    }
    env->SetByteArrayRegion(array, 0, 16, bytes);

    env->ReleaseByteArrayElements(array, bytes, 0);

    return array;
  }

$cd src/main

이 폴더에서 빌드하지 않으면 Your APP_BUILD_SCRIPT points to an unknown file: 오류가 발생한다.

 

이제 빌드를 하면...

$ndk-build

 

src/main/libs 폴더에 APP_ABI 에 정의한 이름( arm64-v8a, armeabi-v7a) 으로 폴더별로 so 파일이 생성된다.

 

 

생성된 so 파일들은 사용할 프로젝트의 src/main/jniLibs/ 폴더에 복사한다. 폴더구조는 그대로 유지한다.

src/main/jniLibs/arm64-v8a, src/main/jniLibs/armeabi-v7a 

 

이제 라이브러리를 사용할 자바 클래스를 생성한다. 패키지 경로는 NDK 모듈의 경로를 그대로 사용해야 한다. 

위에서 생성한 자바 클래스를 패키지 경로 그대로 복사하도록 한다.

 

 

사용할때는 Crypto.getKey(); 처럼 호출하면 된다.

 

'개발 > Android' 카테고리의 다른 글

TextView 에 이미지 포함하기  (0) 2021.08.26
풍선도움말 레이아웃 구현  (1) 2021.03.24
ViewBinding  (0) 2021.02.25
Android Studio Rename Package  (0) 2021.02.24
Appium 설치  (0) 2021.02.17
Posted by Lumasca
,