안드로이드 개발하다 보면 별 문제는 없어보일지 모르지만 안드로이드가 네트워크 인터페이스를 여러개 가지기 때문에 발생하는 문제가 있습니다. 갤럭시 s3 의 경우에는 LTE, 3GS, WI-FI 등 세개의 인터페이스가 있습니다. 그런데 이런 인터페이스들이 사용을 안하면 비활성화 되어 있으면 사용하기 편할텐데 사용 안하더라도 활성화가 되어 있는 데다가 잘못된 (구동하지 않는) IP 주소를 가지고 있어서 문제가 됩니다.

무슨 문제가 있겠어? 라고 하지만 순수 자바 (Pure Java) 로 네트워크 레이어를 구현할 때, 만들어진 라이브러리를 안드로이드로 포팅시 발생하는 문제입니다. 이를 해결하기 위한 방법입니다.

인터넷에 연결이 되어 있고 (LTE,3GS,WI-FI 상관하지 않고) 접속되어 있는 상태에서의 가지고 있는 IP 주소를 가져오는 방법입니다.

Socket socket = new Socket("www.google.com", 80);
String localAddr = socket.getLocalAddress().getHostAddress();
Log.d(TAG, "local address is : " + localAddr);

생각보다 자주 부딛히는 문제라서 정리합니다.





안드로이드 어플리케이션 개발 시 YoutubeStandAlonePlayer 를 쓸 일이 있었서 사용했는데 예상치 못한 버그가 발생하더군요. 그 현상과 해결방법을 정리합니다.

1 현상

안드로이드 앱 개살시 메인 어플리케이션을 Portrait 전용으로 개발중이였습니다.

Intent intent = YouTubeStandalonePlayer.createVideoIntent(context,
                    DEVELOP_KEY, youtubeCode);
                context.startActivity(intent);

와 같은 식으로 유튜브 플레이어를 띄우니 띄운 액티비티(Activity) 와 그 스택에 쌓여있던 액티비티 들의 onResume 이 호출되는 현상이 있습니다. 그래서 플레이중에 멋대로 호출된 Activity 로 튕깁니다. 게다가 어찌 어찌 플레이되더라도 플레이중에 백키를 누르면 호출된 액티비티로 가는게 아니라 앱이 종료됩니다.

2 원인

아마도 Landscape 전용인 YouTubeStandalonePlayer 와 Portrait 로 만들어진 메인 앱과의 차이점 때문인 것 같다고 판단하여 해결법을 찾았습니다.

3 해결

YouTubeStandalonePlayer 를 호출하는 Activity 와 그 스택에 쌓여 있는 Activity 들의 AndroidManifest 안에 android:configChanges="orientation|screenSize|keyboardHidden" 와 같은 내용을 추가해주면 해결됩니다.

<activity
    android:name=".scene.IntroActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:screenOrientation="sensorPortrait" />
<activity

와 같은 식입니다.

ADT (Android Developer Tool)를 사용하다 보면 중대한 한가지 문제(한가지 뿐이겠냐만은..)가 있습니다. 여러명이 작업을 할 때 한명이 프로젝트를 생성하고 git 레파지토리에 프로젝트를 올린 것을 다른 사람들이 받아서 프로젝트를 세팅할려고 할 때 문제가 발생합니다.

~/work/android-projects/Original

에 소스를 받았다고 하면 ADT 나 Eclipse 는 바로 저 위치에서 프로젝트를 만들 수가 없습니다. 바로 workspace 에 복사를 하던가 import 를 해야 하기 때문이지요. 강제로 같은 곳을 지정해주면 에러가 발생합니다. 이 부분은 정말 많은 구글링을 해봐도 거의 답이 없다는 것이 정설입니다. 많은 사람들이 Eclipse 를 욕합니다. 개발자들이 점점 git 이나 svn 을 이용하면서 IntelliJ 로 이동하는게 다 이유가 있는 것 같습니다. (물론 svn 이나 git 으로 바로 프로젝트를 생성하는 방법이 있기는 있는데 많이 불편합니다)

