Tuesday, December 15, 2009

서비스(Service)

서비스는 한 어플리케이션 내의 보이지 않는 작업이라보면 됩니다. 보이지 않는 관계로 스트린 레이아웃을 붙여줄 필요가 없습니다. 보이지 않는 상태로 실행되면서 데이터입출력에 관련된 작업을 수행하고 수행결과 신호 (Notification) 을 줍니다.

서비스도 나름대로의 Life cycle 을 가집니다. OnCreate - OnStart - OnDestroy 로 이어지는것이 기본 흐름인데 한번 시작된 서비스는 onStart 의 내용이 끝난후 바로 onDestroy 로 가는것이 아니라, 다음실행을 위해 대기상태로 들어갑니다. 프로세스가 계속 살아있는것이죠. 그리고, 프로세스가 살아있는 한은 다시 onCreate 으로 들어가지 않고, 서비스를 외부에서 실행시키면 onStart 의 단계로 바로 들어가게 됩니다. 하지만 시스템에 리소스가 모자라면 OS 가 그 프로세스를 죽이게 됩니다. 이때 onDestroy 가 작동되고, 이 서비스가 다시 시작하는 시점에는 onCreate 가 작동됩니다.

서비스의 시작은 일반적으로 startService() 를 사용하며, 종료에는 stopService() 가 사용됩니다.

Friday, December 11, 2009

Manifest 파일

안드로이드 어플리케이션을 구성하는 가장 중요한 기본요소들을 보면 다음과 같다.
1. Activity
2. Service
3. Content Provider
4. Intents
5. Broadcast Receiver
6. Notifications

이 구성요소들을 정의,나열하고 그 메타 데이터들을 주는것이 Manifest 파일의 역할이다.
파일은 각각의 위에 나열된 구성요소에 대한 노드를 가지고 있고 그 내부에 이름들과 그 연결이 정의된다. 또한 사용 아이콘, 현 버젼정보, 프로그램 이름과 인텐트들이 어떻게 넘겨지는지에 대한 정보도 정의될수있다.

시작노드는 manifest로 시작된다.
그 내부에 application노드에서 메타데이터들이 지정되고, 타이틀, 아이콘, 테마 들이 정의된다.
application 노드는 한 manifest에 한개밖에 지정할수 밖에 없는데 이는 또한 다른 어플리케이션 구성요소들이 정의되는 노드의 기반이 된다. 이 내부에는 Activity노드나 Provider 노드. Receiver, Permission등의 노드들이 위치한다.

예로 안드로이드 폰에 기본으로 달려나오는 알람시계의 Manifest 를 보자.
맨 먼저볼것은 큰 노드의 구성이다.

위에 user-permission 부분이
아래에 application 노드가 있다.
application 의 내부에는 1개의 콘텐트제공자, 6개의 액티비티, 3개의 리시버, 1개의 서비스가 달려있음을 본다.

그러면, 프로그램을 시작하면 제일먼저 시작되는 액티비티는 무엇인가?
AlarmClock 이다. action.MAIN, category.DEFAULT, category.LAUNCHER 가 인텐트 필터에 달려있다.

