자바 프로세스에서 어떤 객체들이 얼만큼의 메모리를 점유하고 있는지 알아내기 위해 우리는 Heap 메모리를 분석합니다. 
안드로이드에서는 달빅 VM의 힙 메모리를 3가지 수준에서 분석할 수 있습니다. 

1. 개략적인 수준 - DDMS의 VM Heap 탭



아주 간략히 힙 메모리 통계 정보를 보여줍니다. Total/Allocated/Free 메모리 크기, 주요 타입별 객체 갯수 및 크기를 알 수 있습니다. 이게 전부입니다. 아쉽지만 특정 객체를 꼭 찝어서 할당된 갯수와 크기를 알 수는 없습니다. 
그렇지만 메모리 누수가 의심될 때 실제로 누수인지 아닌지 간단하게 판단하는 용도로 활용할 수 있어보입니다. 의심되는 구간에 대해서 [Cause GC] 버튼을 눌러도 객체들이 GC되지 않고 계속해서 쌓인다면 메모리 누수를 의심할 수 있습니다. (안드로이드에서도 GC log 분석이 된다면 gc 로그를 분석하여 메모리 누수 여부를 판별할 수 있겠지만 제가 아직까지 이 방법을 찾지못했습니다)


2. 약간 상세한 수준 - DDMS의 Allocation Tracker 탭