물론 Command Line 에서는 간단합니다. 'android update project' 명령을 이용하면 쉽게 ant 용 프로젝트로 변경시킬 수가 있고 이대로 공유하면 개발하는데 아무 문제도 없습니다.

그래도 같이 일하는 개발자들이 Command Line 을 좋아할 리가 없으니 IDE 를 이용하는 선에서 협상을 해야 합니다. 결국 답은 Android Studio 가 되겠지요. 그런데 Android Stuido 도 문제가 있습니다. 기존의 Eclipse 기반의 Project 구조를 변경합니다. (기존의 프로젝트를 app 이라는 이름으로 변경하여 구조가 변경됩니다) 이것이 변경되기 때문에 또 Eclipse 개발자가 개발하기 힘듭니다. 즉 정리하자면

  • git 레파지토리에 소스가 있고
  • Eclipse 개발자와 Android Studio 를 이용하는 개발자들 간에 협업을 할 수 있는 프로젝트 구조를 만들어야 함

이 두가지를 만족해야 합니다. 어려워 보이지만 (실제로도 어려웠습니다..) build.gradle 파일을 프로젝트 root 에 만들어주고 Android Studio 에서 'Import Non-Android Studio Project' 로 만들어 주면 됩니다.

build.gradle 파일의 예입니다.

buildscript {

  repositories {
    mavenCentral()
  }

  dependencies {
    classpath 'com.android.tools.build:gradle:+'
  }
}

apply plugin: 'android' 


repositories {

  mavenCentral()
  mavenLocal()
}


dependencies {
  compile fileTree(dir: 'libs' , include: '*.jar')
  compile('com.google.android.gms:play-services:+') {
    exclude group: 'com.android.support', module: 'support-v4'
  }

  compile 'com.android.support:appcompat-v7:+'

  compile project(':aplib_aos')
}

android {

  compileSdkVersion 21
  buildToolsVersion "21.0.1"

  sourceSets {
    debug.setRoot('build-types/debug')
    release.setRoot('build-types/release')

    main {
      manifest.srcFile 'AndroidManifest.xml'
      java.srcDirs = ['src']
      resources.srcDirs = ['src']
      aidl.srcDirs = ['src']
      renderscript.srcDirs = ['src']
      res.srcDirs = ['res']
      assets.srcDirs = ['assets']
    }
  }

}

나머지 부분은 위의 내용을 그대로 써도 되지만 제일 중요한 부분이 바로 dependencies 부분입니다. 이 부분만 자신의 프로젝트에 맞게 구성만 해주시면 됩니다.

dependencies {
  compile fileTree(dir: 'libs' , include: '*.jar')
  compile('com.google.android.gms:play-services:+') {
    exclude group: 'com.android.support', module: 'support-v4'
  }

  compile 'com.android.support:appcompat-v7:+'

  compile project(':aplib_aos')
}

이 부분만 따로 설명을 드리자면 기본적으로 $PROJECT_ROOT 밑의 libs 밑에 있는 jar 파일을 포함시키라는 뜻입니다. 그리고 google-play-service 를 외부 라이브러리로 링크하고 support-library v7 도 외부 라이브러리로 링크하라는 것입니다.

compile project(':aplib_aos')

이 부분이 중요한데 이 부분은 안드로이드 스튜디오의 'File' - 'Import Module' 명령을 이용해서 외부의 라이브러리 프로젝트를 포함시킨 경우에 그 라이브러리 모듈이름을 적어 주는 부분입니다. 위 명령을 이용하면 자동으로 settings.gradle 파일에 어떤 모듈이 포함됐는지 쓰여집니다.

모바일 개발자가 혼자 일하는 상황이면 사실 이런 경우는 전부 삽질일것입니다. 그러나 레파지토리에 소스를 옮겨서 관리하는 경우도 그렇고 한번 내려 받은 소스를 이용해서 다시 프로젝트를 구성하는 경우에는 항상 발생하는 문제일 것이라 생각해서 정리해 둡니다.




Multiple dex files define Landroid/support/v4 관련된 어쩌구 저쩌구 에러가 발생했을 때의 대처법입니다.

