'안드로이드'에 해당되는 글 7건

  1. 2010.04.03 [android] MapView와 ItemizedOverlay 사용 시 NullPointerException이 발생하는 경우 (5)
  2. 2009.12.08 [Android] SDK Build시 SDCard 인식 오류 문제 (1)
  3. 2009.06.11 [android] Wizard에서 Android XML File 생성 시 오류 발생 문제
  4. 2009.06.08 [android] Application, Activity 그리고 Task (2)
  5. 2009.05.28 [android] Android Dev Phone Firmware 복구 하기 (2)
  6. 2009.05.07 [android] Android Dev Phone Firmware Upgrade 하기 (2)
  7. 2009.02.28 Google Android Build 해 보기 #1 (1)
2010.04.03 19:29

[android] MapView와 ItemizedOverlay 사용 시 NullPointerException이 발생하는 경우

Android SDK에는 Open Source를 이용한 API와 함께 Google에서 제공하는 서비스를 이용 할 수 있는 별도의 API가 포함된 SDK가 있다. 이를 이용한 것 중 대표적인 것이 바로 MapView일 것이다.

MapView는 사용자가 만드는 Android Activity에 Google Map을 보여주는 View 클래스이다. 이를 이용하면 Google Map 서버에서 지도와 함께 다양한 정보를 얻을 수 있으므로 꽤나 유용하다. 물론 Google이 직접 만든 Google Map App과는 차이가 있지만 거의 비슷하게나마 사용 할 수 있다.

Google Map App에서 검색을 할 경우 화면에 보여지는 것은 ItemizedOverlay라는 것을 이용한다. 이는 지도 화면 위에 아이템을 투영하여 보여주는 것으로 검색 좌표 결과를 지도와 함께 표시해 줄 때 사용하곤 한다. ItemizedOverlay를 사용 할 때 간혹 지도 화면을 Touch하면 바로 아래와 같은 NullPointerException이 발생하는 경우가 있다.

WARN/dalvikvm(661): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
ERROR/AndroidRuntime(661): Uncaught handler: thread main exiting due to uncaught exception
ERROR/AndroidRuntime(661): java.lang.NullPointerException
ERROR/AndroidRuntime(661):     at com.google.android.maps.ItemizedOverlay.getItemsAtLocation(ItemizedOverlay.java:617)
ERROR/AndroidRuntime(661):     at com.google.android.maps.ItemizedOverlay.getItemAtLocation(ItemizedOverlay.java:586)
ERROR/AndroidRuntime(661):     at com.google.android.maps.ItemizedOverlay.handleMotionEvent(ItemizedOverlay.java:498)
ERROR/AndroidRuntime(661):     at com.google.android.maps.ItemizedOverlay.onTouchEvent(ItemizedOverlay.java:572)
ERROR/AndroidRuntime(661):     at com.google.android.maps.OverlayBundle.onTouchEvent(OverlayBundle.java:63)
ERROR/AndroidRuntime(661):     at com.google.android.maps.MapView.onTouchEvent(MapView.java:625)
ERROR/AndroidRuntime(661):     at android.view.View.dispatchTouchEvent(View.java:3709)
ERROR/AndroidRuntime(661):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:851)
ERROR/AndroidRuntime(661):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:821)
ERROR/AndroidRuntime(661):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:821)
ERROR/AndroidRuntime(661):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:821)
ERROR/AndroidRuntime(661):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:821)

이 Exception은 MapView에 등록한 ItemizedOverlay에 OverlayItem이 하나도 없는 경우 발생하는 경우이다.  Open source가 아닌 Google API에서 발생하는 것으로 명확한 오류는 잘 모르지만 짐작컨데 다음과 같은 원인이 있는 것 같아 다음과 같은 상황을 생각해 볼 수 있다.

1. 화면을 Touch 할 경우만 발생하므로 Touch에 관련된 것이다.
2. ItemizedOverlay를 사용할 경우만 발생하므로 ItemizedOverlay에 대한 정보가 더 필요할 것이다.

즉,  ItemizedOverlay를 좀 더 살펴 볼 필요가 있다. ItemizedOverlay는 MapView에 추가하여 MapView 보다 먼저 Touch 이벤트를 받아 처리하며 일반적인 경우는 ItemizedOverlay에 등록된 Item이 선택이 되었는지 확인하고 선택된 Item의 정보를 callback한다. 이런 점을 미루어 볼 때 Empty item에 대한 처리가 되어 있지 않다는 것을 알 수 있었다.

이와 관련된 정보를 찾다보니 이런 오류가 발생하는 사람들이 꽤 있었는데 ItemizedOverlay를 상속받은 후 Constructor에서 무조건 populate()를 한 번 호출하는 방법으로 오류를 피할 수 있다고 한다.

참고 : http://code.google.com/p/android/issues/detail?id=2035

Google에서 제공하는 MapView 예제에는 다음과 같이 ItemizedOverlay에 OverlayItem을 추가할 때 마다 populate()를 호출하도록 되어 있다.

public void addOverlay(OverlayItem overlay) {

    mOverlays
.add(overlay);

    populate
();

}

Java Document에는 다음과 같이 populate() method에 대한 설명이 되어 있다.

void com.google.android.maps.ItemizedOverlay.populate()

protected final void populate()
Utility method to perform all processing on a new ItemizedOverlay. Subclasses provide Items through the createItem(int) method. The subclass should call this as soon as it has data, before anything else gets called.

번역해 보면 이런 내용이다.

새로운 ItemziedOverlay에 대한 모든 처리를 수행하는 유틸리티 메소드. 상속받은 클래스는 Items들을 createItem(int) 메소드를 통해 제공하다. 이 클래스에서는 데이터를 갖은 후 어떤 것을 호출하기 전에 가능한 한 빨리 이 메소드를 호출 해야만 한다.