이외에도 프로그램의 distribution 을 어느 안드로이드 버젼으로, 어느 화면 사이즈의 기기로 제한할것인가에 관련된 속성도 주는 것이 가능하다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.alarmclock"> 
 
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 
    <uses-permission android:name="android.permission.WAKE_LOCK"/> 
    <uses-permission android:name="android.permission.VIBRATE"/> 
    <uses-permission android:name="android.permission.WRITE_SETTINGS" /> 
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> 
    <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
 
    <application android:label="@string/app_label"
                 android:icon="@drawable/ic_launcher_alarmclock"> 
 
        <provider android:name="AlarmProvider" android:authorities="com.android.alarmclock" /> 
 
        <activity android:name="AlarmClock" android:label="@string/app_label"
                android:icon="@drawable/ic_widget_analog_clock"
                android:configChanges="orientation|keyboardHidden|keyboard|navigation"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.DEFAULT" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
        </activity> 
 
        <activity android:name="SettingsActivity" android:label="@string/settings"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
            </intent-filter> 
        </activity> 
 
        <activity android:name="SetAlarm" android:label="@string/set_alarm"
                android:configChanges="orientation|keyboardHidden|keyboard|navigation" /> 
 
        <activity android:name="AlarmAlert"
                android:excludeFromRecents="true"
                android:theme="@style/alarm_alert"
                android:launchMode="singleInstance"
                android:taskAffinity=""
                android:configChanges="orientation|keyboardHidden|keyboard|navigation"/> 
 
        <!-- This activity is basically the same as AlarmAlert but with a more
             generic theme. It also shows as full screen (with status bar) but
             with the wallpaper background. --> 
        <activity android:name="AlarmAlertFullScreen"
                android:excludeFromRecents="true"
                android:theme="@android:style/Theme.Wallpaper.NoTitleBar"
                android:launchMode="singleInstance"
                android:taskAffinity=""
                android:configChanges="orientation|keyboardHidden|keyboard|navigation"/> 
 
        <activity android:name="ClockPicker" /> 
 
        <receiver android:name="AlarmReceiver"> 
            <intent-filter> 
               <action android:name="com.android.alarmclock.ALARM_ALERT" /> 
               <action android:name="alarm_killed" /> 
               <action android:name="cancel_snooze" /> 
            </intent-filter> 
        </receiver> 
 
        <!-- This service receives the same intent as AlarmReceiver but it does
             not respond to the same broadcast. The AlarmReceiver will receive
             the alert broadcast and will start this service with the same
             intent. The service plays the alarm alert and vibrates the device.
             This allows the alert to continue playing even if another activity
             causes the AlarmAlert activity to pause. --> 
        <service android:name="AlarmKlaxon"> 
            <intent-filter> 
                <action android:name="com.android.alarmclock.ALARM_ALERT" /> 
            </intent-filter> 
        </service> 
 
        <receiver android:name="AlarmInitReceiver"> 
            <intent-filter> 
                <action android:name="android.intent.action.BOOT_COMPLETED" /> 
                <action android:name="android.intent.action.TIME_SET" /> 
                <action android:name="android.intent.action.TIMEZONE_CHANGED" /> 
            </intent-filter> 
        </receiver> 
 
        <receiver android:name="AnalogAppWidgetProvider" android:label="@string/analog_gadget"
         android:icon="@drawable/ic_widget_analog_clock"> 
            <intent-filter> 
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> 
            </intent-filter> 
            <meta-data android:name="android.appwidget.provider" android:resource="@xml/analog_appwidget" /> 
        </receiver> 
    </application> 
</manifest> 

참고로 위 Manifest 의 출처는
http://android.git.kernel.org/?p=platform/packages/apps/AlarmClock.git;a=tree
이다.

Intent 와 Intent filter

Intent

인텐트는 안드로이드 구성요소중의 세가지(Activity, Service, Broadcast Receiver)를 활성화시키는 역할을 담당합니다. 이는 일단 메시지로 보면 편한데 앞으로 실행될 작업에 대한 작업 지시서와 같다고 생각하면 됩니다. Broadcast의 경우 이는 무슨일이 일어났다는 정보도 포함하고 있습니다.

Activity에 대해서는 startActivity() 나 startActivityForResult() 를 이용 다른 Activity 를 시작시키거나 현재의 Activity가 무언가 다른 일을 하게 합니다.

Service에 대해서는 startService() 를 이용 Intent가 넘겨지면서 서비스를 시작하거나 현재 실행되고있는 서비스에 다른 작업지시를 하게 됩니다. 또한 bindService()를 이용 부르고 있는 Activity와 불리워지는 Service사이에 연결을 하는 것도 가능케 합니다.

Broadcast에 대해서는 sendBroadcast(), sendOrderedBroadcast(), sendStickyBroadcast() 를 이용 다른 Broadcast receiver로 메시지를 보내게 됩니다.

