2013년 10월 2일 수요일

dx crashes on projects with > 65,535 methods

Android의 Dalvik에선 허용 메소드 한계가 65,535이다. 이걸 넘어가면 빌드가 안되는 현상 발생.
https://code.google.com/p/android/issues/detail?id=20814

해결책으로는 Proguard를 사용하여 최적화를 수행하거나 dex를 여러개로 쪼개서 런타임에서 불러쓰는 방법이 있다고 한다.

우선 내 안드로이드 앱이 가지고 있는 메소드 개수를 추출해보자. 이를 위해선 dex format을 어셈블/디어셈블 할 수 있는 smali, baksmali가 필요하다. download에서 jar 파일들의 버전명을 삭제해줘야 스크립트 파일들이 제대로 동작한다.
https://code.google.com/p/smali/

dex.sh
#!/bin/bash
function dex-method-count() {
  cat $1 | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'
}
dir=$(mktemp -d -t dex)
baksmali $1 -o $dir
for pkg in `find $dir/* -type d`; do
  smali $pkg -o $pkg/classes.dex
  count=$(dex-method-count $pkg/classes.dex)
  name=$(echo ${pkg:(${#dir} + 1)} | tr '/' '.')
  echo -e "$count\t$name"
done
rm -rf $dir

MacOSX 에서는 기본적으로 JAVA_HOME과 PATH가 잡혀있지 않으므로 설정해주고 위의 쉘을 실행한다.

~/.bash_profile
export PATH=$PATH:.
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/Contents/Home

이제 쉘을 실행시키면 메소드 개수가 출력되는 것을 확인할 수 있다.

$ sudo ./dex.sh
/My_workspace/android/MY_Sample/bin/MY_Sample.apk

2013년 10월 1일 화요일

Trello에 GitHub 연동하기

매우 애용하고 있는 칸반 보드 서비스인 Trello에 GitHub을 연동해보고자 한다. GitHub은 레포지토리 별로 Service Hook을 지원한다. 만약 GitHub/Trello를 사용하고 있는 프로젝트가 있다면 이를 이용하여 Commit, Pull request를 Trello의 지정 리스트에 자동 등록하도록 설정해보자.

1. GitHub에서 Service Hooks 설정하기

repository > Setting > Service Hooks > Trello 순으로 선택.

Trello와 연동하고자 하는 repository에서 setting으로...
Available Service Hooks 맨 아래 쪽에 Trello가 있다.

위 그림에서 알 수 있듯이, 트랠로와의 연동엔 Push List Id, Pull Request List Id, Consumer Token이 필요하다. 우선 Consumer Token을 얻어보자.

2. Consumer Token 얻기

셋팅 입력 폼 밑에 text box를 보면 Install Note가 있다. 1번의 "create a consumer token"을 선택

"create a consumer token"을 선택
Trello의 계정 권한 연동에 대해 물어본다. 당연히 "Allow"
(모자이크로 가려진) consumer token을 얻었다.

token을 쭈욱 복사해서 아까의 consumer token 입력 박스에 붙여 넣자. 자, 그럼 Commit list id와 Pull request id만 남았다. Trello를 열어보자

3. Trello에서 List ID 찾기.

GitHub-Trello 연동을 위해 구글링한 결과, Trello의 board ID를 추출하여 list ID를 구해오는 방식을 설명하더라. 심지어 GitHub의 Install note에도 그렇게 설명되어 있다. 하지만 이제 Trello는 URL 창에 board ID가 노출되지 않는다. 그런 연유로 board ID를 얻기 위하여 한참을 뒤진 결과, Export JSON 발견! 혹시나 했는데 역시나 저기 있더라. 게다가 이 방법은 board ID 없이도 바로 list ID를 추출할 수 있었다.


우선 우측에 "show sidebar" > Menu > Share, print, and Export... > Export JSON

JSON 창이 나오면 맨 첫 줄에 board ID와 board name이 노출된다.(그리고 드디어 URL 창에 board ID가 나온다.) 결국 board ID를 찾았어! 근데 왠지 list ID도 있을 것 같은데... 역시 밑을 잘 찾아보니 해당 board에 등록해놓은 모든 list의 ID와 name 역시 보인다. 빙고! 미리 Trello에서 생성해 놓은 "Commits"와 "Pull Requests"라는 이름의 list를 검색하여 ID를 추출하였다.

board ID를 발견했다. 근데 필요 없어! 바로 밑에 내가 등록해놓은 list ID가 있으니...

이제 모든 입력 폼을 채웠다. 사용할 일만 남았군. +_+) Master branch만 후킹하려면 Master Only 박스를 체크하자. Ignore Regex는 exception rule을 정규표현식으로 입력하게 둔 것 같으나, 사용할 일 없으므로 일단 pass.

이제 모든 준비가 완료되었다. Active를 체크하고 "Update settings" 버튼을 누르자.

4. Enjoy it !
아래와 같이 다소곳이 올라가는 Commits를 볼 수 있다. (아직 해당 프로젝트가 Pull Requests를 받은 적이 없어서 해당 내용은 올라가있지 않다.)



2013년 9월 16일 월요일

ADT version과 상관 없는 NoClassDefFoundError의 해결

Mac으로 Android 개발 환경을 이전하면서 Windows에서 잘만 돌던 프로젝트들이 약속이나 한 듯이 말썽을 일으키는 상황이 발생했다. 대부분은 ADT 17 버전 이후의 변화 때문에 발생하던 것이었고 그 것들은 구글링으로 대부분 해결할 수 있었다. 해결책은 대강 아래와 같다.
1. ClassNotFoundException이 발생할 경우
Android Project -> Properties -> Java Build Path -> Order and Export 탭 선택 -> 외부 라이브러리를 Export 체크 
2. NoClassDefFoundError가 발생할 경우
Android project의 libs 폴더에 관련 jar들을 넣는게 가장 낫다. 그러면 Android project -> Properties -> Java Build Path -> Libraries -> Android Private Libraries에 삽입되어 있는 것을 확인할 수 있다. 빌드 후 [Project Explorer]에서 bin/dexedLibs에 dex 형태로 변환된 jar들을 확인할 수 있다.

문제는 이걸로도 해결이 안되는 NoClassDefFoundError가 튀어나왔다는거... ㅠㅠ

Android Project가 아닌 순수 Java project로서 ANT 빌드한 jar인데, 이 걸 Android Project의 libs 폴더에 넣으면 런타임에서 NoClassDefFoundError가 발생한다. 분명히 dexedLibs에 변환된 jar를 확인했는데도 실제 apk 파일을 디컴파일해보면 관련 패키지가 삽입되어 있지 않다. 이 것 때문에 거의 1주일 동안 Mac으로의 이주가 hold 되었음.

힌트 : Windows에서는 잘 된다. Mac에서는 안 된다. 그럼 양쪽 OS에서의 차이가 무엇일까?로 시작한 원인 찾기. 결과적으로 Mac에서는 JDK의 버전이 1.7이었고 Windows에서는 버전이 1.6이었다. Android 4.1 시절이었나? 1.7을 지원 안한다는 얘기를 얼핏 들었던 기억이 있어서 ANT의 설정을 compiler="javac1.6"으로 수정!... 하면 실패한다!

특정 JDK에서 compiler 옵션을 하위 버전으로 수정하는 것은 경험상 아무 소용이 없었다. (예전에 Java 1.4를 사용하는 서버용으로 제품을 빌드할 때도 그랬음) 실제 JDK1.6 버전을 직접 설치해야한다. 직접 설치한 JDK를 지정하여 1.6으로 컴파일, 그리고 Android Project에 해당 jar를 삽입하니 드.디.어. 성공적으로 동작한다.

<javac srcdir="${src_android}"   
  destdir="${build_android}"  
  fork="yes"  
  executable="/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/javac"  
  compiler="javac1.6"  
  classpath="${android.classpath}"  
  includeantruntime="false"  
  encoding="UTF-8">  

2013년 9월 11일 수요일

Android Studio 시작하기

새 출발을 맞이하여 회사 업무 때문에 그간 써보지 못했던 "fancy"한 것들로 개발 환경을 바꿔보고 싶었다. -Eclipse에서 Android 더부살이로 이미 무척이나 익숙해져 있지만- 말로만 듣던 intellij도 욕심나고 Gradle도 사용해보고 싶고, 결정적으로 너무 무거운 Eclipse에서 벗어날 수 있지 않을까 싶어 Android Studio로 넘어가보려고 한다. 그리고 SVN에서 벗어나 Git으로 바꿔야 할 것 같다.

Groovy 책까지 샀단 말이다!

설치는 매우매우 쉽다. ADT bundle 보다 더 쉬워진 듯한 느낌. 아직은 불안하다는 평이 지배적이지만 "새출발"이니까! (특히 NDK 지원이 그렇다는데, 내가 보안 쪽을 다시 하지 않는 이상 NDK를 쓸 일이 다시 있을까?)

자~ 이제 써볼 일만 남았네... 설치를 다 끝내고 테마부터 수정해보자.

음... 밍밍해

1. 테마 수정
Android Studio -> Preferences 로 이동. (아마 당분간 자주 가게 될거다.)
왼쪽 상단의 검색창에 "appearance"를 입력하면 검색 결과로 두 개의 셋팅이 나온다. Apperarance에서 Theme를 Darcula로 바꿔주자. 그리고 line number를 보이게 하도록 Editor->Apperance로 이동하여 Show line numbers를 활성화 시켜준다.

훨씬 낫네~!

MacOSX에서는 기본 인코딩이 UTF-8이므로 인코딩 관련 설정은 안해줘도 된다. 혹시 모르니 검색창에 "file encodings"으로 들어가서 file encoding, project encoding properties encoding을 UTF-8로 바꾼다. (Transparent native-to-ascii conversion도 체크 확인)

2. Memory Heap 설정
Android Studio는 어플리케이션 폴더에 그냥 설치가 돼 버리므로 파인더로 설정파일에 접근이 힘들다. 터미널에서 메모리 힙의 설정파일을 수정한다.
파일 경로 : /Applications/Android Studio.app/bin/idea.vmoptions
수정 파일 내용 :
 -Xms512m  
 -Xmx768m  
 -XX:MaxPermSize=350m  
 -XX:ReservedCodeCacheSize=96m  
 -XX:+UseCodeCacheFlushing  
 -ea  
 -Dsun.io.useCanonCaches=false  
 -Djava.net.preferIPv4Stack=true  
 -Dfile.encoding=UTF-8  

P.S. 알고보니 이렇게 좋은 포스팅이 있었네... 굳이 내가 안써도 될 듯! :-)
인텔리J 시작하기 Part1