ItemizedOverlay에 OverlayItem을 등록하거나 변경되면 그 정보를 ItemizedOverlay가 처리하도록 populate()를 호출해야 하는 것인데, 만약 Overlay 생성 후 Item을 하나도 추가하지 않으면 populate()가 아예 호출되지 않게 된다. 그렇기 때문에 Touch 시 잘못된 정보로 인한 오류가 발생한다.

어찌보면 ItemizedOverlay의 구현에 문제가 있는 것일 수도 있지만 그 내부는 알 수 없으니 이를 회피하기 위해 Constructor에서 아예 한 번은 populate()를 호출하는 방법을 이용해 이 오류를 회피하면 Touch 시에도 오류가 발생하지 않게 된다.
Trackback 0 Comment 5
2009.12.08 15:41

[Android] SDK Build시 SDCard 인식 오류 문제

Custom SDK로 Build한 경우 SDcard를 지정했음에도 불구하고 SDCard가 인식되지 않는 경우가 있는데 target의 경우 sdcard의 삽입이나 분리를 통해 mount를 인식하게 되어 있다. SDK는 해당 이미지를 로딩하도록 되어 있는데 초기에 mount를 하지 않아 sdcard의 인식이 되지 않는 문제가 있다. (cupcake 기준) 이럴 경우 Emulator를 실행 후 ADB shell에서 다음과 같이 sdcard를 mount 해 주면 된다.

1. Root 권한으로 adb 실행

> cd android-sdk-windows-1.5_r2\tools
> adb root

2. Shell 진입

> adb shell

3. Mount 정보 확인

# mount
mount
rootfs / rootfs ro 0 0
tmpfs /dev tmpfs rw,mode=755 0 0
devpts /dev/pts devpts rw,mode=600 0 0
proc /proc proc rw 0 0
sysfs /sys sysfs rw 0 0
tmpfs /sqlite_stmt_journals tmpfs rw,size=4096k 0 0
/dev/block/mtdblock0 /system yaffs2 ro 0 0
/dev/block/mtdblock1 /data yaffs2 rw,nosuid,nodev 0 0
/dev/block/mtdblock2 /cache yaffs2 rw,nosuid,nodev 0 0

4. SDcard Mount

#mount -rw -t vfat /dev/block//vold/179:0 /sdcard

마운트가 되었는지 다시 확인 해 보면 다음과 같이 나온다

# mount
mount
rootfs / rootfs ro 0 0
tmpfs /dev tmpfs rw,mode=755 0 0
devpts /dev/pts devpts rw,mode=600 0 0
proc /proc proc rw 0 0
sysfs /sys sysfs rw 0 0
tmpfs /sqlite_stmt_journals tmpfs rw,size=4096k 0 0
/dev/block/mtdblock0 /system yaffs2 ro 0 0
/dev/block/mtdblock1 /data yaffs2 rw,nosuid,nodev 0 0
/dev/block/mtdblock2 /cache yaffs2 rw,nosuid,nodev 0 0
/dev/block//vold/179:0 /sdcard vfat rw,fmask=0000,dmask=0000,allow_utime=0022,co
depage=cp437,iocharset=iso8859-1 0 0

근데 이렇게 할 경우 emulator를 실행할 때 마다 이와 같은 작업을 해야하므로 여간 귀찮은 일이 아닐 수 없다. 그럴 경우 아래와 같이 core의 makefile을 수정하는 방법을 이용한다.

$ANDROID_ROOT/build/core/main.mk : 214 line
# Install an apns-conf.xml file if one's not already being installed.
ifeq (,$(filter %:system/etc/apns-conf.xml, $(PRODUCT_COPY_FILES)))
  PRODUCT_COPY_FILES += \
        development/data/etc/apns-conf_sdk.xml:system/etc/apns-conf.xml
  ifeq ($(filter eng tests,$(TARGET_BUILD_VARIANT)),)
    $(warning implicitly installing apns-conf_sdk.xml)
  endif
endif

이 코드 다음에 아래와 같이 vold.conf에 대한 정보를 추가한다.

ifeq (,$(filter %:system/etc/vold.conf:, $(PRODUCT_COPY_FILES)))
  PRODUCT_COPY_FILES += \
        development/data/etc/vold.conf:system/etc/vold.conf
  ifeq ($(filter eng tests,$(TARGET_BUILD_VARIANT)),)
    $(warning implicitly installing vold.conf)
  endif
endif

생성된 system.img를 직접 수정하여 vold.conf를 넣을 수도 있을 수도 있겠지만 system.img 파일은 yaffs2라는 format으로 되어 있다. yaffs2 는 android에서만 이용하는 것이므로 NAND Boot용으로 만들어진 Format이라고 한다. 따라서, 직접 수정은 어렵고 위와 같이 makefile을 수정하는 편이 더 편하다.
Trackback 1 Comment 1
2009.06.11 18:08

[android] Wizard에서 Android XML File 생성 시 오류 발생 문제

이번 Android SDK가 v1.5 r2로 업데이트 된 후 이전에 안보이던 문제가 생겼다. 프로젝트에서 Android XML 파일을 생성하기 위해 Wizard를 실행 할 경우 다음과 같은 메시지와 함께 생성이 되지 않는다.

The sleected wizard could not be started. ..
Reason:
Plug-in com.android.ide.eclipse.adt was unable to load class
com.android.ide.eclipse.wizards.NewXmlFileWizard




Eclipse 플러그인과 관련된 버그 같은데 현재 사용하고 있는 Eclipse Europa 버젼이 문제인지는 확인 해 봐야겠다.

급한대로 일반 파일을 만든다음 XML로 확장자를 변경해서 사용 하라는 사람들도 있는데 꽤나 불편하다. 대신 Android ToolBar의 단축 아이콘을 이용하면 오류가 발생하지 않으므로 이를 이용하면 된다.

