1. Intent란?
Intent는 Android의 컴포넌트 간 통신(IPC, Inter-Process Communication) 을 위한 메시징 객체이다. Intent를 사용하면 Activity, Service, BroadcastReceiver 등과 데이터를 주고받으며 시스템의 다양한 기능을 활용할 수 있다.
Intent의 주요 기능
- Activity 간 전환
- Service 시작 및 바인딩
- Broadcast 메시지 전송 및 수신
- 데이터 공유 및 전달
- 시스템 기능 호출 (카메라, 갤러리, 전화 앱 실행 등)
2. Intent의 유형
Intent는 크게 명시적(Explicit Intent) 과 암시적(Implicit Intent) 으로 구분된다.
2.1 명시적 Intent (Explicit Intent)
특정한 컴포넌트(Activity, Service 등) 를 직접 지정하여 실행하는 방식.
예제: Activity 전환
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("key", "value") // 데이터 전달
startActivity(intent)
예제: Service 실행
val serviceIntent = Intent(this, MyService::class.java)
startService(serviceIntent)
2.2 암시적 Intent (Implicit Intent)
실행할 컴포넌트를 지정하지 않고 Action과 Data 정보를 전달하여, 이를 처리할 수 있는 앱이나 시스템 서비스가 실행되도록 하는 방식.
예제: 웹 페이지 열기
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"))
startActivity(intent)
예제: 전화 걸기
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:123456789"))
startActivity(intent)
주요 암시적 Intent Action 목록
액션 | 설명 |
---|---|
Intent.ACTION_VIEW |
특정 URI(웹 페이지, 파일 등) 보기 |
Intent.ACTION_EDIT |
URI의 데이터를 수정하는 액티비티 실행 |
Intent.ACTION_DIAL |
다이얼 화면에서 전화번호 입력 |
Intent.ACTION_CALL |
전화 걸기 (CALL_PHONE 권한 필요) |
Intent.ACTION_SEND |
데이터(텍스트, 이미지 등) 공유 |
Intent.ACTION_SENDTO |
특정 대상에게 데이터 보내기 |
Intent.ACTION_PICK |
사용자가 항목을 선택하도록 하는 액티비티 호출 |
3. Intent 데이터 전달
3.1 기본 데이터 전달
Intent를 사용하면 문자열, 정수, 불리언 등의 기본 데이터를 다른 Activity로 전달할 수 있다.
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("STRING_KEY", "Hello World")
intent.putExtra("INT_KEY", 123)
startActivity(intent)
getStringExtra와 getIntExtra를 사용하여 데이터를 수신할 수 있다.
val receivedString = intent.getStringExtra("STRING_KEY")
val receivedInt = intent.getIntExtra("INT_KEY", 0)
3.2 객체 전달 제한 및 해결 방법
Android 13(API 33) 이상에서는 Intent를 통해 객체(Parcelable, Serializable)를 직접 전달하는 방식이 제한되었다. 따라서 Bundle을 사용하거나 JSON 직렬화 방식을 활용하는 것이 권장된다.
Bundle을 사용한 전달
val user = User("John", 25)
val bundle = Bundle().apply {
putParcelable("user", user)
}
val intent = Intent(this, TargetActivity::class.java).apply {
putExtras(bundle)
}
startActivity(intent)
- putParcelable 또는 putSerializable을 사용해 Bundle로 감싸서 전달하는 방식.
권장 방식: JSON 직렬화 (Gson 활용)
val user = User("John", 25)
val userJson = Gson().toJson(user)
val intent = Intent(this, TargetActivity::class.java).apply {
putExtra("user_json", userJson)
}
startActivity(intent)
수신 측에서 JSON 역직렬화
val userJson = intent.getStringExtra("user_json")
val user = Gson().fromJson(userJson, User::class.java)
이 방식을 사용하면 Parcelable 없이도 복잡한 객체를 안정적으로 전달할 수 있다.
ViewModel을 활용한 데이터 공유
- 데이터가 많거나, Activity/Fragment 간 유지해야 할 데이터가 있을 경우 ViewModel + LiveData/Flow를 활용하는 것이 좋음.
class SharedViewModel : ViewModel() {
val userLiveData = MutableLiveData<User>()
}
- ViewModel를 사용해 Activity 간 데이터 공유 가능.
4. Intent Filter
인텐트 필터(Intent Filter)는 Android 앱에서 특정 인텐트(Intent)를 받을 수 있도록 설정하는 구성 요소이다.
액티비티(Activity), 서비스(Service), 브로드캐스트 리시버(BroadcastReceiver) 등의 컴포넌트가 실행될 수 있는 인텐트 유형을 정의한다.
4.1 Intent Filter의 3가지 주요 요소
<action>: 수행할 작업 정의
인텐트가 실행될 때 수행할 동작을 나타냅니다.
대표적인 액션 값:
- android.intent.action.MAIN: 앱의 메인 진입점(런처 아이콘 실행)
- android.intent.action.VIEW: 특정 URI(웹 페이지, 이미지 등)를 표시
- android.intent.action.SEND: 공유 기능 (텍스트, 이미지 등 전송)
- android.intent.action.DIAL: 전화 앱에서 전화번호 입력
예제: 웹 페이지를 여는 액션
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
</intent-filter>
<category>: 실행 가능 여부 결정
해당 인텐트를 실행할 수 있는 환경을 정의합니다.
주요 카테고리 값:
- android.intent.category.DEFAULT: 기본 인텐트 (명시적으로 설정되지 않으면 실행되지 않음)
- android.intent.category.LAUNCHER: 앱의 메인 액티비티를 홈 화면에 표시 (런처에서 실행 가능)
- android.intent.category.BROWSABLE: 웹 브라우저에서 실행 가능
- android.intent.category.ALTERNATIVE: 기본 작업의 대안으로 실행 가능
예제: 기본 실행 가능하도록 설정
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<data>: 데이터 타입 및 URI 스키마 설정
인텐트가 다룰 수 있는 데이터 형식을 지정합니다.
- MIME 타입: image/*, text/plain, video/mp4 등
- URI 스키마: http, content, file 등
예제: 웹 URL을 처리하는 경우
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
</intent-filter>
예제: 이미지 공유 기능을 제공하는 경우
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/*"/>
</intent-filter>
4.2 인텐트 필터 매칭 프로세스
Android 시스템이 인텐트 필터를 검사하는 과정:
- 액션(Action) 일치 여부 확인
- 인텐트의 action 값이 <intent-filter>에 정의된 <action> 값과 일치해야 합니다.
- 데이터(Data) 일치 여부 확인
- 인텐트가 포함한 URI 또는 MIME 타입이 <data> 요소와 일치해야 합니다.
- URI 스키마, 호스트, 패스 등이 필터 조건을 충족해야 합니다.
- 카테고리(Category) 일치 여부 확인
- 인텐트에 포함된 category 값이 <category>에 정의된 값 중 하나와 일치해야 합니다.
- 일치하는 컴포넌트 실행
- 인텐트 필터 조건을 만족하는 컴포넌트 중 하나가 실행됩니다.
- 여러 개의 앱이 대응할 경우 앱 선택(Activity Chooser)이 표시됨.
5. startActivityForResult() 대체 방법 (Activity Result API)
Android 11(API 30)부터 startActivityForResult()는 deprecated(사용 중단) 되었으며, 대신 Activity Result API (registerForActivityResult)를 사용한다.
// 결과를 받을 콜백 등록
private val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data
val resultText = data?.getStringExtra("result_key")
Toast.makeText(this, "결과 받음: $resultText", Toast.LENGTH_SHORT).show()
}
}
// B 액티비티 실행
fun startBActivity() {
val intent = Intent(this, BActivity::class.java)
resultLauncher.launch(intent)
}
6. PendingIntent와 인텐트의 차이
6.1 PendingIntent란 무엇인가?
PendingIntent는 나중에 실행될 인텐트(Intent)를 감싸고 있는 객체이다.
즉, 다른 앱이나 시스템에서 특정 시점에 지정된 인텐트를 실행할 수 있도록 위임하는 역할을 한다.
구분 | Intent | PendingIntent |
실행 방식 | 즉시 실행 (startActivity(intent)) | 나중에 실행 (PendingIntent.get...()) |
실행 주체 | 현재 앱에서 실행 | 다른 앱(시스템, 알람, 서비스 등)에서 실행 |
사용 목적 | 액티비티 전환, 데이터 전달 등 | 알람, 푸시 알림, 포그라운드 서비스 등 백그라운드에서 실행 |
// pendingIntent는 지금 바로 실행되지 않지만, 나중에 시스템 또는 다른 앱에서 실행 가능
val intent = Intent(this, TargetActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
6.2 PendingIntent의 주요 활용 사례
알람(AlarmManager)
- AlarmManager와 함께 사용하여 특정 시간에 인텐트를 실행
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 60000, // 1분 후 실행
pendingIntent
)
푸시 알림(Notification)
- NotificationManager와 함께 사용하여 푸시 알림 클릭 시 특정 화면으로 이동
val intent = Intent(this, TargetActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(this, "channel_id")
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("새로운 메시지")
.setContentText("클릭하면 확인할 수 있습니다.")
.setContentIntent(pendingIntent) // 알림 클릭 시 실행
.setAutoCancel(true)
.build()
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(1, notification)
Foreground Service에서 활용
- 백그라운드 실행 제한으로 인해, Foreground Service 실행 시 반드시 PendingIntent 필요
val intent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(this, "channel_id")
.setSmallIcon(R.drawable.ic_service)
.setContentTitle("백그라운드 실행 중")
.setContentText("클릭하여 앱으로 이동")
.setContentIntent(pendingIntent) // 서비스 실행 중 알림 클릭 시 앱으로 이동
.build()
startForeground(1, notification) // Foreground Service 실행
6.3 PendingIntent 생성 방법
PendingIntent는 수행할 작업 유형에 따라 3가지 방법으로 생성된다.
메서드 | 설명 |
getActivity() | 특정 액티비티 실행 (startActivity()) |
getService() | 특정 서비스 실행 (startService()) |
getBroadcast() | 특정 브로드캐스트 리시버 실행 (sendBroadcast()) |
// 액티비티 실행
val pendingActivity = PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
// 서비스 실행
val pendingService = PendingIntent.getService(this, 0, Intent(this, MyService::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
// 브로드캐스트 실행
val pendingBroadcast = PendingIntent.getBroadcast(this, 0, Intent(this, MyReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
6.4 PendingIntent Flags
PendingIntent 생성 시 동작을 제어하는 플래그(Flags)를 설정할 수 있다.
플래그 | 설명 |
FLAG_UPDATE_CURRENT | 기존 PendingIntent가 있으면 업데이트 |
FLAG_CANCEL_CURRENT | 기존 PendingIntent가 있으면 취소 후 새로 생성 |
FLAG_NO_CREATE | 기존 PendingIntent가 없으면 null 반환 |
FLAG_ONE_SHOT | 한 번만 실행 후 자동 삭제 |
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
'Android > Study' 카테고리의 다른 글
[Android] Jetpack Compose의 Recomposition 정리 (0) | 2025.02.20 |
---|---|
[Android] Jetpack Compose 개념 및 XML과의 비교 (0) | 2025.02.20 |
[Android] SearchView 사용기 (0) | 2024.06.24 |
[Android] WebView 사용기 (0) | 2024.06.24 |
[Android] WebSocket를 통해서 채팅 기능 구현 feat. Clean Architecture, Hilt (0) | 2024.06.24 |