Allocation Tracker는 트래킹을 시작한 이후로 새롭게 할당된 객체들 정보를 비교적 상세히 볼 수 있습니다. Allocation Tracke 사용에 대한 자세한 내용은 Tracking Memory Allocations 기사를 참고하시면 됩니다.(한글 번역 : http://blog.naver.com/huewu/110082424176)


3. 아주 상세한 수준 - Eclipse Memory Analyzer



전문가 수준으로 힙 메모리를 파악하기 위해서는 힙 덤프를 생성해서 분석해야 합니다. 현존 최고의 무료 자바 힙메모리 분석 도구는 아마 Eclipse Memory Analyzer(MAT)일 겁니다. MAT는 힙 분석을 위한 너무나 방대하고 다양한 기능을 제공하기 때문에 제가 감히(?) 여기서는 사용법을 설명드리지 않겠습니다. -.-;; 자세한 사용법은 MAT 공식 사이트나 Eclipse Memory Analyzer, 10 useful tips/articles 를 참고하시기 바랍니다(실토하자면 MAT는 저도 제대로 사용해보질 못했습니다. 머리 싸매고 힙 분석할 일이 아직 없네요. 문제 생기면 그때 공부하렵니다 ㅎㅎ).

ps. 어째 글이 점점 성의가 없어지는 거 같네요. 하핫.
Posted by 에코지오
,
1. adb 이용
- 먼저 root 권한이 있는지, /data/misc에 쓰기 권한이 있는지 확인합니다.
- shell로 들어가서 해당 프로세스에 SIGUSR1 시그널을 날리면 힙덤프 파일이 떨궈집니다.

$ adb shell
# mkdir /data/misc
# chmod 777 /data/misc (/data/misc에 쓰기권한 확인)
# ps (애플리케이션 프로세스 ID 확인)
# kill -10 <pid> (SIGUSR1 시그널 전송)

(잠시후 /data/misc 에 heap-dump-*.hprof 파일 생성됨)

$ adb pull <dump-file> <as-file> (로컬로 파일 추출)


2. API 이용
- android.os.Debug 클래스의 public static void dumpHprofData(String fileName) 메소드를 호출합니다.
- 단, fileName은 쓰기 권한 있는 경로를 지정해야합니다.


3. DDMS 이용 


- 애플리케이션에 WRITE_EXTERNAL_STORAGE 퍼미션이 설정됐는지 확인합니다.
- sdcard가 있고, sdcard에 쓰기 권한이 있는지 확인합니다.
- 해당 프로세스 선택후 위 그림에서처럼 힙덤프 버튼을 누르면 /sdcard 경로에 <패키지>.hprof 파일이 생성됩니다.


힙덤프 파일 포맷 변경
위 세가지 방법으로 생성한 힙덤프 파일은 Dalvik VM 고유의 포맷을 가집니다. 안드로이드 SDK에 포함된 hprof-conv.exe를 이용하여 표준 hprof 포맷으로 변경할 수 있습니다.

$ hprof-conv.exe <달빅 hprof 파일> <표준 hprof 파일>

이렇게 변경된 hprof 파일은 jhat이나 Eclipse Memory Analyzer(MAT) 같은 Heap 덤프 분석툴을 이용하여 시각적으로 분석할 수 있습니다.
Posted by 에코지오
,
프로세스 : 문제식별 -> 데이터 수집 -> 데이터 분석 -> 가설설정 -> 원인분석 -> 개선방안 -> 해결조치


문제해결 접근방식
  • Divide&Conquer 분석 : 문제를 작은 구간으로 나누어서 분석
  • Event 분석 : log,dump,trace 등 각종 기록 분석
  • Queue 분석 : 자원(cpu/network/memory/connection 등)의 대기행렬 분석. 병목파악

Event 분석
  • log : 시점별 이벤트. history
  • dump : 특정 시점의 리소스 상태. snapshot
  • trace : 리소스 활동상태 추적. profiling

안드로이드에서 주로 발생하는 문제
  • 애플리케이션 응답없음(ANR)
  • 시스템 응답없음(먹통, lock up)
  • 프로그램 오류
  • 낮은 성능
  • Crash
     => 경험에 의한 자료 부족

주요 원인
  • bug : 애플리케이션 오류
  • resource leak : 메모리 누수, 자원미반납 등
  • bottleneck : 디스크 IO 병목? 네트워크 병목?
  • dead lock : 쓰레드 경합
  • bad query : Provider의 악성 SQL
  • unoptimized : 튜닝 안된 파라미터 설정
     => 경험에 의한 자료 부족

분석 방법
  • 힙덤프 분석
  • 쓰레드 분석
  • 가용자원 분석
  • 프로파일링
  • IO 병목 분석
  • 네트워크 분석
  • 소스 디버깅
  • 로그 분석
  • 파일/데이터(DB) 분석

주요 도구
  • ADB
  • logcat
  • TraceView
  • DDMS
  • Eclipse ADT
  • Eclipse MAT
  • 쉘 명령어 : ps, top, ...

데이터 수집

1. 시스템 정보수집 : 분석의 기본
- SW, HW, 네트워크 정보수집
- cpu,memory,network,disk 등 장치 및 kernel 정보
- 리소스 사용량

2. 특정시점의 자원/상태 정보 : 정적 데이터, snapshot, dump
- 힙메모리 덤프 : kill -10 <pid>
- 쓰레드 덤프 : kill -3 <pid>, /data/anr/traces.txt
- App 상태 정보 : dumpsys
- Device 상태 정보 : dumpstate
- 무선연결 정보 : DDMS > Dump radio state

3. 시스템의 활동상태/이벤트 정보 : 동적 데이터, tracing, monitoring
 - 이벤트 로그(히스토리 분석) : logcat
 - 실행 기록(동적활동 추적) : DDMS > Start Method Profiling
 - 리소스 모니터링 : vmstat, top, ...


문제의 사전예방
  • FindBugs : 잠재된 소스오류 검출
  • JUnit : 단위 테스트
  • Monkey : 스트레스 테스트, 랜덤 이벤트 발생
  • Best Practice 준수
Posted by 에코지오
,
한 건의 데이터를 입력하는 테스트는 개발자가 손으로 디바이스에 직접 틱틱 입력하면서 금방 테스트할 수 있습니다. 그러나 1000 건의 데이터를 입력하는 행위를 재현해야 한다면 이건 도저히 사람이 수동으로 할 일이 아니게 됩니다. 얼마전 저한테 그런 일이 닥쳤습니다. -.-;

시나리오는 이렇습니다.

대기 화면 -> 목록 화면 -> 입력 화면 -> 여러가지 값 입력 -> 저장 버튼 -> 목록 화면 -> back 버튼 -> 대기 화면

이 시나리오를 1000 번, 2000 번 반복해야 합니다.

처음엔 JUnitPerf를 참조해서 테스트케이스 안에서 코딩을 통해 반복을 구현하려고 했지만, 답이 안나오더군요. 제가 안드로이드 테스트 프레임워크를 아직 잘 이해를 못한 탓인거 같습니다. 그래서 결국은 그냥 1 건 입력하는 테스트케이스를 만들고 am instrument를 1000번 반복해서 실행하는 것으로 구현했습니다. ^^;

아래처럼 배치파일을 만듭니다. 

@rem 반복횟수. 첫번째 파라미터로 받음.
set REPEAT=%1

@rem 실행할 명령(my.app.test는 테스트케이스가 포함된 패키지명, my.app.test.InsertTest는 테스트케이스 클래스)
set TEST=adb shell am instrument -w -e class my.app.test.InsertTest  my.app.test/android.test.InstrumentationTestRunner

@rem FOR /L %variable IN (start,step,end) DO command [command-parameters]
FOR /L %%A IN (1,1,%REPEAT%) DO %TEST%

배치파일이 TestInsert.bat라면 반복횟수를 파라미터로 주어 실행합니다.

C:\TestInsert.bat 1000

와우! 성공했습니다. 밥먹으러 가기 전에 돌려놓고 나는 맛있게 밥만 먹으면 됩니다. ^^
Posted by 에코지오
,

안드로이드 테스트 기본

am instrument 명령어 자세한 사용법

테스트케이스 차이점

2개의 핵심 테스트케이스
 isolated testing of a single activity
- 시스템 인프라와 약한 연결
- 일부 시스템 자원을 Mock으로 대체

- functional testing of a single activity
- 시스템 인프라 그대로 이용
- 실제 환경과 동일

테스트케이스 작성 샘플

안드로이드용 다른 테스트 프레임워크
(1) Robotium
- 블랙박스 테스트용
- 하나의 테스트케이스에서 여러 액티티비 사이를 이동 가능
- 뷰 요소를 화면상의 index(몇 번째로 나타나는가)로 참조 : 블랙박스 테스트라면 뷰의 ID를 알 수 없기 때문. 
- 그냥 뷰의 ID(R.id.xxx)로 참조하는 API도 제공하면 더 좋을 듯.

(2) Calculon
- 화이트박스 테스트용
- DSL 개념도입 : Watij와 비슷한 방식으로 테스트 코드 작성
- 다른 액티비티로 이동시 해당 액티비티를 참조하기가 어려움

* Robotium과 Calculon을 잠깐 써본 바로는 둘다 아직은 부족한 점이 많아 보입니다.

Posted by 에코지오
,
SQLite DB 테이블 조회할 때 한글과 영어가 섞인 컬럼에 대해서 정렬을 하게되면, SQLite는 기본적으로 기타문자(특수문자,숫자), 영어, 한글 순서로 정렬을 합니다. 보통 ORDER BY 절에 COLLATE LOCALIZED 키워드를 사용하는데, (사실 이게 뭔지는 저도 잘 모르지만) 사용자 로케일이 ko_KR이더라도 우리가 원하는대로 한글 - 영어 - 기타 순으로 정렬되지는 않더군요. 

ORDER BY name COLLATE LOCALIZED ASC; // 기타 - 영어 - 한글 순으로 정렬됨

1. 구분 컬럼을 이용한 방법
우리나라 사용자에게 좀더 자연스러운, 한글 -> 영어 -> 기타 순서로 정렬하기 위해 고민하다가 검색해보니 역시 유용한 팁이 있네요.


해당 컬럼 값이 한글인지, 영어인지, 기타인지 구분해주는 구분컬럼을 두어서 1, 2, 3 식으로 할당을 합니다. 그리고 ORDER BY 절에 이 구분컬럼으로 먼저 정렬을 하면 조회목록에서 한글이 영어보다 먼저 나오게 됩니다. 위 링크에 나오는 것처럼 구분컬럼을 TAG라고 하면,

ORDER BY tag, name COLLATE LOCALIZED ASC; // TAG 컬럼으로 먼저 정렬하므로 한글 - 영어 - 기타 순으로 정렬됨

그러나 TAG와 같은 구분컬럼을 이용하는 경우에는 복잡성이 증가하고 유연성이 떨어집니다. 
우선 테이블 컬럼이 늘어나게 되고, NAME 컬럼에 값이 추가/수정될 때마다 이게 한글인지 영어인지 기타 인지 판단하여 TAG 컬럼 값 역시 적절히 추가/수정해줘야 합니다(이런 일에는 트리거가 유용하겠죠). 우리에게 테이블에 컬럼을 추가할 수 있는 권한이 없을 수도 있습니다. 만약 언어 로케일 설정 또는 화면별로 정렬 순서를 다르게 가져가야 한다면 TAG 컬럼을 활용하기 어려울 수도 있습니다.

2. ORDER BY 절에서 CASE 문을 이용하는 방법
이런 구분컬럼을 추가하지 않아도 우리가 원하는대로 정렬할 수 있습니다. ORDER BY 절에서 CASE 문을 사용해서 동적으로 한글/영어/기타로 구분하면 됩니다.

ORDER BY (CASE WHEN substr(name ,0, 1) BETWEEN 'ㄱ' AND '힣' THEN 1 
                           WHEN substr(name, 0, 1) BETWEEN 'A' AND 'Z' THEN 2
                           WHEN substr(name, 0, 1) BETWEEN 'a' AND 'z' THEN 2
                           ELSE 3 
                 END), 
                 name COLLATE LOCALIZED ASC

제가 SQL 전문가가 아니기 때문에 더 좋은 쿼리가 있는지는 모르겠습니다. 이 방법은 테이블을 고칠 필요가 없으며, 언어 로케일이나 화면 등 상황에 따라서 ORDER BY 절에서 정렬 순서를 수정하면 되므로 유연합니다. 동일한 CASE 구문이 여러 곳에서 쓰인다면 SQL 함수로 만들거나 자바 메소드로 만들어두면 됩니다. 다만 구분컬럼을 두는 1번 방법보다는 성능면에서 안 좋습니다. 그러나 테스트해 본 바로는 생각보다 그리 느려지지 않았습니다.

ps. 위 2가지 방법 모두 완벽한 정렬은 아닙니다. 첫글자 이후로는 기타 - 영어 - 한글 순으로 소팅됩니다. 즉 아래와 같이 정렬됩니다.
 - 가나다123
 - 가나다abc
 - 가나다라마바

ps2. SQLite가 COLLATE LOCALIZED 키워드를 어떻게 해석하는지 low level의 소스를 분석해보면 좀더 근본적인 해결 방법이 있을것 같습니다.

Posted by 에코지오
,
안드로이드 애플리케이션 소스를 디버깅하는 최선의 방법은 이클립스에서 [Debug As > Android Application]을 실행하는 것입니다. 그러나 어떤 경우에는 이 메뉴를 이용할 수 없거나 또는 이용할 필요가 없는 상황도 생깁니다.  
예를들어 Debug As 메뉴를 실행했더니 바빠 죽겠는데 어디가 꼬였는지(?) 계속 아래와 같은 에러가 발생한다면?

[2010-04-12 11:33:41 - Contacts]Installing Contacts.apk...
[2010-04-12 11:34:19 - Contacts]Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE
[2010-04-12 11:34:19 - Contacts]Please check logcat output for more details.
[2010-04-12 11:34:19 - Contacts]Launch canceled!

또는 로컬의 애플리케이션 소스가 타겟에 설치된 버전과 소스가 동일해서 재설치하거나 덮어쓸 필요가 없는데, 소스는 디버깅하고 싶다면?
이럴 때는 Debug As 메뉴를 고집하지 말고 임시로 수동으로 디버깅하면 됩니다. 

수동으로 프로세스에 디버거 붙이기
디버깅하고자 하는 애플리케이션 프로세스에 디버거를 여러분이 직접 수동으로 붙여서(attach) 디버깅할 수 있습니다. 다음 과정을 따릅니다.

  1. 타겟(에뮬레이터)에서 해당 애플리케이션을 시작시킴 
  2. 이클립스 DDMS에서 해당 프로세스를 선택
  3. 미리 만들어둔 리모트 디버그 실행설정을 실행함 
  4. 이제 소스에 중단점 존재시 디버그 퍼스펙티브로 전환됨

* 이클립스에 리모트 디버그 실행 설정 만들기
  • 프로젝트 오른 클릭 > Debug As > Debug Configurations 실행
  • Remote Java Application 타입으로 새로운 launch 설정 생성
  • Port를 8700번으로 수정
  • Apply 클릭 (Debug 클릭하면 바로 실행됨)


프로세스에 디버거 붙이는 작업을 자동화하기

만약 수동으로 디버거를 붙이는 작업을 자꾸 반복해야 한다면, 이것은 당연히 비효율적인 일이 되고 맙니다. 

또한 디버거를 붙이는 작업을 사람이 수동으로 처리하다보니, 애플리케이션 시작부터 리모트 디버거를 붙이기까지 다소 시간이 걸릴 수 있습니다. 이렇게 되면 디버거가 연결되기 전에 액티비티의 onCreate() 같은 메소드에 찍어둔 중단점은 지나쳐 버릴 수가 있습니다 (아 물론, 이 문제는 에뮬레이터의 Dev Tools 애플리케이션의 Development Settins에서 아래처럼 Wait For Debugger 옵션을 체크하여 방지할 수 있습니다).



어쨋든 디버거 붙이는 과정은 가급적 스크립트로 만들어두고 자동으로 실행시키는 것이 좋습니다.


▶ 타겟(에뮬레이터)에서 해당 애플리케이션을 시작

am(Activity Manager) 명령어를 이용합니다. 타겟에서 지정된 액티비티를 디버그 모드로 시작하는 명령형식은 다음과 같습니다.

am start -D -n <package-name>/<package-name>.<class-name> 

자동으로 해당 액티비티 프로세스의 디버깅 포트가 8700 포트로 포워딩되며 만약 8700 포트로 붙는 디버거가 없으면 액티비티는 디버거가 붙을 때까지 대기합니다. 다음은 Contacts 네이티브 애플리케이션의 주소록 목록화면 액티비티 띄우는 예제입니다.

$ adb shell am start -D -n com.android.contacts/.ContactsListActivity


▶ 이클립스 DDMS에서 해당 프로세스를 선택 

이클립스 DDMS를 보지 않고 방금 띄운 프로세스의 디버깅 포트를 알아내는 것이 핵심입니다. 디버깅 포트는 이렇게 알아낼 수 있습니다.

(1) 해당 프로세스가 마지막에 뜬 프로세스인 경우

adb jdwp | tail -1

(2) 프로세스의 이름을 알고 있는 경우

# ps| grep 프로세스명 | awk '{print $2}'
# 다음은 프로세스명이 android.process.acore인 경우 예제
$ adb shell ps | grep android.process.acore | awk '{print $2}'

이제 리모트 디버깅 실행설정에서 설정해둔 8700 포트를 이렇게 알아낸 포트로 포워딩하면 됩니다.

# 먼저 위에서 알아낸 디버깅 포트를 $DEBUG_PORT 변수에 저장합니다
$ adb forward tcp:8700 jdwp:$DEBUG_PORT


▶ 이클립스 리모트 디버그 실행설정을 실행
이클립스에 만들어둔 '리모트 디버그 실행설정'도 스크립트을 통해서 실행하는 방법이 있으면 좋겠네요. 이 부분은 좀더 찾아봐야겠습니다.

Posted by 에코지오
,

지난 글에서는 로컬의 네이티브 애플리케이션 소스를 이클립스를 통해 쉽게 디버깅할 수 있도록, 에뮬레이터에 내장된 것과 동일한 키로 서명하는 방법을 알아봤습니다. 그러나 굳이 내장된 것과 동일하게 서명하지 않고(즉 Custom Debug Keystore를 만들지 않고) 로컬 네이티브 애플리케이션을 디버깅할 수 있습니다. 

(1) 내장된 애플리케이션을 설치 제거하거나(uninstall)

(2) 내장된 패키지(apk) 파일을 내가 빌드한 apk 파일로 덮어쓴 후(overwrite)

그러고 나서 이클립스에서 Debug As로 디버깅하면 됩니다.

1. 네이티브 애플리케이션 uninstall하기

에뮬레이터에서 기존 네이티브 애플리케이션을 설치제거(uninstall)합니다. 

# 그냥 언인스톨하면 안됩니다
$ adb uninstall com.android.calculator2
Failure

# 아직 rm으로 파일을 삭제할 수 없습니다
$ adb shell rm /system/app/Calculator.apk
rm failed for /system/app/Calculator.apk, Read-only file system

# remount는 /system 파티션을 ro(read-only)에서 rw(read-write)로 바꿉니다
$ adb remount

# 이제 rm으로 apk를 삭제하고 uninstall합니다
$ adb shell rm /system/app/Calculator.apk
$ adb uninstall com.android.calculator2

Success

# 기존 데이터를 보존하고 uninstall하려면 -k 옵션 추가
$ adb shell pm uninstall -k com.android.calculator2

▶ 네이티브 애플리케이션 제거 순서 요약 : remount => remove apk => uninstall 


2. 또는 네이티브 패키지 파일을 덮어쓰기

내장된 애플리케이션 패키지 파일(apk)을 로컬에서 빌드된 파일로 강제로 덮어씌우고 디버깅할 수 있습니다.

# remount는 /system 파티션을 ro(read-only)에서 rw(read-write)로 바꿉니다
$ adb remount

# 내장된 apk를 로컬 apk로 overwrite합니다
$ adb push C:\Calculator\bin\Calculator.apk /system/app


이클립스에서 Debug As 실행

내장된 애플리케이션을 언인스톨하거나 로컬 패키지 파일로 덮어쓴 후에 이클립스에서 [프로젝트 오른 클릭 > Debug As > Android Application]을 실행합니다. 이제 로컬에서 빌드된 네이티브 애플리케이션이 타겟에 새롭게 설치되면서 소스를 디버깅할 수 있습니다. (이 경우 apk는 /data/app에 설치됩니다. /system/app에 설치되지 않습니다)


별거 없네요. 어때요? 참, 쉽죠? ^^

Posted by 에코지오
,
이클립스(+ ADT 플러그인) 환경에서 애플리케이션을 개발하고 소스(*.java)를 디버깅하는 방법은 무척이나 쉽습니다. 소스에 중단점을 찍고나서 [프로젝트 선택 > 오른클릭 > Debug As > Android Application]을 실행하는게 전부이죠.



개발자가 Debug As > Android Application을 실행했을 때 이클립스가 무슨 일을 하는지 알아볼까요?

1. 에뮬레이터가 런치되면서 기본 액티비티가 시작됩니다.

2. DDMS의 Devices 뷰에서는 해당 애플리케이션 프로세스가 선택되어 있고 초록색 벌레가 붙어있는 것을 볼 수 있습니다.



3. 소스에 중단점(break point)이 있으면 디버그 퍼스펙티브로 전환됩니다.

이 모든 걸 이클립스가 알아서 자동으로 실행해줍니다. 한편 Console에는 아래와 같은 메시지가 출력됩니다.

[2010-03-30 11:08:56 - ActivityLifecycleProject]------------------------------
[2010-03-30 11:08:56 - ActivityLifecycleProject]Android Launch!
[2010-03-30 11:08:56 - ActivityLifecycleProject]adb is running normally.
[2010-03-30 11:08:56 - ActivityLifecycleProject]Performing my.andr3.life.MyActivity activity launch
[2010-03-30 11:08:56 - ActivityLifecycleProject]Automatic Target Mode: launching new emulator with compatible AVD 'myavd'
[2010-03-30 11:08:56 - ActivityLifecycleProject]Launching a new emulator with Virtual Device 'myavd'
[2010-03-30 11:09:05 - ActivityLifecycleProject]New emulator found: emulator-5554
[2010-03-30 11:09:05 - ActivityLifecycleProject]Waiting for HOME ('android.process.acore') to be launched...
[2010-03-30 11:11:24 - ActivityLifecycleProject]HOME is up on device 'emulator-5554'
[2010-03-30 11:11:24 - ActivityLifecycleProject]Uploading ActivityLifecycleProject.apk onto device 'emulator-5554'
[2010-03-30 11:11:24 - ActivityLifecycleProject]Installing ActivityLifecycleProject.apk...
[2010-03-30 11:11:59 - ActivityLifecycleProject]Success!
[2010-03-30 11:12:00 - ActivityLifecycleProject]Starting activity my.andr3.life.MyActivity on device
[2010-03-30 11:12:09 - ActivityLifecycleProject]ActivityManager: Starting: Intent { cmp=my.andr3.life/.MyActivity }
[2010-03-30 11:12:13 - ActivityLifecycleProject]Attempting to connect debugger to 'my.andr3.life' on port 8615

콘솔 로그를 분석해보면 생각보다 많은 작업들이 벌어지는 것을 알 수 있습니다.
  1. 에뮬레이터가 떠있지 않다면 에뮬레이터를 띄움
  2. 프로젝트/bin에 빌드된 패키지 파일(.apk)을 디바이스에 업로드함 : adb push
  3. 업로드된 apk 파일을 /data/app에 설치(or 재설치) : adb install -r 
    - LogCat 로그를 보면 에뮬레이터 내부적으로 무슨 일이 더 벌어지는지 상세히 알 수 있음
  4. 애플리케이션 프로세스(Dalvik VM)가 생성되면서 기본 액티비티를 시작시킨다. : am start
  5. DDMS는 해당 VM의 디버그 포트(JDWP)를 8700 포트로 포워딩(DDMS에서 해당 프로세스가 선택됨) : adb forward
  6. 이클립스 디버거가 8700 포트에 연결(Dalvik VM과 이클립스가 통신시작) : DDMS에서 해당 프로세스에 초록색 벌레 아이콘 나타남
  7. 소스 중단점 존재시 이클립스 디버그 퍼스펙티브로 전환됨

* 'Dalvik VM - DDMS - Eclipse' 사이의 연결관계에 대한 자세한 내용은 ekwang님의 글 참조 : http://ekwang.tistory.com/4

Posted by 에코지오
,

네이티브 애플리케이션 소스를 수정하여 컴파일, 테스트, 디버깅해야 할 경우가 있습니다. 주로 제조사에서 그런 작업을 합니다. 네이티브 애플리케이션 커스터마이징을 위해 제일 먼저 할 일은 당연히 이클립스에 네이티브 애플리케이션 프로젝트를 구성하는 것입니다. 이클립스 환경에서 네이티브 앱을 빌드하는 방법을 알아보죠.

1. 일단 안드로이드 소스 저장소(http://android.git.kernel.org/)에서 해당 네이티브 애플리케이션 소스를 다운받습니다. snapshot 링크를 클릭하면 압축파일로 한번에 쉽게 다운로드 받을 수 있습니다. 



2. 압축을 풀고 이클립스에서 새로운 Android Project로 구성합니다. 생성 마법사에서 Android Project 선택 후 Create project from existing source 선택하여 소스 경로를 설정합니다.



3. 다행히 Calculator 처럼 공개된 안드로이드 프레임워크 API(android.jar)만 사용하는 애플리케이션이라면 일반적인 유저 애플리케이션처럼 큰 문제 없이 잘 빌드됩니다.


4. 그러나 Contacts 처럼 숨겨진 프레임워크 API에 의존하는 경우 android.jar 만으로는 컴파일 자체가 안됩니다. Contacts는 안드로이드 풀소스 빌드 과정에서 중간 결과물로 생성되는 classes.jar 등에 의존하고 있는데, 이런 경우는 짤없이 안드로이드 전체 소스를 다운받아 몇 십분~몇 시간 걸리는 full 빌드를 우분투 환경에서 한번은 해줘야 합니다. 


android.jar 외에 어떤 jar 파일을 빌드패스에 추가할 지는 Android.mk 파일 등을 참조하여 판단하면 됩니다.

좀 더 자세한 설명은 다음 링크를 참조하세요.


* 전체 네이티브 패키지(애플리케이션, 프로바이더 등)를 이클립스를 이용하여 한꺼번에 빌드하기 위한 세팅은 다음 링크를 참조합니다.

http://source.android.com/using-eclipse
http://blog.naver.com/jang2818?Redirect=Log&logNo=20078863663



Posted by 에코지오
,