Notice
Recent Posts
Recent Comments
Dharma
[Android-NDK] NativeActivity 에서 다른 Shared Library 추가시 앱이 구동 안되는 문제 - 해결 - 본문
프로그래밍
[Android-NDK] NativeActivity 에서 다른 Shared Library 추가시 앱이 구동 안되는 문제 - 해결 -
광이랑 2013. 8. 8. 21:58
Android NDK (Native Development Kit) 을 이용해서 개발하고 있습니다. NativeActivity 를 이용하고 있습니다. 그런데 작지만 해결하기 어려운 버그가 있습니다.
NativeActivity 는 Java 의 Activity 의 일종인데 JNI 를 이용한 Native C/C++ Entry Point 를 쓰레드 (Thread)를 이용해서 호출하는 부분을 잘 감싸서 NDK 를 이용해서 개발하고자 하는 사람들에게 편의를 제공할려는 목적으로 만들어 진것으로 보입니다. 특히나 게임 , 전화, 멀티미디어 용 어플리케이션을 개발하는 사람들은 필히 관심을 가져볼 만합니다.
발생한 이슈는 제가 추천한 책에서 언급된 소스에 다른 모듈을 붙일려고 하는 순간에 발생했습니다. 참고로 만들어본 Android.mk 파일입니다.
LOCAL_PATH := $(call my-dir)
TOP_ROOT_PATH := $(LOCAL_PATH)
include $(call all-subdir-makefiles)
# 이 하위 Android.mk 에서 Shared Library 를 만들어 줍니다.
# 그 라이브러리 이름을 codec 이라고 (예를 들어서) 해줍니다.
include $(CLEAR_VARS)
LOCAL_PATH = $(TOP_ROOT_PATH)
LS_CPPP=$(subst $(1)/, ,$(wildcard $(1)/*.cpp ))
LOCAL_MODULE := game
LOCAL_SRC_FILES := $(call LS_CPPP,$(LOCAL_PATH))
LOCAL_CFLAGS += -D GL_GLEXT_PROTOTYPES
LOCAL_LDLIBS := -landroid -llog -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue png
LOCAL_SHARED_LIBRARIES := codec
# 이 부분이 문제의 그 부분입니다.
include $(BUILD_SHARED_LIBRARY)
$(call import-module, android/native_app_glue)
$(call import-module, libpng)
이게 대체 뭐지? 라고 생각하시는 분들은 제가 곧 'NDK 프로그래밍 따라하기' 포스트 한 두개를 올릴테니 그 때까지 이 부분을 보실 필요는 없습니다.
위의 Android.mk 를 이용해서 컴파일을 하면 libgame.so 가 만들어 집니다. 책에서 나와 있는 그대로 만들어 집니다. 그러나 codec 이라는 (libcodec.so)를 이용해야 하는 필요가 생겨서 따로 만들어 줘서 프로젝트에 포함시켜 주면 실행이 안되고 에러가 발생합니다.
잘 된 캡슐화의 문제점 중의 한가지가 난감한 에러가 발생하면 해결하기 어렵다는 점입니다. 구글링도 해보고 여러가지 독립적인 테스트를 해 본 결과 전혀 엉뚱한 작업을 진행중에 해결이 됐습니다. 100% 확신을 한 바는 아니지만 NativeActivity 가 결국 Java 클래스 이고 내부적으로는 결국 JNI 를 이용해서 Library 를 불러오는데, 정해진 방법으로만 호출하기 때문에 (위의 예제의 경우에는 libgame.so ) 다른 라이브러리를 호출을 못하기 때문에 발생하는 것 같습니다. 따라서 해결해 주기 위해서는 몇가지 수동으로 처리해 줘야 합니다.
$ cd $PROJECT_ROOT
$ cd src/com/comjuck/game (없으면 만들어 주셔야 합니다)
$ emacs NativeActivity
package com.comjuck.game;
import android.app.NativeActivity;
import android.os.Bundle;
public class GameActivity extends NativeActivity {
static {
System.loadLibrary("codec");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
GameActivity 를 만들어주고 NativeActivity 에서 상속을 받습니다. (물론 package 경로에 맞춰주는 것을 잊어주시면 안됩니다) , 그리고 위에서 표기한 대로 추가해 준 라이브러리를 직접 불러줍니다.
그리고 AndroidManifest.xml 을 열어서 추가해 준 Activity 를 android.app.NativeActivity 대신 지정해 줍니다.
$ cd $PROJECT_ROOT
$ emacs AndroidManifest.xml
<activity android:name="PhoneActivity"
android:label="@string/app_name">
이제는 문제 없이 앱이 실행되는군요.
ps. 이걸 알아내기 위해서 4시간을 소모했습니다. ㅜ.ㅜ