9148c358d0
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 폴더 제거.
5.2 KiB
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 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 자동.