100% 제 환경에서 발생하는 일이였습니다. 먼저 환경을 소개하자면 회사에서 개발하는 안드로이드 (Android) 프로젝트인데 전부 환경이 달라서 문제가 발생했습니다.

  • PM 인 저는 Command Line 에서 프로젝트를 개발합니다. 사용하고 있는 툴(Tool)은 Emacs 에 Ant 를 이용해서 빌드합니다.
  • 회사에서 작업하는 개발자는 Android Studio 를 이용해서 개발합니다.
  • 회사 외부에서 개발하는 개발자는 ADT (Android Development Tool) 을 이용합니다.

저와 외부에서 개발하는 개발자간의 호환은 별 문제가 없습니다. Eclipse 와 Command Line 은 거의 프로젝트 세팅이 비슷한거 같습니다. 물론 따로 설정해줘야 하는 부분이 있지만.. 하지만 ADT 와 안드로이드 스튜디오 간에는 차이가 확실히 존재하더군요.

play-services 를 이용해서 개발하는 것입니다. ADT 에서는 따로 Library Project 를 설정해서 기존 프로젝트에 포함시켜주면 되는 것이였습니다. 그러나 Android Studio 는 방법이 다르더군요.

Google Play Service 세팅법 을 참조해서 하면 build.gradle 을 열고 다음과 같이 추가해 주면 되는 것입니다.

dependencies {

    compile 'com.google.android.gms:play-services:6.5.87'
}

그러나 에러가 발생하더군요. 이유는 간단했습니다. ADT 에서 참조하는 libs 에 android-support-v4.jar 이 포함됐기 때문입니다. 그렇다고 바로 지우자니 그 담부터는 ADT 를 이용하는 외부 개발자님의 빌드가 깨지겠지요.

그래서 다음과 같이 바꾸어 줍니다.

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile ('com.google.android.gms:play-services:+') {
                exclude group: 'com.android.support', module: 'support-v4'
    }
}

그리고 Android Studio 에 있는 Toolbar 를 보면 'Sync Project with Gradle Files' 라는 버튼을 눌러주고 프로젝트를 빌드해 주면 됩니다.


안드로이드 개발을 위해서 구글이 내놓은 새로운 개발툴 입니다. 최근에 이클립스가 maven 지원이 더딘것 때문에 사용자를 늘려가던 (유료인데도 불구하고!!) IntelliJ 기반입니다. 물론 구글이 내놓아서 공짜랍니다. 크기는 무려 700메가 정도군요, 기가단위가 아니라서 가벼운게냐..


조금 더 만져보니 이게 프로젝트가 비쥬얼 스튜디오 마냥 한번에 하나의 프로젝트만 열게 되어 있군요. 그래서 여러개를 한꺼번에 오픈하는 방식인 ADT 보다 가볍다는 소리를 듣는군요. 


자세한 설명과 다운로드는 바로 http://developer.android.com/sdk/installing/studio.html 에서 다운받을 수가 있습니다. 


지금까지 ADT 를 잘 사용했는데 왜 이걸 또 배워야 하느냐고 물으실 수가 있습니다. 저는 구글의 대변인은 아니지만 ㅎㅎ 이게 비록 베타인데도 웨어러블 (Wearable) 앱 만드는데 최적화가 되어 있습니다. (추천한다고 여기 저기 쓰여져 있습니다) 그리고 메이븐도 사용할 수가 있습니다. 자세한 것은 위의 주소에 가면 설명이 되어 있지만 따로 가져와 본다면 




제가 하는 영역과 관련되서 딱 하나의 불만은 NDK 가 지원 안된다는 점이지만 뭐 급할 것은 없겠지요. 받아서 설치하시고 나면 


바로 테마를 Default 에서 취향에 맞춰서 Darcula (드라큘라가 아니다? -ㅅ- ) 바꿔주셔도 좋습니다. 테마가 두개 밖에 없으니 알아서 골라주세용 


