본문 바로가기
TIL/Android

[Android] 인텐트(intent)란? / 컨텍스트(Context) /명시적 인텐트, 암시적 인텐트, 인텐트 필터

by 왁왁s 2022. 11. 10.

인텐트(Intent) 란?

 

인텐트는 직역하면 '의도'로, 개발자가 어떤 의도를 가지고 메서드를 실행할 것인지를 인텐트에 담아서 안드로이드에 전달하면 해당 인텐트를 해석하고 실행한다. 

 

좀 더 자세히 말하면 액티비티를 실행하기 위해서는 단순히 컨텍스트가 제공하는 메서드를 호출하면 되는데, 이때 실행할 액티비티가 명시된 인텐트(Intent)를 해당 메서드에 전달해야 한다.

 

 

이렇듯 액티비티를 실행하려면 기본적으로 인텐트가 필요하지만, MainActivity는 특별한 설정을 하지 않아도 안드로이드에 자동으로 등록되고 실행이 가능하다.

 

그러나 새롭게 생성한 액티비티는 인텐트에 담아서 시스템에 전달하여야 실행이 가능하다.

 

새롭게 생성한 액티비티를 실행하기 위해 인텐트로 전달하는 순서는 아래와 같다.


 

새롭게 생성한 액티비티(Activity) 실행 순서

 

1. 새롭게 생성한 액티비티 이름과 전달하고자 하는 데이터를 담은 인텐트를 생성한다.

2. statActivity() 메서드에 인텐트를 담아 호출하면 액티비티 매니저에 전달된다.

3. 액티비티 매니저는 인텐트를 분석해 작성한 액티비티를 실행시킨다.

4. 전달된 인텐트는 타겟한 액티비티까지 전달되고, 타겟 액티비티에서 전달받은 인텐트의 데이터를 활용한다. 

 

 

이렇듯 인텐트(Intent)는 메시징 객체로, 다른 앱 구성 요소로부터 작업을 요청하는 데 사용할 수 있다. 

 

인텐트가 구성 요소 사이의 통신을 촉진하는 데는 여러 가지 방식이 있지만 기본적으로 3가지로 나눈다.

 


액티비티의 시작 

Activity는 앱 안의 단일 화면을 나타냅니다. Activity의 새 인스턴스를 시작하려면 Intent를 startActivity()로 전달하면 된다. Intent는 시작할 액티비티를 설명하고 모든 필수 데이터를 담는다.

 

액티비티가 완료되었을 때 결과를 수신하려면, startActivityForResult()를 호출한다.

액티비티는 해당 결과를 이 액티비티의 onActivityResult() 콜백에서 별도의 Intent 객체로 수신한다.

 

서비스의 시작

Service는 사용자 인터페이스 없이 백그라운드에서 작업을 수행하는 구성 요소이다.

Android 5.0(API 레벨 21) 이상부터는 JobScheduler로 서비스를 시작할 수 있으며, Android 5.0(API 레벨 21) 이하 버전은 Service 클래스의 메서드를 사용하면 서비스를 시작할 수 있다.

 

서비스를 시작하여 일회성 작업을 수행하도록 하려면(예: 파일 다운로드) Intent를 startService()에 전달하면 된다. Intent는 시작할 서비스를 설명하고 모든 필수 데이터를 담고 있다. 서비스가 클라이언트-서버 인터페이스로 디자인된 경우, 다른 구성 요소로부터 서비스에 바인딩하려면 Intent를 bindService()에 전달하면 된다. 

 

브로드케스트 전달

브로드캐스트는 모든 앱이 수신할 수 있는 메시지이다.

시스템은 시스템이 부팅될 때 또는 기기가 충전을 시작할 때 등 시스템 이벤트에 대한 다양한 브로드캐스트를 전달한다. Intent를 sendBroadcast() 또는 sendOrderedBroadcast()에 전달하면 다른 앱에 브로드캐스트를 전달할 수 있다.

 

 

  • 액티비티의 시작: startActivity(Intent), startActivityForResult(Intent, requestCode)
  • 서비스의 시작: startService(Intent), bindService(Intent)
  • 브로드케스트 전달: sendBroadcast(Intent), sendOrderedBroadcast(Intent), sendStickyBroadcast()

 



 

