JNI 프로그램 작성을 위한 개발 환경 셋팅
- JNI를 사용하기 위해서는 윈도우즈와 리눅스에서 개발환경을 셋팅할 수 있다.
- 리눅스와 윈도우즈 둘의 차이점은 cygwin 설치 밖에 없음.
- Android SDK, Android NDK, Cygwin 프로그램이 시스템에 설치되었고 ADT가 Eclipse에 설치되었다면 Android 프로젝트에서 JNI(Java Native Interface)를 이용하여 C, C++언어에서 작성된 공유 라이브러리(*.so)를 로드하고 포함된 함수를 호출할 수 있는 프로그램을 작성할 수 있다.
리눅스에서의 개발환경 셋팅
- Linux용 이클립스 다운로드
- JDK 설치 http://www.java.com 에서 jdk 다운로드
- .bin 파일 실행권한 주기 chmod 555 ~.bin
- 설치하기 ./~.bin
- 환경설정 /etc/profile 수정 >> export JAVA_HOME=/usr/java/jre1.6.0/bin
- 적용하기 source /etc/profile
- 이클립스 실행하기 - ./eclipse -vm /usr/java/jre1.6.0.21/bin/java
- Eclipse Android SDK install
- SDK 다운로드
- Install the ADT Plugin for Eclipse >> https://dl-ssl.google.com/android/eclipse/
- Android NDK
- 이클립스에 NDK 빌드 연동하기
윈도우즈에서의 개발환경 셋팅
Cygwin 설치
- Cygwin 이란 ? 윈도우 시스템에서 Linux와 비슷한 환경을 만들어주는 프로그램
- Cygwin 홈페이지 : http://www.cygwin.com/
- Cygwin Dowload setup.exe 파일을 다운받아 실행
- Cygwin 설치방법
- setup.exe 파일 실행 - install from internet 선택
- Root 경로 지정 & install For All Users
- Download 받을 패키지가 저장될 경로 지정(Select Local package Directory)
- Internet 연결 - Direct connection 선택
- Download Site 선택 - ftp://ftp.kaist.ac.kr
- Progress - 패키지 목록을 가져옴 --> 처음 설치할 경우 설치할 패키지를 선택할 수 있다는 알림창 뜸
- 설치할 수 있는 패키지 목록이 대화창에 출력됨, 필요한 것 선택 Devel/gcc-g++, Devel/gcc-core, Devel/make, Editor/vim
- 시작메뉴에 Cygwin Bash Shell 메뉴 생성된 것 확인 . 설치 완료
Android NDK 설치
- NDK Download 받기
- URL : http://developer.android.com/sdk/ndk/index.html
- Android developers 사이트에 가면 SDK 페이지 좌측에 메뉴에 Native Development Tools 메뉴에서 NDK 선택
- Download the Android NDK 에서 자신의 개발환경에 맞는 OS 선택 - 이 페이지의 설명은 Windows 기반임.
- Download the Android NDK Webpage
- NDK 설치하기
- 다운로드 받아서 Path만 지정해주면 NDK를 사용하기 위한 절차는 끝
Hello JNI Example
- NDK 설치가 끝나면 테스트해보기 위한 Sample Code가 있다. Sample Code 중 HelloJni를 구동하는 절차를 설명한다.
- 윈도우즈 환경 셋팅에서 설치한 cgywin을 사용하여 NDK 빌드를 할 수 있다.
NDK 빌드
- Cygwin Bash Shell 을 실행해서 android-ndk-r4 폴더로 이동
Hello Jni 실행
- Android NDK에서 제공하는 Sample code는 원시코드의 헤더파일이 이미 만들어져있기 때문 NDK 빌드만 하면 에뮬레이터로 결과를 확인할 수 있다.
HelloJni Sample Code
- NDK에 포함되어 있는 샘플 코드는 원시코드의 헤더파일이 이미 만들어져있으나, 샘플코드를 기반으로 헤더파일을 만들고 JNI 프로그램을 작성하는 절차를 설명하도록 한다.
안드로이드 프로젝트 생성
자바 클래스 작성
- JNI 규칙에 따라서 공유라이브러리를 로드하고 라이브러리에 포함된 함수를 호출하는 native 메소드를 선언한다.
- HelloJni.java
package com.example.hellojni; import android.app.Activity; import android.widget.TextView; import android.os.Bundle; public class HelloJni extends Activity { /**Called when the activity is first created.*/ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv= new TextView(this); tv.setText(stringFromJNI()); // A native 함수호출 setContentView(tv); } // A native function public native String stringFromJNI(); // 정의하지 않은 함수 호출시 java.lang.UnsatisfiedLink Errorexception 발생! public native String unimplementedStringFromJNI(); // com.example.HelloJni/lib/libhello-jni.so static { System.loadLibrary("hello-jni"); } }
- Native Method Declaration : public native String stringFromJNI();
- Native 선언은 자바 가상 머신 내에서 원시 함수를 호출할 수 있는 브릿지를 제공해 준다.
- 라이브러리 적재 : System.loadLibrary()
- 원시 코드 구현을 포함하고 있는 라이브러리는 System.loadLibrary()를 호출함으로써 적재된다. 정적 초기화 구문(static initializer ensures) 내에서 이 호출을 함으로써, 클래스당 단 한번만 적재되도록 한다. 클래스에 대해 공유되는 멤버들은 static을 이용하여 선언한다. 클래스 멤버를 선언하는 위치에 static{....} 과 같이 초기화 블럭을 정의하여 사용할 수 있다.
- main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/textView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
헤더파일 작성과 프로그램 컴파일
- 프로그램 컴파일은 command line을 이용하므로 앞에서 설치한 cgywin을 사용한다.
- 생성된 HelloJni.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class hufs_dislab_hellojni_HelloJni */ #ifndef _Included_hufs_dislab_hellojni_HelloJni #define _Included_hufs_dislab_hellojni_HelloJni #ifdef __cplusplus extern "C" { #endif /* * Class: hufs_dislab_hellojni_HelloJni * Method: stringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_hufs_dislab_hellojni_HelloJni_stringFromJNI (JNIEnv *, jobject); /* * Class: hufs_dislab_hellojni_HelloJni * Method: unimplementedStringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_hufs_dislab_hellojni_HelloJni_unimplementedStringFromJNI (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
라이브러리 생성을 위한 jni 디렉토리 생성
- 만들어진 헤더파일(HelloJni.h)을 jni 디렉토리로 이동시킨다.
- jni 디렉토리는 프로젝트 내에 생성하고 이 디렉토리는 위에서 생성한 헤더파일, C파일, Android.mk 파일을 저장한다.
Android.mk 파일 생성
- LOCAL_MODULE 에 설정한 값으로 나중에 생성될 공유 라이브러리 이름이 된다. HelloJniTest --> libHelloJniTest.so (일반적으로 라이브러리 이름은 소문자로 해야함...;; )
- 컴파일할 소스파일이 여러 개일 경우에는 LOCAL_SRC_FILES에 나열해 준다.
- Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := HelloJniTest LOCAL_SRC_FILES := HelloJni.c include $(BUILD_SHARED_LIBRARY)
Native code 작성(C파일 생성)
- 생성한 헤더파일에 선언된 C 함수를 구현한다.선언된 C함수를 모두 구현하지 않아도 무방하다.
- Hello-Jni.c
#include <string.h> #include <jni.h> jstring Java_hufs_dislab_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) { return (*env) -> NewStringUTF(env, "Hello From JNI !"); }
C소스 컴파일 / 공유라이브러리 생성
- 앞에서 구현한 C 코드를 컴파일하여 라이브러리를 생성한다.
- 위의 그림과 같이 Cygwin을 실행하고 해달 프로젝트로 이동한다. 그리고 ndk-build 명령을 이용하여 컴파일을 한다.
- 컴파일이 끝나면 프로젝트 안에 libs/armeabi 디렉토리가 생성되고 HelloJniTest.so 가 생긴 것을 확인할 수 있다.
- 라이브러리 생성 과정까지 마치고 에뮬레이터를 돌려 결과를 확인한다. JNI 프로그램 작성 끝!
참고
Android NDK
- NAtive code를 안드로이드 애플리케이션에 적용할 수 있게 함
- NDK는 다음을 제공
- C와 C++로 라이브러리 작성하는 툴
- 라이브러리를 Android에 적재할 수 있는 .apsk로 변환하는 방법 제공
- Native System headers & libraries
- Documentation, samples & tutorials
- NDK 활용의 예 : 신호처리, 물리 시뮬레이션, 커스텀 바이트코드/ 명령어 인터프리터 등과 같이 메모리를 너무 많이 할당하지 않으면서도 CPU를 많이 사용하는 작업에 적함
- 장점 : 빠른실행
- 단점 : 이식성 없음, JNI 오버헤드 수반, 시스템 라이브러리에 접근불가, 디버깅 어려움
- 한계
- C에서 실행되는 메소드를 단순히 재코딩 하는것 으로는 성능향상에 큰 도움이 되지 않는다.
- NDK가 native-only 어플리케이션 개발은 힘들다.(Please note that the NDK does not enable you to develop native-only application)
- 안드로이드의 첫 번째 런타임은 Dalvik 가상머신에 있다.
- 포함 되어 있는 C 헤더들
- libc ( C 라이브러리 ) 헤더
- libm ( math 라이브러리 ) 헤더
- Jni Interface 헤더
- 호환성을 보장하는 방법( application using a native library produced with the NDK)
- 해당 매니페스트 파일에 android:minSdkVersion="3" 속성과 함께 <users-library> 엘리먼트를 반드시 선언한다.
출처 : http://dislab.hufs.ac.kr/lab/Android/JNI_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8_%EC%9E%91%EC%84%B1
'공부 > Android' 카테고리의 다른 글
안드로이드 코드(.java)에서 Layoutparams에 dip 단위 사용하기 (0) | 2013.07.24 |
---|---|
안드로이드 레이아웃 겹치기 (0) | 2013.07.23 |
안드로이드에대한 기본 이해와 설명, (안드로이드 네이티브 라이브러리) (0) | 2013.07.19 |
안드로이드 SharedPreference (0) | 2013.07.18 |
안드로이드 키보드 Devices Docs. (0) | 2013.07.18 |