Java Perspective에 Android Eclipse Plugin을 설치하면 아래와 같이 Android Category 가 설치 된 것을 볼 수 있으며, 이 중 빨간색으로 표시된 아이콘을 선택하면 Android XML File을 바로 생성 할 수 있다.




Trackback 0 Comment 0
2009.06.08 11:20

[android] Application, Activity 그리고 Task

안드로이드 플랫폼에서는 Application 이외에 Activity도 있고 Task 라는 개념도 있다. 이런 개념은 일반적인 OS의 것과 사뭇 달라 약간 혼란스러운 면이 있다. 일단 이런 용어들은 안드로이드에서만 사용하는 새로운 개념으로 생각하고 전반적인 모습을 살펴보도록 하자.


1. Android Applicatin Basic Concept
안드로이드 Application의 기본적인 컨셉은 Application, Activity, Activity Stack 그리고 Task의 4가지이다. 각각의 컨셉은 다음과 같다.


a. Application
Application은 하나 이상의 Activity와 Resource 등이 하나로 묶여 있는 꾸러미 (Bundle)를 말한다. Application은 APK 형식의 파일로 되어 있으며 단말에 복사 설치 할 수 있다.


b. Activity
Activity는 Android Application의 기본 구성 단위로 특정 동작의 수행을 나타내는 객체이다. 하나 이상의 Activity로 구성될 수 있으며 다른 Activity를 호출하거나 다른 Activity에게 노출하여 다양한 조합으로 Application을 구성 할 수 있다.

Activity는 보여주기, 편집하기, 전화걸기, 사진찍기, 검색하기, 데이터 보내기, 음성인식 시작하기 혹은 특정한 타입의 사용자 액션에 대한 동작과 같이 한가지 혹은 그 영역이 잘 정의된 형태의 Visual User Interface로 디자인 되었다.

당연한 이야기지만, 화면에 어떤 것을 표현하는 Application이라면 적어도 display에 대응되는 Activity를 적어도 하나 이상 가지고 있어야 한다.

Android 단말을 이용할 때 사용자들 User Interface를 통해 Activity들을 하나씩 시작하며 이동하게 되고, 내제된 동작에 대해 전혀 생각하지 않게 되므로 이런 경험(User Experience)들은 Activity에서 Activity로 넘어가든 Task에서 Task로 넘어가든 일관된 모습을 가져야 한다.

Activity들은 특정 타입의 Content (데이터)를 처리하며 사용자 행동을 입력 받도록 되어 있다. 일반적으로, 각각의 Activity들은 Life Cycle을 가지게 되는데 이는 다른 같은 Application이나 Task 내에서도 독립적이다. - 각 Activity들은 독립적으로 시작되고, 필요에 따라 사용자 혹은 시스템에 의해 시작, 실행, 중지, 재게, 정지 그리고 재시작 한다. Activity들은 독립적이기 때문에 다양한 방법으로 재사용 될 수도 있고 다른 Activity들로 대치될 수도 있다.

이런 Activity는 Application Component 4가지 (Activity, Services, Broadcase Receiver, Content Provider) 중 가장 중요한 부분이다. Appclication Component 에 대한 자세한 내용은 Application Component을 참고하기 바란다.


c. Activity Stack

사용자가 Activity에서 Activity로 넘어감(Application이 넘어 갈 수도 있음)에 따라 Android 시스템은 사용자가 접했던 Activity들을 순차적으로 기록 유지하고 있게 된다. 이것이 Back Stack으로 알고 있는 Activity Stack이다. 일반적으로 사용자가 새로운 Activity를 생성할 때, Activity Stack에 추가되므로 BACK 키를 누르면 스택에 있는 이전 Activity를 보여준다. 그러나, 사용자가 마지막으로 HOME으로 온 경우는 BACK 키를 눌러도 되돌가 갈 수 없다.

현재 Stack에 Activity를 추가하는 것은 activity가 새로운 task(Home으로 돌아가는 것 없이 task가 시작되었던 것 만큼 오래 걸림)로 시작하는 것과는 상관이 없으므로 뒤로 돌아가는 것은 이전 task에서 있는 activity들로 돌아가는 것을 허락하는 것이다.

사용자는 Application Launcher나 short-cut 아니면 "Recent Task" 스크린에서 Root Activity를 선택함으로써 가장 최근의 Home 보다 더 빨리 task를 가질 수 있다.

Activity만이 Activity Stack에 더해 질 수 있으므로 view, window, menu 그리고 dialog 등은 안된다. 그러므로, 사용자가 스크린 A를 가지고 있고 다음 이어진 순서로 스크린 B로 갔다가 BACK 키를 눌러 스크린 A로 돌아오기를 원한다면, nativigation을 설계 할 때 스크린 A는 Activity로 구현되어야 하는 것이다. 하나의 예외가 있다면 Application이 manage navigation 자체를 관리하는 경우이다.



d. Task

Task는 사용자가 특정 목적을 이루기 위해 따르게 되는 연속된 Activity들로 Activity가 어떤 Application에 속해 있는지는 상관 하지 않는다.

새로운 Task에 대해 명확하게 정해지기 전까지 사용자가 시작하는 모든 Activity들은 현재 Task의 일부로 간주된다. 이런 Activity들은 다른 Application에도 있을 수 있다는 것이 주목할 만한 점이다. Contact에서 시작한 task가 E-mail address를 선택해서 email activity를 유지하고, file을 첨부해서 picture gallery에서 이미지를 선택 할 수 있는 것이다. Contacts, email 그리고 picture gallery는 모두 별도의 application이다.

