[Android] Intent

유민국·2023년 8월 1일
0

Intent

Intent란?

Intent는 메시징 객체로 컴포넌트간의 통신 역할을 해준다.
Intent는 실행하고자 하는 4대 구성 요소와 관련된 정보를 가지고 있다.
안드로이드 4대 구성 요소(Activity, Service, Broadcast Receiver, Content Provier)를 실행하기 위해서 Intent객체가 필요하고, 구성 요소끼리 정보전달을 가능하게 해준다.
개발자는 실행하고자 하는 4대 구성 요소의 정보를 Intent에 담고 이를 안드로이드 OS에게 전달하면 안드로이드 OS에 의해 해당 구성 요소가 실행된다.

  • Intent 객체에 데이터를 저장 및 추출 할 수 있다(putExtra, getExtra)

1. 명시적 인텐트

명시적 인텐트는 Intent에 클래스 객체나 컴포넌트 이름을 지정하여 호출할 대상을 확실히 알 수 있는 경우에 사용하며 실행되는 컴포넌트가 무엇인지 명시되어 있다.

val intent = Intent(this, MyActivity::class.java);
startActivity(intent);
  • 주로 애플리케이션 내부에서 사용.
    인텐트는 엑티비티 호출시 데이터를 전달 또는 데이터를 리턴 받을 수 있습니다.

현재 엑티비티에서 다른 엑티비티를 호출할 때 사용하며, 실행을 원하는 액티비티는 manifest에서 exported속성이 true로 설정되어야 한다.

2. 암시적 인텐트

암시적 인텐트는 작업을 지정하여 기기에서 해당 작업을 수행할 수 있는 모든 앱을 호출할 수 있도록 합니다.
호출하려는 컴포넌트의 패키지명과 클래스명을 모르는 경우(다른 앱을 선택해야 하는 경우) 사용하는 방법으로 호출하려는 작업의 내용을 지정하고, 시스템이 이 작업을 처리할 수 있는 컴포넌트를 찾아서 호출한다.

  • ex) 웹 브라우저를 실행 할 때 (Chrome, Safari, Edge) 중에서 어느것으로 실행 할 것 인가를 선택

암시적 인텐트에는 웹브라우저 호출, 이메일 전송, 전화 앱 등이 해당한다.

주의: 사용자에게 개발자가 startActivity()로 전송한 암시적 인텐트
를 처리할 앱이 전혀 없을 수도 있고, 관리자가 프로필 제한이나 설정
을 적용한 탓에 앱에 엑세스할 수 없을 수도 있는데 이런 경우 호출은 
실패하고 앱이 꺼지게 된다. 어느 Activity든 Intent를 수신하도록 
하려면 Intent 객체의 resolveActivity()를 호출해야 한다. 결과가 
null이 아닌 경우, 인텐트를 처리할 수 잇는 앱이 최소한 하나는 있다
는 듯이며 startActivity()를 호출해도 안전하다. 하지만 null일 경
우라면 해당 Intent는 사용하면 안되고 해당 Intent를 발생시키는 기
능을 비활성화 시켜놔야한다. 

암시적 인텐트 수신

앱이 수신할 수 있는 암시적 인텐트가 어느 것인지 알리려면, <intent-filter> 요소를 사용하여 각 앱 구성 요소에 대해 하나 이상의 인텐트 필터를 매니페스트 파일에 선언합니다. 각 인텐트 필터는 인텐트의 작업, 데이터 및 카테고리를 기반으로 어느 유형의 인텐트를 수락하는지 지정합니다. 시스템은 인텐트가 인텐트 필터 중 하나를 통과한 경우에만 암시적 인텐트를 앱 구성 요소에 전달합니다.

앱 구성 요소는 자신이 수행할 수 있는 각각의 고유한 작업에 대하여 별도의 필터를 선언해야 합니다. 예를 들어 이미지 갤러리 앱에 있는 액티비티에 두 개의 필터가 있을 수 있습니다. 한 필터는 이미지를 보고, 다른 필터는 이미지를 편집하기 위한 것입니다. 액티비티가 시작되면, Intent를 검사한 다음 Intent에 있는 정보를 근거로 어떻게 동작할 것인지 결정합니다(편집기 제어 항목을 표시할 것인지 말 것인지 등).