각 경우 넘겨진 Intent에 대해 안드로이드 시스템은 적절한 Activity를 찾아 다음작업으로 넘어가는것을 도와주게 됩니다.

이과정에서 Intent란 보내어지고 받는 오브젝트를 지칭하는것이고, Intent filter란 다음 작업이 정확히 명시되지 않은 상태에서 보내진 Intent에 대해 안드로이드 시스템이 연결시키는 과정에서 어느 Activity/Service/Broadcast가 받을것인가를 찾는 Intent Resolution 작업시 참조하는 정보입니다.

Intent Object

인텐트 오브젝트는 번들의 개념에서 보는데 이것저것 다 집어놓은 주머니 같다 생각하면 됩니다. 일반적으로 다음 Activity 를 호출하며 그에 필요한 정보를 넣어주는 경우가 많습니다.

이 안에는

1. Component Name: 인텐트를 받을 클라스. 만약 주어지지 않은 경우 안드로이드 시스템은 Intent Resolution 을 통해 다음 클라스를 찾아냅니다.

2. Action: 앞으로 해야할 작업을 칭합니다. 이미 정의된 것을 사용할수도 있고 만들어 쓸수도 있습니다. 만들어 사용하는것에 대해서는 안드로이드 패키지 이름이 앞에 붙어있어야한 합니다. 이미 정의되어있는것은 아래에서 확인할 수 있습니다.
http://developer.android.com/reference/android/content/Intent.html

3. Data: 데이타의 URI 나 MIME 타입이 해당됩니다.
데이터는 직접 해당 Class를 부르면서 데이터 스트링을 직접 보낼수도, URI의 개념을 이용해 보내질 수 있습니다. URI의 개념을 이용하는 경우 데이터가 직접보내지는것이 아니라 데이터가 있는곳을 가르키는 URI를 Intent에 포함시키는 것입니다.
URI의 경우 예들을 보면, Action이 ACTION_EDIT일때는 그 데이터는 수정으로 위해 보여져야 할 데이터의 URI로 추측할 있을 겁니다. ACTION_CALL이면 데이터는 tel: 에 전화번호의 URI가 되야합니다. ACTION_VIEW면, 데이터는 http: 에 화면에 보여질 정보를 가진 URI가 있을 겁니다.
MIME타입이 중요한 이유는 데이터의 그림, 음악과 같이 그 종류가 명시되어야 할 경우가 있기 때문입니다.

4. Category: 인텐트를 핸들할 콤포넌트의 종류를 말합니다.

이제 Intent가 준비되면 한 Activity는 다음 Activity를 startActivity나 startActivityForResult 를 이용해 부르고 Intent를 넘깁니다. startActivity는 단순히 다음 Activity를 부르는데 쓰며 startActivityForResult 는 다음 Activity를 부르고 그 Activity가 되돌려주는 Intent 를 onActivityResult() 로 받아야 할 경우 씁니다. Notepad Tutorial 은 startActivityForResult 를 기준으로 Sample Notepad 예제는 startActivity를 기준으로 만들어져 있습니다.

Sample Notepad 예제에서 노트를 새로 생성될때의 상황을 보면 메뉴에서 MENU_ITEM_INSERT 가 선택되며 onOptionsItemSelected() 가 불려집니다. 이 메소드는 내부적으로 다음과 같이 startActivity() 실행시키게 됩니다.

startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData())); 

이과정에서 AndroidManifest.xml이 참조되어지는데 Activity는 ACTION_INSERT라는 작업을 어디서 해야하는지를 찾게 됩니다. 결국 Manifest의 내용에서 NoteEdit을 찾아내고 해당 Activity 를 시작합니다. Manifest를 사용하지 않고 아예 Intent 에 불리워 질 클라스 이름을 적어넣는 것도 가능합니다. 이를 Explicit intent라 하는데, 이것이 바로 Notepad tutorial에서 소개된 방법입니다.