Task를 시작하는 Activity는 Root Activity에서 호출된다. 이는 반드시 그런 것은 아니지만 Application Launcher, Home Screen의 Shourtcut 아니면 "Recent tasks" (HOME키를 오래 누르고 있으면 나옴)에서 빈번히 호출된다. 사용자들은 task를 처음 시작했을 때외 마찬가지로 root activity에 대한 icon을 선택하므로써 task로 되돌아 갈 수 있다. 한 번 task에 속해지면, BACK 키를 눌렀을 때 task의 이전 activity로 되돌아가게 된다. Activity Stack은 하나 혹은 그 이상의 Task로 만들어져 있다.

Task에 대한 몇 가지 예를 들어 보자:

* 첨부 데이터와 함께 문제 메시지를 보낸다
* 유튜브 비디오를 보고 email로 다른 사람들과 공유한다.


Interruping the Task
task의 매우 중요한 속성은 사용자가 다른 task를 수행하기 위해 현재 실행 중인 task를 interrupt를 할 수 있으며, 떠나 왔던 원래 task를 완료하기 위해 다시 되돌아 갈 수 있다는 것이다. 이것은 사용자들이 여러개의 task를 동시에 실행 할 수 있으며 task 간 전환도 할 수 있게 하는 것이다. 다른 task로 넘어가는 방법이 두 가지가 있는데, 사용자가는 interrupt 전의 위치로 되돌아 올 수 있어야 한다.

* 사용자는 notification에 의해 interrupt 된다 - notification은 나타나면 사용자는 그에 맞는 동작을 하길 원한다
* 사용자가 다른 task를 수행 하길 원한다 - 사용자는 HOME 키를 눌러 Home으로 되돌아가 Applicaiton을 실행한다.


물론 예외적인 규칙이 있다. 위에 언급된 두 가지 방법 이외, Task를 시작하는 제 3의 방법이 있는데, Activity를 시작 할 때 자기 자신을 Task로 시작하게 하는 경우다. Maps와 Browser가  이런 동작을 하는 Application이다.

예를 들어, email에서 address를 선택하는 것은 Maps activity를 새로운 task로 시작하는 것과 같고, email에서 link를 선택하는 것은 Browser Activity를 새로운 task로 시작하는 것과 같다. 이런 상태에 BACK 키를 누른 경우 Home에서 시작한 것이 아니므로 다른 Task(email)에 있는 이전 Activity로 되돌아 가게 된다.




2. Activity & Task

Activity와 Task는 기존의 일반적인 OS의 것과는 꽤 많은 차이가 있어 위의 설명으로는 이해가 어려울 수 있다. 다음의 예를 들어 Activity와 Task의 관계에 대해 명확히 알아보자

a. Home Key와 Back의 차이

Application을 실행하면 해당 Application의 Root Activity가 먼저 실행 된다. 그 상태에서 BACK 키나 HOME 와 같은 Activity 전환에 대한 키를 누를 수가 있다. Android 에서는 이런 동작에 따라 Activity와 Task에 대한 동작이 달라진다.

1) Home Activity에서 Application을 실행

Home에서 Application을 실행 할 경우 Application의 Root Activity는 다음과 같은 상태가 된다.

Home Activity : Foreground → Background
App Activity : <Create> → Foreground




2-1) BACK 키를 눌러 Home으로 이동하는 경우

만약 BACK 키를 누를 경우 Back Activity는 Home Activity이므로 현재 Activity를 제거하고 Home으로 되돌아간다. Back 키를 누르더라도 Activity가 Destory 되지 않는 예외 경우도 있는데 Audio Player와 처럼 Background 실행이 필요한 경우Service 형태로 처리한 경우이다.

Home Activity : Background → Foreground
App Activity : Foreground → <Destory>

그림으로 나타내 보면 다음과 같다.



이 상태에서 Application을 실행하면 처음 Application을 실행 할 때와 동일한 동작을 수행한다.




2-2) HOME 키를 눌러 Home으로 이동하는 경우

Activity를 실행 중 HOME 키를 누르면 무조건 Home Activity로 되돌아간다. 이럴 경우 실행 중이던 Activity는 잠시 Background 상태가 되지만 제거 되지는 않는다.

Home Activity : Background → Foreground
App Activity : Foreground → <Stop>  → Background




만약 이 상태에서 Stop된 Application과 동일한 Application을 실행 하는 경우 이미 실행 중이며 Background 상태였던 Activity가 다시 활성화 된다.

Home Activity : Foreground → Background
App Activity : Background → <Running>  → Foreground


만약, 새로운 Application을 실행할 경우 새로운 Task 가 활성화 되는 것으로 기존 Application과 동시에 실행되는 모습이 된다.

Home Activity : Foreground → Background
App Activity : Background in Task #1
New Acitiivy : <Create> → Foreground in Task #2




b. Activity 재사용하기

Activity A가 다른 application에 있는 Activity B를 시작할 때, activity B는 재사용 되었다(re-used)라고 한다. 이런 경우는 보통 Activity A는 여건이 없고 Activity B에는 있을 때 발생한다.


1) Contacts에서 Gallery를 재사용하여 사진얻기

Contacts Activity는 주소록의 사진 항목을 가지고 있지만, 사진이 보관되어 지는 곳은 보통 Gallery이다. 그렇기에 Contacts에서 사진을 가져오기 위해 Gallery activity를 재사용 할 수 있다. 이것은 Gallery activity의 재사용에 대한 좋은 예일 것이다. 다음 그림은 이미지 영역 지정(Crop)까지의 일련의 Activity 들을 나타내고 있다.



사용자가 Contacts를 선택하고, viewing을 위한 주소를 선택하고, MENU > Edit를 선택하고, Gallery activity를 실행 해 줄 사진 필드를 선택한다. 사용자는 원하는 사진을 선택하고, 영역을 지정(Crop) 한 후 저장한다. 이 이미지는 주소록의 사진 필드로 넣어져야 하기 때문에 저장 된다.

