ndk-build를 이용한
Native Code 빌드 및 사용방법
다음과 같은 이유로 Android App에서 Native Code(C/C++등)로 코드를 작성하여 사용해야 할 경우가 존재합니다.
- 처리 속도 및 성능향상
- C/C++로 만들어진 코드 재사용
- Native Code로만 개발 가능한 기능 구현등
본 포스팅에서는 Android Studio에서 Native Code를 작성하고 빌드하는 방법에 대해 "최대한 많은 스크린 샷"을 통해 설명하고자 합니다.
작성 예제는 Native코드를 포함한 라이브러리(ndklib)와 이 라이브러리를 사용하는 app(ndklibdemo)으로 모듈을를 구분하여 작성 하도록 하겠습니다.
프로젝트 및 라이브러리 생성
1. 프로젝트 생성
2.라이브러리 모듈생성
[File>New>New Module..] 메뉴를 통해 새로운 라이브러리 모듈 추가
(Native Code가 작성될 모듈입니다.)
Native Code 빌드를 위한 툴킷 설치
1. NDK 설치
1) [Tool>SDK Manager] 메뉴를 통해 프로젝트 설정 창을 열고 [SDK Tools]탭을 선택후,
[NDK] 항목을 체크해서 설치합니다.
(1) Android NDK는 Native Development Kit의 약자로, C / C++과 같은 Native 언어를 사용하여 앱의 일부를 구현할 수있게 해주는 개발 툴킷입니다.
NDK 빌드환경 구성 및 코드 작성
1. C/C++ 소스 폴더 생성
1) 프로젝트 표시창의 뷰타입을 "Project"로 변경 후,
ndklib 라이브러리의 [ src/main ] 하위에 jni 폴더를 생성합니다.
2. NDK 빌드환경 구성
1) [File>Setting] 메뉴을 통해 설정 다이얼로그를 연후, [Tool>External Tools] 항목을 선택합니다.
2) NDK Group에 세가지 환경을 추가합니다. 각각의 역할은 아래와 같으며 각 설정방법은 아래에 기술합니다.
(1) ndklib-javah
- Java Class를 기반으로 Jni규격에 맞게 헤더파일을 생성해주는 역할
(2) ndklib-build
- Native(C/C++) 코드를 빌드하는 구성
(3) ndklib-clean
- Native(C/C++) 코드의 빌드 결과물을 지워주는 구성
3) [ + ] 버튼을 눌러 각 구성을 추가합니다.
1) ndklib-javah
(1) Group: NDK
(2) Program: javah.exe의 경로를 적어 줍니다.
$JDKPath$\bin\javah.exe |
(3) Arguments: javah.exe 실행시 전달되는 파라미터 입니다. 그냥 아래 내용대로 적어 줍니다.
-classpath "$Classpath$" -v -jni $FileClass$ |
(4) Working directory: Native Code 소스파일을 작성할 폴더 경로를 적어 줍니다.
D:\Git-Repos\Android\ndklibdemo\ndklib\src\main\jni |
- 위에서 생성한 jni폴더를 지정합니다.
- 지정한 경로에 헤더파일 생성됩니다.
2) ndklib-build
(1) Group: NDK
(2) Program: ndk-build.cmd의 경로를 적어 줍니다.
C:\Users\unodi\AppData\Local\Android\Sdk\ndk-bundle\ndk-build.cmd |
(3) Working directory: Library module의 src/main 폴더 경로를 적어 줍니다.
D:\Git-Repos\Android\ndklibdemo\ndklib\src\main |
(3) ndklib-clean
(1) Group: NDK
(2) Program: ndk-build.cmd의 경로를 적어 줍니다.
C:\Users\unodi\AppData\Local\Android\Sdk\ndk-bundle\ndk-build.cmd |
(3) Arguments:
clean |
(4) Working directory: Library의 main 폴더 경로를 적어 줍니다.
D:\Git-Repos\Android\ndklibdemo\ndklib\src\main |
Native Code 작성
1. Native Wrapping Java Class 작성
1) [라이브러리>java>패키지]에 Native API를 Wrapping하는 Java Class를 작성합니다.
2) 생성된 Wrapping class에 라이브러리를 로드하는 기본 코드를 구현합니다.
static { System.loadLibrary("ndklib"); } "ndklib"부분은 생성된 라이브러리의 이름을 기술 합니다. |
public native int nativeSum(int a, int b); native로 구현할 함수의 원형을 기술 합니다. 이 선언을 기반으로 javah가 Jni규격에 맞는 함수명을 생성하게 됩니다. |
2. Native 코드 작성
1) Header 파일 생성
위에서 생성한 클래스에서 오른쪽 마우스를 누른후, [NDK>ndklib-javah] 메뉴를 선택해서 헤더파일을 생성합니다.
아래와 같이 class파일을 찾지 못한다고 표시되는 경우, 프로젝트를 한번 빌드한후 다시 시도합니다.
정상적으로 수행되면 아래와 같이 *.h 파일이 생성됩니다.
생성된 header파일은 [jni] 폴더에서 확인 할 수 있습니다.(ndklib-javah 환경 구성에서 지정한 경로 입니다.)
2) cpp 파일 구현
헤더파일이 위치한 [jni]폴더에 cpp파일을 생성하여 함수내용을 구현합니다.
#include "com_thirteenrain_ndklib_NativeWrapper.h" JNIEXPORT jint JNICALL Java_com_thirteenrain_ndklib_NativeWrapper_nativeSum (JNIEnv *env, jobject obj, jint a, jint b) { return a+b; } |
Gradle연동
1. android.mk 생성
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := ndklib FILES := NativeSum.cpp LOCAL_SRC_FILES := $(FILES) LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY) |
"ndklib" - 라이브러리 이름을 기술합니다. NativeSum.cpp - 빌드할 CPP 파일을 기술합니다. |
2. NDK build - gradle 연동
1) Java Wrapping Class를 오른쪽 클릭하여 NDK Build를 Gradle과 연동합니다.
(1) Build System: ndk-build
(2) project Path: 위에서 생성한 Android.mk를 선택합니다.
이 작업을 통해 ndklib 모듈의 gradle에 NativeBuild 구문이 추가되어, Gradle빌드시 ndkBuild가 함께 진행되도록 설정됩니다.
android { externalNativeBuild { ndkBuild { path file('src/main/jni/Android.mk') } } } |
이상으로 Native Code 라이브러리 생성을 위한 설정이 완료되었습니다.
Native Code Library Build
1. Java Wrapping Class 우클릭 > NDK > ndklib-build 메뉴를 통해 Native Code를 빌드 할 수 있습니다.
2. ndklib/src/main/libs 하위에 라이브러리 파일(*.so)이 생성됩니다.
Native Library 사용
1. 코드 작성
1) 테스트를 위해 MainActivity의 onCreate 메소드에 ndklib의 NativeWapper.nativeSum을 호출하는 코드를 삽입합니다.
NativeWrapper nativeApi = new NativeWrapper(); int result = nativeApi.nativeSum(5, 10); |
2. dependency 추가
1) [Alt+Enter] 단축키로 ndklib에 대한 dependency를 추가해 줍니다.
2) ndklib에 대한 dependency가 추가되었습니다.
디버깅
1) 디버깅 Tool설치
(1) LLDB
: Native Debugging을 위해서는 LLDB를 설치해야 합니다.(LLDB는 Android Studio에서 사용하는 Native Debugger입니다.)
2) Debug type
(1) Debug type이 [java]로 설정되어 있으면 Native Code에 대한 디버깅이 되지 않습니다.
: Java - Java Code만 디버깅 합니다.
: Auto - 디버깅 대상을 자동으로 판단합니다.
: Native - Native Code만 디버깅 합니다.
: Dual - Java, Native 둘다 디버깅 합니다.
실행확인
1) cpp 소스에 중단점을 설정합니다.
2) 툴바의 디버그 버튼 혹은 [Shit+F9] 단축키를 눌러 디버그를 진행합니다.
3) 중단점에 적중되어 Native Code 디버깅이 가능합니다.
'안드로이드' 카테고리의 다른 글
native code에서 java class에 접근과 android 난독화(proGuard) (0) | 2020.07.16 |
---|---|
Realeas 모드 디버깅 세팅 (0) | 2020.07.16 |
CardView (0) | 2019.04.09 |
View의 background 속성을 이용해 View의 모양 변경하기 (0) | 2019.04.04 |
Error type 3: Activity class {com.x.y.MainActivity} does not exist. (1) | 2019.04.03 |