Skip to content

Android 14+/17 대응: Foreground Service 및 edge-to-edge 처리 적용#18

Merged
rimdoo merged 4 commits into
mainfrom
feature/doo/update-sample
May 11, 2026
Merged

Android 14+/17 대응: Foreground Service 및 edge-to-edge 처리 적용#18
rimdoo merged 4 commits into
mainfrom
feature/doo/update-sample

Conversation

@rimdoo
Copy link
Copy Markdown
Contributor

@rimdoo rimdoo commented May 8, 2026

변경 요약

두 sample (live-video-sample, live-audio-sample) 에 동일한 Android 14+/17 대응을 적용합니다.

1. Foreground Service 추가

  • LiveEventService 신설 — 호스트는 microphone(+camera for video), 참여자는 mediaPlayback 타입으로 startForeground
  • LiveEventActivity (base) lifecycle 에서 service start/stop 처리
  • Android 14+ 의 typed FGS 강제와 Android 17 의 background-audio hardening (WIU 자격 필요) 에 대응
  • 매니페스트에 FOREGROUND_SERVICE_MICROPHONE / FOREGROUND_SERVICE_CAMERA / FOREGROUND_SERVICE_MEDIA_PLAYBACK 권한 선언

2. Edge-to-edge 처리

  • 모든 activity layout 의 root view 에 android:fitsSystemWindows="true" 추가 → status/navigation bar 영역으로 content 가 깔리지 않게 함
  • 두 테마에 android:windowOptOutEdgeToEdgeEnforcement 추가 (Android 15 backstop)

3. live-audio-sample SDK 1.2.8 마이그레이션

  • AGP 7.4.2 → 8.5.2, Gradle 7.5 → 8.7, compileSdk 33 → 36, sendbird-live 1.1.2 → 1.2.8
  • API 변경 대응 — liveEvent.host (단일) → hosts.firstOrNull(), hostType/HostTypetype/LiveEventType, LiveEventListeneronExited / onReconnected 추가

4. 두 sample compileSdk/targetSdk 36 으로 정렬

5. live-audio-sample 크래쉬 수정

  • LiveEventOpenChannelFragment.setTitle 이 빈 title 일 때 fragment 의 getString 을 호출하는데, fragment commit 직후라 attach 안 된 상태에서 크래쉬 (Fragment not attached to a context)
  • video sample 로 만든 비어있는 title 이벤트에 audio sample 로 입장 시 재현
  • activity 의 getString 으로 fallback 을 미리 resolve 해서 fragment 가 자체 getString 분기에 도달하지 않도록 수정

테스트 플랜

  • Android 14/15 device — 호스트 방송 중 home 진입 → 음성 끊김 없음 + FGS 알림 표시
  • Android 13 device — FGS 정상 (API 34 미만은 typed FGS no-op, plain startForeground 으로 fallback)
  • 모든 화면 (Splash / Main / Sign-in / live event flow) — status/nav bar 영역 침범 없음
  • Participant 입장 → home 진입 → 재생 끊김 없음 (mediaPlayback FGS)
  • video sample 로 빈 title 이벤트 만든 후 audio sample 로 입장 → 크래쉬 없음
  • adb shell dumpsys audio | grep AudioHardening — host activity 동안 level: partial mute 이벤트 없음

알려진 이슈

  • Android 17 (API 37) emulator 에서 호스트 음성 송출이 transient 하게 무음 되는 케이스 관찰됨. 같은 코드/같은 emulator 에서 재현 불안정. SDK 측 audio focus 처리 (live SDK 1.2.8 의 AppRTCAudioManager deprecated requestAudioFocus API → AudioFocusRequest.Builder migration) 가 머지/릴리즈된 이후 재검증 필요. 본 PR 의 sample 변경으로는 해결 불가능한 영역.

🤖 Generated with Claude Code

Add LiveEventService as microphone+camera (host) or mediaPlayback
(participant) foreground service started during LiveEventActivity
lifecycle. Required for Android 14+ typed FGS enforcement and
Android 17 background audio hardening, which silences AudioTrack
write and fails requestAudioFocus for backgrounded apps without an
active FGS with while-in-use capability.

Apply android:fitsSystemWindows="true" to all activity layouts and
windowOptOutEdgeToEdgeEnforcement to themes so content stops
extending under the status and navigation bars on Android 15+.

Bump targetSdk to 37.
Mirror the live-video-sample changes for the audio-only sample:

- Bump AGP 7.4.2 → 8.5.2, Gradle 7.5 → 8.7, compileSdk 33 → 35,
  sendbird-live 1.1.2 → 1.2.8 to resolve transitive dependency
  (viewpager2:1.1.0, annotation-experimental:1.4.0) requirements.
- Migrate source for live SDK 1.2.8 API: hostTypes/HostType →
  types/LiveEventType, liveEvent.host (single) → hosts.firstOrNull(),
  add onExited and onReconnected to LiveEventListenerImpl.
- Add LiveEventService as microphone (host) or mediaPlayback
  (participant) foreground service started during LiveEventActivity
  lifecycle to prepare for Android 14+ typed FGS enforcement.
- Apply android:fitsSystemWindows="true" to all activity layouts and
  windowOptOutEdgeToEdgeEnforcement to themes.

Revert targetSdk to original (live-video-sample 35,
live-audio-sample 33) to keep runtime behavior unchanged.
LiveEventOpenChannelFragment.setTitle calls fragment.getString as a
fallback when the value is null or blank. The fragment is committed
asynchronously in initOpenChannelView, so when entering an event that
has no title (e.g., a video-sample-created event with empty title),
getString runs before the fragment attaches and crashes with
"Fragment not attached to a context".

Resolve the fallback in the activity context (always available)
before assigning to the fragment so the fragment never hits its own
getString branch.
@rimdoo rimdoo changed the title Add foreground service and edge-to-edge handling for Android 17 Android 14+/17 대응: Foreground Service 및 edge-to-edge 처리 적용 May 8, 2026
@rimdoo rimdoo requested a review from sf-jed-kyung May 8, 2026 05:47
val asHost = intent?.getBooleanExtra(EXTRA_AS_HOST, false) ?: false
val notification = buildNotification(liveEventId, asHost)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
val type = if (asHost) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

live의 host는 항상 foreground로 있다는 것을 전제로 하는거겠죠?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

옙 맞습니다!

@rimdoo rimdoo requested a review from sf-jed-kyung May 11, 2026 06:31
Copy link
Copy Markdown

@sf-jed-kyung sf-jed-kyung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@rimdoo rimdoo merged commit b8c2544 into main May 11, 2026
2 checks passed
@rimdoo rimdoo deleted the feature/doo/update-sample branch May 11, 2026 06:53
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.

3 participants