아 그리고 에디터를 이용할때 사용하는데 전혀 거부감이 없었습니다. 그 말인즉슨 에디터가 기본으로 이맥스(Emacs) 키 바인딩을 지원한다는 것이겠지요. 이것 또한 아주 마음에 드는 부분이였습니다. 


NDK (Native Development Kit Environment) 입니다. 구글은 Java 환경의 SDK 만 가지고 모든 것이 가능할 것이라고 주장했었으나, 몇 버젼 지나지 않아 자신들의 주장을 철회하고 Native C/C++ 프로그램이 가능한 NDK 를 공개했습니다. 

 왜 NDK 를 사용하는가에 관해서는 몇가지 이유가 있겠지만 

 - 빠른 연산을 위해서 (아무래도 C/C++ 이 자바 보다 속도가 빠른것은 주지의 사실입니다) 
 - 수많은 Open Source 들이 아직도 C/C++ 로 되어 있기 때문에


일단 이 두개를 크게 들 수가 있겠습니다. 그렇다고 해서 윈도우 다루는 부분까지 전부 NDK 로 하는 것을 추천하지는 않습니다. 속도가 필요한 부분이나 위에서 언급된 오픈 소스로 만들어진 라이브러리를 응용하는 부분에 사용할 것을 추천합니다. 

 NDK 를 컴파일 하기 위해서 알아야 할 구글에서 만들어둔 Makefile 입니다. Makefile 의 문법을 쓰고 있지만 세세하게 다 작성할 필요 없이 형태에만 맞춰주면 나머지는 빌드스크립트가 알아서 처리를 해 줍니다. 물론 이 방법 말고 OpenSource 를 컴파일하기 위해서는 방법이 따로 필요하지만 그 건 다른 포스트에서 다루기로 하겠습니다. 

 실제로 예제를 따라 만들어 보면 쉽게 이해가 될 것 같습니다. 
 

 NDK 를 개발하기 위한 준비 과정입니다. SDK 와 NDK 를 받아서 적당한 곳에 풀고 SDK 에 관련된 명령을 어디서든 실행할 수 있게 PATH 에 걸어주고, NDK 또한 어디서건 실행이 가능하게 PATH 에 걸어줍니다. 

안드로이드 프로젝트를 만들어줍니다. Eclipse (ADT) 에서도 만들어 줄 수 있지만 저는 기본적으로 Command Line 을 선호하므로 Terminal 에서 만들어 줍니다. 

필수로 입력해야할 내용들입니다. -n 은 프로젝트의 이름 (위에서는 HelloNDK) -t 은 현재 자신의 개발 머신에 설치되어 있는 SDK 버젼의 id 입니다. -k 는 패키지 명입니다. (위에서는 com.comjuck) -a 는 Activity 의 이름입니다. 

 디자인 부분을 손봐줍니다. 그냥 간단하게 TextView 하나 생성해 줍니다. 

 MainActivity 에서 Layout 에서 만들어준 TextView 에 NativeCode 에서 리턴한 문자열을 출력하는 예제를 만들 예정입니다. 따라서 위와 같이 작성해주면 됩니다. 

 실제로 Android 프로젝트를 빌드하는 과정입니다. 그냥 위 명령 그대로 입력하면 컴파일 될 것입니다. 

EDIT: ubuntu 에서 javah 사용시 classpath 를 명시해 줘야 하더군요. 

javah -classpath <android-sdk-path>/platforms/android-20/android.jar:$PROJECT_PATH/bin/classes com.comjuck.MainActivity 


Android 부분이 에러 없이 컴파일 된다고 해도 실제로 Native Code 부분이 없기 때문에 실행하면 에러가 발생합니다. 따라서 Native 부분을 작성해 주는 과정입니다.  javah 명령을 이용해서 header 를 자동으로 생성해 주기로 합니다. javah 는 native 키워드가 붙은 부분에 대해서 자동으로 선언을 만들어 줍니다. (JNI 가 기본으로 제공해 주는 기능입니다) 

그래서 생성된 파일(이름에 주목하면 package 명 + Class 명이 합쳐진 형태)을 $PROJECT_PATH/jni 디렉토리로 복사해줍니다. 

