Concepts of Intent
1. Component
- 컴포넌트는 애플리케이션의 구성요소이다.
- 우리가 만드는 애플리케이션은 여러 개의 컴포넌트로 구성된다.
- 컴포넌트는 개발자 코드에서 클래스로 만들어진다.
- 그럼 애플리케이션에 모든 클래스가 컴포넌트냐? No
- 컴포넌트 클래스는 시스템에서 라이프사이클이 관리된다.
- 일반 클래스는 개발자 코드에서 라이프사이클이 관리된다.
- 안드로이드 시스템의 컴포넌트
1) Activity : 화면 출력 능력
2) Service : 장시간의 백그라운드 작업 능력
3) BroadcastReceiver : 어플리케이션이나 시스템의 이벤트 모델로 실행
4) ContentProvider : 앱간의 데이터 공유
- 컴포넌트 사용 방법 : 내가 Activity를 사용할 거면 Activity를 상속 받아서 만들면 된다. 각 컴포넌트의 갯수는 개발자 마음대로
2. Intent
- 컴포넌트를 실행시키기 위해 시스템에 띄우는 메시지(메시지를 담는 VO 클래스)
- ex) A Activity에서 B Activiy로 화면 전환을 하고 싶다 : 전환할 때 B Activity의 개발자 코드를 생성해서 실행시키면 되지 않을까?
- 불가능(Activity의 라이프사이클은 시스템에서 하기 때문)
- 그럼 어떻게 해야할까? A Activity에서 시스템에 Intent 정보를 발생시키고, 시스템에서 정보를 분석해 컴포넌트(B Activity)를 실행
- 애플리케이션 내부의 컴포넌트 뿐만 아니라 외부의 컴포넌트를 실행시킬 때도 Intent에 의해 실행
Activity 실행
1. Activity 실행
- public void startActivity(Intent intent)
- 시스템에 인텐트를 띄우는 함수, 매개변수에 인텐트 정보
- 컴포넌트 실행 정보가 담기는 인텐트 객체에 실행 대상이 되는 컴포넌트의 이름을 주고 해당 인텐트를 startActivity의 매개변수로 준다.
val intent = Intent(this, DetailActivity::class.java)
startActivity(intent)
1. Extra Data
- Intent로 컴포넌트를 실행시키면서 데이터를 전달하는 방법
- 1) Intent를 실행시키는 Activity의 코드
- public Intent putExtra(String name, CharSequence value)
- key-value로 여러 가지 데이터를 보낼 수 있음
intent.putExtra("id", i)
intent.putExtra("title", datas[i])
- 2) Intent에 의해 실행되는 Activity의 코드
- Extra 데이터 획득은 컴포넌트를 실행시킨 Intent 객체를 획득해서 얻는다 → Activity에서 intent 프로퍼티를 이용하면 자기 자신을 실행시킨 Intent 객체를 획들할 수 있음
- public int getIntExtra(String name, int defaultValue)
- public String getStringExtra(String name)
- public double getDoubleExtra(String name, double defaultValue)
val id = intent.getIntExtra("id", 0)
val title = intent.getStringExtra("title")
Activity Result
1. Activity Result
- activity result : 액티비티를 실행시킨 다음 (코드적으로)되돌아 왔을 때 되돌려 받는 데이터
- Intent로 액티비티를 실행시키고 결과를 되돌려 받는 방법은 두가지가 있다.
- startActivityForResult() 함수를 이용하는 방법과 ActivityResultLauncer를 이용하는 방법
- startActivityForResult()은 deprecated, 하지만 여전히 사용하는 개발자가 많다.
2. StartActivityForResult
- public void startActivity(Intent intent)
- public void startActivityForResult(Intent intent, int requestCode)
- startActivity가 아닌 startActivityForResult를 사용하는 이유 : 되돌아왔을 때 사후 처리할 것이 있다는 것, 사후 처리는 onActivityResult 함수에서 함
- 하지만 한 Activity에서 여러 Activity로 이동하면서 결과를 되돌려 받을 수 있고, 이 경우 어떤 Activity인지 식별하기 위해 startActivityForResult의 두번째 매개변수와 onActivityResult의 첫번째 매개변수 사용
- onActivityResult의 두번째 매개변수는 인텐트에 의해서 실행된 액티비티가 결과를 되돌리기 전에 어떻게 요청을 처리해서 되돌릴 것인지를 표현하기 위한 상태 코드 값(보통 OK, Cancel)
val intent: Intent = Intent(this, DetailActivity::class.java)
startActivityForResult(intent, 10)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?){
super.onActivityResult(requestCode, resultCode, data)
if(requestCode==10 && resultCode==RESULT_OK){
...
}
}
3. ActivityResultLauncher
- 액티비티를 실행시키고 실행 결과를 획득 → startActivityForResult
- 퍼미션 조정 결과 획득
- 두 가지를 한 번에 실행하기 위해 안드로이드 11버전에서 새롭게 지원
- 1) Intent를 실행시키는 Activity의 코드
val requestActivity: ActivityResultLauncer<Intent> =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
}
val intent: Intent = Intent(this, DetailActivity::class.java)
requestActivity.launch(intent)
- 2) Intent에 의해 실행되는 Activity의 코드
- Intent의 Extra Data에 데이터를 추가해서 결과 데이터를 전달
- setResult()로 상태 등록
intent.putExtra("result", "hello $id")
setResult(RESULT_OK, intent)
finish()
Implicit Intent
1. Explicit Intent vs Intent Filter
- 인텐트에 의해 실행되는 컴포넌트의 정보 중 어떤 것을 이용하냐에 따라 인텐트가 구분
- 명시적 인텐트(Explicit Intent) : class type reference 정보를 이용하는 인텐트
- 안드로이드 Manifest 파일에 activity가 클래스 명으로 등록되어 있고 필요 시 시스템에서 클래스 명(class type reference)으로 activity를 인지해서 실행
- 같은 애플리케이션 내의 컴포넌트 간에 실행 시킬 때는 가능
- 암시적 인텐트(Implicit Intent) : 인텐트 필터 정보를 이용하는 인텐트
- 암시적 인텐트를 등록하기 위해서는 Manifest 파일에 컴포넌트를 등록할 때 인텐트 필터 정보를 담아줘야 함
- 인텐트 필터 : 이 필터를 통과할 수 있는 정보가 들어오면 실행이 되고 아니면 말고, 태그에 action, category, data 등의 정보를 담아줌
- 인텐트 필터가 포함된 컴포넌트를 호출할 때는 클래스 명이 아닌 인텐트 필터에 등록된 정보로 호출할 수 있음
- 따라서 다른 애플리케이션의 컴포넌트를 실행시킬 때 인텐트 필터 정보를 이용해서 실행
- Manifest 파일에 컴포넌트를 등록할 때 name이 생략 불가능한 정보이니까 암시적 인텐트여도 name을 작성해야 하고, 그럼 name으로 호출해도 되지 않냐? : 가능하다. 단, 이 경우 명시적 인텐트 방법을 사용하는 것이다.
2. Intent Filter
- 위의 그림은 우리가 흔히 앱을 실행시킬 때의 모습이다.
- 왼쪽의 앱을 실행시키기 위한 화면은 Launcher App으로 이것 또한 애플리케이션이다.
- 그럼 Launcher App에서 애플리케이션을 실행시키기 위해서는 암시적 인텐트를 사용해야하나? 맞다.
- 그래서 안드로이드 Manifest 파일을 실행시키면 아래 이미지와 같이 기본적으로 intent-filter 태그가 등록되어 있다(와우)
- Intent Filter에 등록되는 정보(개발자 마음대로 원하는 것만 사용하면 됨)
- action : 컴포넌트의 능력을 표현하는 문자열
- category : 컴포넌트가 어느 범주에 포함되어야 하는지의 문자열
- data : 컴포넌트에서 필요한 데이터의 정보
- data android:scheme="http" → 웹 베이스의 url 정보를 원한다
val intent = Intent()
intent.action = "ACTION_EDIT"
intent.data = Uri.parse("http://www.google.com")
startActivity(intent)
- 인텐트 필터가 등록되어 있는 컴포넌트를 실행시킬 때 인텐트에 정보를 담는 방법
- 클래스 정보는 들어가지 않았지만 시스템에 등록되어 있는 컴포넌트 중에 이런 정보를 가지고 있는 컴포넌트를 실행