Gallery에서 Contact application로 사진을 준다는 것에 주목한다. 다음 예제는 result를 가져오지 않는 activity의 재사용에 대한 것이다. 이 또한 activity나 activity stack을 통핸 navigation history를 묘사하고 있음에 주목해야 한다. - 사용자는 모든 activity의 back 동작을 통해야만 Home으로 되돌아 갈 수 있다.

application을 디자인할 때 다른 application에 있는 activiity를 어떻게 재사용할지 생각하는 것과 자신이 만든 activity를 다른 applicatin에게 어떻게 재사용하도록 할지를 염두해 두는 것은 은 매우 바람직한 것이다. 만약 activity를 추가 할 때 기존에 있던 Activity와 동일한 intent filter를 적용한다면, 시스템은 사용자에게 이 activity들 중 어떤 것을 선택 할 것인지 알려준다.


2) Gallery에서 Messaging 재사용하여 사진 공유하기

공유라는 것은 한 application이 다른 application으로 부터 온 activity를 재사용하는 또 다른 좋은 예제이다.
아래 그림에서와 같이, 사용자는 Gallery를 시작하고, 사진을 선택하고, MENU > Share를 선택한 후 Messaging을 집는다.
이것은 Messaging Activity를 시작하게 하며, 새로운 Message를 만들고 원본 이미지를 첨부한다. 사용자는 "받는 이" 필드를 채우고, 짧은 문장을 작성 후 보내게 된다. 현재 사용자는 Messaing 프로그램에 있게 된다. 만약 사용자가 Gallery로 되돌아가려 하면, 반드시 BACK 키를 눌러야 한다. (사용자는 HOME으로 가기 위해 모든 Activity에 대해 Back 동작을 수행 할 수 있다)


이전 Contacts 예제와 달리, Message activity의 재사용에 대한 예제는 Gallery activity가 시작될 때 아무것도 가져가지 않는다.


c. Activity 대체

윗 글에서 Actiivity의 intent filter를 기존 activity와 동일하게 설정 할 경우 사용자가 어떤 Activity를 이용할지 선택할 수 있다고 언급 했었다. 이를 Activity 대체라 부른다.

이것은 Activity A가 다른 application에 있는 Activity B를 대체하는 경이다. 이런 상황은 보통 activity A가 activity B의 기능보다 더 나은 기능을 제공 하기 때문에 발생한다. 다시 말해서, A와 B는 동등하거나 A가 B를 대체할만큼 A와 B가 동등하다는 것이다. 이 경우 A와 B가 꽤 많이 다른 Activity들이며 서로가 다른 것들을 가지고 있을 때 Activity의 재사용과 두드러지게 대비된다.

이 예제에서는, 사용자는 Phone Ringtone Activity에 대한 대체로 Rings Extended라는 것을 다운로드 했다. 이제 Settings, Sound & Display, Phone Ringtone을 선택할 때, 시스템은 Android System의 ringtone activity와 새로운 것 사이에서 고를 수 있도록 해 준다. 이 다이얼로그 박스는 "Use by default for this action"이라는 항목을 기억할 수 있다. 만약 "Rings Extended"를 선택하면 Activity는 실행이됙 기존 Android ringtone activity는 대체된다.



c. Multi Tasking

Activity가 실행 중 HOME 키를 누르면 새로운 Task로 인식되며 Multi Tasking이 시작된다. 다음은 Maps에 대한 예로 설명한다.

1단계 - 사용자는 View Map Activity를 실행하고 지도 위치를 검색한다. 네트워크가 느리다고 한다면, maps는 지도를 그리는데 비정상적으로 오래 걸린다.

2단계 - 사용자는 이렇게 기다리는 동안에 뭔가를 하고 싶어하므로 HOME 키를 눌러 maps의 네트워킹 접속을 방해하지 않고 background에서 loading이 계속되도록 한다.

Activity가 Backgournd로 옮겨지면 Activity Lifecycle에 따라 onStop() 메소드가 호출이 되므로 Activity를 작성 할 때 계속 할 것인지 아니면 잠시 멈출 것인지 결정 할 수 있다. 네트워크로 부터 데이터를 다운로드하는 Activity들에 있어서 downloading을 계속 하도록 두는 것은 추천 할 만한 것으로 사용자의 multi-task를 가능하게 한다.

3단계 - map activity는 이제 Backround에서 실행되고 있고, Home은 Foreground로 실행되고 있다. 사용자가 Calendar Activity를 실행하면 foreground가 되고, 사용자 focus를 가지며, 오늘 날짜의 달력이 보여진다.



4단계 - 사용자가 HOME을 누르러 Maps를 다시 실행하면 지도 데이터가 완전하게 load 되어진 모습이 보여진다.



Home에 있는 applicaion laucher는 "View Map"과 "Day View" Activity를 별도의 task로 실행했으므로 시스템은 multitasking이다.


d. 두 개의 시작점으로 실행하기

모든 application은 적어도 하나의 이상의 시작점 (entry point)를 가져야 한다 - 시작점는 사용자 혹은 시스템이 application 내부에 있는 activity에 접근하기 위한 방법이다. Home에 있는 applicatin laucher에 있는 각각의 icon이 application의 시작점을 나타내고 있는 것이다. Application은 다른 application에서 실행 될 수도 있다. 또한 각각의 activity는 application에 잠재되어 있는 시작점이다.


Phone Application은 Contacts와 Dialer 두 개의 시작점을 가지고 있다.ㅏ용자는 Contacts에서 phone number를 선택하여 Dialer를 실행 할 수 있다. 아래 그림에서와 같이, 사용자는 Contacts Icon을 선택하여 Activity를 실행 시킬 수 있으며, Phone Number를 선택하여 Dialer Activity를 호출, 전화를 걸 수 있다.