Native 코드들이 위치하는 곳은 $PROJECT_PATH/jni 입니다. 

 Native Code 가 위치해야 하는 $PROJECT_ROOT/jni 에 javah 를 이용해서 생성해준 com_comjuck_MainActivity.h 에 대응하는 Body 를 만들어줍니다. 여기서는 HelloNDK.c 로 만들어 주고 위와 같은 코드를 채워줍니다. 

AndroidManifest.xml 파일을 열어서 이제부터 NDK 를 사용할 것이라는 것을 지정해줘야 합니다. 딱히 해줄것은 없고 minSDKVersion 정보를 최소 14로 맞춰주는 것입니다. 

Native Code를 컴파일 하기 위해서 필요한 Android 용 Makefile 입니다. 현재 지금 있는 것을 컴파일 하기 위해서는 단지 위와 같이 작성해주면 됩니다. 

Android.mk 의 예제입니다. 

LOCAL_PATH 는 ndk-build 가 실행될 때의 위치에 따라서 정보가 다르게 저장되긴 하지만 기본적으로 $PROJECT_ROOT/jni 을 지정하게 되어 있습니다. 

include $(CLEAR_VARS) 는 LOCAL_PATH 를 제외한 모든 LOCAL_ 로 시작되는 변수들이 초기화 됩니다. 왜 필요한가 의문을 가질 수 있지만 여러개의 프로젝트를 컴파일할 때 꼭 필요한 명령입니다. 

LOCAL_CFLAGS 는 추가해줄 컴파일 옵션에 관한 세팅입니다. 

LOCAL_MODULE 은 만들고자 하는 모듈의 이름입니다. 

LOCAL_LDLIBS 는 연결하고자 하는 링크옵션입니다. 

LOCAL_SRC_FILES 는 컴파일 될 대상인 소스파일들의 리스트입니다. 여기에 나열만 해주는 것으로 알아서 처리가 됩니다. 

include $(BUILD_SHARED_LIBRARY) 는 shared object (so 파일) 을 생성하기 위한 명령입니다. BUILD_STATIC_LIBRARY 는 static object (a 파일)을 만들어주기 위한 명령입니다. 

$PROJECT_ROOT 나 jni 디렉토리에서 ndk-build 만 입력하면 컴파일 됩니다. 그리고 다시 $PROJECT_ROOT 에 가서 ant -e debug 를 입력하셔서 다시 컴파일 해주시면 됩니다. 

여러가지 방법이 있겠지만 Command Line 을 이용하자면 

$ ant -e installd


를 이용하면 Device 에 인스톨 됩니다. 
 


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시간을 소모했습니다. ㅜ.ㅜ 

저는 Command Line 에서 GIT 을 쓰고 있습니다. '뭐든지 가장 기본이 되는 것부터 마스터를 하자!' 라고 평소 떠들고 다니기도 하지만, CLI (Command Line Interface) 가 가장 마음이 편안해 (?) 지는 환경이기 때문이도 합니다. 그러나 Eclipse 에서 개발이 최적화 되어 있는 분들은 어떤 방식이 되도 무조건 Eclipse 에서 돌아가길 원합니다. (진정한 IDE 라고 할 수 있죠) 그런분들에게 추천하고 싶은 포스트가 있습니다. 

http://www.vogella.com/articles/EGit/

일단 포스트 주소입니다. 그리고 이 포스트와는 별도로 저 분의 사이트는 안드로이드 개발하는 분들에게 참조가 될 만한 내용을 정말 많이 가지고 있어서 즐겨찾기 해두시고 가끔가다 찾으시면 효율이 좋을 것입니다. 

 


저는 컴퓨터 관련 서적 자체를 잘 추천 안하는 편입니다. 요즘 같이 급박하게 기술이 바뀌는 세상에서는 사실상 공식 페이지가 최고의 레퍼런스가 되는 것이 현실이다 보니, 주변에서 기술 관련 서적을 산다고 하면 적극적으로 말리는 편입니다.

