
NDK/JNI는 안드로이드 시스템/네이티브 성능 최적화 분야에서 필수로 쓰인다.
미러링처럼 초당 수십 장의 이미지를 압축하고, 전송해야 하는 작업은 Java나 Kotlin이 아닌 C나 C++ 같은 네이티브 언어를 사용한다.
NDK와 JNI는 코틀린/자바와 C/C++을 연결해주는 기술이다.
안드로이드 앱에서 C/C++ 코드를 사용할 수 있게 해주는 개발 도구 모음.
C/C++ 코드를 안드로이드 앱에서 실행 가능한 형태로 컴파일, 빌드하는데 필요한 모든 것을 담고 있는 툴킷
주로 아래와 같은 경우에 사용된다
성능 최적화
높은 성능이 필요한 작업에 c/c++로 구현
ex) 영상 처리, 게임, 복잡한 연산
기존 라이브러리 재사용
이미 c/c++로 만들어진 라이브러리 (ex. H.264 코덱 라이브러리)를 그대로 가져와 안드로이드 앱에 활용
하드웨어 직접 제어
특정 하드웨어 장치에 더 가깝게 접근해야 할 때
자바/코틀린 코드와 c/c++ 네이티브 코드 간의 다리 역할을 하는 인터페이스
NDK가 개발 환경이라면,
JNI는 두 언어가 서로 호출하고 데이터를 주고받을 수 있도록 하는 규칙인 것.





c++로 작성된 네이티브 코드

익숙한 코틀린 코드에서의 네이티브 함수를 호출하는 파일

앱을 실행해 보면 native-lib.cpp의 stringFromJNI() 함수가 반환한 값을 MainActivity에서 받아서 화면에 띄우는 것을 볼 수 있다.
/**
* A native method that is implemented by the 'hellondk' native library,
* which is packaged with this application.
*/
external fun stringFromJNI(): String
external 키워드를 통해 네이티브 함수(C++ 라이브러리) 와 연결할 것임을 선언한다.
companion object {
// Used to load the 'hellondk' library on application startup.
init {
System.loadLibrary("hellondk")
}
}
라이브러리를 로딩하는 코드이다.
앱이 시작될 때 C++로 작성된 libhellondk.so 파일을 메모리에 올린다.
로드될 라이브러리 이름은 CMakeLists.txt 에서 지정된 이름을 사용한다.
// Example of a call to a native method
binding.sampleText.text = stringFromJNI()
이렇게 호출하여 사용한다.

먼저, MainActivity에서 호출할 함수 인터페이스 마냥 선언해서 만들어주고, 자동 생성 눌러주면

C++ 함수를 만들어준다.
저 긴긴 네이밍을 직접 쓰지 않아도 된다.
Java_com_hwiwon_hellondk_MainActivity_addNumbers()
Java_com_hwiwon_hellondk_MainActivity_addNumbers(JNIEnv *env, jobject thiz, jint a, jint b)
마지막 2개의 a, b 파라미터는 실제 매개 변수라 그렇다 쳐도, *env, thiz는 뭘까?
JNI 환경 포인터. C++ 함수가 자바 가상머신 JVM과 소통할 수 있는 통로이다.
이 포인터가 없으면, C++ 코드는 자바의 클래스나 객체에 접근할 수 없다.
이 네이티브 함수를 호출한 Java/Kotlin 객체 자체를 가리키는 레퍼런스
C++에서 this와 비슷
인스턴스 메소드의 경우
thiz는 MainActivity의 특정 인스턴스를 가리킨다.
해당 MainActivity가 가진 변수나 함수에 c++에서 접근할 수 있다.
정적 메소드의 경우
jobject 대신 jclass 타입이 온다.
해당 함수를 호출한 클래스 자체를 가리킨다.