사용자 한번이라도 application 실행 중에 있다면, Tab과 메뉴 아이템, 리스트 아이템, 스크린에 있는 버튼 혹은 다른 interface control을 이용하여 새로운 주소록을 만들거나 편집과 같은 다른 Activity에 접근할 수 있다.


e. Task 전환

이 시나리오는 사용자가 두 개의 task를 어떻게 전환하는지 보여준다. 이 예제에서, 사용자는 문자 메시지를 작성하고 이미지를 첨부하지만 끝내기 전에 잠깐 달력을 본다. 그리고 첨부된 사진이나 문자 메시지를 남겼던 곳으로 되돌아 온다.

1) Task 시작하기
문자 메시지와 사진을 첨부하려 한다면 다음과 같이 선택해야 한다:

Home > Messaing > New Message > MENU > Attach > Pictures. 이 마지막 단계는 사진을 선택하기 위해 Picture Gallery가 실행된다. Picture Gallery는 별도의 application임을 알아둔다.



사진을 선택하기 전쯤에서 잠깐 멈춰서 별도의 task에서 Calendar를 보려 한다. 현재 activity가 Calendar로 바로 가는 버튼이 없으므로 Home에서 시작해야 한다.

2) 두 번째 Task 시작하기

Home > Caledar를 선택하여 Calendar 이벤트를 본다. Application Laucher는 각각의 application이 실행 될 때 마다 새로운 task로 실행을 하기 때문에 Calendar는 Home에서 새로운 task로 실행이 된다.


3) 첫 번째 Task로 전환하여 마무리 하기

Calendar를 다 보고 난 후 root activity를 다시 시작하여 사진을 첨부하는 곳으로 되돌아 갈 수 있다:
Home > Messaging 선택, 이것은 Messaing으로 가는 것이 아니라 떠나기전 있던 곳인 Picture Gallery로 바로 진입한다. 이제 메시지에 첨부할 사진을 선택하고, 메시지를 보내면 처음 시작했던 task를 마치게 된다.






.




참고 : http://developer.android.com/guide/practices/ui_guidelines/activity_task_design.html

**
Trackback 0 Comment 2
2009.05.28 16:30

[android] Android Dev Phone Firmware 복구 하기


전에 업급했듯 Android 단말은 개발용 단말인 Dev Phone 1과 상용 단말인 G1 단말이 있다. Dev1과 G1의 가장 큰 차이는 바로 adb service의 제공 여부다. adb service는 SDK와 단말 사이에 대한 Protocol을 지원하는 것인데 G1은 상용 단말이므로 기본 동작은 disable 되어 출시된다.

Dev Phone은 G1과 달리 이통사와 상관 없이 출시되고 또한 기업의 개발자들이 구매를 하므로 G1 보다 구매 가격이 높다. 따라서, G1을 이미 구매한 사람들이나 일반적인(?) Android 프로그래머는 단말에서 테스트 하기 어렵다.

그런데, Dev1이 아닌 G1 단말에서도 adb를 가능하게 해 주는 방법이 공개되었다. 초기 Android Version의 Back door를 이용하여 adb service를 활성화 하는 것인데 이를 이용하면 G1 단말에서 개발이 가능하게 된다 (이전 글 Android Dev Phone & G1 Phone Unlock 참조). 그 대신, adb는 root 권한을 가질 수 없으며, G1 단말 제조사인 HTC의 공식 update 도 사용 할 수 없어 일부 S/W 개발자가 배포한 Customized Firmware를 이용하거나, Customized Firmware를 직접 만들어 넣는 수 밖에 없다.

Dev Phone의 경우 adb root service는 기본으로 제공한다. 그러나, 최초 부팅 시 Google 계정 등록 화면으로 진행하도록 되어 있어 마치 Lock이 걸린 것 처럼 보일 수 있다. 그런데 만약 이를 해결 하기 위해 G1의 활성화 방법, 즉, Firmware를 업데이트 하는 방법으로 해결 할 경우 껍데기는 Dev1이지만 내부 version은 G1이므로 위에서 언급한 G1에 대한 문제점이 그대로 발생하게 된다.

그렇다고 원래대로 되돌리기도 그리 쉽지는 않다. 이렇게 Dev Phone이 G1으로 변경된 상태에서 Dev Phone Update를 진행하면 비록, Hardware는 Dev1이라 할지라도 Software가 G1이므로 정상적인 업데이트가 진행되지 않는다.

만약 일반적인 Dev Phone의 업데이트 과정을 진행한다면 다음과 같은 메시지를 보게 된다.

Android System recovery utility
E:Can;t open /cache/recovery/command

Home_Back - reboot system now
Alt+L - toggle log text display
Alt+S - appliy sdcard:update.zip
Alt+W - wipe data/factory reset

Installing from sdcard...
Finding update package...
Opening update package...
Verfying udpate package...
E:No signature (5 files)
E:Verification failed
Installation aborted.

Press Home+Back to reboot


결국 S/W가 G1으로 변경되면서 Bootloader Binary도 같이 변경되었기 때문에 해당 업데이트가 진행되지 않는 것이다.

Bootloader Version은 다음과 같이 세 가지 SPL이 있다.

HBOOT-0.95.3000 : Engineering SPL (Dev1)
HBOOT-0.95.0000 : Original SPL (G1)
HSPL10.95.3000 : Hard SPL ( Customized)

다음과 같은 방법으로 현재 Bootloader Binary 정보를 확인 해 볼 수 있는데 G1일 경우 HBOOT-0.95.0000 임을 확인 해 볼 수 있다.

1. 단말 종료
2. CAMERA 버튼 + POWER 로 부팅


따라서, G1용 Bootloader 를 Dev1이나 Customized Version으로 변경을 해 주어야 하며 이는 다음과 같은 방법으로 진행한다.