그러나 이 책은 정말 감히 추천할 만 합니다. 사실 저는 원서(Android NDK , Beginner's Guide)로 봤는데, 저자의 소스코드만 보더라도 상당한 내공이 느껴집니다. C++ 이나 Object Oriented Programming 에 상당한 조예가 느껴집니다. 팀원이 한글판으로 보고 있는데도 상당히 괜찮다고 하니 번역도 괜찮게 되어 있는 편인가 봅니다. 

안드로이드에서 가장 어려운 축에 드는 NDK(Native Development Kit) 부분을 '따라하기' 식으로 쉽게 풀어서 설명했을 뿐 아니라, 따라하기의 예로 든 것이 바로 '게임' 입니다. 더구나 철저하게 Bottom-up 식으로 설명을 하고 있기 때문에 아니 이게 이런 게임이 되는거야? 하는 신기함도 느끼실 수가 있습니다.

더구나 C 의 함수로 돌아가는 형태를 객체화를 시키는 능력을 보자면 코드를 만들어내는 사람의 내공을 느낄 수가 있는데 그런면에서 이 저자는 가히 탁월한 능력을 보여줍니다.

단 책이 몇 개의 심각한 오타를 가지고 있습니다. (국내판은 확인도 안하고 그대로 번역한 것 같은 느낌까지 준다고 하는군요. ) 따라하기 소스는 필히 원작자의 돌아가는 소스코드를 가지고 공부하시길 추천합니다. 

 
저는 안드로이드를 Emacs 로 개발하고 있는 중인데요. 외부 jar 가 추가 될 때 자동으로 classpath 에 추가 하고 자동으로 import 기능을 활성화 시키는 방안을 찾는 중인데, 없더군요.. 

물론 Eclipse 를 사용하면서 Google AdMob SDK 같은 외부 jar를 사용하기는 쉽습니다. 외부 라이브러리로 추가해 주면 끝이기 때문입니다. 다만 CLI (Command Line Interface) 에서 Ant 를 이용해서 빌드를 할 때는 마구 마구 귀찮아집니다. 하지만 쉽게 하는 방법이 생겼더군요. 

$(ANDROID_PROJECT_ROOT) 밑에 /libs 라는 디렉토리를 만들고 그 안에다가 GoogleAdMobAdsSdk-6.0.1.jar android-support-v4.jar 두개의 파일을 복사해줍니다. 


$(ANDROID_PROJECT_ROOT) 밑의 ant.properties 파일을 열고 다음과 같이 추가해 줍니다. 

  jar.libs.dir=libs


이제 

$ ant clean && ant debug 



해 주시면 성공적으로 바인딩 되는 것을 확인하실 수 있습니다. 

다만 위와 같이 따로 libs 를 추가해 주면 JDE 환경에서 자동으로 classpath 뒤져서 Import 해주는 기능이 libs 에 추가된 jar 에 대해서는 동작하지 않습니다. 이럴 때를 위해서 따로 함수를 만들어 뒀습니다. (100% 제가 만든것입니다 쿨럭..) 



(defun android-mode-my-hook () 
  (progn
    (and (file-exists-p 
          (concat (android-root) "/libs"))
         (setq jde-global-classpath 
               (append jde-global-classpath 
                       (directory-files
                        (concat (android-root) "/libs")
                        t "jar"))))
    ))
(add-hook 'android-mode-hook 'android-mode-my-hook)


다음과 같이 만들어 주면 됩니다. 저는 java 설정만 따로 모아놓고 쓰지만 그렇지 않으신 분들은 .emacs 파일 구석에 적어두시면 될 것입니다. 물론 jdee 와 android-mode 설정 뒤에 적어주셔야 할 것입니다. jde-global-classpath 는 jdee 를 추가 해줘야 생기는 변수고 android-root 는 안드로이드 프로젝트의 루트를 찾아주는 편리한 함수인데 android-mode 를 추가해줘야만 쓸 수가 있습니다. 

점점 lisp 으로 코딩하는게 재밌어 지기 시작합니다. ㅎㅎ 
 

+ Recent posts