명시적 인텐트(Intent)

어떤 구성 요소로 메시지를 보낼 지 즉, 다음에 수행할 컴포넌트의 이름을 명확하게 개발자가 직접 지정한다.

보통 앱(App) 내의 있는 컴포넌트(Component)를 실행할 때 사용하는데, 이는 시작하려는 액티비티 또는 서비스의 클래스 명을 알고 있어야 하기에 앱 내의 컴포넌트를 시작할 때 쓴다.

 

- 대상 앱의 패키지명 또는 구성 요소 클래스 이름을 제공.

ex) new Intent(context, 클래스 이름)

 

조금 더 추가적으로 설명하자면,

 

1. 인텐트를 충족하는 어플리케이션이 무엇인지 지정한다.

2. 대상 앱의 패키지 이름 또는 구성 요소 클래스 이름을 제공한다.

3. 시작하고자 하는 액티비티 또는 서비스의 클래스 이름을 알고 있어야 하기 때문에, 앱 안에서 구성 요소를 시작할 때 사용한다.

 

 

 

ex) 사용자 작업에 응답하여 새로운 액티비티를 시작하거나 백그라운드에서 파일을 다운로드하기 위해 서비스를 시작하는 것 등

 

 


 

암시적 인텐트(Intent)

특정 컴포넌트를 클래스명을 주는 것과 같은 직접적인 지정 없이, 어떠한 작업을 수행할 것인지 일반적인 작업을 선언해 다른 앱의 컴포넌트가 이를 처리할 수 있도록 한다. 해당 인텐트를 처리할 수 있는 컴포넌트를 시스템이 필터링하여 수행하거나 사용자에게 선택하도록 한다.

 

조금 더 추가적으로 설명하자면,

1. 암시적 인텐트를 사용하면 Android 시스템에서, 시작할 적절한 구성 요소를 찾는다. 

2. 안드로이드 시스템에서 다른 여러 앱(App)에 있는 매니페스트(manifest) 파일에 선언된 인텐트 필터(intent filter)와 비교 및 참조한다. 3. 해당 인텐트와 일치하는 인텐트 필터가 있으면시스템에서 해당 구성 요소를 시작하고 인텐트(Intent) 객체를 전달한다.4. 호환되는 인텐트 필터가 여러 개인 경우, 시스템에서 대화상자를 표시하여 사용자가 어느 앱을 사용할 지 직접 선택할 수 있게 한다.

 

ex) 사용자에게 지도에 있는 한 위치를 표시하고자 하는 경우, 암시적 인텐트를 사용하여 해당 기능을 갖춘 다른 앱이 지정된 위치를 지도에 표시하도록 요청할 수 있습니다.

 

ex) 사진 업로드 할 때 카메라 or 갤러리 앱 중 사용자에게 선택하도록 하는 것

 

 


인텐트 필터(intent-filter)

인텐트 필터란 앱의 매니페스트 파일에 들어 있는 표현으로, 해당 구성 요소가 수신하고자 하는 인텐트의 유형을 나타낸다. 예를 들어 액티비티에 대한 인텐트 필터를 선언하면 다른 여러 앱이 특정한 종류의 인텐트를 가지고 액티비티를 직접 시작할 수 있다. 마찬가지로 액티비티에 대한 인텐트 필터를 선언하지 않는 경우, 이것은 명시적인 인텐트로만 시작할 수 있다.

 

암시적 인텐트가 시스템을 통해 전달되어 다른 액티비티를 시작하는 방법. 

[1] 액티비티 A가 작업 설명이 있는 Intent를 생성하여 이를 startActivity()에 전달한다. [2] Android 시스템이 모든 앱에서 해당 인텐트와 일치하는 인텐트 필터를 검색한다. 일치하는 항목을 찾으면, [3] 시스템이 해당 액티비티의 onCreate() 메서드를 호출하여 이를 Intent에 전달하고, 일치하는 액티비티(액티비티 B)를 시작한다.

 

 


 

 

Intent 객체 생성하기

