애플리케션들은 한 개 이상의 액티비티들로 구성되어 있으며, 애플리케이션 안에서 액티비티들은 느슨하게 연결되어있다.
첫 번째 액티비티에서 두 번째 액티비티로 전화하려면? intents
이용
Intents are the messageing system by which onen activity is able to launch another activity.
An intent is an abstract description of an operation to be performed.
startActivity
to launch an ActivitysendBroadcast
to send it to any interested BroadcastReceiver componentsstarService
(Intent) orbindService
(Intent, ServiceConnection, flags) to communication with a background Serviceintent 객체에 bundle 타입 data 를 전달할 수 있다.
Explicit intent 명시적 인텐트
구체적으로 지정
"애플리케이션 A의 컴포넌트 B 를 작동시켜라"
Implicit intent 암시적 인텐트
기본 조건만 지정
"지도를 보여줄 수 있는 컴포턴트라면 어떤 거라도 괜찮아!"
Manifest 파일에 컴포넌트에 관한 상세 정보를 등록
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentsample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.IntentSample">
<!-- App. 에 등록된 2개의 컴포넌트 => 모두 액티비티 -->
<activity
android:name=".SubActivity"
android:exported="true" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<!-- MainActivity 를 가장 먼저 실행 -->
<action android:name="android.intent.action.MAIN" />
<!-- 바탕화면에 App.Launcher Icon 으로 나타나야함 -->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
실행하고자 하는 액티비티 이름을 지정
this
=> MainActivity
SubActivity::class.java
=> 메모리에 저장된 섭액티비티 클래스를 가리킴. 즉, 섭액티비티 클래스 정보를 추출할 때 시작점이 됨 : reflection
var intent = Intent(this, SubActivity::class.java)
startActivity(intent)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.button.setOnClickListener {
val intent = Intent(this, SubActivity::class.java)
startActivity(intent)
}
}
class SubActivity : AppCompatActivity() {
private lateinit var binding: ActivitySubBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySubBinding.inflate(layoutInflater)
setContentView(binding.root)
// Activity stack 에서 SubActivity 제거
// -> MainActivity 가 스택에서 사라지지 않는 이상 다시 활성화
binding.button.setOnClickListner {
finish()
}
}
}
Extra : intent 에 포함되어 전달되는 데이터
- key-value 쌍의 형태로 Extra 에 추가
- Key 만을 사용해 value 을 가져오기 떄문에 value 의 타입을 알아야함
- 데이터 전달
intent.putExtra()
- 데이터 받기
intent.getInExtra(key, value)
// 클래스 밖에서 선언한 문자열
// SubActivity 에서도 참조 가능
const val MY_STRING = "my_string"
const val MY_INT = "my_int"
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.button.setOnClickListener {
val intent = Intent(this, SubActivity::class.java)
val str = binding.editText.text.toString()
// Intent 객체에 메시지를 포함해 전달
intent.putExtra(MY_STRING, str)
intent.putExtra(MY_INT, 13)
startForResult.launch(intent)
}
}
class SubActivity : AppCompatActivity() {
private lateinit var binding: ActivitySubBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySubBinding.inflate(layoutInflater)
setContentView(binding.root)
// if 조건문이 null 이면,
// Extra 에서 String 과 Int 값을 가져옴
if (intent.extras == null || intent == null) return
val qString: String? = intent.getStringExtra(MY_STRING)
val qInt: Int = intent.getIntExtra(MY_INT, 0)
binding.editText.setText(qString + qInt.toString())
// 위의 코드 블록과 같은 내용
// 인텐트 객체가 부가 메시지를 포함하는지 확인
if(intent.hasExtra(MY_STRING) && intent.hasExtra(MY_INT))
{
// Elvis 연산을 사용한 Null safe 검사
// extras 의 타입은 Bundle 로 getString() 사용
val extras: Bundle? = intent.extras ?: return
val qString = extras?.getString(MY_STRING)
val qInt = extras?.getInt(MY_INT)
binding.editText.setText("$qString $qInt")
}
binding.button.setOnClickListener {
finish()
}
}
}
if (intent.extras == null || intent == null) return
val extras: Bundle? = intent.extras ?: return
extras = intent.extras if intent.extras != nullextras = null if intent.extras == null
액티비티 사이의 작업은 양방향 작업
startForResult.launch(intent)
-> 단순히 액티비티 전환이 아닌 결과를 돌려받기 위한 액티비티 호출
startForResult
-> 결과 돌려받았을 때 처리할 메소드 정의
package com.example.intentsample
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts
import com.example.intentsample.databinding.ActivityMainBinding
const val MY_STRING = "my_string"
const val MY_INT = "my_int"
const val RETURN_MESSAGE = "com.example.intent sample.RETURN_MESSAGE"
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.button.setOnClickListener {
val intent = Intent(this, SubActivity::class.java)
val str = binding.editText.text.toString()
intent.putExtra(MY_STRING, str)
intent.putExtra(MY_INT, 13)
startForResult.launch(intent)
}
}
private val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult(),
object : ActivityResultCallback<ActivityResult> {
override fun onActivityResult(result: ActivityResult?) {
if (result?.resultCode == Activity.RESULT_OK) {
if (result.data != null) {
val extras: Bundle? = result.data!!.extras
val returnStr =
extras?.getString(RETURN_MESSAGE) ?: ""
binding.editText.setText(returnStr)
}
}
}
}
)
}
package com.example.intentsample
import android.app.Activity
import android.content.Intent
import android.os.Build.VERSION_CODES.M
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.intentsample.databinding.ActivityMainBinding
import com.example.intentsample.databinding.ActivitySubBinding
class SubActivity : AppCompatActivity() {
private lateinit var binding: ActivitySubBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySubBinding.inflate(layoutInflater)
setContentView(binding.root)
if (intent.extras == null || intent == null) return
/*
val qString: String? = intent.getStringExtra(MY_STRING)
val qInt: Int = intent.getIntExtra(MY_INT, 0)
binding.editText.setText(qString + qInt.toString())
*/
if(intent.hasExtra(MY_STRING) && intent.hasExtra(MY_INT))
{
val extras: Bundle? = intent.extras ?: return
val qString = extras?.getString(MY_STRING)
val qInt = extras?.getInt(MY_INT)
binding.editText.setText("$qString $qInt")
}
binding.button.setOnClickListener {
// 결과를 bundle 객체로 생성 -> Intent 객체에 실어보냄
val returnStr = binding.editText.text.toString()
val data = Intent()
data.putExtra(RETURN_MESSAGE, returnStr)
setResult(Activity.RESULT_OK, data)
finish()
}
}
}