Skip to content

서비스(Bound & Foreground) 실습 구현 및 구조 정리#23

Merged
sh1mj1 merged 16 commits intodevfrom
android/4components/service
May 21, 2025
Merged

서비스(Bound & Foreground) 실습 구현 및 구조 정리#23
sh1mj1 merged 16 commits intodevfrom
android/4components/service

Conversation

@sh1mj1
Copy link
Owner

@sh1mj1 sh1mj1 commented May 21, 2025

작업 요약

안드로이드 서비스 구조에 대한 학습을 바탕으로, 다음과 같은 실습 및 구조 개선을 진행했습니다:

Bound Service 구현

  • SimpleBoundPlaybackService, SimpleBoundServiceActivity 를 통해 기본적인 바운드 서비스 예제 구현
  • StateFlow 기반으로 재생 상태 및 progress 전달
  • PlaybackControlUI로 UI 컴포저블 분리

Foreground + Bound Service 구현

  • ForegroundBoundMusicService, ForegroundBoundMusicActivity 파일 생성
  • MediaPlayer, MediaSessionCompat, Notification 활용한 음악 재생 기능 구현
  • 알림 제어 버튼(Play/Pause/Next/Prev) 처리
  • 서비스는 포그라운드 상태에서 startForeground()로 실행되며, 바인딩을 통해 UI와 상호작용
  • 알림 채널은 Activity에서 조건부 생성 (Android 13 대응)

리팩토링 및 정리

  • PlaybackBoundService2 등 불필요한 실험 파일 제거
  • 서비스 클래스 네이밍 정비 (MusicPlayerServiceForegroundBoundMusicService 등)
  • MusicPlayerActivity UI 분리 및 상태 흐름 구조화
  • play() 관련 중복 로직 함수 분리
  • service.md에 전체 실습 흐름 정리 문서 작성 및 파일 구조 설명 추가

리소스 추가

  • 음악 재생 테스트용 MP3 파일 추가
  • 재생 제어용 아이콘 드로어블 리소스 추가

학습 테스트

  • TestLifecycleServiceTest를 통해 서비스 생명주기 관련 테스트 추가

주요 파일 구조 변화

fourComponents.service/
├── SimpleBoundPlaybackService.kt
├── SimpleBoundServiceActivity.kt
├── ForegroundBoundMusicService.kt
├── ForegroundBoundMusicActivity.kt
├── PlaybackControlUI.kt
└── service.md

추후에 더 공부할 것들:

  • AIDL을 활용한 프로세스 간 통신(IPC) 구현 실습
  • Messenger 기반 IPC 구조 실습 (Handler, Message 전달)
  • startForegroundService()와 strict background execution 제한 대응 방식 정리
  • JobScheduler, WorkManager vs ForegroundService 차이 비교 및 샘플 구현
  • 서비스 생명주기 예외 상황 테스트 (ex. 강제 종료, 메모리 부족 등)
  • Notification + MediaStyle + MediaSession 연결 흐름 더 깊게 파보기
  • RemoteViews를 이용한 커스텀 알림 레이아웃 구현 (위젯 스타일 알림)
  • BroadcastReceiver와 Service 연동 실습 (알람, 부팅, 네트워크 변경 등)
  • Binding된 서비스와 ViewModel의 역할 분리 및 테스트 전략 고민
  • Android 14 이상에서 백그라운드 제약 정책 변화 정리