Intent 객체에는 Android 시스템이 어느 구성 요소를 시작할지 판별하는 데 사용하는 정보( 정확한 컴포넌트 이름 또는 인텐트를 수신해야 하는 컴포넌트 카테고리 )가 담겨 있다. 또한 수신자 구성 요소가 작업을 적절히 수행하기 위한 정보( 수행할 작업이 담긴 데이터 위치 ) 또한 담겨 있다.

 

명시적 인텐트

명시적 인텐트는 앱 내의 특정 액티비티나 서비스 등 특정한 앱 구성 요소를 시작하는 데 사용하는 인텐트

 

명시적 인텐트를 생성하려면 Intent 객체에 대한 구성 요소 이름을 정의한다. 다른 인텐트 속성은 모두 선택 사항이다.

 

Intent(Context, Class) 

val intent = Intent(this, MoveActivity::class.java)

Intent(Context, Class) 생성자가 앱에 Context를 제공하고 구성 요소에 Class 객체를 제공한다. 

 

인텐트(Intent)를 사용해 액티비티 전환 간의 액티비티를 종료하지 않으면 뒤로 가기를 수십 번 눌러야 하는 경우가 발생한다. 이를 방지하기 위해 적절하게 액티비티를 종료하는 명령어를 작성해줘야 한다. 

이때 finish()를 사용한다.

finish()

 


 

컨텍스트(Context)란?

안드로이드 어플리케이션의 전반적인 정보를 담고 있는 객체로,

시스템을 사용하기 위한 정보(프로퍼티)와 도구(메서드) 가 담겨 있는 클래스이다.

 

대부분 컨텍스트는 컴포넌트 실행(Runtime)시 함께 생성되고, 생성된 컴포넌트가 가지고 있는 메서드를 호출해서 각각의 도구를 사용할 수 있다.

 

또한 액티비티는 컨텍스트를 상속받아 구현된다.

 

그렇다면 어떤 정보를 담고 있는가?

 


 

Activity에 대한 Context (Activity Context)

Acitivity에 대한 Context이기 때문에 Activity가 생김에 따라 Context도 새롭게 생겨난다.

 

위에서 살펴봤던 아래의 코드에서 this 부분이 Context이다.

val intent = Intent(this, MoveActivity::class.java)

startActivity(intent)

첫 번째 인자인 context는 this로 대체할 수 있는데, this는 현재 Activity를 가리킨다.

즉, Activity Context를 뜻한다.

 

 

startActivity의 intent 앞에 this가 생략된 것이다. 원래의 원문은 context.startActivity(this.intent) 이다.

 

 

Activity Context 생명 주기

Activity Context는 주로 Activity 안에서 많이 사용되며, Context는 Activity의 생명주기를 따른다. 

onCreate() 하면 생기고 onDestroy() 하면 사라지는 생명 주기를 따른다.

 

 

Context 넘겨주는 이유 

Context가 넘어갔을 때, 바로 전에 호출한 Activity에 대한 정보가 필요하기 때문이다.

Acitivty에 대한 정보를 앱의 스택에 쌓고, 취소 키를 눌렀을 때 이전 화면으로 돌아갈 수 있도록 할 수 있다.

 

 


 

 

App 전체에 대한 Context (ApplicationContext)

말 그대로 어플리케이션 자체의 Context이다. 하나의 어플리케이션 당 1개가 존재한다.

Activity와 달리 Application은 포괄적인 범위이다. 

 

앱에서는 프로세스와 어플리케이션을 따로 관리한다. 이는 모바일 환경의 특성 때문에 최적화를 위한 이유인데,

아무리 앱을 끄더라도 항상 돌아가는 듯한 느낌을 준다.

 

예를 들어 앱을 취소 버튼을 눌러 종료를 시켰는데도 홈 키 왼쪽 버튼을 누르면 앱이 살아 있는 것을 확인할 수 있다.

이는 프로세스와 어플리케이션을 따로 관리해, 프로세스는 꺼졌음에도 어플리케이션은 남아있기 때문이다.

 

AcitivityManagerService라는 것이 있는데, 앱의 프로세스와 어플리케이션의 관계와 같은 정보를 가지고 있다.

그런데 AcitivityManagerService에 대한 필요한 정보들을 Application Context 가 가지고 있다. 

앱 당 1개만 존재하는 이유이기도 하다.

댓글