도래울

Android Intent 와 Intent filter 본문

개발/Android

Android Intent 와 Intent filter

도래울 2016. 2. 5. 12:59

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>

아~~ 너무 복잡합니다.

Comments