본문 바로가기
공부/Android

Android - 인텐트(Intent) 완전 정복

by hhhello 2024. 6. 14.

인텐트란 무엇인가?

지난 글에서 컴포넌트(Component)는 독립적이고 그렇기 때문에 이 컴포넌트는 시스템에 의해 실행된다고 말했다. 컴포넌트에서 다른 컴포넌트를 직접적으로 제어하지 않는다는 말이다.

이때 시스템에게 ‘OO컴포넌트 좀 제어해주세요~’라고 메세지를 보내야 하는데 이 메세지가 바로 인텐트(Intent)이다. 인텐트에 데이터를 담아서 다른 컴포넌트로 보낼 수도 있다.

인텐트 사용해보기

인텐트를 사용하기 전에 두 액티비티를 만들어주자. 두 액티비티 간의 화면 전환에서 인텐트를 사용할 것이기 때문이다.

 <activity
    android:name=".DetailActivity"
    android:exported="true"
    android:theme="@style/Theme.Intent" />
<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

화면은 어떻게 만들든 상관없지만 나는 MainActivity에 화면 전환용 버튼을 그렸다.
코드는 버튼을 클릭하면 (1) 인텐트 생성 후 (2) startActivity함수로 화면 전환을 하도록 작성했다.

아래 코드에서 인텐트 생성(1) 하는 코드에서 DetailActivity클래스를 직접 생성하지 않는다는 것을 알 수 있다. 이는 시스템이 AndroidManifest.xml 에서 컴포넌트를 읽어들인 후 그 컴포넌트를 대신에서 생성해주기 때문이다.

class MainActivity : AppCompatActivity() {

    private lateinit var button: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        
        // ...

        button = findViewById(R.id.btn_nav)
        button.setOnClickListener {
            val intent = Intent(this, DetailActivity::class.java) // (1)
            startActivity(intent) // (2)
        }
    }
}

다음은 DetailActivity 코드이다.
화면은 글자 조금이랑 MainActivity로 돌아가는 버튼 하나를 그렸다.
코드는 버튼을 누르면 (1) finish함수로 액티비티가 종료되도록 작성하였다.

class DetailActivity : AppCompatActivity() {

    lateinit var button: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // ...
        
        button = findViewById(R.id.btn_nav_back)
        button.setOnClickListener {
            finish() // (1)
        }
    }
}

아래는 시현영상이다. DetailActivity에서 finish함수를 호출하여 액티비티를 종료하면 MainActivity로 돌아온다. 모바일에서 네비게이션의 개념은 스택처럼 동작하기 때문이다. 스택이 뭔지 모른다고? 화면을 접시처럼 쌓아올리는 것이라 생각하면 된다.

 

인텐트에 데이터를 담아 전송하기

MainActivity코드에서 버튼 클릭하는 코드이다. 여기서 인텐트를 생성한 뒤 putExtra함수로 데이터를 담을 수 있다.

// MainActivity.kt
button.setOnClickListener {
    val intent = Intent(this, DetailActivity::class.java)
    intent.putExtra("myMessage", "야호")
    startActivity(intent)
}

putExtra 함수의 인자는 namevalue로 구성되어 있는데 namevalue 를 구분하는 식별자이고 value는 실제로 전송할 값이다.
putExtra 함수를 보면 Android API가 지원하는 value 의 타입들이 있다. 모든 데이터 타입을 전송할 수 있는 게 아니다.
data class 같은 객체를 전송하고 싶다면 ‘json으로 변환하여 String으로 전송’한다든지 다른 형식으로 변환해야 할 것이다.

아래는 DetailActivity코드이다.
Activity 클래스에서 intent를 이미 갖고 있기 때문에 그냥 intent를 바로 사용할 수 있다.
intent.getOOOOExtra(name: String)으로 전송받은 데이터를 불러올 수 있다.
이 함수도 아까 putExtra 함수와 마찬가지로 데이터 타입이 대칭되는 것을 주목해라.

class DetailActivity : AppCompatActivity() {

    lateinit var button: Button
    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // ...
        
        textView = findViewById(R.id.tv_title)
        
        // ...

        val message = intent.getStringExtra("myMessage")
        textView.text = message?: "불러오기 실패"
    }
}

정상적으로 ‘야호’글씨가 출력된 것을 볼 수 있다.

명시적 인텐트 vs 암시적 인텐트

사실 우리가 지금까지 다룬 인텐트는 바로 명시적 인텐트이다. 이와 반대되는 개념으로 암시적 인텐트가 존재한다.

명시적 인텐트는 클래스를 참조해서 내부 앱의 컴포넌트를 요청하는 데에 사용된다. 반면 외부 앱의 컴포넌트는 참조될 수 없으므로 이때 암시적 인텐트를 사용한다.

암시적 인텐트는 AndroidManifest.xml 파일에 intent-filter 부분에서 선언할 수 있다.