[Android 앱개발 입문] Intent (# 추가하기)
Intent
: 일종의 메시지 객체
- 이것을 이용해 다른 앱 구성요소(액티비티, 서비스, 브로드캐스트 리시버)로 작업을 요청할 수 있음
- startActivity(intent), startService(intent), sendBroadcast(intent)
- 안드로이드 앱의 구성 요소들 사이에서 실행을 위임하거나 정보를 전달하는 역할을 함
1. Intent의 유형
1) 명시적 인텐트 (explicit intent)
: 특정한 컴포넌트를 직접적으로 호출할 때 사용되는 인텐트
- 이 방법으로 개발자는 인텐트 객체에 시작하고자 하는 구성 요소의 이름을 명확하게 설정하고,
startActivity() 또는 startService() 메소드를 통해 해당 컴포넌트를 실행시킴
(시스템이 액티비티 추론할 필요 없이 개발자가 직접 지정)
//주로 앱 내부에서 다른 액티비티나 서비스를 시작할 때 사용됨.
(ex. 메인 액티비티에서 사용자의 입력을 받아 세부 정보를 표시하는 새로운 액티비티를 띄울 때)
2) 암시적 인텐트
: 특정한 컴포넌트를 명시하지 않고,
수행하고자 하는 일반적인 작업을 인텐트 객체에 설정해 startActivity() 메소드에 넘김
- 안드로이드 시스템은 이 인텐트를 처리할 수 있는 모든 애플리케이션을 검색해
적합한 인텐트 필터를 가진 컴포넌트를 찾아 실행시킴
(1) 인텐트 필터
: 특정 인텐트에 반응하는 액티비티, 서비스 또는 브로드캐스트 리시버의 능력을 정의
= 어떤 인텐트를 수신할 준비가 되어있는지를 나타내는 설정
- 본인의 앱이 수신할 수 있는 암시적 인텐트가 무엇인지 알기 위해서는
각 앱 구성 요소에 대한 하나 이상의 인텐트 필터를 <intent_filter> 요소로 매니페스트 파일에 선언해야 함
- 각 인텐트 필터가 인텐트의 작업, 데이터 및 카테고리를 근거로 어느 유형의 인텐트를 수신할지를 결정함
// AndroidManifest.xml 에서 android:name 속성 값이 SecondActivity인 <activity>요소 하위에 <intent-filter> 태그 추가
<activity
android:name=".SecondActivity"
android:label="Second Activity"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.DIAL"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="tel"/>
</intent-filter>
</activity>
// action의 action.DIAL : 다이얼을 받을 수 있는 앱
// data -> 데이터는 tel을 통해 받을것임
// android:name = 안드로이드 시스템에서 해당 구성 요소를 찾아 실행할 때 사용. (구성 요소의 실제 구현된 클래스 이름)
// android:label = 앱의 화면에 표시되는 텍스트. 사용자 인터페이스에서 해당 구성 요소를 식별할 때 사용
<action> | 수신되는 인텐트의 액션을 지정 (안드로이드에서는 액션에 따라 시스템이 어떤 동작을 수행해야 하는지를 결정) //ex. android.intent.action.VIEW는 데이터를 보여주는 액션 |
<category> | 인텐트의 추가적인 정보를 제공 이를 통해 시스템이 인텐트를 처리하는 방법을 더 세부적으로 제어 가능 // category android:name="android.intent.category.LAUNCHER" -> 앱 실행 시 그 액티비티가 먼저 실행됨 |
<data> | 인텐트와 관련된 데이터를 지정 URI, MIME, 파일 확장자 등의 형태로 지정될 수 있음 // ex. tel 스키마를 가진 데이터를 다루기 위해 <data android:scheme='tel'/> |
(2) 일반적 사용법
: 암시적 인텐트는 주로 다른 앱의 컴포넌트를 실행시키는 데 사용됨
ex. 사용자가 '지도 보기'를 요청할 때, 해당 작업을 처리할 수 있는 모든 앱 중 사용자가 선택할 수 있게 목록 제공
2. 인텐트 객체 분석하기
1) 컴포넌트 이름
: 타겟 컴포넌트의 이름을 명시해, 인텐트가 전달될 정확한 대상을 지정
ex. new Intent(context, TargetActivity.class) 에서 TargetActivity.class 가 컴포넌트 이름임
- 컴포넌트 이름이 없으면 인텐트는 암시적으로 처리되고, 시스템이 적절한 대상을 찾음
2) 액션
: 인텐트가 수행해야 할 일반적인 작업을 정의. 수행되어야 할 작업을 나타내는 문자열
- ex. Intent.ACTION_VIEW : 사용자에게 데이터를 보여줄 때 사용됨
- ex. Intent.ACTION_DIAL : 전화 다이얼을 열기 위해 사용
3) 데이터
: 작업을 수행하는 데 필요한 데이터의 URI(정보의 고유한 명칭. url보다 상위)를 지정함
ex. Uri.parse("tel:12345") : 전화 앱에 전화번호 데이터를 제공
작업(액션) | 데이터 | 설명 |
ACTION_VIEW | 웹페이지를 표시 | |
ACTION_CALL | tel:114 | 114번 전화번호로 전화연결 시작 |
ACTION_DIAL | tel:114 | 114번 전화번호로 전화걸기 화면 표시 |
- 데이터는 보통 Uri 객체로 액션과 결합해 사용됨
4) 카테고리
: 인텐트의 유형을 더 구체적으로 지정하여, 어떤 컴포넌트가 처리할 수 있는지 알려줌
- ex. Intent.CATEGORY_HOME : 홈 화면 애플리케이션을 시작할 때 사용됨
카테고리 | 설명 |
CATEGORY_BROWSABLE | 대상 액티비티가 웹브라우저에 의해 시작되어서 이미지와 같은 데이터를 표현할 수 있음 |
CATEGORY_LAUNCHER | 이 액티비티가 작업의 최초 액티비티이고, 이것이 시스템의 애플리케이션 시작 관리자에 목록으로 게재되어 있음 |
5) 엑스트라
: 복잡한 데이터를 인텐트에 전달하기 위한 키-값 쌍의 추가 정보
ex. intent.putExtra("extra_key", "value") 에서 "extra_key" 는 전달할 데이터의 키이고, "value"는 실제 값임
- 엑스트라를 통해 기본 타입부터 Serializable 객체가지 다양한 데이터 전달 가능
3. 명시적 인텐트로 다른 액티비티 시작하기
- 명시적 인텐트는 특정한 액티비티를 시작할 때 사용됨.
(안드로이드는 이를 통해 현재 액티비티에서 다른 액티비티로 전환할 수 있음)
// 현재 액티비티에서 AnotherActivity를 시작하기 위한 명시적 인텐트 생성
val intent = Intent(this, AnotherActivity::class.java)
// 인텐트에 데이터 추가 (옵션)
intent.putExtra("key", "value")
// AnotherActivity 시작
startActivity(intent)
1) 인텐트 생성 : Intent 클래스의 객체를 생성함
- 매개변수 : 현재 컨텍스트 (this) , 시작하고자 하는 액티비티의 Class 객체
2) 데이터 전달 (선택사항) : putExtra 메소드를 사용해 인텐트에 키-값 쌍으로 이루어진 추가 데이터 삽입 가능
- 시작될 액티비티에서 이 데이터를 사용할 수 있음
3) 액티비티 시작 : startActivity 메소드를 호출해 인텐트를 사용함
- 이 호출이 실행되면 안드로이드 시스템은 명시된 인텐트에 따라 AnotherActivity를 시작함
-> 현재 액티비티에서 다른 액티비티로의 전환을 명확하게 제어 가능 (앱의 흐름 관리에 필수적인 기능)
activity 추가 => app > new > Activity > Empty Activity
1) activity_first.xml 파일 수정
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height=“match_parent"
android:gravity = “center”
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="첫번째 액티비티 입니다."
android:id="@+id/textView" />
<Button
android:layout_width=“wrap_content"
android:layout_height="wrap_content"
android:text="두번째 액티비티 시작하기"
android:id="@+id/buttonFirstActivity"
android:layout_marginTop="43dp" />
</LinearLayout>
2) activity_Second.xml 수정
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="두번째 액티비티 입니다."
android:id="@+id/textView" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="닫기"
android:id="@+id/buttonSecondActivity"
android:layout_marginTop="43dp" />
</LinearLayout>
3) FirstActivity 수정
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_first)
val btn = findViewById<Button>(R.id.buttonFirstActivity)
btn.setOnClickListener{
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
}
4) SecondActivity 수정
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val btn = findViewById<Button>(R.id.buttonSecondActivity)
btn.setOnClickListener{
finish()
}
}
}
4. 암시적 인텐트로 다른 액티비티 시작하기
: 암시적 인텐트로 다른 액티비티를 시작하기 위해서는 인텐트 안에 작업과 데이터를 지정해야 함
ex. 114 번호로 다이얼 작업을 수행할 수 있는 액티비티 실행시키기 위해 call_intent 생성 후 startActivity()메소드에 전달
tel:114 = 전화번호 114의 URI 객체
val call_intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:114"))
startActivity(call_intent)
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="다이얼 작업 시작하기"
android:id="@+id/buttonDialActivity"
android:onClick="doOnBtnClick"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="지도보기 작업 시작하기"
android:id="@+id/buttonMapActivity"
android:onClick="doOnBtnClick"/>
package com.example.acrivityintent2
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.Button
//import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
//import androidx.core.view.ViewCompat
//import androidx.core.view.WindowInsetsCompat
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//enableEdgeToEdge()
setContentView(R.layout.activity_first)
// ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
// val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
// v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
// insets
// }
val btn = findViewById<Button>(R.id.buttonFirstActivity)
btn.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
fun doOnBtnClick(view: View){
when(view.id){
R.id.buttonDialActivity -> {
val call_intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:114"))
startActivity(call_intent) //암시적 인텐트
}
R.id.buttonMapActivity -> {
val map_intent = Intent(Intent.ACTION_VIEW, Uri.parse("geo:37.565350, 127.01445"))
startActivity(map_intent)
}
}
}
}
코드 정렬 -> ctrl + alt + L