|
4.2 어플리케이션 컴포넌트
(1) 안드로이드 패키지
컴파일된 자바 코드와 어플리케이션에 필요한 각종 데이터 및 리소스는 안드로이드 패키지(Android Package)에 번들이 되어 모바일 장치에 배포나 설치가 됩니다. 안드로이드 패키지는 확장자가 .apk로 아카이브된(archive)된 파일입니다. 하나의 .apk 파일은 하나의 어플리케이션으로 간주됩니다.
안드로이드 어플리케이션이 동작하는 양상은 3 가지 모습으로 표현할 수 있습니다. 첫 번째 모습은 모든 어플리케이션은 자신의 리눅스 프로세스 상에서 동작합니다. 어플리케이션을 실행시키면 안드로이드가 새로운 프로세스를 생성합니다. 그리고 어플리케이션이 더 이상 필요하지 않을 경우 프로세스를 종료합니다. 그 외에 다른 어플리케이션이 시스템 리소스를 요구할 때 다른 프로세스를 종료해야만 가능한 경우라면 안드로이드를 다른 프로세스를 강제로 종료할 수 있습니다.
안드로이드 어플리케이션 동작의 또 다른 모습은 각 프로세스는 자신의 자바 VM을 가진다는 것입니다. 이렇게 동작을 하기 때문에 각 어플리케이션은 다른 어플리케이션과 격리되어 동작합니다.
마지막 모습은 각 어플리케이션은 유일한 리눅스 사용자 ID를 할당 받는다는 것입니다. 어떤 어플리케이션의 파일들은 단지 그 어플리케이션의 사용자에게만 보이도록 권한(permission)이 설정됩니다. 두 개 이상의 어플리케이션이 같은 사용자 ID를 가지게 하는 예외적인 경우가 있는데, 이런 경우는 서로 다른 어플리케이션의 파일들을 볼 수 있게 됩니다.
(2) 어플리케이션 컴포넌트
안드로이드의 핵심 특징 중 하나는 다른 어플리케이션의 컴포넌트를 재사용할 수 있다는 것입니다. 만약 내 어플리케이션이 다른 어플리케이션의 기능을 이용하고 싶다면 다른 어플리케이션의 소스 코드도 필요 없고, 링크도 필요 없이 사용이 가능합니다. 물론 다른 어플리케이션의 자신의 기능을 노출해 줘야 합니다. 이렇게 되면 다른 어플리케이션의 기능 중 일부를 단순 호출하기만 하면 됩니다. 이런 특징 때문에 안드로이드 어플리케이션은main() 함수와 같은 하나의 진입점(entry point)만 가지지 않습니다. main()함수 자체가 없습니다.
이런 재사용을 가능하게 하는 구조가 바로 안드로이드 컴포넌트입니다. 안드로이드 컴포넌트는 다음과 같은 4 가지 종류가 있습니다.
- 액티비티(activity)
가시적인(visible) 사용자 인터페이스를 가지는 것들을 액티비티라고 합니다. 각 액티비티는 Activity 기본 클래스(base class)를 상속받아서 구현합니다. 하나의 어플리케이션은 여러 개의 액티비티로 구성이 될 수 있습니다. 각 액티비티는 전체 화면 또는 화면의 일부인 윈도(window)로 구성됩니다. 윈도는 뷰(view)를 가지고, 이 뷰는 컨트롤(control)과 같은 것으로 버튼, 텍스트, 스크롤 바, 메뉴 등을 가집니다. - 서비스(service)
가시적인 사용자 인터페이스를 가지지 않고 백그라운드(background)에서 동작하는 것들을 서비스라고 합니다. 각 서비스는 Service 기본 클래스를 상속받아서 구현합니다. 서비스의 예로는 음악을 연주하는 서비스가 있습니다. 음악 연주 어플리케이션은 사용자 인터페이스가 필요하겠지만, 사용자가 음악 연주를 시작한 후에는 중지나 종료를 하기 전까지는 특별히 사용자 인터페이스가 필요하지 않습니다. 이런 부분은 서비스로 구현할 수 있습니다. - 브로드캐스트
수신자(broadcast receiver)
널리 공지사항을 알리고자 하는 경우 특정 알림에 반응하는 것들을 브로드캐스트 수신자라고 합니다. 각 브로드캐스트 수신자는 BroadcastReceiver 기본 클래스를 상속받아 구현합니다. 반대로 사용자에게 뭔가를 알리고자 할 때는 NotificationManager를 이용합니다. 예를 들어, 타임존(timezone)이 바뀌었거나, 배터리가 부족하거나, 어떤 그림이 선택이 되었거나, 언어가 바뀌었거나 하는 다양한 상황이 있겠지요. 이럴 때 정보를 알리고자 하면NotificationManager를 사용하고, 알림을 받고자 하면BroadcastReceiver 기본 클래스를 상속받아 구현하면 됩니다. - 컨텐츠
공급자(content provider)
어떤 어플리케이션의 데이터를 다른 어플리케이션에 제공하고자 할 때 사용하는 것들을 컨텐트 공급자라고 합니다. 각 컨텐츠 공급자는ContentProvider 기본 클래스를 상속받아 구현합니다.
(3) 인텐트(intent)
앞에서 설명한 것과 같이 안드로이드 컴포넌트는 4 가지 종류가 있습니다. 안드로이드에서 각 컴포넌트를 활성화시키는 방법은 인턴트(intent)라는 비동기 메시지를 이용합니다. 인턴트는 메시지를 담고 있는 Intent 객체입니다.
인텐트 객체로 활성화될 수 있는 컴포넌트는 액티비티, 서비스, 브로드캐스트 수신자 3 가지입니다. 컨턴츠 공급자는 인턴트로 활성화되지 않고, ContentResolver로부터 요청을 받았을 때 활성화됩니다. 인턴트를 인자로 전달하여 이들 컴포넌트를 활성화하는 방법은 다음과 같습니다.
- 액티비티
활성화
액티비티를 호출하는 쪽에서 Context.startActivity()나Activity.startActivityForResult()를 부르면 됩니다. 그러면 안드로이드가 받아서 호출되는 쪽의 onNewIntent() 메소드를 불러 줍니다. 물론 인자로 인텐트가 전달됩니다. 전달된 인텐트 인자를 보고 의도를 파악하면 됩니다. 이와 별도로 호출된 액티비티는 getIntent() 메소드를 호출하여 의도를 파악할 수도 있습니다. - 서비스
활성화
서비스를 호출하는 쪽에서 Context.startService() 메소드를 부르면 됩니다. 그러면 안드로이드가 받아서 호출되는 쪽의 onStart() 메소드를 불러 줍니다. 물론 인자로 인텐트가 전달됩니다. - 브로드캐스트
수신자 활성화
브로드캐스트 수신자를 호출하는 쪽에서 Context.sendBroadcast()나Context.sendOrderedBroadcast() 또는Context.sendStickyBroadcast()를 부르면 됩니다.
컴포넌트가 활성화된 후에는 자신이 스스로 종료(shut down)할 수도 있고, 다른 컴포넌트가 종료시킬 수도 있습니다. 각 컴포넌트를 종료하는 방법은 다음과 같습니다.
- 액티비티
종료
액티비티가 스스로 종료하고자 하는 경우는 finish() 메소드를 호출하면 됩니다. 반면에 다른 액티비티를 startActivityForResult() 메소드를 호출하여 활성화시킨 후에 종료하고자 할 때 finishActivity() 메소드를 호출하면 됩니다. - 서비스
종료
서비스가 스스로 종료하고자 하는 경우는 stopSelf() 메소드를 호출하면 됩니다. 반면에 다른 서비스를 Centext.bindService()나 onBind(), bindService() 등의 함수로 호출하여 시작시킨 후에 종료하고자 하면Context.stopService() 메소드를 호출하면 됩니다. - 컨텐츠
공급자 종료
별도의 종료를 위한 메소드가 제공되지 않습니다. 컨턴츠 공급자는ContentResolver에 반응하여 활성화되고 일을 처리한 후 종료됩니다. - 브로드캐스트
수신자 종료
컨텐츠 공급자와 유사하게 별도의 종료를 위한 메소드가 제공되지 않습니다. 브로드캐스트 메시지에 반응하여 활성화되고 일을 처리한 후 종료됩니다.
(4) 매니패스트(manifest) 파일
안드로이드가 어플리케이션의 특정 컴포넌트를 시작하려면 안드로이드는 어플리케이션에 어떤 컴포넌트들이 있는지 알고 있어야 합니다. 이를 위해서 어플리케이션은 자신의 컴포넌트들을 매니패스트 파일에 선언을 해야 하며, 이 매니패스트 파일도 안드로이드 패키지인 .apk 파일 안에 번들되어야 합니다.
모든 어플리케이션은 항상 AndroidManifest.xml로 명명된 매니패스트 파일을 가지고 있어야 합니다. 매니패스트 파일은 구조화된 XML 파일입니다. 이 파일에는 컴포넌트(액티비티, 서비스, 브로드캐스트 수신자, 컨텐츠 제공자)들이 어떤 것들이 있는지와 링크 시에 필요한 라이브러리가 어떤 것들이 있는지와 어플리케이션의 권한(permission) 등이 기술되어 있습니다. 다음은 매니패스트 파일의 예입니다.
<?xml
versio="1.0" encoding="utf-8"?> |
<activity> 요소의 name 속성에 이 액티비티를 구현한 Acitivity 하위 클래스 이름을 적습니다. 위 예의 경우는 "com.example.project.FreneticActivity"입니다. 만약 액티비티의 라벨이나 아이콘이 사용자에게 표시될 필요가 있을 경우는 label과icon도 기술합니다. 매니패스트 파일에는 <activity> 요소 외에 서비스를 기술하기 위한 <service>, 컨텐츠 제공자를 기술하기 위한 <provider>, 브로드캐스트 수신자를 기술하기 위한 <receiver> 요소가 있습니다.
인턴트 객체에는 타켓 컴포넌트를 명시적으로 적어 넣을 수 있지만, 타켓 컴포넌트를 명시적으로 적지 않을 수도 있습니다. 만약 타켓 컴포넌트를 명시적으로 적지 않으면 안드로이드는 인턴트 필터(intent filter)를 보고 어떤 컴포넌트를 활성화할 지 결정합니다. 다음은 매니패스트 파일에 기술된 인턴트 필터의 예입니다.
<?xml
versio="1.0" encoding="utf-8"?> |
위 예는 앞의 매니패스트 파일에 인턴트 필터가 추가된 것입니다. 위 코드의 굵은 글씨로 표시된 부분이 추가된 부분입니다. 인텐트 필터에 <action>과 <category>, <data>요소가 있습니다. 첫 번째 인턴트 필터는 어플리케이션 론처(launcher)에서 실행될 컴포넌트의 경우에 사용되는 일반적인 액션, 카테고리 조합입니다. 즉, 액션은"android.intent.action.MAIN"을 사용하고, 카테고리는"android.intent.category.LAUNCHER"를 사용합니다. 매니패스트 파일에 대한 자세한 내용은 별로도 설명할 예정입니다.
'차근차근 > Android' 카테고리의 다른 글
태스크란? (Task, Activity Stack ) (0) | 2014.07.29 |
---|---|
안드로이드 어플리케이션 기초1 - 안드로이드 아키텍처 (0) | 2014.07.29 |
안드로이드 어플리케이션 기초3 - 액티비티와 태스크 (0) | 2014.07.29 |
안드로이드 어플리케이션 기초4 - 프로세스와 쓰레드 (0) | 2014.07.29 |
MediaScanner 을 APP에서 실행시키기 (0) | 2014.07.29 |