sh1mj1 added 16 commits May 17, 2025 01:16
- `startService()` 호출 시 `onCreate()`와 `onStartCommand()`가 순차적으로 호출되는 것을 확인한다.
- 서비스 내부에서 `stopSelf()`를 호출하고 `destroy()`를 통해 서비스를 종료하면 `onDestroy()`가 호출되는 것을 확인한다.
- 테스트를 위해 `TestLifecycleService` 클래스를 추가하고, 각 생명주기 콜백에서 로그를 기록하도록 구현한다.
실제 음악 재생은 하지 않고, progress 만 이동하도록
- `PlaybackBoundServiceActivity`를 추가하여 바인드 서비스와 상호작용하는 UI 구현
- 서비스 상태 관찰 로직 추가
- 서비스 바인딩 및 언바인딩 로직 구현
- `PlaybackControlUI` Composable 함수 추가
- `playbackService`가 null일 경우 NPE 발생 가능성 제거
- 서비스 상태 관찰 로직을 단순화
- `progress` 상태를 `mutableFloatStateOf`로 변경하고, `derivedStateOf`에서 `floatValue` 사용
- 불필요한 로그 삭제
- `PlaybackControlUI` 컴포저블 함수를 `PlaybackBoundServiceActivity`에서 별도 파일로 분리
- AndroidManifest.xml에 `POST_NOTIFICATIONS`, `FOREGROUND_SERVICE`, `FOREGROUND_SERVICE_MEDIA_PLAYBACK 권한을 추가
- `PlaybackBoundService2` 서비스를 Manifest에 등록
- `PlaybackBoundService2` 음악 재생, 일시 정지 기능
- `PlaybackForegroundServiceActivity`:
    - `PlaybackBoundService2`에 바인딩하여 재생 상태 및 진행률을 관찰하고 UI에 표시
    - 서비스의 `play()`, `pause()` 메서드를 호출하여 재생 제어
    - `onStart()`에서 서비스 시작 및 바인딩, `onStop()`에서 바인딩 해제
    - 알림 권한 요청 로직 추가 (Android T 이상)
- 아티스트, 다음, 일시정지 아이콘 벡터 드로어블 리소스를 추가
- `androidx.media3:media3-session` 및 `androidx.media:media` 라이브러리 의존성을 추가
- `MusicPlayerService` 클래스를 생성하여 음악 재생 서비스 구현
- `MediaSessionCompat`을 사용하여 미디어 세션을 관리하고, 알림을 통해 미디어 컨트롤 제공
- `NotificationCompat.MediaStyle`을 사용하여 미디어 스타일의 알림을 생성
- 서비스 내에서 `MediaPlayer`를 사용하여 음악을 재생하고, 현재 재생 상태, 곡 정보, 재생 시간 등을 `MutableStateFlow`를 통해 관리
- `Binder`를 통해 액티비티에서 서비스에 접근하여 음악 목록 설정, 현재 재생 정보 가져오기 등의 기능을 수행
- `PendingIntent`를 사용하여 알림의 액션 버튼에 대한 처리 구현
- 코루틴을 사용하여 주기적으로 현재 재생 시간을 업데이트
- 서비스와 바인딩하여 음악 재생 기능을 UI와 연동한다.
- `ServiceConnection`로 서비스 연결 및 해제 시 로직을 처리한다.
- 서비스로부터 음악 재생 상태, 현재 트랙 정보, 진행 상태 등을 `StateFlow`로 받아 UI에 반영한다.
- UI 요소(재생/일시정지, 이전 곡, 다음 곡 버튼, 진행 바 등)를 Compose를 사용하여 구현한다.
- TopAppBar에 서비스 시작/중지 및 바인딩/언바인딩을 위한 아이콘 버튼을 추가한다.
- `MusicPlayerScreen` 컴포저블을 새로 생성하여 `MusicPlayerActivity`의 UI 로직을 분리한다.
- 알림 채널 생성 로직을 이동한다: `BaseApplication` -> `MusicPlayerActivity`
- `MusicPlayerService`의 알림 빌더에서 중복된 `addAction` 호출을 제거한다.
- `AndroidManifest.xml`에서 `BaseApplication` 지정을 제거한다.
- `play()` 메서드를 private으로 변경하고, `prev()` 및 `next()` 메서드에서 이를 호출한다.
- 불필요한 MediaPlayer 의 반복 초기화를 제거한다.
- `MusicPlayerActivity` -> `ForegroundBoundMusicActivity`
- `MusicPlayerService` -> `ForegroundBoundMusicService`
- `PlaybackBoundServiceActivity` -> `SimpleBoundServiceActivity`
- `PlaybackBoundService` -> `SimpleBoundPlaybackService`

`AndroidManifest.xml`에 변경된 클래스 이름들을 반영한다
- 서비스 유형(Bound, Unbound - Foreground, Background) 설명 추가
- 각 서비스 유형별 예시 및 사용 사례 정리
- Bound Service 예제로 로컬 바인더를 이용한 음악 재생 서비스 구현 ([SimpleBoundMusicService.kt](SimpleBoundMusicService.kt), [SimpleBoundMusicActivity.kt](SimpleBoundMusicActivity.kt))
- 포그라운드 + 바운드 서비스 예제 ([ForegroundBoundMusicActivity.kt](ForegroundBoundMusicActivity.kt), [ForegroundBoundService.kt](ForegroundBoundService.kt))
@sh1mj1 sh1mj1 merged commit eb82ce7 into dev May 21, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant