Files
2nd/10_Wiki/Topic_Programming/Coding/Android_14_Migration_Notes.md
T
Antigravity Agent 9148c358d0 docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
2026-07-05 00:33:48 +09:00

5.2 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
android-14-migration-notes Android 14+ 마이그레이션 — 주요 변화 Coding draft B conceptual 2026-05-09 2026-05-09
android
migration
vibe-coding
language applicable_to
Kotlin
Android
Android 14
target SDK 34
photo picker
foreground service type
predictive back

Android 14+ Migration

targetSdk 34/35 의 주요 변화 체크리스트. FGS type 의무화 / Photo picker 권장 / 6h 데이터 sync 한도 / Predictive back / Notification permission.

📖 핵심 개념

  • targetSdk 변경 = 새 동작 적용.
  • Permission 변경: media, photo picker.
  • FGS type 의무.
  • 새 권장: predictive back, large screen.

💻 코드 패턴

Photo Picker (권한 없이 사진 선택)

val launcher = registerForActivityResult(
    ActivityResultContracts.PickVisualMedia()
) { uri -> /* uri 한 장 */ }

launcher.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))
// 또는 ImageAndVideo / SingleMimeType("image/jpeg")

다중:

val launcher = registerForActivityResult(
    ActivityResultContracts.PickMultipleVisualMedia(maxItems = 5)
) { uris -> /* List<Uri> */ }

→ READ_MEDIA_IMAGES 권한 불필요. 사용자 친화 + privacy.

Selected Photos Access (READ_MEDIA_VISUAL_USER_SELECTED)

사용자가 일부 사진만 access 허용 (모두 X).

val perms = arrayOf(
    Manifest.permission.READ_MEDIA_IMAGES,
    Manifest.permission.READ_MEDIA_VIDEO,
    Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED, // 14+
)

Foreground Service type (Android 14+ 의무)

<service
    android:name=".PlayerService"
    android:foregroundServiceType="mediaPlayback" />

Android_Foreground_Service_Patterns 참조.

dataSync 6시간 한도 (14+)

24시간 안 dataSync FGS 6시간 한도 — WorkManager 로 분할.

Predictive back gesture (14+)

<application android:enableOnBackInvokedCallback="true">
// Compose
BackHandler(enabled = canGoBack) { goBack() }

// 또는 OnBackPressedDispatcher
override fun onCreate(savedInstanceState: Bundle?) {
    onBackPressedDispatcher.addCallback(this) {
        // back 처리
    }
}

→ 사용자가 swipe back 시 미리보기 애니메이션.

Notification permission (13+)

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
if (Build.VERSION.SDK_INT >= 33) {
    requestPermission(Manifest.permission.POST_NOTIFICATIONS)
}

Background activity launch (14+)

// 14+ 더 엄격: background 에서 activity launch 어려워짐
// 권장: 사용자 작업이 보이는 곳 (notification action, FGS) 으로 trigger

Pending intent — exported 명시 (12+)

PendingIntent.getActivity(ctx, 0, intent, 
    PendingIntent.FLAG_IMMUTABLE) // 또는 FLAG_MUTABLE — RemoteInput 시

Exact alarm permission (12+)

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
val am = getSystemService<AlarmManager>()
if (am?.canScheduleExactAlarms() == true) {
    am.setExactAndAllowWhileIdle(...)
} else {
    // 권한 요청 / fallback
}

Implicit intent — package 명시 (15+ 권장)

// ❌ implicit
Intent(Intent.ACTION_VIEW, uri)

// ✅ package 명시
Intent(Intent.ACTION_VIEW, uri).setPackage("com.android.chrome")
// 또는 setComponent

Edge-to-edge 의무 (15+)

// Activity
enableEdgeToEdge()

// Compose
Scaffold { padding -> 
    // padding 사용해서 system bar 안 가리게
    Column(Modifier.padding(padding)) { ... }
}

Large screen / fold

val widthSizeClass = calculateWindowSizeClass(activity).widthSizeClass
when (widthSizeClass) {
    WindowWidthSizeClass.Compact -> NavigationBar(...)
    WindowWidthSizeClass.Medium -> NavigationRail(...)
    WindowWidthSizeClass.Expanded -> PermanentNavigationDrawer(...)
}

Resume / pause 정확히

DisposableEffect(Unit) {
    val obs = LifecycleEventObserver { _, ev ->
        when (ev) {
            Lifecycle.Event.ON_RESUME -> resume()
            Lifecycle.Event.ON_PAUSE -> pause()
            else -> {}
        }
    }
    lifecycle.addObserver(obs)
    onDispose { lifecycle.removeObserver(obs) }
}

🤔 의사결정 기준

변경 우선
Notification 권한 즉시 (13+)
FGS type 즉시 (14+)
Photo picker 전환 적극 권장
Predictive back 14+
Edge-to-edge 15+ 의무
Implicit intent 15+ 권장

안티패턴

  • targetSdk 안 올림: Play Store 거부.
  • Permission 옛 (READ_EXTERNAL_STORAGE): 13+ 동작 X. media-specific.
  • FGS type 누락: SecurityException.
  • Notification 권한 안 받고 notify: 무시.
  • Edge-to-edge X + 15+: 검은 bar.
  • Predictive back 안 옵트인: 새 UX 못 씀.
  • Background activity launch 시도: 차단.

🤖 LLM 활용 힌트

  • 매년 targetSdk + 1.
  • Photo picker / FGS type / notification permission 3종이 큰 변화.
  • WindowSizeClass 로 fold / tablet 자동.

🔗 관련 문서