Intent Resolution

인텐트는 component 이름 필드에 대상이 정확히 명시되어있는 Explicit intent와 대상이 없는 Implicit intent가 있습니다. 문제는 이 Implicit intent입니다. 대상이 없으므로 안드로이드 시스템은 필요한 정보들을 모아서 대상을 찾아내는 작업을 수행합니다. 이를 Intent resolution이라합니다. 이 과정에서 안드로이드시스템은 (1)액션, (2)데이터, (3)카테고리의 세가지 정보를 가지고 Intent filter를 쭉 훝어봅니다. Intent filter라는 것은 어떤 클라스와 같은 Component가 만들어질때 이 Component는 어떤 작업을 수행할 수 있다고 명시해놓은 것을 칭합니다. 일반적으로 Manifest 파일에 아래와 같이 정의됩니다.
<intent-filter . . . >
    <action android:name="code android.intent.action.MAIN" />
    <category android:name="code android.intent.category.LAUNCHER" />
</intent-filter>

이 작업수행의 수행에 있어 시스템은 세가지 테스트를 모두 다 통과하는지를 확인하게 됩니다. 세가지 테스트가 다 통과되지 않으면 안드로이드 시스템은 인텐트를 받을 대상이 없다고 판단하는것입니다.

먼저, Action 을 보고 인텐트에 있는것 과 같은 것이 있는지 봅니다.

다음은 카테고리를 봅니다. 인텐트에 카테고리 정보가 없다면 어떨까요. 이경우 테스트를 통과하고 싶으면 implicit intent의 경우 대상 component에 android.intent.category.DEFAULT가 명시되어 있어야 합니다. explicit은 상관 없습니다. 여기에 예외가 있는데 android.intent.action.MAIN 과 android.intent.category.LAUNCHER은 이 DEFAULT가 필요 없습니다.

다음차례는 데이터입니다.

<intent-filter . . . >
    <data android:type="video/mpeg" android:scheme="http" . . . /> 
    <data android:type="audio/mpeg" android:scheme="http" . . . />
    . . .
</intent-filter>

너무 복잡합니다.

Wednesday, October 7, 2009

Object, Class, Package

이페이지는 http://java.sun.com/docs/books/tutorial/java/concepts/index.html 를 정리 번역한 것입니다.
.

Object
자바는 흔히 객체지향 언어라고 합니다. 그럼 객체란 무엇인가요? 객체(Object)를 가장 쉽게 이해할수 있는 방법은 우리주위를 그냥 무엇이 있는지 둘러보고 무엇이 있는지 보는 겁니다. 컵이 보이고 볼펜이 보이고 창문을 통해 옆집이 보입니다. 이것들이 다 객체들입니다. 소프트웨어세계의 객체는 이러한 실생활속에 객체와 그리 다르지 않습니다. 일단은 실생활 속의 객체들을 소프트웨어 세계로 추상화한것이라 생각하면 쉽습니다.

객체는 상태(State)와 행위(Behavior)의 두가지 속성을 가집니다. 상태에 대한 답을 하기위해 이런 질문을 던져봅니다. 이 객체는 어떤 상태에 있습니까? 그 객체가 자전거이라면 그 색깔, 크기, 변속기의 유무, 달려있는 변속단수가 상태가 될수 있을겁니다. 행위라면 그 객체가 할수 있는 행위, 가는것, 서는 것, 페달이 돌아가는것, 등등이 될겁니다.

이 실생활의 상태와 행위개념은 소프트웨어의 세계로 들어어면서 필드와 메소드의 개념으로 대치됩니다. 필드는 자전거의 색깔이 되는 것이고 그안에 파란색이다, 빨간색이다의 변수(Variable) 개념이 들어가면서 상태가 소프트웨어적으로 정의 되는 겁니다. 행위는 소프트웨어 객체가 할 수 있는 일이 됩니다. 행위는 객체 내부의 행위일수도 다른 객체와 의사소통을 하는 일이 될수도 있습니다.

