Intent와 PendingIntent 이해하기


PendingIntent도 일종의 Intent라고 생각해도 된다.
그런데 Intent의 기본 개념은 특정 컴포넌트(Activity, Service, Broadcast Receiver, Content Provider)를 실행시키는 메시지라는 것이다.

역시 마찬가지로 PendingIntent도 Intent의 일종이므로 특정 컴포넌트를 실행시키는 기능을 한다는 것이다.

그런데 PendingIntent는 생성자가 없고 
다음 세 개의 메소드들에 의해서 객체가 생성된다. 

getActivity(Context, int, Intent, int),
getBroadcast(Context, int, Intent, int),
getService(Context, int, Intent, int).

그런데 이들 세 개의 메소드 중 어느 메소드에 의해서 생성된 PendingIntent 객체냐에 따라서 그 객체가 activity를 실행시킬지 서비스를 수행할지, 방송을 실행시킬지가 결정된다는 것이다.


다음은 Intent에 대한 설명이다. 이 설명을 보면 PendingIntent와 개념상 매우 유사함을 볼수가 있다.

Three of the core components of an application - activities, services, and broadcast receivers - are activated through messages, called intents.
⇒ 안드로이드 애플리케이션에는 3개의 핵심 컴포넌트가 있는데 activities, services, and broadcast receivers이다.
그런데 이들을 실행시키는 것은 메시지에 의해서 이루어지는데 바로 그 메시지를 intent라 한다.

Intent messaging is a facility for late run-time binding between components in the same or different applications.
The intent itself, an Intent object, is a passive data structure holding an abstract description of an operation to be performed - or, often in the case of broadcasts, 
a description of something that has happened and is being announced.
There are separate mechanisms for delivering intents to each type of component:


ㆍAn Intent object is passed to Context.startActivity() or   

   Activity.startActivityForResult() to launch an activity or get an existing 

   activity to do something new.

   ⇒ 이건 Intent가 Activity를 실행하는 용도로 쓰인다는 뜻이다.


ㆍAn Intent object is passed to Context.startService() to initiate a service 

   or deliver new instructions to an ongoing service. Similarly, an intent 

   can be passed to Context.bindService() to establish a connection 

   between the calling component and a target service.

   ⇒ 이건 Intent가 서비스를 실행하는 용도로 쓰인다는 뜻이다.


ㆍIntent objects passed to any of the broadcast methods (such as

   Context.sendBroadcast(), Context.sendOrderedBroadcast(), or

   Context.sendStickyBroadcast()) are delivered to all interested 

   broadcast receivers.

   ⇒ 이건 Intent가 BR(방송)을 실행하는 용도로 쓰인다는 뜻이다.


이렇게 Intent가 Activity, Service, Broadcast Receiver를 수행하는 기능을 하듯이 PendingIntent도 PendingIntent 객체를 생성하는 세 개의 메소드가

getActivity(Context, int, Intent, int),
getBroadcast(Context, int, Intent, int),
getService(Context, int, Intent, int)인데 이들 각각은 순서대로
activity를 실행,
Broadcast Receiver를 실행,
서비스를 실행시키는 용도로 PendingIntent 객체가 생성된다는 것이다.


즉 PendingIntent 객체가 getBroadcast(Context, int, Intent, int)에 의해서 생성되었으면 그 PendigIntent 객체로는 방송을 실행한다는 것이고 getActivity(Context, int, Intent, int)에 의해서 생성된 PendingIntent 객체는 activity를 실행시킨다는 것이다.
어느 메소드에 의해서 객체가 생성되었느냐에 따라서 PendingIntent객체가 실행하는 컴포넌트가 달라진다는 것이다.


public static PendingIntent getBroadcast (Context context, int requestCode, Intent intent, int flags)

⇒ Retrieve a PendingIntent that will perform a broadcast, like calling

   Context.sendBroadcast().


context : The Context in which this PendingIntent should perform the 

                 broadcast.

requestCode : Private request code for the sender (currently not used).

intent : The Intent to be broadcast.

