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_$패키지명_$클래스명_$함수명 이다.
//바인딩 변수 생성할때 초기화
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//기존
//setContentView(R.layout.activity_main)
//변경 binding.root로 전달
setContentView(binding.root)
}
fun initView(){
binding.txtName.text = "Name" //사용은 기존코드에 binding. 만 앞에 추가하면 된다.
}