Class
이제는 개념적으로 정의한것을 하나하나 더 구체적으로 소프트웨어의 세계로 접목시키는 방법을 볼 단계가 되었습니다. 객체라고 했는데, 그 객체를 자전거 전부로 뭉뚱그려서 정의해야할지 산악자전거, 세발자전거, 로드 자전거로 분류하여 정의할지 모호합니다. 이를 위해 클라스(Class)와 상속(Inheritance)의 개념이 동원됩니다. 일단은 다 뭉뚱그려서 자전거를 하나의 클라스로 만들고, 가장 포괄적인 상태와 행위만을 정의합니다. 이를 수퍼클라스로 하고 그 성격을 상속하여 하위에 좀더 세분화된 클라스를 놓습니다. 산악자전거, 로드자전거, 세발자전거 들이 그것입니다. 이 레벨의 클라스를 정의하면서 산악, 로드만의 독특한 상태들와 행위들을 추가적으로 집어넣습니다. 이런식으로 계속 세분화시켜가면서 프로그램내에서 이용하기 쉬울 정도의 성격을 가진 세부적인 객체를 만들어나갑니다.

이 상속의 관계를 자바의 세계에서는 다음의 표현으로 구현합니다.
class MountainBike extends Bicycle {
 // new fields and methods defining a mountain bike would go here
}

Interface
인터페이스(Interface)는 하나의 객체가 그 외부의 세계와 어떤 행위를 가하거나 당하는것을 말합니다. 자전거라면 기어 단을 바꾸는것, 회전수를 늘리는것, 브레이크를 밟는것이 될겁니다. 이를 자바코드에서는 다음과 같이 구현합니다.
interface Bicycle {
 void changeCadence(int newValue);
 void changeGear(int newValue);
 void speedUp(int increment);
 void applyBrakes(int decrement);
}

그리고 자전거 클라스에는 다음과 같이 implements 라는 문을 사용하여 연결합니다.
class ACMEBicycle implements Bicycle {
 // remainder of this class implemented as before
}

Package
패키지는 위에서 언급하였던 소프트웨어적인 요소를 관련있는것을 모야 하나의 패키지라 이름지워놓은 것으로 뭉뚱그려 모아놓은것을 말합니다. 이 안에는 많은 클라스들이, 자건거의 이미지가, 자전거가 할수있는 행위들의 묶음인 인터페이스가, 자전거의 상태들에 대한 정의들이 들어갈수도 잇습니다

리뷰
마지막으로 다음문장들을 곰곰히 생각해보면서 이제까지 배운것을 정리합니다..
.
실세계의 객체는 상태와 행위를 포함합니다.
Real-world objects contain state and behavior.
.
소프트웨어 객체의 상태는 필드에 저장되어잇습니다.
A software object's state is stored in fields.
.
소프트웨어 객체의 행위는 메소드를 이용하여 구현됩니다. .
A software object's behavior is exposed through methods.
.
소프트웨어세계에서 객체의 모습을 구체화시키는 것은 클라스를 통해 합니다.
A blueprint for a software object is called a class.
.
가장일반적으로 공유되는 행위는 수퍼클라스에서 정의되어지고 상속을 통하여 하위클라스로 공유됩니다. 이 과정에서 extends 라는 키 워드를 사용합니다.Common behavior can be defined in a superclass and inherited into a subclass using the extends keyword.
.
메소드를 모두 모아 놓은 것을 인터페이스라 합니다. 하지만 그 메소드의 행위가 어떤것인지 그 단계단계의 절차까지 이내에 정의 되어있지는 않습니다.
A collection of methods with no implementation is called an interface.

단어정리
객체(Object)
상태(State)
행위(Behavior)
필드(Field)
변수(Variable)
메소드(Method)
상속(Inheritance)
상호작용.인터페이스(Interface)

Motorola new android phone



버라이죤에서 출시된다며 계속 소문이 돌고있는 단말기입니다.