<intent-filter> 내부에서는 다음과 같은 세 가지 요소 중 하나 이상을 사용하여 허용할 인텐트 유형을 지정할 수 있습니다.

  1. <action>
  • name 특성에서 허용된 인텐트 작업을 선한한다. 값은 클래스 상수가 아닌 Action의 리터럴 문자열 값이어야 합니다.
  1. <data>
  • 허용된 데이터 유형을 선언한다. 데이터 URI(scheme, host, port, path)와 MIME 유형의 여러 가지 측면을 나타내는 하나 이상의 특성을 사용한다.
  1. <category>
  • name 특성에서 허용된 인텐트 카테고리를 선언한다. 값은 클래스 상수가 아닌 Action의 리터럴 문자열 값이어야 합니다.
참고: 암시적 인텐트를 수신하려면 CATEGORY_DEFAULT 카테고리를 인
텐트 필터에 포함해야 한다. startActivity() 및 
startActivityForResult() 메서드는 마치 CATEGORY_DEFAULT 범주
를 선언한 것처럼 모든 인텐트를 취급한다. 이 카테고리를 인텐트 필터
에서 선언하지 않으면 액티비티에 어떤 암시적 인텐트도 확인되지 않습
니다.

ex) 데이터 유형이 텍스트인 경우 ACTION_SEND 인텐트를 수신할 인텐트 필터가 있는 액티비티 선언

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

Intent 기본 사항

component name

  • 선택 사항이지만 intent를 명시적으로 만들어 줌
  • Intent의 필드는 ComponentName 객체로, 이것을 지정하려면 대상 component의 클래스 이름(앱의 패키지 이름 포함)을 사용해야 한다. ex) com.example.ExampleActivity
  • component name을 설정하려면 setComponent(), setClass(), setClassName()을 사용 하거나 Intent 생성자를 통해 설정한다.
참고 : Service를 시작하는 경우, Intent에 어느 서비스가 응답할지 
확신할 수 없고, 사용자도 어느 서비스가 시작되었는지 볼 수 없게 되
기 때문에 항상 component name을 지정해야 한다. 

Action

수행할 작업을 나타내는 문자열이다.(EX. ACTION_VIEW, ACTION_SEND)
Action은 대체로 나머지 Intent의 구조(특히, 데이터와 엑스트라에 포함되어 있는 정보)를 결정한다.
보통은 Intent 클래스나 다른 프레임워크 클래스가 정의한 작업을 지정해야 한다.

Data

Action을 수행할 데이터 및 해당 데이터의 MINE 유형을 참조하는 URI 객체이다.
데이터의 유형은 일반적으로 Intent의 Action에서 결정된다. 예를 들어 ACTION_EDIT 인 경우, 데이터에 편집할 문서의 URI가 들어 있어야 한다.

  • Intent를 생성할 때는 데이터 유형(데이터의 MIME 유형)을 지정하는 것이 중요하다. 예를 들어 이미지를 표시할 수 있는 Activity라면 URI 형식이 비슷할지언정 오디오 파일은 재생하지 못한다.
  • Data URI만을 설정한다면 setData()를 통해
  • MIME 유형만을 설정, setType()을 통해
  • setDataAndType() : 위의 두 가지를 모두 설정 가능
주의 : URI와 MIME 유형을 둘 다 설정하고자 하는 경우 꼭 ```setDataAndType()``` 하도록 해야한다.
```setData()```, ```setType()```은 서로의 값을 무효화 하기 때문

Category

Intent를 처리해야 하는 component의 종류에 대한 추가 정보를 담은 문자열이다.
Intent 안에는 카테고리 설명이 포함할 수 있지만 대부분의 Intent는 카테고리가 필요하지 않다
카테고리는 addCategory()로 지정할 수 있다.

