안녕하세요 돼지왕왕돼지입니다.
지난번에는 일반 console application 에서의 JNI 를 사용하는 법에 대해 알아보았습니다.
2012/03/24 - [프로그래밍 놀이터/자바] - [Java] JNI Tutorial ( HelloJNI )
이번에는 안드로이드에서의 JNI Tutorial HelloJNI 를 알아봅니다.
Android JNI Tutorial HelloJNI
Android JNI 사용을 위한 준비물.
1. 일반 Android 앱 개발 도구
( Java, Eclipse, Android SDK등 요런 녀석들은 다들 가지고 있을 것이라고 생각합니다. )
2. Android NDK.
- Android NDK 는 Native Development KIT 으로 native program 개발을 위한 개발 도구입니다.
아래 사이트에서 다운로드 받을 수 있으며, 이클립스처럼 압축을 푸는 것만으로 설치가 끝납니다.
단!! 설치되는 폴더 path 에 space 가 들어있지 않아야 합니다.
( 필자는 나중에 위치를 옮겼습니다. )
http://developer.android.com/sdk/ndk/index.html
3. Cygwin
- Cygwin 은windows 환경에서 Linux 의 환경을 가상으로 쓸 수 있도록 도와주는 terminal program 입니다. 왜 Linux 환경이 필요할까요? 안드로이드는 Linux OS 를 바탕으로 한 framework 입니다. 그래서 library 를 만들 때 so 파일로 만들어주어야 android 에서 사용할 수 있습니다. Windows 는 dll 로 library 를 만드는 것 아시죠? 그래서 so 파일을 만들지 위해 linux 환경이 필요한 것입니다.
아래 사이트에서 "setup.exe" 를 클릭하여 setup 파일을 다운받아 설치해주면 됩니다.
http://cygwin.com/install.html
2012/03/24 - [프로그래밍 놀이터/안드로이드] - [Android/안드로이드] cygwin 설치방법 ( JNI 사용 위한 native library compile에 focus )
HelloJNI 만들기.
Android 용 HelloJNI 는 Button 을 누르면 TextView 에 string 을 출력하는데, 이 string 을 JNI 를 통해 native 코드로 가져오는 것입니다. 결과화면을 미리 볼까요? "printHelloJNI With JNI" 버튼을 눌러 "This is JNI test :)" 라는 string 을 native 로부터 얻어와 프린트해줍니다.
1. 먼저 Android Project 를 만듭니다. ( 이건 다 하실 수 있죠? )
쉬운 library compile 을 위해서 project 를 ndk 설치폴더의 하위폴더로 만들어줍니다.
(만약 다른 workspace 에 미리 만들어버렸다면 프로젝트 우클릭 - [Refactor] - [Move] 로 위치를 변경합니다. )
2. layout 파일을 작성합니다. 저는 기본 폼을 따라 main.xml 로 하였습니다.
<layout/main.xml>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textivew"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="printHelloJNI With JNI"
android:id="@+id/btn"
/>
</LinearLayout>
3. Activity 파일을 작성합니다.
<JNITest.java>
package com.sklee.jnitest;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class JNITestActivity extends Activity {
private TextView mTextView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView = (TextView) findViewById( R.id.textivew );
findViewById( R.id.btn ).setOnClickListener( new OnClickListener() {
public void onClick(View v) {
mTextView.setText( new HelloJNI().getString() );
}
});
}
}
4. JNI 연결을 위해 native function을 정의하는 HelloJNI.java 를 만듭니다.
<HelloJNI.java>
package com.sklee.jnitest;
public class HelloJNI {
private static final String LIB_NAME = "hellojni";
public native String getString();
static{
System.loadLibrary( LIB_NAME );
}
}
[왜 Activity 하나에 몰아넣지 않나요?]
5. JNI header 파일 추출.
해당 프로젝트의 폴더의 /bin/classes 폴더로 이동합니다. 다음 커맨드 라인 명령을 통해서 jni header 파일을 추출합니다.
javah -jni com.sklee.jnitest.HelloJNI
다른 tutorial 들에서는 /bin 폴더에서 이 명령을 수행하라고 합니다. 하지만, 저는 계속 에러가 나더라구요. 그래서 classes 로 이동하여 했더니 잘 됩니다. 사실 classes 안에 들어간 후부터 package 폴더가 시작되니 classes 까지 가서 명령어를 입력하는 것이 맞습니다.
( javah 가 안 된다면, java sdk 의 bin 폴더를 환경 변수 path 로 걸어주세요. )
생성되는 .h 파일은 명령어를 실행한 폴더에 만들어지며, 이름은 packageName + class파일이름이기 떄문에 이 예제의 경우는 com_sklee_jnitest_HelloJNI.h 로 만들어집니다. 편의를 위해 HelloJNI.h 로 rename 해줍시다.
6. header 파일을 기준으로 native 코드 c 파일을 만들어줍니다.
<HelloJNI.c>
#include <jni.h>
#include "HelloJNI.h"
JNIEXPORT jstring JNICALL Java_com_sklee_jnitest_HelloJNI_getString(JNIEnv *env, jobject object){
return (*env)->NewStringUTF( env, "This is JNI test :)" );
}
jni.h 는 jni 를 위해 include 해야 하며, 기 생성한 HelloJNI.h 는 link 을 위해 include 해줍니다.
signature 는 이해하기가 어려울 수 있는데, HelloJNI.h 안에 있는 signature 를 그대로 사용하면 됩니다.
7. Library compile 을 위한 Android.mk 를 만들어줍니다.
<Android.mk>
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellojni
LOCAL_SRC_FILES := HelloJNI.c
include $(BUILD_SHARED_LIBRARY)
Android.mk 에 대한 정확한 이해를 위해서는 많은 공부가 필요합니다. Tutorial 이기 때문에 여기서는 간단한 이해만을 해보겠습니다. 여기서 우리가 주의깊게 봐야할 내용은 2가지인데요. LOCAL_MODULE 과 LOCAL_SRC_FILES 입니다. LOCAL_MODULE 은 output 으로 나오는 library file 이름이라고 보시면 됩니다. 이 부분은 System.loadLibrary( "여기" )의 "여기" 부분과 이름이 같아야 합니다. LOCAL_SRC_FILES 는 library 에 들어갈 native 코드파일들을 명시합니다. 우리는 1개의 c파일만 가지고 있으니 HelloJNI.c 를 써줍니다.
8. native 와 관련된 파일들을 프로젝트의 "jni" folder 를 만들어서 복사해줍니다.
native 관련 파일들은 HelloJNI.h, HelloJNI.c, Android.mk 3개입니다.
9. cygwin 을 이용해서 library compile 을 해줍니다.
먼저 cygwin terminal 을 실행합니다.
프로젝트의 main 폴더로 이동하여, ndk-build를 실행시켜줍니다.
저는 프로젝트를 NDK/works/HelloJNI 에 생성했기에 "../../ndk-build" 로 명령을 실행했습니다.
결과물은 libs/armeabi/libhellojni.so 로 저장이 됩니다.
전체 결과를 [Package Explorer]를 통해 볼까요?
10 . 모든 준비는 끝났습니다. 이제 보통 안드로이드 앱을 실행시키듯 싱행해주시면 되겠습니다.
10-1. 간혹 Library Link 가 맞지 않는 경우가 있는데. 그럴 땐 다음과 같이
java.lang.UnsatisfiedLinkError 가 발생합니다.
이 때는 library link 부분을 점검해주시면 되겠습니다.
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[Java] JNI Tutorial - String 과 Array 사용. (4) | 2012.03.26 |
---|---|
[Android/안드로이드] cygwin 설치방법 ( JNI 사용 위한 native library compile에 focus ) (0) | 2012.03.24 |
[Java] JNI Tutorial ( HelloJNI ) (4) | 2012.03.24 |
[Java] JNI Invocation API. (0) | 2012.03.22 |
[Java] JNI functions. (0) | 2012.03.22 |
댓글