제가 개발자의 입장에서 생각하는 특이사항이라면 화면 레졸루션에 있습니다. 480x854 이라죠. 물론 CPU 도 더 강해지는 것 같고요.

이 단말기를 고려해서인지 새로나온 1.6 SDK 의에뮬에는 AVD 옵션에 기존의 320x480 에 추가하여 480x854의 스킨이 하나 더 들어가 있습니다.

일단 여기저기서 모아본 이 기기의 스펙을 보면 (추정의 수준임)


모델명 Scholes / Droid / Tao
네트워크: ?
CPU: OMAP3430 – 600 MHz ARM Cortex A8 + PowerVR SGX 530 GPU + 430MHz C64x+ DSP + ISP (Image Signal Processor)
메모리: 512MB/256MB ROM/RAM
OS: Android2.0(Eclair)
키보드: QWERTY
스크린: 480x854, 3.7 inch HVGA
카메라: 5.0 megapixel with autofocus and video recorder
배터리: Li-ion 1400 mAh.
기타: 3.5mm audio jack

Thursday, October 1, 2009

HTC Hero (Sprint version)


현재 나와있는 단말기들을 합성해서 비교본을 만들어 봤습니다.


이제 안드로이드가 CDMA 로 넘보기 시작했습니다.
HTC Hero 의 Sprint 버젼이 나오는데 기존의 Hero 와는 약간다르다고 하더군요.

기본적인 하드웨어 사양은 같고, 차이라면
1. 트랙볼사이즈가 왕창 커진거,
2. 배터리 커진거 1350 에서 1500 으로
3. 일설에 의하면 화면밝기가 좀더 좋아졌다기도 하고,
4. Sense UI 가 좀 빨라졌다나요..
등등..

제품사양은
모델명 Hero
네트워크: HSPA/WCDMA (900/2100 MHz, Up to 2 Mbps up-link and 7.2 Mbps down-link speeds), Quad-band GSM/GPRS/EDGE (850/900/1800/1900 MHz)
CPU: Qualcomm® MSM7200A™, 528 MHz
메모리: 512MB ROM, 288MB RAM, 확장
OS: Android 1.5 (Cupcake)
키보드: QWERTY
스크린: 320 x 480, 3.2 inch HVGA
카메라: 5MP AF
배터리: 1500 mAh lithium polymer
기타: 3.5mm audio jack

8월 AdMob 리포트



소스: http://metrics.admob.com/




이번달도 어김없이 리포트가 나오는군요.
이번달의 하이라이트를 보면,

1. 지난 6개월간 아이폰 OS 의 시장점유율은 33% 에서 40% 로 올라갔는데 아시아와 아프리카에서는 아직 점유율이 높지는 않다.
- 이말은 애플이 향후 아시아로 집중적인 마케팅을 할수도 있을 것이라는 말처럼들리기도 하네요. 지금 북미는 55%, 유럽은 45% 정도인데 아시아에서는 12% 이니, 아직 끌어올릴 여지가 많죠.

2.  안드로이드는 미국과 유럽에서 급격히 성장세를 보인다. 두번쨰 안드로이드 폰인 HTC Magic 은 북미과 유럽에서 상위 10대 기종으로 뽑힌다. 전 세계 지역대상 안드로이드로부터의 리퀘스트는 전월대비 17% 높아졌다.

3. 시장점유율이 낮아지고는 있지만, 노키아는 아직 상위 20개 단말기중 12개를 가지고 있다. 그중 가장 강세를 보이는 것이 N975800 XpressMusic 인데 유럽에서 4, 5위를 달리고 있다.

4. 북미에서는 52% 의 스마트폰 사용이 아이폰에 의해 일어나고 있고 다음은 RIM의 14%와 안드로이드의 13% 이다. 팜은 9% 를 기록하였다.
- 마이크로소프트가 6% 로 팜보다도 못하군요.

5. 전세계적으로 리퀘스트의 건수는 전월대비 9% 올랐다.
- 참고로 7월에는 17% 늘었음.