먼저 adb root service가 가능한지 확인 해 본다.adb root를 입력하여 root 계정을 활성화 여부를 확인 한다.
※ adb service는 활성화 한 상태이어야 한다.

$ adb root
error: closed


만약 root 계정이 활성화 되지 않는다면 위와 같이 에러 메시지가 출력되며 그렇지 않는 경우 adb shell로 접속 시 root 권한으로 실행 할 수 있다. (※ G1인 경우 adb를 이용한 root 계정은 거의 얻을 수 없다고 본다)

root 권한을 얻었다면 이제 이미지 복구를 위해 다음과 같은 과정을 거쳐 이미지를 복구한다.

- Android Market이나 별도의 파일로 제공되는 Telnet Application을 설치한다.
- 복구에 필요한 recovery.img 파일과 Hard SPL 혹은 Engineering SPL을 SDCard에 update.zip으로 복사한다.
- 재부팅 후 Home Screen 화면에서 Keypad를 연다.
- ↙↙telnetd↙ 를 입력한다. (※ 이 때 telnetd라고 출력되는 것은 정상)
- Telnet Application을 실행하면 root 권한을 가진 shell 로 접속이 되는 것을 확인 해 볼 수 있다.
- 이제 Telnet App에서 다음과 같이 입력한다.
# mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system
# cd /sdcard
# flash_image recovery recovery.img
# cat recovery.img > /system/recovery.img
- 단말 종료 후 HOME + POWER 버튼을 눌러 Firmware Update 모드로 진입한다.
- ALT + L을 누르면 Update 메시지가 출력되며, ALT + S를 눌러 SPL Verify를 진행한다.
- 업데이트가 완료되면 HOME + BACK을 누르면 Writing이 진행되고 자동으로 재부팅 된다.
- 재부팅 시 Flash ROM Writing이 진행되는 것을 볼 수 있다.
- 두 번 정도의 재부팅이 진행되면 ANDROID LOGO가 약간 달라진 것을 볼 수 있다.

이제 Dev Phone Update v1.5 Binary를 설치 해 볼 수 있으며 이와 관련된 부분은 이전 글 Android Dev Phone Firmware Update 하기 를 참고 하기 바란다.

참고 링크

* http://forum.xda-developers.com/showthread.php?t=442480
* http://www.androidandme.com/2009/05/guides/beginners-guide-for-rooting-your-android-g1-to-install-cupcake/
* http://androidcommunity.com/forums/f54/haykuro-adp1-5hr3-adp1-5hr3-a2sd-1-5-cupcake-16001/index515.html
Trackback 0 Comment 2
2009.05.07 01:14

[android] Android Dev Phone Firmware Upgrade 하기

Android는 지속적으로 update 되고 있으며 최근 SDK와 release된 cupcake version 은 v1.5 이다.

HTC의 경우 Dev1에 대한 Fireware를 제공하고 있으며 다음 문서에서 update binary 및 방법을 알 수 있다.