보편적인 카테고리 2가지
CATEGORY_BROWSABLE

  • 대상 Activity가 웹브라우저를 통해 시작되도록 허용하고 이미지, 이메일 메시지 등의 링크로 참조된 데이터를 표시하게 한다.
    CATEGORY_LAUNCHER
  • 이 Activity가 Action의 최초 Activity이며, 시스템의 애플리케이션 시작 관리자에 목록으로 게재된다.

Extras

  • 위에 나열된 속성(name, action, data, category...)은 인텐트를 정의하는 특성을 나타내어 OS는 이와 같은 속성을 읽어 어느 앱 구성 요소를 시작해야 할지 확인할 수 있지만 Intent는 앱 구성 요소로 확인되는 방법에 영향을 미치지 않는 추가 정보도 담고 있을 수 있다.

요청된 작업을 수행하는 데 필요한 추가 정보가 담긴 키-값 쌍으로 되어 있다.
putExtra로 데이터를 추가할 수 있으며 모든 엑스트라 데이터를 포함한 Bundle객체르 만든 다음 BundleIntentputExtras()로 삽입할 수도 있다.

  • Intent 클래스는 표준화된 데이터 유형에 대해 여러 EXTRA_* 상수를 지정하고 있다.
주의 : Intent를 통해 다른 앱으로 데이터를 전송할 때 Pacelable 
또는 Serializable 데이터를 사용하지 말도록 한다. 앱이 Bundle 객
체에 있는 데이터에 엑서스하려고 시도한 경우 Pacelable, 
Serializable 클래스에 엑세스 하지 못하면 시스템이 
RuntimeException을 발생시킨다.

Flags

플래그느 Intent 클래스에서 정의되고 인텐트에 대한 메타데이터와 같은 기능을 한다. 시작할 방법에 대한 지침(Activity가 어느 Action에 소속되어야 하는지 등)이나 Activity를 시작한 다음에 어떻게 처리해야 하는지(해당 Activity가 최근 Activity 목록에 소속되는지 여부)도 알려줄 수 있다.

setFlag()를 통해 설정할 수 있고 Intent에 의해 실행되는 구성 요소의 유형에 따라 달라진다. FLAGACTIVE 플래그는 모두 Context.startActivity()와 함께 사용되고 FLAGRECIVER 플래그는 모두 Context.sendBroadcast()와 함께 사용된다.

Intent Filter 란?

앱에 Intent가 전달되었을 때 Intent Filter에 기술된 조건에 맞는 Intent만 통과시킴 (말 그대로 필터링)

Manifest에서 activity 내부에 선언하며, 해당 activity가 어떤 동작인지, 어떤 카테고리인지 명시하여 일치하는 암시적 인텐트를 받을 수 있도록 함

ex) A 앱에서 Intent에 ACTION_VIEW, CATEGORY_BROWSABLE를 설정한 후 전송하면?

  • 암시적 인텐트이므로 CATEGORY_DEFAULT가 자동 추가된 후 전송

  • 설치된 앱들 중 Intent Filter에 ACTION_VIEW, CATEGORY_BROWSABLE,
    CATEGORY_DEFAULT가 정의된 앱들의 목록이 등장함
    (해당 앱들의 Filter가 Intent를 통과시킴)

  • 목록에서 앱을 선택하면 해당 앱으로 Intent 전달하며 컴포넌트를 실행함
    (코드 예시)

[A 앱] // 웹 사이트를 열기 위한 인텐트를 전송
val intent = Intent().apply {
action = Intent.ACTION_VIEW
data = Uri.parse("https://www.google.com")
}
context.startActivity(intent)

[B 앱 Manifest] // A앱이 보낸 intent의 액션 및 카테고리가 일치하여 통과

<activity
	android:name="com.text.BTestActivity">
	<intent-filter>
    	<action android:name="action.ACTION_VIEW/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
    </intent-filter>
</activity>

B 앱에서 A 앱의 암시적 인텐트를 통과시켜 받았으므로, B 앱에서는 해당 인텐트의 data (google 주소)를 받아 웹을 띄워 줄 수 있다

profile
안녕하세요 😊

1개의 댓글

comment-user-thumbnail
2023년 8월 1일

이런 유용한 정보를 나눠주셔서 감사합니다.

답글 달기