NDK는 아래 링크에서 다운로드해서 설치하면 된다.
developer.android.com/ndk/downloads
프로젝트의 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 |