* HTC Android Dev Phone Update ( http://www.htc.com/www/support/android/adp.html )

다음은 위의 내용 중 v1.5 에 대한 내용을 간략히 설명한 것이다.

1. 업데이트 할 파일 준비

Update 방법으로 Recovery Mode와 Fastboot Mode 두 가지가 있으며 이에 따라 필요한 바이너리는 다음과 같다.

* Recovery Mode
a. Radio Image
b. Recovery Image

* Fastboot Mode
a. Radio Image
b. System Image

여기서는 전통적인 Recovery Mode를 기준으로 진행하기로 한다.

2. Radio Image 업데이트

Radio Image를 받은 후 SDCard에 update.zip이란 이름으로 복사한다.
만약 SDK tool인 adb를 이용하면 다음과 같이 입력한다.

$ cd $ANDROID_SDK
$ cd tools
$ adb push <radio-image-package>.zip /sdcard/update.zip
$ adb sync


POWER 버튼을 5초 이상 눌러 단말을 종료 후, HOME + POWER 버튼을 눌러 Recovery Mode로 진입한다.
진입에 성공하면 다음과 같은 이미지를 볼 수 있다.


키패드를 열어 ALT + L을 눌러 Recovery Mode로 정상 진입 했음을 확인한다.
ALT + S를 눌러 SDCard에 있는 이미지 파일로 update를 진행 한다.

진행 중 Verify, Update가 완료되면 BACK + HOME 버튼을 눌러 Writing 후 재부팅 하도록 해야 한다.
만약 정상적인 방법으로 재부팅이 된다면 Update는 진행되지 않는다.

재부팅 후 다음과 같은 업데이트 화면이 나타나면 완료시 자동으로 재부팅 한다. (version에 따라 이미지는 달라질 수 있다)



3. Recovery Image 업데이트
Radio Image와 마찬가지로 Image 파일을 update.zip이란 이름으로 SDCard에 저장 후 위의 update 과정을 실행한다.

모든 업데이트 과정이 끝나면 다음과 같은 메뉴에서 version 이 update 된 것을 볼 수 있다.

App Menu - Settings - About phone


Trackback 0 Comment 2
2009.02.28 12:07

Google Android Build 해 보기 #1

진즉 나왔던 Google Android가 어찌 생겼는지 한 번 보고 싶다는 생각이 불쑥 들어 이리 저리 자료를 찾아 보았다.

Google 홈페이지에서 검색된 곳은 http://code.google.com/android 들어 갔더니 Android Develper 갔더니 예전 자료만 있고 개발자 홈페이지를 새로 만들었다고 http://developer.android.com 로 가보라는 링크가 있었다. 결국 Android 공식 홈페이지는 http://www.android.com/ 였는데 구글에서는 2순위로 rank 되어 있었다.

어쨌든 Guide에 나와 있는 Host 중 Ubuntu Linux (x86 32bit)가 있어 Linux를 설치하고 하나씩 맞춰 나갔다.

1. Tools

Android는 Open Source이므로 배포나 개발 참여를 위해 코드 관리를 하고 있다. 이런 경우 회사나 개인은 cvs나 svn과 같은 tool을 이용하곤 했는데 Android는 git이라는 tool을 이용한다. 이게 리누즈 토발즈가 만든거라나.. 암튼. 이걸 이용하도록 되어 있다곤 하는데 별도의 script를 두어 사용하는걸 보니 쓰는게 그리 녹록하지는 않을 것 같다. 어쨌든 필요한 tool은 전부 설치한다.
  • Git 1.5.4 또는 최신 버젼 그리고 GNU Privacy Guard를 설치한다.
$ sudo apt-get install git-core gnupg
  • JDK 5.0, update 12 나 상위 버젼을 설치한다.
sudo apt-get install sun-java6-jdk
  • flex, bison, gperf, libsdl-dev, libesd0-dev, libwxgtk2.6-dev (optional), build-essential, zip, curl 패키지를 설치
$ sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev
  • 필요하다면 Valgrind 설치한다. 이는 Memory leak이나 stack corruption, array bounds overflows를 찾는데 도움이 된다.
$ sudo apt-get install valgrind
  • Intrepid (8.10) 사용자는 libreadline 최신 버전이 필요할 수도 있다.
$ sudo apt-get install lib32readline5-dev

내가 가진 Ubuntu에서는 lib32readline5-dev에 대한 package는 찾을 수 없다고 나왔다. 어디에 사용하는건지는 잘 모르겠지만 아직까지는 별문제 없이 쓰고 있다. 그리고 JDK를 설치하면 JAVA_HOME에 대한 정보를 설정해 주어야 하는데 다음과 같이 세팅하면 된다.
$ export JAVA_HOME=/usr/lib/jvm/java-6-sun

2. Download Code

처음에도 잠깐 이야기 했지만 코드를 download 하기 위해서는 git이라는 것을 이용해야 하는데 Android에서는 repo라는 별도의 script 를 제공하고 있다.
  1. repo 스크립드를 설치할 폴더를 지정한다. 나의 경우는 ~/disk3/android/bin 에 설치했다.
      $ cd ~/disk3/android
      $ mkdir bin
      $ export PATH=~/disk3/android/bin:$PATH
  2. repo 스크립트를 다운로드 후 실행 가능 상태로 모드를 설정한다.
    $ curl http://android.git.kernel.org/repo >~/disk3/android/bin/repo
    $ chmod a+x ~/disk3/android/bin/repo

필요하면 PATH에 export해서 사용해도 상관없는데 자주 사용하는게 아니니까 그냥 쓴다.

3. Workspace 설정

repo 스크립트를 이용하려면 우선 workspace를 설정해야 한다.
  1. 작업에 필요한 폴더를 생성한다:
    $ mkdir ~/disk3/android/mydroid
    $ cd ~/disk3/android/mydroid
  2. repo init 을 실행해서 가장 최근의 버그가 수정된 Repo의 버젼을 받을 수 있다. 이 때 다음과 같이 manifest URL을 지정한다.
    $ repo init -u git://android.git.kernel.org/platform/manifest.git
    • 만약 "master"가 아닌 다른 branch에서 check out을 하려면 다음과 같이 -b 옵션을 주어 받을 수 있다.
      $ repo init -u git://android.git.kernel.org/platform/manifest.git -b cupcake
  3. Repo init을 실행하면 Configuration 과정에서 실 사용자 이름과 email 주소를 물어보는 단계가 나타난다. 만약 code를 반영하는 경우를 염두해 두고 있다면 email은 Google account 와 관련된 email을 사용해야 한다.

4. Source Code 동기화

repo 스크립트를 이용해서 최근 version의 코드를 받는다.
$ repo sync 

repo sync가 시작되면 source만 2GB가 되므로 꽤 오랜시간 동안 코드를 받는다.
동기화가 완료되면 다음과 같이 mydroid 폴더에 소스가 받아진 것을 확인 해 볼 수 있다.
mc500@jshong-vb:~/disk3/android/mydroid$ ls -l
total 56
-r--r--r--  1 mc500 mc500   87 2009-02-28 07:10 Makefile
drwxr-xr-x  9 mc500 mc500 4096 2009-02-28 07:10 bionic
drwxr-xr-x  5 mc500 mc500 4096 2009-02-28 07:10 bootable
drwxr-xr-x  8 mc500 mc500 4096 2009-02-28 07:10 build
drwxr-xr-x 18 mc500 mc500 4096 2009-02-28 07:10 dalvik
drwxr-xr-x 15 mc500 mc500 4096 2009-02-28 07:10 development
drwxr-xr-x 61 mc500 mc500 4096 2009-02-28 07:12 external
drwxr-xr-x  5 mc500 mc500 4096 2009-02-28 07:12 frameworks
drwxr-xr-x  5 mc500 mc500 4096 2009-02-28 07:12 hardware
drwxr-xr-x 23 mc500 mc500 4096 2009-02-28 07:13 kernel
drwxr-xr-x  4 mc500 mc500 4096 2009-02-28 07:13 packages
drwxr-xr-x  9 mc500 mc500 4096 2009-02-28 07:14 prebuilt
drwxr-xr-x  6 mc500 mc500 4096 2009-02-28 07:14 system

5. Build

이제 mydroid 폴더에서 make만 실행하면 되는데 그 전에 Java Tool Build에 필요한 환경 변수를 다음과 같이 설정한다.
$ export ANDROID_JAVA_HOME=$JAVA_HOME

그리고 make
$ cd ~/disk3/android/mydroid 
$ make


Trackback 0 Comment 1