flags : May be FLAG_ONE_SHOT, FLAG_NO_CREATE, 

             FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT, or any of 

             the flags as supported by Intent.fillIn() to control which 

             unspecified parts of the intent that can be supplied when the 

             actual send happens.

Returns : Returns an existing or new PendingIntent matching the given 

                 parameters. May return null only if FLAG_NO_CREATE has 

                 been supplied.


요약하면 Intent는 Activity, Service, BR을 실행시키는 message이다. PendingIntent도 일종의 Intent인데 이것의 객체가 getActivity()에 의해서 생성된 것이면 그 PendingIntent 객체는 Activity를 실행시키고 getBroadcast()에 의해서 생성된 객체이면 그 객체는 방송을 실행시킨다.


방송을 내 보낼때 어떤 컴포넌트에게 내보내는지는 Intent가 특정 컴포넌트를 호출하는 기능(명시적, 암시적 호출)이 있으므로 Intent의 이 기능을 PendingIntent가 활용해서 특정 컴포넌트에게 방송을 내보낸다.


이때 특정 컴포넌트가 방송을 수신할 수 있기 위해서는 Menifest에 방송 수신에 대한 정보를 기록해 두어야 한다.






안드로이드 앱에서 구글, 네이버, 다음의 검색 기능을 이용한 웹 검색하는 기능은 Intent를 이용해서 구현할 수 있다.


Intent의 action 가운데 Intent.ACTION_WEB_SEARCH가 이 기능을 안드로이드 시스템에 요청하는 action이다.

이 action을 Intent에 담아서 startActivity로 날리면 안드로이드 시스템은 웹 search를 위한 동작을 수행하게 된다.

기본적으로는 구글 검색을 수행하지만 만일 디바이스(폰)에 네이버 앱이나, 다음 앱이 설치되어 있다면 이들 셋 중에서 선택하는 창이 뜨고 이 창에서 구글, 네이버, 다음의 검색 기능을 이용해서 특정 웹 검색을 수행할 수 있다.




이때 검색할 단어(내용)을 설정하는 것은 Intent의 extra에 담아서 수행하면 된다.

이때 putExtra에 사용할 key를 안드로이드 시스템에서 미리 설정해 두고 있다. 

그것이 SearchManager.QUERY라는 key값이다.

구글(네이버, 다음...)의 웹 검색 창에서 무엇을 검색할지를 안드로이드 시스템에게

알리는데 key 값이다.


Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);

intent.putExtra(SearchManager.QUERY, "검색할 단어");


if (intent.resolveActivity(getPackageManager()) != null) {

     startActivity(intent);

} else {

     String msg = "Sorry, there is no web browser available"; 

     Toast.makeText(this, msg, Toast.LENGTH_LONG).show();

}


Context 클래스의 메소드인 getPackgaeManager() 메소드는 다음과 같다.


public abstract PackageManager getPackageManager () 

⇒ Return PackageManager instance to find global package information.


디바이스에 있는 전 패키지 정보를 획득하기 위한 PackageManger 객체를 반환해 주는 메소드이다.


public ComponentName resolveActivity (PackageManager pm) : Intent 클래스의 메소드

⇒ Return the Activity component that should be used to handle this intent. 


resolveActivity() 메소드는 Intent를 수행할 Activity를 반환한다. 만일 수행할 Activity가 없으면 null을 반환한다.

이럴때 startActivity()를 수행하면 앱이 강제종료를 먹게된다.


그런데 아래 코드의 경우 웹 검색할 앱(Activity)가 구글, 네이버, 다음이 폰에 설치되어 있다면

아래 코드에서는 com.android.internal.app.ResolverActivity가 반환이 된다.

ResolverActivity는 안드로이드 API reference에서 search를 해도 보이지 않는다.

통상적인 클래스들은 API reference에서 search를 하면 자동완성 기능으로 제시가 되는데

ResolverActivity는 표시가 안된다. 

결론적으로 ResolverActivity는 여러개의 Activity가 Intent에 매칭될때 이를 관리하는

클래스이다.



+ Recent posts