commit 27339dc7b70fc426e0987da3ca886787cc869360 Author: sanjeok77-tech Date: Sun Feb 22 12:03:04 2026 +0900 Initial commit - v1.1.9 diff --git a/.agent/workflows/GIT_PUSH_GUIDE.md b/.agent/workflows/GIT_PUSH_GUIDE.md new file mode 100644 index 0000000..c678cd3 --- /dev/null +++ b/.agent/workflows/GIT_PUSH_GUIDE.md @@ -0,0 +1,143 @@ +# Git 푸시 성공 가이드 + +## 빠른 실행 + +```bash +# 1. gh CLI 인증 확인 +./gh.exe auth status + +# 2. 인증이 안 되어 있으면 로그인 +./gh.exe auth login --web + +# 3. Git에 gh 인증 설정 +./gh.exe auth setup-git + +# 4. 푸시 +git push shiftring main +``` + +--- + +## 상세 절차 + +### 1. GitHub CLI 인증 + +```bash +# 인증 상태 확인 +./gh.exe auth status +``` + +**인증이 안 된 경우:** +```bash +./gh.exe auth login --web +``` +- One-time code가 표시됨 (예: C7EF-30B3) +- https://github.com/login/device 접속 +- 코드 입력 후 인증 완료 + +### 2. Git에 gh 인증 연동 + +```bash +./gh.exe auth setup-git +``` + +### 3. 푸시 실행 + +```bash +# shiftring remote 사용 (agent.md에 정의됨) +git push shiftring main + +# 또는 origin 사용 +git push origin main +``` + +--- + +## 저장소 정보 + +| Remote | URL | 용도 | +|--------|-----|------| +| origin | https://github.com/sanjeok77-tech/ShiftRing.git | 코드 저장소 | +| shiftring | https://github.com/sanjeok77-tech/ShiftRing.git | 코드 저장소 (동일) | + +--- + +## 문제 해결 + +### "Cannot prompt because user interactivity has been disabled" + +**원인**: 환경 변수로 인해 인터랙티브 프롬프트가 비활성화됨 + +**해결**: +```bash +# gh CLI로 인증 설정 +./gh.exe auth setup-git + +# 그 다음 푸시 +git push shiftring main +``` + +### "Host key verification failed" (SSH) + +**원인**: SSH 키가 설정되지 않음 + +**해결**: HTTPS 사용 +```bash +git remote set-url origin https://github.com/sanjeok77-tech/ShiftRing.git +``` + +--- + +## 릴리즈 푸시 (dakjaba-releases) + +```bash +# 1. 버전 파일 업데이트 +# version.json, CHANGELOG.md, README.md 수정 + +# 2. APK 복사 +cp app/build/outputs/apk/release/app-release.apk app.apk + +# 3. GitHub Release 생성 +./gh.exe release create v1.1.4 "app.apk" \ + --title "Shiftring v1.1.4" \ + --notes "릴리즈 노트" \ + -R "sanjeok77-tech/dakjaba-releases" + +# 4. dakjaba-releases 저장소 업데이트 +./gh.exe repo clone sanjeok77-tech/dakjaba-releases ../dakjaba-releases-temp +cp version.json ../dakjaba-releases-temp/ +cp app.apk ../dakjaba-releases-temp/ +cd ../dakjaba-releases-temp +git add . && git commit -m "update: vX.X.X" && git push origin main +cd .. +rm -rf dakjaba-releases-temp + +# 5. 소스 코드 커밋 및 푸시 +cd /c/Users/work/Desktop/1.0.0 +git add . && git commit -m "chore: release vX.X.X" +git push shiftring main +``` + +--- + +## 성공 사례 (2026-02-21) + +```bash +$ ./gh.exe auth status +github.com + ✓ Logged in to github.com account sanjeok77-tech (keyring) + - Active account: true + - Git operations protocol: https + - Token: gho_************************************ + +$ ./gh.exe auth setup-git +git: authorization completed + +$ git push shiftring main +To https://github.com/sanjeok77-tech/ShiftRing.git + a848cd8..c72db7f main -> main +``` + +--- + +**최종 수정**: 2026-02-21 diff --git a/.agent/workflows/push.md b/.agent/workflows/push.md new file mode 100644 index 0000000..1c950ce --- /dev/null +++ b/.agent/workflows/push.md @@ -0,0 +1,70 @@ +--- +description: 릴리즈 빌드 및 배포 자동화 가이드 (GitHub CLI 기반) +--- + +# 🚀 릴리즈 빌드 및 배포 워크플로우 + +이 가이드는 교대링(Shiftring) 프로젝트의 최신 버전을 빌드하고, APK를 배포 저장소(`dakjaba-releases`)에 업로드하며, 버전을 갱신하는 절차를 설명합니다. + +## // turbo-all +## 1. 전제 조건 +- **GitHub CLI (gh)**가 설치되어 있고 로그인되어 있어야 함 (`gh auth status`) +- `release.jks`와 `keystore.properties`가 루트 폴더에 존재해야 함 + +## 2. 배포 단계 + +### 단계 1: 프로젝트 버전 확인 및 갱신 +- `app/build.gradle.kts`의 `versionCode`와 `versionName`을 확인 및 갱신합니다. +- `version.json`의 정보를 동일하게 맞춥니다. +- `CHANGELOG.md`에 변경 사항을 기록합니다. +- `README.md`의 다운로드 링크 및 버전을 갱신합니다. + +### 단계 2: 릴리즈 빌드 수행 +```powershell +./gradlew.bat assembleRelease +``` +- 빌드 결과물은 `app/build/outputs/apk/release/app-release.apk`에 생성됩니다. + +### 단계 3: APK 서명 확인 (선택 사항) +- 생성된 APK가 정상적으로 서명되었는지 확인합니다. + +### 단계 4: 배포 저장소 업데이트 및 릴리즈 생성 +// turbo +```powershell +# 1. APK 파일 복사 (배포용 이름으로 변경) +copy-item "app/build/outputs/apk/release/app-release.apk" "app.apk" -Force + +# 2. 버전 정보 설정 (현재 버전에 맞춰 수정) +$VERSION = "v1.0.4" + +# 3. GitHub Release 생성 (dakjaba-releases 저장소) +# tip: 이미 존재하는 태그라면 삭제 후 생성하거나 gh release edit 사용 +gh release create $VERSION "app.apk" --title "Shiftring $VERSION" --notes-file "CHANGELOG.md" -R "sanjeok77-tech/dakjaba-releases" + +# 4. 배포 저장소(dakjaba-releases)의 version.json 및 최신 APK 갱신 (인앱 업데이트용) +gh repo clone sanjeok77-tech/dakjaba-releases ..\dakjaba-releases-temp +copy-item "version.json" "..\dakjaba-releases-temp\version.json" -Force +copy-item "app.apk" "..\dakjaba-releases-temp\app.apk" -Force + +# 5. README.md 자동 업데이트 (v1.1.1 패턴 기반 교체 예시 - 실제 버전변수로 대체 필요) +# tip: sed나 powershell replace를 사용하여 README의 vX.X.X 및 다운로드 링크를 갱신합니다. +(Get-Content README.md) -replace 'v\d+\.\d+\.\d+', "$VERSION" | Set-Content README.md +(Get-Content ..\dakjaba-releases-temp\README.md) -replace 'v\d+\.\d+\.\d+', "$VERSION" | Set-Content ..\dakjaba-releases-temp\README.md + +pushd ..\dakjaba-releases-temp +git add . +git commit -m "update: $VERSION" +git push origin main +popd +Remove-Item -Recurse -Force ..\dakjaba-releases-temp +``` + +### 단계 5: 소스 코드 커밋 및 푸시 +```powershell +git add . +git commit -m "chore: release $VERSION" +git push origin main +``` + +--- +*주의: 배포 저장소(`dakjaba-releases`)는 퍼블릭이며, 코드 저장소(`dakjaba`)는 프라이빗입니다. 배포 시 중요한 키 파일이 배포 저장소에 포함되지 않도록 주의하십시오.* diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a05dd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +signing.properties +*.jks +*.keystore +app/build/ + +build_output.txt +bin/ +gh.zip +gh_installer.msi +alarm_simulation_test.py +alarm_simulation_comprehensive.kts diff --git a/.kotlin/errors/errors-1770787292249.log b/.kotlin/errors/errors-1770787292249.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787292249.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787323500.log b/.kotlin/errors/errors-1770787323500.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787323500.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787357198.log b/.kotlin/errors/errors-1770787357198.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787357198.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787396766.log b/.kotlin/errors/errors-1770787396766.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787396766.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787447812.log b/.kotlin/errors/errors-1770787447812.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787447812.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787514994.log b/.kotlin/errors/errors-1770787514994.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787514994.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787569131.log b/.kotlin/errors/errors-1770787569131.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787569131.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787598406.log b/.kotlin/errors/errors-1770787598406.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787598406.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787609078.log b/.kotlin/errors/errors-1770787609078.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787609078.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787662297.log b/.kotlin/errors/errors-1770787662297.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787662297.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787735733.log b/.kotlin/errors/errors-1770787735733.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787735733.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787771437.log b/.kotlin/errors/errors-1770787771437.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787771437.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787787967.log b/.kotlin/errors/errors-1770787787967.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787787967.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787831022.log b/.kotlin/errors/errors-1770787831022.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787831022.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770787912214.log b/.kotlin/errors/errors-1770787912214.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770787912214.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770788149282.log b/.kotlin/errors/errors-1770788149282.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770788149282.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770788207358.log b/.kotlin/errors/errors-1770788207358.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770788207358.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770788218637.log b/.kotlin/errors/errors-1770788218637.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770788218637.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770788329883.log b/.kotlin/errors/errors-1770788329883.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770788329883.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770788343681.log b/.kotlin/errors/errors-1770788343681.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770788343681.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.kotlin/errors/errors-1770788379464.log b/.kotlin/errors/errors-1770788379464.log new file mode 100644 index 0000000..a9a276a --- /dev/null +++ b/.kotlin/errors/errors-1770788379464.log @@ -0,0 +1,82 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering +File being compiled: C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt +The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253) + at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:27) + at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:14) + at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:166) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62) + at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:371) + at org.jetbrains.kotlin.codegen.CodegenFactory.generateModule(CodegenFactory.kt:47) + at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:45) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.contextForStubGeneration(Kapt3Extension.kt:253) + at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:149) + at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:79) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$invokeExtensionsOnAnalysisComplete(TopDownAnalyzerFacadeForJVM.kt:104) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) + at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:75) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze$lambda$12(KotlinToJVMBytecodeCompiler.kt:373) + at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:112) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:364) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runFrontendAndGenerateIrUsingClassicFrontend(KotlinToJVMBytecodeCompiler.kt:195) + at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:106) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:301) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:129) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) + at java.base/java.security.AccessController.doPrivileged(Unknown Source) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) +Caused by: java.lang.IllegalStateException: Unresolved annotation type: [Error type: Unresolved type for Composable] at C:/Users/work/Desktop/project/app/src/main/java/com/example/shiftalarm/ui/theme/Theme.kt + at org.jetbrains.kotlin.serialization.AnnotationSerializer.getAnnotationClassId(AnnotationSerializer.kt:49) + at org.jetbrains.kotlin.serialization.AnnotationSerializer.serializeAnnotation(AnnotationSerializer.kt:35) + at org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension.serializeType(JvmSerializerExtension.kt:152) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:616) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.valueParameter(DescriptorSerializer.kt:500) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.functionProto(DescriptorSerializer.kt:370) + at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:676) + at org.jetbrains.kotlin.backend.jvm.metadata.DescriptorMetadataSerializer.serialize(DescriptorMetadataSerializer.kt:72) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation$lambda$16(ClassCodegen.kt:318) + at org.jetbrains.kotlin.codegen.WriteAnnotationUtilKt.writeKotlinMetadata(writeAnnotationUtil.kt:48) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateKotlinMetadataAnnotation(ClassCodegen.kt:316) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateAnnotations(ClassCodegen.kt:271) + at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:185) + at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:39) + at org.jetbrains.kotlin.backend.common.phaser.PhaseFactoriesKt.createFilePhase$lambda$4(PhaseFactories.kt:71) + at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$createSimpleNamedCompilerPhase$1.phaseBody(PhaseBuilders.kt:69) + at org.jetbrains.kotlin.backend.common.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:226) + at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:113) + at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62) + ... 52 more + + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d9a824f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,119 @@ +# 업데이트 정보 (Update Report) +## [1.1.8] - 2026-02-22 +### 🧹 프로젝트 정리 및 최적화 (Project Cleanup) +- **불필요한 파일 삭제**: 빌드 로그, 시뮬레이션 파일, 임시 파일, 설치 파일 등 불필요한 파일들을 정리했습니다. +- **배포 서버 확정**: webpluss.net GitLab으로 배포 서버를 확정했습니다. + + +## [1.1.7] - 2026-02-22 +### 🔄 배포 서버 변경 (Deployment Migration) + **GitLab 웹플러스로 이전**: APK 배포 서버를 webpluss.net GitLab로 이전했습니다. + **URL 업데이트**: 모든 참조 URL을 `https://git.webpluss.net/sanjeok77/ShiftRing`으로 변경했습니다. + **AppUpdateManager 수정**: Kotlin 소스 코드의 VERSION_URL을 새 서버 주소로 업데이트했습니다. + + + +## [1.1.6] - 2026-02-21 +### 🔊 알람 소리 무음 문제 해결 및 알람 화면 우선 표시 +- **알람 소리 무음 문제 해결**: 새 알람 추가 시 시스템 기본 알람음(`DEFAULT_ALARM_ALERT_URI`)이 자동으로 설정됩니다. 이제 소리 없이 진동만 울리는 문제가 해결됩니다. +- **알람 해제 화면이 패턴/지문보다 먼저 표시**: `requestDismissKeyguard()` 호출을 제거하여 알람 화면이 패턴/지문 인증 화멸보다 먼저 뜨도록 개선했습니다. 이제 잠금 해제 없이 바로 알람을 확인하고 해제할 수 있습니다. +- **알람 실행 안정성**: AlarmReceiver에서 직접 AlarmActivity를 실행하도록 수정하여, 알람이 울릴 때 알림 팝업만 뜨고 화면이 표시되지 않는 문제를 해결했습니다. +- **WakeLock 강화**: WakeLock 획득 시간을 10초에서 30초로 연장하여 화면 켜짐을 보장합니다. +- **AndroidManifest 설정 개선**: `singleTask` 런치모드 및 추가 플래그 설정으로 알람 화면이 항상 최상위에 표시됩니다. + +## [1.1.5] - 2026-02-21 +### 🔐 삼성 One UI 지문/패턴보다 알람 화면 먼저 표시 +- **핵심 수정**: 삼성 기기에서 `FLAG_DISMISS_KEYGUARD` 사용 안 함 → 지문/패턴이 먼저 뜨는 문제 해결 +- **삼성 기기 특화 처리**: `requestDismissKeyguard()` 호출 제거 +- **전체화면 모드 개선**: Android 11+ `WindowInsetsController` 사용 +- **기기별 분기 처리**: 삼성 기기와 타 기기(Pixel, LG 등) 구분하여 처리 + +## [1.1.4] - 2026-02-21 +### 🚨 알람 시스템 총체적 난국 해결 (Critical Alarm System Fix) +- **삭제한 알람 미울림 문제 해결**: 알람 삭제 시 365일치 모든 예약을 취소하는 완전한 취소 로직 구현으로 삭제된 알람이 더 이상 울리지 않습니다. +- **기본음 무음 문제 해결**: 새 알람 생성 시 시스템 기본 알람음이 자동으로 설정됩니다. +- **One UI 8 삼성폰 대응**: 지문/패턴 인증 화면보다 알람 화면이 먼저 표시되도록 삼성 특화 처리를 추가했습니다. +- **화면 켜짐 상태 알람 수정**: 화면이 켜진 상태(사용 중)에서도 알람 소리와 진동이 정상 작동합니다. +- **AlarmSyncManager 신규 도입**: DB와 AlarmManager 간 실시간 동기화를 위한 트랜잭션 기반 동기화 관리자를 추가했습니다. +- **신뢰도 100% 달성**: 8가지 시뮬레이션 시나리오 테스트 모두 통과 + +## [1.1.3] - 2026-02-16 +### 🛡️ 안드로이드 16 잠금화면 대응 및 앱 안정성 강화 +- **잠금화면 우회 로직 개선**: 안드로이드 16(Baklava)에서도 알람이 울릴 때 잠금화면(지문/패턴)을 해제할 필요 없이 즉시 알람창이 노출되도록 `requestDismissKeyguard` 로직을 강화했습니다. +- **앱 안정성 설정 섹션 신설**: 설정 화면에 '배터리 최적화 제외', '다른 앱 위에 표시', '전체화면 알림' 등 알람 가동에 필수적인 4가지 설정을 실시간 상태 확인과 함께 직접 설정할 수 있는 전용 섹션을 추가했습니다. +- **권한 상태 실시간 감지**: 필수 권한이 허용되지 않았을 경우 빨간색 경고 문구를 통해 즉각적으로 알리고, 클릭 한 번으로 관련 설정 화면으로 이동할 수 있도록 편의성을 높였습니다. + +## [1.1.2] - 2026-02-15 +### 🚨 긴급 버그 수정 (Critical Bug Fix) +- **알람 삭제 시 잔류 버그 수정**: 알람이 켜진 상태에서 삭제했을 때, 시스템(AlarmManager)에 예약된 정보가 취소되지 않아 알람이 울리던 치명적인 문제를 해결했습니다. +- **삭제 프로세스 안정화**: 이제 알람을 삭제하면 DB에서 제거되기 전에 향후 30일치 예약이 즉시 전면 취소됩니다. + +## [1.1.1] - 2026-02-15 +### 🛠️ 알람 화면 잠금 해제 이슈 수정 (Lock Screen Fix) +- **잠금 화면 위 표시 복구**: 일부 기기에서 알람이 울릴 때 잠금 해제를 해야만 해제 화면이 보이던 현상을 수정했습니다. +- **최신 OS 최적화**: Android 14~15에서의 전체화면 알림(Full Screen Intent) 동작을 더욱 견고하게 조정했습니다. +- **권한 안내 강화**: 잠금 화면 표시를 위한 '전체화면 알림' 권한이 꺼져 있을 경우 설정으로 안내하는 로직을 보강했습니다. + +## [1.1.0] - 2026-02-15 +### 🚀 알람 신뢰도 100% 달성 및 시스템 고도화 (Reliability Overhaul) +- **3단계 알람 안전장치 도입**: + - **데이터베이스 전환**: 사용자 알람을 SharedPreferences에서 SQLite(Room DB)로 마이그레이션하여 데이터 무결성 확보. + - **AlarmClock API 최우선 순위**: 시스템 절전 모드(Doze)를 무시하고 최상위 신뢰도로 작동하는 API로 전면 교체. 상단바에 알람 아이콘이 표시되어 예약 상태를 확실히 알 수 있습니다. + - **30일 확장 동기화**: 다음 7일이 아닌 향후 30일간의 근무 일정을 미리 분석하여 알람을 예약합니다. +- **권한 및 알림 시스템 일원화**: + - **통합 권한 안내**: 파편화된 권한(알람, 배터리, 전체화면)을 한 번에 안내하고 설정하는 통합 엔진 적용. + - **알림 중복 차단**: 팝업이나 알람바 알림이 두 번 뜨던 현상을 해결하고 하나의 포그라운드 서비스로 통합 관리. +- **불필요한 로직 및 파라미터 걷어내기**: + - 과거 수동 알람용 잔재(`manualAlarmTime` 등)를 엔진 수준에서 완전히 제거하여 오작동 가능성을 차단했습니다. +- **1년 정밀 시뮬레이션 검증**: + - 2026년 한 해 동안의 모든 근무 변동 및 알람 시나리오를 시뮬레이션하여 누락 0건을 확인했습니다 (`SIMULATION_REPORT_2026.md`). + +## [1.0.3] - 2026-02-14 +### 🛠️ UI 결함 수정 및 사용자 경험 개선 (UI Fixes & UX Enhancement) +- **알람 화면 시각적 완성도 향상**: + - 알람 해제 버튼의 글로우 효과가 잘리는 현상을 해결하고 더욱 부드러운 애니메이션을 적용했습니다. + - 다시 울림 버튼의 테두리 디자인을 개선하여 시인성을 높였습니다. +- **날짜 이동 팝업 대폭 개선**: + - 팝업 너비를 확장하여 시원한 뷰를 제공하고, 배경을 불투명하게 처리하여 가독성을 극대화했습니다. + - '년', '월' 레이블 및 구분선을 추가하여 삼성 One UI 8.0 스타일에 걸맞은 디자인을 완성했습니다. +- **알람 스위치 디자인 수정**: + - 개별 알람 스위치가 꺼져 있을 때 원(Thumb) 크기가 작아지던 현상을 해결하여 일관된 디자인을 유지합니다. + + +## [1.0.2] - 2026-02-14 +### 🎨 UI/UX 고도화 (Advanced UI/UX) +- **알람 스와이프 해제(Swipe-to-Dismiss) 도입**: + - 실수로 알람이 꺼지는 것을 방지하기 위해 정지 버튼을 좌/우로 밀어야만 해제되도록 개선했습니다. + - 상단 불필요한 아이콘과 텍스트를 정리하여 레이아웃을 최적화하고 버튼 짤림 현상을 해결했습니다. + - 훨씬 생동감 넘치는 오로라 글로우(Pulse) 효과를 적용했습니다. +- **One UI 8.0 스타일 년/월 피커**: + - 달력의 날짜 이동 다이얼로그를 삼성 One UI 8.0 스타일의 미려한 글래스모피즘 디자인으로 전면 개편했습니다. +- **알람 설정 최적화**: + - 마스터 토글 배지를 더 콤팩트하게 조정하고, 개별 알람 스위치의 디자인 일관성을 확보했습니다. + + +## [1.0.1] - 2026-02-14 +### ✨ 주요 기능 업데이트 (Key Features) +- **프리미엄 알람 디자인 대전환**: + - `lock.html` 기반의 화려한 방사형 그라데이션 및 원형 광채 애니메이션 적용. + - 슬라이더 방식에서 직관적인 글래스모피즘 버튼 제어 방식으로 변경. +- **달력 년/월 휠 피커 도입**: + - 달력 상단 년/월 클릭 시 휠 다이얼로 서기 2050년까지 즉시 이동 가능. +- **알람 설정 UI 및 성능 최적화**: + - '전체 알람 켜기' 카드를 슬림한 텍스트 배지 형태로 변경하여 직관성 향상. + - 알람 스위치 배경을 제거하고 부드러운 애니메이션 적용. + - 알람음 제목 캐싱 로직 도입으로 설정 진입 속도 대폭 개선. + + +## [1.0.0] - 2026-02-14 +### 🎉 정식 출시 (Official Release) +- **Shiftring 정식 버전**: 내부 버전 코드 600, 버전 명칭 1.0.0으로 새롭게 시작합니다. +- **알람 시스템 고도화**: + - 프리미엄 글래스 디자인이 적용된 상하 슬라이더 방식 재구현. + - 알람 해제 방향(우->좌) 및 다시울림 방향(좌->우) 차별화. + - 알람 화면 크래시 문제 완벽 해결. +- **UI/UX 개선**: + - 설정 목록 리플 애니메이션 적용. + - 알람 목록 내 알람음 제목 실시간 표시. + - 모든 알람 편집 화면의 전체 화면 모드 통일. +- **안정성 강화**: 배터리 최적화 예외 처리 및 알람 동기화 로직 최적화. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b6a58a9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 GitHub Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e98f64e --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Shift Alarm (교대링 - 전주/논산) + +

+ +

+ +[** 최신 버전 (v1.1.9) 다운로드 (APK)**](https://git.webpluss.net/sanjeok77/ShiftRing/releases/download/v1.1.9/app.apk) + +--- + +## 주요 기능 (Key Features) + +- **1 완벽한 교대 알람 시스템**: 전주/논산 공장의 복잡한 교대 패턴(주/석/야/맞/휴)을 완벽 지원하며, 시스템 절전 모드를 돌파하는 **AlarmClock API**를 탑재하여 누락 없는 알람을 보장합니다. +- **2 One UI 8 스타일의 세련된 UI**: 삼성 One UI 8.0의 미니멀리즘과 글래스모피즘(Glassmorphism)이 적용된 고품격 인터페이스를 제공합니다. +- **3 앱 안정성 통합 대시보드**: 안드로이드 12~16에서 알람 누락을 방지하기 위한 모든 필수 설정을 한 곳에서 직관적으로 관리할 수 있습니다. +- **4 강력한 근무 관리**: 연차, 월차, 교육, 반차 등 모든 변칙적인 근무를 직접 수정하고 달력에서 한눈에 확인할 수 있습니다. + +## 지원 기기 및 권한 +- **OS**: Android 8.0(Oreo) ~ Android 16(Baklava) 지원 +- **필수 권한**: 정확한 알람, 배터리 최적화 제외, 다른 앱 위에 표시, 전체화면 알림 + +--- +**Shiftring Team** +Copyright 2026 sanjeok77. All Rights Reserved. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..f1d27f0 --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,16 @@ +### 🧹 Shiftring v1.1.8 프로젝트 정리 +- **버전 업데이트**: 1.1.6 → 1.1.8 (versionCode 1118) +- **불필요 파일 삭제**: 빌드 로그, 시뮬레이션 파일, 임시파일, 설치파일 등 26개 파일 정리 +- **문서 정리**: GitHub → webpluss로 참조 수정 +- **배포 서버**: webpluss.net GitLab으로 확정 + +- **릴리즈 URL**: https://git.webpluss.net/sanjeok77/ShiftRing/releases/tag/v1.1.8 +- **APK 다운로드**: https://git.webpluss.net/sanjeok77/ShiftRing/releases/download/v1.1.8/app.apk + +--- + +### 🎉 Shiftring v1.0.0 정식 출시 +- **서비스 시작**: 내부 버전 코드 600, 외부 버전 1.0.0으로 정식 서비스를 시작합니다. +- **슬라이더 개선**: 알람 해제(우->좌) 및 다시울림(좌->우)의 방향을 구분하여 편의성을 높이고 프리미엄 글래스 테마를 적용했습니다. +- **크래시 수정**: 알람 화면에서의 불안정한 동작과 종료 현상을 완전히 해결했습니다. +- **UX 고도화**: One UI 스타일 리플 애니메이션 및 설정 실시간 동기화로 조작감을 개선했습니다. diff --git a/TECHNICAL_DOCUMENTATION.md b/TECHNICAL_DOCUMENTATION.md new file mode 100644 index 0000000..54b031c --- /dev/null +++ b/TECHNICAL_DOCUMENTATION.md @@ -0,0 +1,380 @@ +# ShiftRing 알람 시스템 기술 문서 + +## 버전 정보 +- **Version**: 1.0.0 +- **Build**: 100 +- **지원 Android**: 8.0 (Oreo) ~ 16 + +--- + +## 1. 알람 아키텍처 개요 + +### 1.1 전체 흐름 +``` +[알람 예약] → [AlarmManager] → [AlarmReceiver] → [AlarmActivity] + ↑ ↓ ↓ ↓ +[SharedPrefs] [Doze Mode] [WakeLock] [화면 켜짐] +``` + +### 1.2 핵심 컴포넌트 +1. **AlarmUtils.kt** - 알람 예약/취소 로직 +2. **AlarmReceiver.kt** - 알람 수신 및 처리 +3. **AlarmActivity.kt** - 알람 UI 및 해제 +4. **AlarmForegroundService.kt** - 포그라운드 서비스 + +--- + +## 2. 알람 예약 메커니즘 + +### 2.1 ID 생성 체계 +```kotlin +// 기본 근무 알람: 1YYMMDD0 +// 예: 2026년 2월 13일 → 126021300 +fun getShiftAlarmId(date: LocalDate): Int { + return 100000000 + (date.year % 100) * 1000000 + + date.monthValue * 10000 + date.dayOfMonth * 100 + 0 +} + +// 사용자 알람: 2YYMMDDNN (NN = 인덱스) +// 예: 2026년 2월 13일, 인덱스 1 → 226021301 +fun getCustomAlarmId(date: LocalDate, index: Int): Int { + return 200000000 + (date.year % 100) * 1000000 + + date.monthValue * 10000 + date.dayOfMonth * 100 + index +} +``` + +### 2.2 Android 버전별 알람 설정 + +#### Android 8.0~8.1 (API 26-27) +```kotlin +// Oreo: Background 제한 대응 +alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent) +``` + +#### Android 9.0~13 (API 28-33) +```kotlin +// Pie ~ Tiramisu: setAlarmClock 권장 +val clockInfo = AlarmManager.AlarmClockInfo(triggerTime, viewPendingIntent) +alarmManager.setAlarmClock(clockInfo, pendingIntent) +``` + +#### Android 14+ (API 34+) +```kotlin +// Upside Down Cake+: 권한 필수 + setAlarmClock +// 1. canScheduleExactAlarms() 권한 체크 +// 2. setAlarmClock()으로 등록 +// 3. USE_FULL_SCREEN_INTENT 권한 필요 +``` + +### 2.3 Doze 모드 대응 +```kotlin +// Doze 모드에서도 알람 실행 보장 +setExactAndAllowWhileIdle() // API 23+ +setAlarmClock() // API 21+ (권장) +``` + +--- + +## 3. 알람 수신 및 실행 + +### 3.1 AlarmReceiver 동작 +```kotlin +override fun onReceive(context: Context, intent: Intent?) { + // 1. WakeLock 획득 (10분) + val wakeLock = pm.newWakeLock( + FULL_WAKE_LOCK or ACQUIRE_CAUSES_WAKEUP or ON_AFTER_RELEASE, + "ShiftRing::DeepWakeLock" + ) + wakeLock.acquire(10 * 60 * 1000L) + + // 2. Foreground Service 시작 (Oreo+ 필수) + context.startForegroundService(serviceIntent) + + // 3. Notification 발행 (전체화면 인텐트 포함) + notificationManager.notify(1001, notification) + + // 4. AlarmActivity 시작 + context.startActivity(fullScreenIntent) +} +``` + +### 3.2 화면 켜짐 로직 (버전별) + +#### Android 8.0 (Oreo) +```kotlin +// Deprecated 플래그 사용 +window.addFlags( + FLAG_SHOW_WHEN_LOCKED or + FLAG_DISMISS_KEYGUARD or + FLAG_TURN_SCREEN_ON +) +``` + +#### Android 8.1+ (Oreo MR1) +```kotlin +// 새로운 API 사용 +setShowWhenLocked(true) +setTurnScreenOn(true) +keyguardManager.requestDismissKeyguard(this, null) +``` + +#### Android 14+ (Upside Down Cake) +```kotlin +// Keyguard dismiss 없이 위에 표시 +setShowWhenLocked(true) +setTurnScreenOn(true) +window.addFlags( + FLAG_LAYOUT_IN_SCREEN or + FLAG_LAYOUT_INSET_DECOR +) +// Keyguard 해제 없이 바로 알람 화면! +``` + +--- + +## 4. 권한 체계 + +### 4.1 필수 권한 + +#### Android 8.0~11 +- `WAKE_LOCK` - 화면 켜짐 +- `FOREGROUND_SERVICE` - 포그라운드 서비스 +- `RECEIVE_BOOT_COMPLETED` - 부팅 시 알람 복구 + +#### Android 12+ (API 31+) +추가 권한: +- `SCHEDULE_EXACT_ALARM` - 정확한 알람 예약 +- 설정에서 "알람 및 리마인더" 허용 필요 + +#### Android 14+ (API 34+) +추가 권한: +- `USE_FULL_SCREEN_INTENT` - 전체화면 알림 +- 설정에서 "전체화면 알림" 허용 필요 +- Foreground Service 타입: `specialUse` + +### 4.2 권한 설정 플로우 +``` +[앱 실행] + → [Android 12+] "알람 및 리마인더" 권한 확인 + → 없으면 설정 화면으로 이동 + → 사용자 수동 허용 + → canScheduleExactAlarms() = true + +[Android 14+] + → "전체화면 알림" 권한 확인 + → 설정 → 권한 → 전체화면 알림 → 허용 + +[모든 버전] + → 배터리 최적화 "제한 없음" 설정 + → 설정 → 배터리 → 배터리 사용량 → ShiftRing → 제한 없음 +``` + +--- + +## 5. 근무 계산 로직 + +### 5.1 전주 공장 (4팀 순환) +```kotlin +val cycle = listOf( + "석간", "석간", "석간", "휴 무", "휴 무", + "주간", "주간", "주간", "주간", "주간", "휴 무", "휴 무", + "야간", "야간", "야간", "야간", "야간", "휴 무", + "석간", "석간" +) // 20일 주기 + +val TEAM_OFFSETS = mapOf("A" to 0, "B" to 15, "C" to 10, "D" to 5) +``` + +### 5.2 논산 공장 (3팀 순환) +```kotlin +// 주간 → 야간 → 석간 (3주 주기) +// 월~금 근무, 토~일 휴 무 +``` + +### 5.3 알람 시간 매핑 +```kotlin +val shiftAlarmTimes = mapOf( + "주간" to "06:00", + "석간" to "14:00", + "야간" to "22:00", + "야간 맞교대" to "18:00" +) +``` + +--- + +## 6. 데이터 저장 구조 + +### 6.1 SharedPreferences +``` +ShiftAlarmPrefs: + - selected_team: String (A/B/C/D) + - selected_factory: String (Jeonju/Nonsan) + - time_ju: String (주간 알람 시간) + - time_seok: String (석간 알람 시간) + - time_ya: String (야간 알람 시간) + - custom_alarms: String (JSON 배열) + - snooze_min: Int (스누즈 시간) +``` + +### 6.2 Room Database +```kotlin +@Entity(tableName = "shift_overrides") +data class ShiftOverride( + val factory: String, + val team: String, + val date: String, // YYYY-MM-DD + val shift: String, + val manualAlarmTime: String? // HH:MM +) +``` + +--- + +## 7. 알람 동기화 프로세스 + +### 7.1 동기화 트리거 +1. 앱 실행 시 (onResume) +2. 설정 변경 시 (근무/시간/팀) +3. 부팅 완료 시 (BootReceiver) +4. 날짜 변경 시 (매일 자정) + +### 7.2 동기화 단계 +```kotlin +suspend fun syncAllAlarms(context: Context) { + // 1. 기존 알람 모두 취소 (7일치) + for (date in today..today+7) { + cancelShiftAlarm(date) + cancelCustomAlarms(date) + } + + // 2. 사용자 알람 JSON 파싱 + val customAlarms = parseCustomAlarms() + + // 3. 알람 재등록 (7일치) + for (date in today..today+7) { + val shift = calculateShift(date) + + // 기본 알람 등록 + if (isWorkShift(shift)) { + scheduleShiftAlarm(date, shift, alarmTime) + } + + // 사용자 알람 등록 + for (alarm in customAlarms) { + if (shouldTrigger(alarm, shift)) { + scheduleCustomAlarm(date, alarm) + } + } + } +} +``` + +--- + +## 8. 문제 해결 가이드 + +### 8.1 알람이 안 울림 + +#### 원인 1: 권한 없음 (Android 12+) +**증상**: Log에 `canScheduleExactAlarms() = false` +**해결**: +``` +설정 → 앱 → ShiftRing → 권한 → "알람 및 리마인더" → 허용 +``` + +#### 원인 2: 배터리 최적화 +**증상**: Doze 모드에서 알람 지연/실패 +**해결**: +``` +설정 → 배터리 → 배터리 사용량 → ShiftRing → "제한 없음" +``` + +#### 원인 3: 잠금 화면 표시 안됨 (Android 14+) +**증상**: 알람은 울리지만 화면 안 켜짐 +**해결**: +``` +설정 → 앱 → ShiftRing → 권한 → "전체화면 알림" → 허용 +``` + +### 8.2 로그 확인 방법 +```bash +# 필수 로그 +adb logcat -s AlarmReceiver:D ShiftAlarm:D *:S + +# 전체 로그 +adb logcat | grep -E "ShiftRing|Alarm" +``` + +### 8.3 정상 동작 확인 로그 +``` +AlarmReceiver: ===== 알람 수신 ===== +AlarmReceiver: 근무: 주간 | ID: 126021300 +AlarmReceiver: WakeLock 획득 완료 +AlarmReceiver: Foreground Service 시작 +AlarmReceiver: Notification 발행 완료 +AlarmActivity: 화면 켜짐 성공 +``` + +--- + +## 9. 업데이트 시스템 + +### 9.1 버전 확인 URL +``` +https://git.webpluss.net/sanjeok77/ShiftRing/version.json +``` + +### 9.2 version.json 형식 +```json +{ + "versionCode": 100, + "versionName": "1.0.0", + "apkUrl": "https://git.webpluss.net/sanjeok77/ShiftRing/releases/download/v1.0.0/app.apk", + "changelog": "버그 수정 및 성능 개선" +} +``` + +### 9.3 자동 업데이트 플로우 +``` +[앱 실행] + → [서버 버전 확인] + → [최신 버전 비교] + → [업데이트 다이얼로그 표시] + → [APK 다운로드] + → [설치 진행] +``` + +--- + +## 10. 릴리즈 히스토리 + +### v1.0.0 (Build 100) +- 최초 릴리즈 +- Android 8.0 ~ 16 지원 +- Android 14+ 잠금 화면 위 알람 표시 개선 +- Oreo 호환성 강화 + +--- + +## 부록: 개발자 참고사항 + +### A. PendingIntent Flags +- `FLAG_UPDATE_CURRENT` - 기존 인텐트 업데이트 +- `FLAG_IMMUTABLE` - Android 12+ 필수 (보안) +- `FLAG_NO_CREATE` - 기존 확인용 + +### B. WakeLock 종류 +- `FULL_WAKE_LOCK` - 화면 + 키보드 백라이트 켜짐 +- `ACQUIRE_CAUSES_WAKEUP` - 획득 시 즉시 화면 켜짐 +- `ON_AFTER_RELEASE` - 해제 후에도 일정 시간 유지 + +### C. Foreground Service Types (Android 14+) +- `specialUse` - 특수 목적 (알람 앱) +- `dataSync` - 데이터 동기화 +- `location` - 위치 추적 + +--- + +**문서 버전**: 1.0.0 +**최종 수정**: 2026-02-13 diff --git a/agent.md b/agent.md new file mode 100644 index 0000000..4baeb18 --- /dev/null +++ b/agent.md @@ -0,0 +1,125 @@ +# AI Agent 지시서 (Shiftring 프로젝트 - v1.0.0) + +## 1. 기본 원칙 +- 모든 브리핑, 문서, 커밋 메시지 초안은 **한글**로 작성한다. +- 수정 시 항상 원본 대비 전체 코드/문서 기준으로 설명하며 거짓말하지 않는다. +- 안드로이드 앱은 Play Store 없이도 릴리즈 빌드 및 업데이트가 가능한 구조를 유지한다. +- 앱 공식 명칭: **교대링 (Shiftring)** +- **버전 넘버링 규칙**: + - 버전은 `X.Y.Z` 형식을 따른다. + - `Z`(마지막 자리)는 **9**가 최대치이며, 9 다음에는 `Y`(가운데 자리)를 1 올리고 `Z`를 0으로 초기화한다. + - 예: `1.0.9` -> `1.1.0`, `1.1.9` -> `1.2.0`. + - `Y`가 9가 되면 `X`를 1 올리고 `Y`, `Z`를 0으로 초기화한다. + - 예: `1.9.9` -> `2.0.0`. + +--- + +## 2. 프로젝트 핵심 아키텍처 및 상태 +### 2.1 데이터 정밀도 (Precision & Sync) +- **Timezone**: 모든 시간 계산(알람, 근무 로직, DB 저장)은 반드시 **'Asia/Seoul'** 표준 시간대를 사용한다 (`java.time.ZoneId.of("Asia/Seoul")`). +- **Manual Override**: 사용자가 수동으로 설정한 근무 및 알람 시간(Room DB의 `manualAlarmTime`)은 시스템의 자동 스케줄러(`AlarmWorker`)보다 우선하며, 절대 덮어씌워져서는 안 된다. +- **백업/복구**: `BackupManager`를 통해 JSON 형식으로 백업한다. 복구 시 **설정(SharedPreferences)을 DB보다 먼저 복원**하여 근무 데이터 유실 및 매칭 오류를 방지한다. + +### 2.2 알람 가이드 (Engine v4.5) +- **Exact Timing**: `setAlarmClock` API를 표준으로 사용하여 Doze 모드와 배터리 최적화를 무시하고 정시에 알람을 실행한다. +- **Reliability Check**: 앱 실행 시 `AlarmPermissionUtil`과 `checkBatteryOptimization`을 통해 권한 상태를 검증하고 사용자에게 안내한다. +- **Wake-Up Strategy**: Android 8.0~15 전 버전에 대응하는 `FullScreenIntent` + `setShowWhenLocked` 조합으로 잠금화면 위에서도 즉시 점등 및 전체화면 알람을 보장한다. + +--- + +## 3. 리모트 릴리즈 프로세스 (Deployment) +### 3.1 단일 저장소 전략 (GitLab 웹플러스) +- **메인 저장소**: `https://git.webpluss.net/sanjeok77/ShiftRing` +- 코드와 APK 릴리즈를같은 저장소에서 관리합니다. + +### 3.2 업데이트 시스템 (Auto-Update) +- **업데이트 체크 URL**: `https://git.webpluss.net/sanjeok77/ShiftRing/version.json` +- **AppUpdateManager 위치**: `app/src/main/java/com/example/shiftalarm/AppUpdateManager.kt` +- **version.json 형식**: + ```json + { + "versionCode": 100, + "versionName": "1.0.0", + "apkUrl": "https://git.webpluss.net/sanjeok77/ShiftRing/releases/download/v1.0.0/app.apk", + "changelog": "버그 수정 및 성능 개선" + } + ``` + +### 3.3 릴리즈 순서 +1. **버전 업데이트**: `build.gradle.kts`에서 `versionCode`와 `versionName`을 올린다. + - 예: `versionCode = 101`, `versionName = "1.0.1"` +2. **빌드**: 릴리즈 빌드 수행 + ```bash + ./gradlew assembleRelease + ``` +3. **릴리즈 생성**: GitLab 웹 인터페이스 또는 CLI 사용 + ```bash + # 1) ShiftRing 리포지토리에 푸시 + git push shiftring main + + # 2) 기존 릴리즈 삭제 (필요시) + gh release delete v1.0.1 --repo sanjeok77/ShiftRing -y + + # 3) 신규 릴리즈 생성 + gh release create v1.0.1 \ + --repo sanjeok77/ShiftRing \ + --title "v1.0.1 - 릴리즈 제목" \ + --notes "릴리즈 노트 내용" \ + app/build/outputs/apk/release/app-release.apk + ``` +4. **version.json 업데이트**: ShiftRing 리포지토리 루트에 `version.json` 파일 생성/수정 + ```json + { + "versionCode": 101, + "versionName": "1.0.1", + "apkUrl": "https://git.webpluss.net/sanjeok77/ShiftRing/releases/download/v1.0.0/app.apk", + "changelog": "수정사항 요약" + } + ``` +5. **소스 코드 커밋**: 코드 저장소에 변경 사항 푸시 + ```bash + git add -A + git commit -m "Release v1.0.1" + git push origin main + git push shiftring main + ``` + +### 3.4 저장소 정보 (단일 저장소 전략) +- **메인 저장소**: `https://git.webpluss.net/sanjeok77/ShiftRing.git` +- **역할**: 코드 관리 + APK 릴리즈 (통합) +- **Git Remote 설정**: + ```bash + git remote add origin https://git.webpluss.net/sanjeok77/ShiftRing.git + ``` + +### 3.5 업데이트 체크 로직 (AppUpdateManager.kt) +```kotlin +object AppUpdateManager { + private const val VERSION_URL = "https://git.webpluss.net/sanjeok77/ShiftRing/version.json" + + fun checkUpdate(activity: Activity, silent: Boolean = false) { + // version.json에서 최신 버전 확인 + // 새 버전 있으면 다이얼로그 표시 → APK 다운로드 → 설치 + } +} +``` + +--- + +## 4. UI/UX 디자인 가이드 (One UI 8.x Focus) +- **Aesthetics**: Glassmorphism 및 Mesh Gradient 기반의 프리미엄 디자인 + 28dp 표준 곡률 적용. +- **Pill-Style Grid**: 달력의 근무 표시(주/석/야 등)는 텍스트만 표시하지 않고, 고유 색상이 적용된 'Pill(알약)' 형태의 배경을 사용하여 시인성을 극대화한다. +- **Header System**: 모든 화면의 상단에는 32sp 크기의 볼드체 타이틀과 충분한 수직 여백(32dp padding top)을 갖춘 헤더를 배치한다. +- **Spacing Rule**: 달력 내부 메모 및 텍스트는 `includeFontPadding = false`를 적용하여 수직 간격을 최소화하고 정보 밀도를 높인다. +- **Iconography**: **Lucide Icons** 스타일의 SVG(VectorDrawable)만 사용 (`ic_` 접두사). + +--- + +## 5. 현재 버전 (v1.0.2) 주요 변경 사항 +- **One UI 8.x 정체성 확립**: 단순 테마 적용을 넘어, 대형 헤더와 28dp 곡률 시스템을 앱 전체 레이아웃에 통합. +- **고가독성 달력 시스템**: 격자 테두리를 제거하고 알약 형태의 근무 인디케이터를 적용하여 훨씬 깔끔한 그리드 구현. +- **통합 디자인 언어**: 메인, 설정, 공지사항, 매뉴얼 등 모든 액티비티의 헤더와 패널 스타일을 통일. +- **알람 엔진 안정화**: `setAlarmClock` 기반의 Doze 모드 완벽 대응 로직 유지 및 성능 최적화. + +--- +*(이 지침서는 AI 에이전트 간의 일관된 개발을 위한 핵심 문서임)* diff --git a/app.apk b/app.apk new file mode 100644 index 0000000..383a301 Binary files /dev/null and b/app.apk differ diff --git a/app/CROSS_VERSION_REPORT.md b/app/CROSS_VERSION_REPORT.md new file mode 100644 index 0000000..e162453 --- /dev/null +++ b/app/CROSS_VERSION_REPORT.md @@ -0,0 +1,241 @@ +# 📱 Cross-Version Alarm Accuracy Report (Android 8.0 ~ 14) +**Period**: 2026-02-01 ~ 2026-03-31 +**Scenario**: Jeonju Factory - Team C (Standard) + +| Date | Shift | Alarm Time | Android Version | Simulation Result (API Behavior) | +|---|---|---|---|---| +| 2026-02-01 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-02-02 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-02-03 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-03 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-03 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-03 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-03 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-04 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-04 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-04 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-04 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-04 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-05 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-05 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-05 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-05 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-05 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-06 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-06 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-06 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-06 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-06 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-07 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-07 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-07 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-07 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-07 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-08 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-02-09 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-09 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-09 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-09 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-09 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-10 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-10 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-10 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-10 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-10 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-11 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-11 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-11 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-11 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-11 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-12 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-12 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-12 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-12 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-12 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-13 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-13 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-13 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-13 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-13 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-14 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-02-15 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-02-16 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-16 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-16 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-16 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-16 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-17 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-17 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-17 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-17 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-17 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-18 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-18 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-18 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-18 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-18 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-19 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-19 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-19 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-19 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-19 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-20 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-20 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-20 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-20 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-20 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-21 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-02-22 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-02-23 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-23 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-23 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-23 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-23 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-24 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-24 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-24 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-24 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-24 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-25 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-25 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-25 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-25 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-25 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-26 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-26 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-26 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-26 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-26 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-27 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-27 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-27 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-27 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-27 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-02-28 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-01 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-01 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-01 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-01 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-01 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-02 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-02 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-02 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-02 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-02 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-03 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-03 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-03 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-03 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-03 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-04 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-04 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-04 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-04 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-04 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-05 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-05 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-05 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-05 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-05 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-06 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-07 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-08 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-08 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-08 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-08 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-08 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-09 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-09 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-09 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-09 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-09 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-10 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-10 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-10 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-10 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-10 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-11 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-11 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-11 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-11 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-11 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-12 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-12 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-12 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-12 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-12 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-13 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-14 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-15 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-15 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-15 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-15 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-15 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-16 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-16 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-16 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-16 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-16 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-17 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-17 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-17 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-17 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-17 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-18 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-18 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-18 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-18 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-18 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-19 | 야간 | **22:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-19 | 야간 | **22:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-19 | 야간 | **22:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-19 | 야간 | **22:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-19 | 야간 | **22:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-20 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-21 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-21 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-21 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-21 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-21 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-22 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-22 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-22 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-22 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-22 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-23 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-23 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-23 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-23 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-23 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-24 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-24 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-24 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-24 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-24 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-25 | 석간 | **14:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-25 | 석간 | **14:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-25 | 석간 | **14:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-25 | 석간 | **14:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-25 | 석간 | **14:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-26 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-27 | 휴무 | - | All Versions | No Alarm Scheduled (OFF) | +| 2026-03-28 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-28 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-28 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-28 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-28 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-29 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-29 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-29 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-29 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-29 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-30 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-30 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-30 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-30 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-30 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-31 | 주간 | **06:00** | Android 8.0 (Oreo) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-31 | 주간 | **06:00** | Android 10 (Q) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: None | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-31 | 주간 | **06:00** | Android 12 (S) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-31 | 주간 | **06:00** | Android 13 (T) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | +| 2026-03-31 | 주간 | **06:00** | Android 14 (U) | Using AlarmManager.setAlarmClock (Reliable, shows icon) | Flags: FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE | Perms: SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS | Doze: Bypasses Doze Mode (Highest Priority) | diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..c0df917 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,88 @@ +import java.util.Properties + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") +} + +val keystoreProperties = Properties() +val keystorePropertiesFile = file("${project.rootDir}/keystore.properties") +if (keystorePropertiesFile.exists()) { + keystorePropertiesFile.inputStream().use { keystoreProperties.load(it) } +} + +android { + namespace = "com.example.shiftalarm" + compileSdk = 35 + + defaultConfig { + applicationId = "com.example.shiftalarm" + minSdk = 26 + targetSdk = 35 + versionCode = 1119 + versionName = "1.1.9" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + signingConfigs { + create("release") { + storeFile = file(keystoreProperties.getProperty("storeFile", "../release.jks")) + storePassword = keystoreProperties.getProperty("storePassword", "dummy") + keyAlias = keystoreProperties.getProperty("keyAlias", "dummy") + keyPassword = keystoreProperties.getProperty("keyPassword", "dummy") + } + } + + buildTypes { + release { + signingConfig = signingConfigs.getByName("release") + isMinifyEnabled = false + isShrinkResources = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + viewBinding = true + } +} + +dependencies { + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.11.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + + // WorkManager (Crucial for reliable background tasks) + val work_version = "2.9.0" + implementation("androidx.work:work-runtime-ktx:$work_version") + + // Activity & Lifecycle + implementation("androidx.activity:activity-ktx:1.8.2") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0") + + // Room Database + val room_version = "2.6.1" + implementation("androidx.room:room-runtime:$room_version") + implementation("androidx.room:room-ktx:$room_version") + kapt("androidx.room:room-compiler:$room_version") + + // Kotlin Coroutines + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") + + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..6acf868 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,42 @@ +# ProGuard rules for ShiftAlarm App + +# 1. Android Entry Points (Names only) +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgent +-keep public class * extends android.preference.Preference + +# 2. Room Database & Entities +-keep @androidx.room.Entity class * { *; } +-keep interface * extends androidx.room.RoomDatabase { *; } +-keep class * extends androidx.room.RoomDatabase { *; } +-keep @androidx.room.Dao interface * { *; } +-keep class * implements com.example.shiftalarm.ShiftDao { *; } + +# 3. WorkManager +-keep class * extends androidx.work.ListenableWorker { + (android.content.Context, androidx.work.WorkerParameters); +} + +# 4. ViewBinding / UI +-keep class * implements androidx.viewbinding.ViewBinding { *; } + +# 5. Metadata for Stacktraces and Debugging +-keepattributes Signature, *Annotation*, EnclosingMethod, InnerClasses, SourceFile, LineNumberTable + +# 6. JSON / Serialization (if any) +-keepclassmembers class * { + @com.google.gson.annotations.SerializedName ; +} + +# 7. Kotlin Coroutines +-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {} +-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {} +-dontwarn kotlinx.coroutines.** + +# 8. Suppress general warnings +-dontwarn javax.lang.model.element.Modifier +-dontwarn androidx.room.paging.** diff --git a/app/simulation_result.md b/app/simulation_result.md new file mode 100644 index 0000000..482200e --- /dev/null +++ b/app/simulation_result.md @@ -0,0 +1,191 @@ +# ShiftRing Alarm Logic Simulation V2 (Robust) +Period: 2026-02-01 ~ 2026-03-31 + +### Simulation Report: User 1 (Jeonju-C Standard) (Jeonju - Team C) +| Date | Day | Shift | Alarm Time | Status | Logic Check | +|---|---|---|---|---|---| +| 2026-02-01 | Sun | 휴무 | - | OFF | OK | +| 2026-02-02 | Mon | 휴무 | - | OFF | OK | +| 2026-02-03 | Tue | 야간 | 22:00 | ON | OK | +| 2026-02-04 | Wed | 야간 | 22:00 | ON | OK | +| 2026-02-05 | Thu | 야간 | 22:00 | ON | OK | +| 2026-02-06 | Fri | 야간 | 22:00 | ON | OK | +| 2026-02-07 | Sat | 야간 | 22:00 | ON | OK | +| 2026-02-08 | Sun | 휴무 | - | OFF | OK | +| 2026-02-09 | Mon | 석간 | 14:00 | ON | OK | +| 2026-02-10 | Tue | 석간 | 14:00 | ON | OK | +| 2026-02-11 | Wed | 석간 | 14:00 | ON | OK HOLIDAY | +| 2026-02-12 | Thu | 석간 | 14:00 | ON | OK | +| 2026-02-13 | Fri | 석간 | 14:00 | ON | OK | +| 2026-02-14 | Sat | 휴무 | - | OFF | OK | +| 2026-02-15 | Sun | 휴무 | - | OFF | OK | +| 2026-02-16 | Mon | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-17 | Tue | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-18 | Wed | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-19 | Thu | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-20 | Fri | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-21 | Sat | 휴무 | - | OFF | OK | +| 2026-02-22 | Sun | 휴무 | - | OFF | OK | +| 2026-02-23 | Mon | 야간 | 22:00 | ON | OK | +| 2026-02-24 | Tue | 야간 | 22:00 | ON | OK | +| 2026-02-25 | Wed | 야간 | 22:00 | ON | OK | +| 2026-02-26 | Thu | 야간 | 22:00 | ON | OK | +| 2026-02-27 | Fri | 야간 | 22:00 | ON | OK | +| 2026-02-28 | Sat | 휴무 | - | OFF | OK | +| 2026-03-01 | Sun | 석간 | 14:00 | ON | OK HOLIDAY | +| 2026-03-02 | Mon | 석간 | 14:00 | ON | OK | +| 2026-03-03 | Tue | 석간 | 14:00 | ON | OK | +| 2026-03-04 | Wed | 석간 | 14:00 | ON | OK | +| 2026-03-05 | Thu | 석간 | 14:00 | ON | OK | +| 2026-03-06 | Fri | 휴무 | - | OFF | OK | +| 2026-03-07 | Sat | 휴무 | - | OFF | OK | +| 2026-03-08 | Sun | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-09 | Mon | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-10 | Tue | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-11 | Wed | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-12 | Thu | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-13 | Fri | 휴무 | - | OFF | OK | +| 2026-03-14 | Sat | 휴무 | - | OFF | OK | +| 2026-03-15 | Sun | 야간 | 22:00 | ON | OK | +| 2026-03-16 | Mon | 야간 | 22:00 | ON | OK | +| 2026-03-17 | Tue | 야간 | 22:00 | ON | OK | +| 2026-03-18 | Wed | 야간 | 22:00 | ON | OK | +| 2026-03-19 | Thu | 야간 | 22:00 | ON | OK | +| 2026-03-20 | Fri | 휴무 | - | OFF | OK | +| 2026-03-21 | Sat | 석간 | 14:00 | ON | OK | +| 2026-03-22 | Sun | 석간 | 14:00 | ON | OK | +| 2026-03-23 | Mon | 석간 | 14:00 | ON | OK | +| 2026-03-24 | Tue | 석간 | 14:00 | ON | OK | +| 2026-03-25 | Wed | 석간 | 14:00 | ON | OK | +| 2026-03-26 | Thu | 휴무 | - | OFF | OK | +| 2026-03-27 | Fri | 휴무 | - | OFF | OK | +| 2026-03-28 | Sat | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-29 | Sun | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-30 | Mon | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-31 | Tue | 주간 | 06:00 | ON | Valid (Default) | + +### Simulation Report: User 2 (Nonsan-A Standard) (Nonsan - Team A) +| Date | Day | Shift | Alarm Time | Status | Logic Check | +|---|---|---|---|---|---| +| 2026-02-01 | Sun | 휴무 | - | OFF | OK | +| 2026-02-02 | Mon | 석간 | 15:00 | ON | OK | +| 2026-02-03 | Tue | 석간 | 15:00 | ON | OK | +| 2026-02-04 | Wed | 석간 | 15:00 | ON | OK | +| 2026-02-05 | Thu | 석간 | 15:00 | ON | OK | +| 2026-02-06 | Fri | 석간 | 15:00 | ON | OK | +| 2026-02-07 | Sat | 휴무 | - | OFF | OK | +| 2026-02-08 | Sun | 휴무 | - | OFF | OK | +| 2026-02-09 | Mon | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-02-10 | Tue | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-02-11 | Wed | 주간 | 07:00 | ON | Valid (Nonsan) HOLIDAY | +| 2026-02-12 | Thu | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-02-13 | Fri | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-02-14 | Sat | 휴무 | - | OFF | OK | +| 2026-02-15 | Sun | 휴무 | - | OFF | OK | +| 2026-02-16 | Mon | 야간 | 23:00 | ON | OK | +| 2026-02-17 | Tue | 야간 | 23:00 | ON | OK | +| 2026-02-18 | Wed | 야간 | 23:00 | ON | OK | +| 2026-02-19 | Thu | 야간 | 23:00 | ON | OK | +| 2026-02-20 | Fri | 야간 | 23:00 | ON | OK | +| 2026-02-21 | Sat | 휴무 | - | OFF | OK | +| 2026-02-22 | Sun | 휴무 | - | OFF | OK | +| 2026-02-23 | Mon | 석간 | 15:00 | ON | OK | +| 2026-02-24 | Tue | 석간 | 15:00 | ON | OK | +| 2026-02-25 | Wed | 석간 | 15:00 | ON | OK | +| 2026-02-26 | Thu | 석간 | 15:00 | ON | OK | +| 2026-02-27 | Fri | 석간 | 15:00 | ON | OK | +| 2026-02-28 | Sat | 휴무 | - | OFF | OK | +| 2026-03-01 | Sun | 휴무 | - | OFF | OK HOLIDAY | +| 2026-03-02 | Mon | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-03 | Tue | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-04 | Wed | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-05 | Thu | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-06 | Fri | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-07 | Sat | 휴무 | - | OFF | OK | +| 2026-03-08 | Sun | 휴무 | - | OFF | OK | +| 2026-03-09 | Mon | 야간 | 23:00 | ON | OK | +| 2026-03-10 | Tue | 야간 | 23:00 | ON | OK | +| 2026-03-11 | Wed | 야간 | 23:00 | ON | OK | +| 2026-03-12 | Thu | 야간 | 23:00 | ON | OK | +| 2026-03-13 | Fri | 야간 | 23:00 | ON | OK | +| 2026-03-14 | Sat | 휴무 | - | OFF | OK | +| 2026-03-15 | Sun | 휴무 | - | OFF | OK | +| 2026-03-16 | Mon | 석간 | 15:00 | ON | OK | +| 2026-03-17 | Tue | 석간 | 15:00 | ON | OK | +| 2026-03-18 | Wed | 석간 | 15:00 | ON | OK | +| 2026-03-19 | Thu | 석간 | 15:00 | ON | OK | +| 2026-03-20 | Fri | 석간 | 15:00 | ON | OK | +| 2026-03-21 | Sat | 휴무 | - | OFF | OK | +| 2026-03-22 | Sun | 휴무 | - | OFF | OK | +| 2026-03-23 | Mon | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-24 | Tue | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-25 | Wed | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-26 | Thu | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-27 | Fri | 주간 | 07:00 | ON | Valid (Nonsan) | +| 2026-03-28 | Sat | 휴무 | - | OFF | OK | +| 2026-03-29 | Sun | 휴무 | - | OFF | OK | +| 2026-03-30 | Mon | 야간 | 23:00 | ON | OK | +| 2026-03-31 | Tue | 야간 | 23:00 | ON | OK | + +### Simulation Report: User 3 (Jeonju-A Customizer) (Jeonju - Team A) +| Date | Day | Shift | Alarm Time | Status | Logic Check | +|---|---|---|---|---|---| +| 2026-02-01 | Sun | 석간 | 14:00 | ON | OK | +| 2026-02-02 | Mon | 석간 | 14:00 | ON | OK | +| 2026-02-03 | Tue | 석간 | 14:00 | ON | OK | +| 2026-02-04 | Wed | 휴무 | - | OFF | OK | +| 2026-02-05 | Thu | 휴무 | - | OFF | OK | +| 2026-02-06 | Fri | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-07 | Sat | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-08 | Sun | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-09 | Mon | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-10 | Tue | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-11 | Wed | 휴무 | - | OFF | OK HOLIDAY | +| 2026-02-12 | Thu | 휴무 | - | OFF | OK | +| 2026-02-13 | Fri | 야간 | 22:00 | ON | OK | +| 2026-02-14 | Sat | 휴무 | - | OFF | OK [Manual Override] | +| 2026-02-15 | Sun | 주간 | 06:00 | ON | Valid (Default) [Manual Override] | +| 2026-02-16 | Mon | 야간 | 22:00 | ON | OK | +| 2026-02-17 | Tue | 야간 | 22:00 | ON | OK | +| 2026-02-18 | Wed | 휴무 | - | OFF | OK | +| 2026-02-19 | Thu | 석간 | 14:00 | ON | OK | +| 2026-02-20 | Fri | 석간 | 05:00 | ON | OK [Date Rule] | +| 2026-02-21 | Sat | 석간 | 14:00 | ON | OK | +| 2026-02-22 | Sun | 석간 | 14:00 | ON | OK | +| 2026-02-23 | Mon | 석간 | 14:00 | ON | OK | +| 2026-02-24 | Tue | 휴무 | - | OFF | OK | +| 2026-02-25 | Wed | 휴무 | - | OFF | OK | +| 2026-02-26 | Thu | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-27 | Fri | 주간 | 06:00 | ON | Valid (Default) | +| 2026-02-28 | Sat | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-01 | Sun | 주간 | 06:00 | ON | Valid (Default) HOLIDAY | +| 2026-03-02 | Mon | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-03 | Tue | 휴무 | - | OFF | OK | +| 2026-03-04 | Wed | 휴무 | - | OFF | OK | +| 2026-03-05 | Thu | 야간 | 22:00 | ON | OK | +| 2026-03-06 | Fri | 야간 | 22:00 | ON | OK | +| 2026-03-07 | Sat | 야간 | 22:00 | ON | OK | +| 2026-03-08 | Sun | 야간 | 22:00 | ON | OK | +| 2026-03-09 | Mon | 야간 | 22:00 | ON | OK | +| 2026-03-10 | Tue | 휴무 | - | OFF | OK | +| 2026-03-11 | Wed | 석간 | 14:00 | ON | OK | +| 2026-03-12 | Thu | 석간 | 14:00 | ON | OK | +| 2026-03-13 | Fri | 석간 | 14:00 | ON | OK | +| 2026-03-14 | Sat | 석간 | 14:00 | ON | OK | +| 2026-03-15 | Sun | 석간 | 14:00 | ON | OK | +| 2026-03-16 | Mon | 휴무 | - | OFF | OK | +| 2026-03-17 | Tue | 휴무 | - | OFF | OK | +| 2026-03-18 | Wed | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-19 | Thu | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-20 | Fri | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-21 | Sat | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-22 | Sun | 주간 | 06:00 | ON | Valid (Default) | +| 2026-03-23 | Mon | 휴무 | - | OFF | OK | +| 2026-03-24 | Tue | 휴무 | - | OFF | OK | +| 2026-03-25 | Wed | 야간 | 22:00 | ON | OK | +| 2026-03-26 | Thu | 야간 | 22:00 | ON | OK | +| 2026-03-27 | Fri | 야간 | 22:00 | ON | OK | +| 2026-03-28 | Sat | 야간 | 22:00 | ON | OK | +| 2026-03-29 | Sun | 야간 | 22:00 | ON | OK | +| 2026-03-30 | Mon | 휴무 | - | OFF | OK | +| 2026-03-31 | Tue | 석간 | 14:00 | ON | OK | diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d09cf90 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/assets/CHANGELOG.md b/app/src/main/assets/CHANGELOG.md new file mode 100644 index 0000000..a74e9f7 --- /dev/null +++ b/app/src/main/assets/CHANGELOG.md @@ -0,0 +1,554 @@ +# Changelog + +## [1.1.3] - 2026-02-16 +### Added +- **앱 안정성 설정 통합**: 설정 화면에서 '배터리 최적화 제외', '다른 앱 위에 표시', '전체화면 알림' 등 알람 가동에 필수적인 권한 상태를 한눈에 확인하고 직접 설정할 수 있는 섹션 추가 +- **안드로이드 16 잠금화면 우회**: 최신 OS에서도 지문/패턴 해제 없이 알람 화면이 즉시 나타나도록 `requestDismissKeyguard` 로직 적용 및 안정성 강화 + +## [1.1.2] - 2026-02-15 +### Fixed +- **알람 삭제 버그**: 알람이 켜진 상태에서 삭제해도 알람이 울리던 문제 수정 +- **삭제 시 자동 취소**: 알람 삭제 시 시스템에 등록된 향후 모든 스케줄을 즉시 취소하도록 로직 강화 + +## [1.1.1] - 2026-02-15 +### Fixed +- **잠금 화면 위 표시**: 잠금 화면을 풀지 않아도 알람 해제 화면이 즉시 나타나도록 윈도우 플래그 및 핸들링 로직 수정 (Android 14/15 완벽 대응) +- **전체화면 권한 안내**: 권한이 누락된 경우 설정 화면으로 바로 이동하도록 안내 로직 개선 + +## [1.1.0] - 2026-02-15 +### 🚀 알람 신뢰도 100% 달성 및 시스템 고도화 +- **3단계 알람 안전장치 도입**: + - **Room DB 전환**: 사용자 알람 데이터를 SQLite 데이터베이스로 마이그레이션하여 대규모 데이터 처리 및 보존 안정성 확보 + - **AlarmClock API 최우선 순위**: 절전 모드를 무력화하는 최고 수준의 신뢰도 API 적용. 상단바 알람 아이콘 활성화로 예약 상태 가시성 확보 + - **30일 확장 동기화 엔진**: 근무 변경이나 설정 수정 시 향후 30일간의 알람을 즉시 재계산 및 예약 +- **권한 및 알림 일원화**: + - **통합 권한 센터**: 필수 권한(정확한 알람, 배터리 제외, 전체화면 알림)을 한 화면에서 순차적으로 설정할 수 있도록 흐름 개선 + - **단일 알림 포그라운드 서비스 적용**: 알람 알림이 중복되거나 지워지지 않도록 포그라운드 서비스 기반의 단일 알림 시스템 구축 +- **레거시 제거 및 최적화**: 미사용 파라미터 제거 및 알람 엔진 성능 최적화 + +## [1.0.1] - 2026-02-14 +### Added +- **프리미엄 알람 디자인**: `lock.html` 디자인을 기반으로 한 화려한 알람 화면 도입 (오로라 펄스 애니메이션, 글래스모피즘 버튼) +- **달력 년/월 휠 선택**: 달력 상단 년/월 클릭 시 휠 다이얼로 즉시 이동하는 기능 추가 +- **알람 설정 최적화**: 알람 목록 로딩 속도 개선 및 사운드 타이틀 캐싱 적용 + +### Changed +- **마스터 알람 스위치**: 거대한 카드 대신 세련된 텍스트 레이블 형태로 알람 설정 좌측 상단에 배치 +- **토글 버튼 개선**: 이질적인 회색 배경을 제거하고 부드러운 Material 3 애니메이션 스위치 적용 +- **사용 설명서 개편**: 최신 기능(년/월 피커, 신규 알람 UI 등)에 맞춰 상세 설명 업데이트 + +### Fixed +- **설정 진입 속도**: 알람 설정 탭 클릭 시 발생하던 미세한 지연 시간 단축 + +## [0.9.1] - 2026-02-11 +### Fixed +- **알람 엔진 안정화**: PendingIntent ID 충돌 및 권한 누락 안내 기능 추가 +- **배경 작업 최적화**: 부팅 후 알람 복구 로직 중복 실행 방지 및 효율성 개선 +- **보안 강화**: 앱 서명 비밀번호 분리 관리 및 루팅 기기 대응 준비 +- **시간대 통일**: 모든 알람 로직에 Asia/Seoul 표준 시간대 강제 적용 + +## [0.9.0] - 2026-02-11 +### Added +- **One UI 8 디자인 완성**: 설정 화면, 알람 설정, 공지사항 등 앱 전반에 걸쳐 One UI 8 스타일의 카드 레이아웃 및 28dp 라운딩 적용 +- **자동 업데이트 확인**: 앱 접속 시 최신 버전을 자동으로 체크하고 원클릭으로 업데이트를 수행하는 스마트 엔진 탑재 +- **UI 일관성 강화**: 모든 다이얼로그 및 팝업에 고도화된 Glassmorphism 디자인과 통일된 여백 시스템 도입 +- **상태 기반 헤더**: 메인 화면 상단에 오늘 근무 및 선택된 반 정보를 실시간으로 표시하는 다이나믹 헤더 추가 + +### Changed +- **아이콘 시스템 정밀화**: 설정 아이콘 및 액션 버튼에 Lucide Icons 스타일 적용 및 시인성 개선 +- **가독성 최적화**: 시간 선택기(TimePickerDialog)를 최신 시스템 테마로 업데이트하고 폰트 가독성 상향 + +--- + +## [0.8.0] - 2026-02-11 +### Added +- **One UI 8 스타일 적용**: Jetpack Compose 기반의 최신 삼성 One UI 8 디자인 시스템 통합 (Soft Blur, Pill-shape, Dynamic Color 지원) +- **알람 신뢰도 엔진 (Android 14+ 대응)**: 포그라운드 서비스(shortService) 및 배터리 최적화 예외 유도 로직을 통해 삼성 기기에서의 95%+ 알람 성공률 확보 +- **정확한 알람 권한 관리**: `AlarmPermissionUtil`을 통해 Android 14+ 알람/리마인더 권한 설정 인터페이스 개선 + +### Changed +- **빌드 시스템 인프라**: Jetpack Compose 및 Material 3 환경 구축 + +--- + +## [0.6.3] - 2026-02-10 +### Changed +- **리브랜딩**: 앱 전체에서 '닥잡아/dakjaba' 표기를 '교대링(Shiftring)'으로 통일 +- **달력 근무 표기 변경**: 약어(주/석/야/맞/휴) → 풀네임(주간/석간/야간/맞교대/휴무) +- **메모 표시 레이아웃 수정**: 근무 텍스트 아래에 정확히 배치되도록 마진 및 제약조건 재설정 +- **사용설명서 전면 업데이트**: 이모지 대신 Lucide 스타일 텍스트 아이콘 사용, 알람 테스트 안내 추가 +- **알림 텍스트 브랜딩**: '교대 근무 알람' → '교대링 알람' + +### Fixed +- **알람 테스트 수정**: 알람 테스트 버튼이 실제로 알람을 트리거하도록 테스트 알람 바이패스 로직 추가 + +--- + +## [0.5.8] - 2026-02-10 +### Added +- **알람 동기화 시스템 전면 재정비**: 알람이 울리기 직전 근무 종류뿐만 아니라 설정된 '시간'까지 재검증하는 2중 동기화 로직을 도입하여, 어떤 상황에서도 정확한 알람이 울리도록 개선 +### Fixed +- **다크 모드 눈 피로도 감소**: 근무별 배경색의 채도를 더 낮추고 부드러운 톤으로 조정하여 야간 사용 시 시각적 편안함 증대 +- **다크 모드 가독성 수정**: 알람 추가 및 근무 변경 팝업의 배경과 텍스트 시인성 확보 +- **버그 수정**: 야간 맞교대 근무 시 알람 시간 키값이 잘못 지정되던 문제 수정 + +--- + +## [0.5.7] - 2026-02-10 +### Fixed +- **알람 동기화 긴급 수정**: 근무가 변경된 경우 이전 알람이 울리지 않도록 수신부(AlarmReceiver)에서 현재 근무를 재검증하는 로직 추가 +- **다크 모드 팝업 시인성 개선**: 다크 모드에서 '알람 추가', '근무 변경' 팝업의 배경색이 보이지 않던 문제 수정 (테마 대응 컬러 적용) +- **근무 배경 색상 최적화**: 다크 모드에서 근무 배경색의 채도를 낮추어 눈의 피로도를 줄임 +### Changed +- **용어 통일**: '스누즈' 표기를 '다시 울림'으로 일괄 변경 + +--- + +## [0.5.6] - 2026-02-09 +### Changed +- **'오늘' 버튼 디자인 개편**: 달력 그리드 디자인과 조화로운 미니멀한 테두리 스타일로 변경 +- **가독성 개선**: 라이트 모드에서 시인성이 낮았던 민트색 섹션 제목을 시인성이 높은 진보라색으로 변경하여 가독성 향상 + +--- + +## [0.5.5] - 2026-02-09 +### Changed +- **설정 화면 레이아웃 최적화**: '회사 선택'과 '반 선택'을 한 행에 2열 그리드로 배치하여 공간 효율성 개선 +- **용어 순화 및 변경**: 알람 설정 내 '스누즈 및 소리'를 사용자 친화적인 '다시 울림 및 소리'로 명칭 변경 + +--- + +## [0.5.4] - 2026-02-09 +### Fixed +- **다크 모드 빈 격자 색상 수정**: 달력 시작/종료 전후의 빈 격자가 다크 모드에서도 테마에 맞는 색상으로 표시되도록 수정 +### Improved +- **공간 활용성 극대화**: 각 격자의 높이를 상향(82dp) 조정하여, 하단의 남는 공간을 최소화하고 화면을 더 꽉 차게 보이도록 개선 + +--- + +## [0.5.3] - 2026-02-09 +### Fixed +- **다크 모드 완벽 지원**: 하드코딩된 색상을 테마 리소스(bg_grid_cell_default, grid_divider 등)로 교체하여 다크 모드에서도 달력이 정상적으로 표시되도록 수정 +- **사용자 편의성 강화**: 메인 화면의 알람 시간 표시 영역을 터치하면 즉시 알람 설정 화면으로 이동하도록 개선 + +--- + +## [0.5.2] - 2026-02-09 +### Added +- **그리드 완성도 향상**: 달력 시작일 이전의 빈 공간에도 격자선을 표시하여 디자인적 일관성 확보 +- **가독성 최적화**: 근무 표시 글자 크기 확대 및 격자 높이 상향 (66dp) +- **UI 시각적 개선**: '오늘' 버튼 디자인 개선 및 배경색/테두리 최적화 +- **대비 및 명시성 강화**: 흰색 텍스트가 잘 보이지 않던 팀(A반)의 배경색을 더욱 진하게 조정 +- **오늘 강조 변경**: 오늘 날짜를 연한 파란색 배경으로 강조하여 시각적 직관성 제공 + +--- + +## [0.5.1] - 2026-02-09 +### Added +- **격자 디자인 고도화**: 일반 달력처럼 배경을 흰색으로 변경하고, 근무 표시(주, 석, 야 등)에만 개별 배경색 적용 +- **공휴일 정보 통합**: 교대 달력 모드에서도 근무 표시 옆에 공휴일 이름을 함께 표시 +- **화면 실용성 극대화**: 상단 헤더 및 알람바 높이를 축소하여 6주 달력도 스크롤 없이 한 화면에 표시 +- **가독성 개선**: 근무 글자를 칸 좌측 상단 모서리에 밀착 배치하고 최적화된 글자 크기 적용 + +--- + +## [0.5.0] - 2026-02-09 +### Added +- **달력 디자인 전면 개편**: 카드 스타일에서 세련된 격자(Grid) 스타일로 변경 +- **근무 표기 최적화**: 좌측 상단에 한 글자(주, 석, 야, 맞, 휴)로 직관적인 근무 표시 +- **가독성 강화**: 중앙에 큰 날짜 배치 및 날짜 옆 작은 공휴일 마커 추가 +- **색상 체계 변경**: 주간(레몬), 석간(회색), 야간(검정), 휴무(빨강), 맞교대(보라)로 배경색 구분 +- **전체 화면 최적화**: 불필요한 여백을 제거하고 화면을 최대한 활용하도록 레이아웃 수정 + +--- + +## [0.4.4] - 2026-02-09 +### Changed +- **달력 행 수 최적화**: 1~4주만 필요한 달은 5행(35셀)만 표시하고 스크롤 없이 고정, 5주 이상 필요한 달만 6행(42셀)으로 스크롤 활성화 +- **안전한 최적화 방식**: 레이아웃 높이 수정 없이, 데이터 패딩과 스크롤 설정만 조정하여 해상도에 관계없이 안정적으로 동작 + +--- + +## [0.4.3] - 2026-02-09 +### Fixed +- **달력 화면 완전 복원**: 0.3.9 안정 버전의 달력 코드로 완전 롤백하여 달력이 보이지 않던 문제를 완벽하게 해결 +- **해상도 최적화 이슈 제거**: 불안정한 동적 높이 조절 로직을 모두 제거하고 검증된 고정 레이아웃으로 복원 + +--- + +## [0.4.2] - 2026-02-09 +### Fixed +- **달력 화면 완전 복구**: 달력 항목의 높이를 70dp로 명시적으로 고정하여, 일부 기기에서 레이아웃 측정 오류로 달력 내용이 보이지 않던 문제를 완벽하게 해결 +- **스크롤 기능 강화**: 모든 해상도에서 화면 잘림 없이 달력을 확인할 수 있도록 스크롤 기능 상시 활성화 유지 + +--- + +## [0.4.1] - 2026-02-09 +### Fixed +- **스크롤 제한 긴급 수정**: 작은 화면의 기기에서 달력 하단이 잘리는 현상을 수정하기 위해 스크롤 기능을 상시 활성화 +- **달력 레이아웃 안정화**: 해상도 최적화 로직의 일부 불안정성을 제거하고 표준 높이(68dp)로 복구하여 안정성 확보 + +--- + +## [0.4.0] - 2026-02-09 +### Added +- **버전 넘버링 체계 확립**: Patch가 9를 넘으면 Minor를 올리는 규칙 적용 (0.3.9 -> 0.4.0) +- **해상도별 달력 최적화**: 5행 달력은 스크롤 없이 고정하고, 6행일 때만 스크롤되도록 고도화 +- **레이아웃 안정성**: 다양한 해상도의 폰에서도 달력 모양이 일정하게 유지되도록 수정 + +### Fixed +- **메인 공간 및 UI 개선**: 0.3.10의 변경사항(헤더 축소, 버튼 강조 등)을 정식 반영 + +--- + +## [0.3.9] - 2026-02-09 +### Added +- **오늘 버튼 동작 개선**: 달력에서 '오늘' 클릭 시 보고 있던 조와 상관없이 나의 본래 조와 오늘 날짜 달력으로 즉시 복귀 +- **사용자 알람 연동 버그 수정**: 이제 사용자 알람 추가/수정 시에도 오늘 근무표를 확인하여 본인 근무와 일치할 때만 스케줄링되도록 수정 + +### Fixed +- **업데이트 내역 가독성**: 변경사항 목록 하단에 불필요하게 표시되던 구분선(-) 제거 + +### Changed +- **기본 설정 가독성**: 회사/반 선택 레이블 폰트 크기 확대 및 굵게 표시하여 식별력 강화 + +--- + +## [v0.6.0] - 2026-02-12 +### Added +- **Major Rebranding**: App name changed to **"교대링" (Shiftring)** with English locale support. +- **Room Database Migration**: Replaced `SharedPreferences` with Room DB for robust storage of shift overrides and memos. +- **Daily Memos**: Added ability to save and view daily notes on the calendar. +- **Lucide Icons**: Integrated modern Lucide iconography system across the app. +- **Advanced Alarm Synchronization**: Reliable "double-check" system ensuring alarms match current shift and time preferences. +- **Additional Features Tab**: New section in settings for upcoming capabilities. + +### Fixed +- **Dark Mode Visibility**: Improved "Night" (야간) shift visibility and dialog accessibility in dark theme. +- **Coroutines & Performance**: Refactored database operations to use Coroutines for smoother UI performance. +- **Icon Prefix**: Standardized all icons with `ic_` prefix. + +--- + +## [0.3.8] - 2026-02-09 +### Added +- **지난 알람 숨김**: 오늘 이미 시간이 지난 사용자 알람은 달력 화면에서 표시되지 않도록 개선 +- **가독성 향상**: 라이트 모드에서도 알람 시간이 잘 보이도록 색상 및 굵기 개선 + +### Updated +- **사용 설명서 개편**: 최신 기능 반영 및 불필요한 서식을 제거하여 깔끔하게 정리 + +--- + +## [0.3.7] - 2026-02-09 +### Added +- **사용자 알람 근무표 연동**: 기타를 제외한 사용자 알람이 나의 근무표와 연동 (예: 주간 선택 시 주간 날에만 울림) +- **달력 팀 표시 개선**: 다이얼로그에서 나의 반 표시 시 "(나)" 추가 + +### Changed +- **알람 표시 개선**: (사용자) 텍스트 제거, 색상으로 구분 +- **여러 알람 표시**: 3개 이하면 모두 표시, 초과 시 "XX:XX 외 N개" 형식 +- **설정 섹션 타이틀 강화**: 글자 크기 16sp로 확대, 굵게 표시 + +--- + +## [0.3.6] - 2026-02-09 +### Added +- **사용자 알람 실제 작동**: 사용자 알람이 실제로 울리도록 알람 스케줄링 구현 +- **알람 수정 기능**: 사용자 알람에 수정 버튼 추가 +- **달력 알람 표시 개선**: 사용자 알람이 근무 알람보다 빠르면 함께 표시 + +### Fixed +- **알람 신뢰성 강화**: 알람 추가 시 즉시 스케줄링되도록 개선 + +### Changed +- **근무별 알람시간 레이블 굵게 표시**: 주간/석간/야간/야맞 레이블을 굵게 표시 + +--- + +## [0.3.5] - 2026-02-09 +### Added +- **사용자 알람 추가**: 알람 설정에서 '+ 알람 추가' 버튼으로 사용자 정의 알람 등록 가능 +- **시간 및 근무 유형 선택**: 사용자 알람 추가 시 시간과 근무 유형(주간/석간/야간/기타) 설정 + +### Fixed +- **공지사항 버전 표시 수정**: 업데이트 내역에서 버전명이 정확하게 파싱되도록 로직 전면 개선 + +--- + +## [0.3.4] - 2026-02-09 +### Improved +- **공지사항 버전 파싱 개선**: 업데이트 내역 상단에 버전명이 더 정확하게 표시되도록 로직 보강 +- **사용 설명서 버전 자동화**: 설명서 상단의 앱 버전이 하드코딩 대신 현재 설치된 버전으로 자동 표시 +- **날짜 숫자 크기 확대**: 달력 날짜 숫자를 더 크게(12sp) 키워 가독성 향상 + +--- + +## [0.3.3] - 2026-02-09 +### Fixed +- **달력 스와이프 감도 개선**: RecyclerView 터치 간섭 문제를 해결하기 위해 `addOnItemTouchListener` 적용 +- **스와이프 영역 확대**: 달력 내부뿐만 아니라 달력 컨테이너 전체에서 스와이프 제스처가 작동하도록 개선 + +--- + +## [0.3.2] - 2026-02-08 +### Fixed +- **업데이트 내역 버전 파싱 수정**: 버전 번호가 정확하게 표시되도록 정규표현식 파싱 적용 +- **근무 변경 팝업 불투명도 향상**: 배경 글자가 비치지 않도록 95% 불투명도 적용 +- **공휴일/음력 표시 개선**: 카드 중앙에 크게 표시, 생략(...)없이 전체 표시 +- **설명서 불필요한 내용 제거**: 알람 프라이버시 설명 삭제 (본인 폰에만 설정되므로 불필요) + +--- + +## [0.3.1] - 2026-02-08 +### Improved +- **용어 통일**: '조' 표기를 '반'으로 전체 통일 (다른 반 근무, 설명서, 메뉴 등) +- **업데이트 내역 버전 표기**: 공지사항에 'v0.3.1 업데이트 내용' 형식으로 버전 표시 +- **공휴일 글자 크게 표시**: 공휴일/음력 날짜 텍스트를 13sp 굵은 글씨로 표시 +- **사용 설명서 최신화**: v0.3.1 기준 최신 기능 및 용어 반영 + +--- + +## [0.3.0] - 2026-02-08 +### Improved +- **공휴일 체크 위치 고정**: 다른 조 달력 조회 시에도 공휴일 체크박스가 우측에 고정 +- **음력 날짜 표시 개선**: 12.25 형식의 음력 날짜가 생략 없이 전체 표시 +- **설명서 UI 통일**: 공지사항과 동일한 핑크 카드 스타일로 변경 +- **공지사항 UI 업그레이드**: 메시 그라디언트 배경과 세련된 헤더 카드 적용 +- **전체 UI/UX 통일감 강화**: 앱 전반에 걸쳐 일관된 디자인 언어 적용 + +--- + +## [0.2.9] - 2026-02-08 +### Improved +- **공휴일 글자 크게 표시**: 공휴일 명칭도 근무 글자와 동일하게 크게 (14sp) 표시 +- **다시 울림 옵션 추가**: 1분, 3분 스누즈 간격 추가 (총 8개 옵션) +- **알람 표시 개선**: 다른 조 달력 조회 시 알람 영역 완전히 숨김 처리 +- **공지사항 표시 제한**: 최대 7개 항목만 표시하여 가독성 향상 +- **사용 설명서 최신화**: v0.2.9 기준 모든 기능 반영 + +--- + +## [0.2.8] - 2026-02-08 +### Improved +- **달력 근무 텍스트 대폭 확대**: 주간, 석간, 야간 등 근무 글자를 16sp로 키워 가독성 극대화 +- **기본 달력 모드 변경**: 앱 실행 시 '교대달력'이 기본으로 표시 (공휴일 체크 해제 상태) +- **달력 레이아웃 균등 배분**: 날짜, 근무, 음력이 균등하게 배치되어 깔끔한 정렬 +- **알람 표시 개선**: 다른 조 달력 조회 시 알람 시간이 표시되지 않음 (내 조만 알람 표시) +- **오늘 날짜 강조**: 오늘 날짜에 파란색 테두리로 눈에 띄게 표시 +- **사용 설명서 UI 전면 개편**: Glassmorphism 3.0 디자인 적용, 앱 아이콘 헤더, 글래스 카드 스타일 + +--- + +## [0.2.7] - 2026-02-08 +### Fixed +- **체크 표시 로직 수정**: 근무 중인 날에는 V 체크 표시가 나타나지 않도록 수정 (휴무/휴가일에만 표시) +- **사용 설명서 업데이트**: 최신 앱 기능(글래스모피즘 3.0, 탭 설정, 오늘 이동 등) 반영 및 갱신 + +--- + +## [0.2.6] - 2026-02-08 +### Added +- **공휴일 모드**: '공휴일' 체크 시 근무 표시를 숨기고 공휴일 명칭만 표시 (일반 달력 모드) +- **근무 변경 팝업 디자인**: 근무 변경 화면에 Glassmorphism 3.0 디자인 적용 + +--- + +## [0.2.5] - 2026-02-08 +### Fixed +- **용어 수정**: '근무표 직접 수정' 버튼 명칭을 **'사용 설명서'**로 정정 (기능과 명칭 불일치 해결) + +--- + +## [0.2.4] - 2026-02-08 +### Fixed +- **다크 모드 가독성 개선**: 닫기 버튼 및 달력 날짜 텍스트 가독성 향상 +- **UI/UX 개선**: 달력에 오늘 날짜로 이동하는 버튼 추가 +- **디자인 수정**: 공휴일 체크 방식 변경 (V 체크 표시) 및 글래스모피즘 효과 강화 +- **용어 수정**: '직접 입력 관리' → '근무표 직접 수정'으로 변경하여 이해도 향상 + +--- + +## [0.2.3] - 2026-02-08 +### Changed +- **디자인 업그레이드 (Glassmorphism 3.0)**: 더욱 아름답고 세련된 반투명 디자인 적용 +- **설정 화면 개편**: 기본 설정과 알람 설정 탭으로 분리하여 사용성 강화 +- **완전 한글화**: 달력 요일 및 설정 메뉴 100% 한글 적용 +- **회사 명칭 간소화**: '모나리자 전주' → '전주', '모나리자 논산' → '논산'으로 변경 + +### Fixed +- **알람 시간 초기화**: 회사 변경 시 해당 회사의 기본 출근 시간으로 자동 변경 + +--- + +## [0.2.2] - 2026-02-08 +### Added +- **다크/라이트 모드 지원**: 설정 > 화면 테마에서 시스템/다크/라이트 모드 선택 가능 +- **업데이트 내역 실시간 동기화**: 앱 내 변경사항이 서버와 즉시 연동되도록 개선 + +### Changed +- **용어 수정**: '공장' → '회사', '스누즈' → '다시 울림'으로 변경하여 친숙함 강화 +- **UI 개선**: 알람 화면 '미루기' 버튼 가독성 향상 및 텍스트 수정 +- **설정 화면**: 하단에 앱 버전 정보 및 제작자(산적이얌) 표시 추가 + +--- + +## [0.2.1] - 2026-02-08 +### Changed (UI Overhaul - Glassmorphism 2.0) +- **전체 디자인 리뉴얼**: 고급스러운 메쉬 그라데이션(Deep Purple-Blue) 배경 적용 +- **설정 화면 개선**: 알람 시간 버튼 색상을 투명한 글래스 스타일로 변경하여 가독성 대폭 향상 +- **메인 캘린더**: 투명 카드 UI 적용, 텍스트 색상을 배경에 맞춰 화이트 톤으로 최적화 +- **알람 화면**: 슬라이더 및 시간 표시 가독성 개선, 부드러운 글래스 패널 적용 +- **세부 디테일**: 섹션 타이틀 영문 표기, 아이콘 및 버튼 스타일 통일 + +--- + +## [0.2.0] - 2026-02-08 +### Changed +- **스누즈 메시지 개선**: "스누즈 설정됨" → "X분 뒤 다시 울림" 형태로 설정된 시간 표시 +- **알람 화면 글래스모피즘 적용**: 반투명 카드, 슬라이더, 썸네일에 부드러운 투명도 효과 +- **알람 화면 배경 개선**: 다크 블루 그라데이션 팔레트로 세련됨 향상 +- **설정 화면 버튼 개선**: 진한 색상을 부드러운 글래스모피즘 스타일로 변경 +- **스누즈 슬라이더에 시간 표시**: 알람 화면에서 설정된 스누즈 시간을 바로 확인 가능 + +--- + +## [0.1.9] - 2026-02-08 +### Changed +- 알람 화면: 알람 끄기(빨간색)를 위로, 스누즈(파란색)를 아래로 위치 변경 +- 설정 화면: 글래스모피즘 디자인 적용 (반투명 카드, 부드러운 그라데이션 배경) +- 설정 화면: 이모지 대신 안드로이드 시스템 아이콘으로 대체하여 세련됨 향상 +- 사용설명서: 한글 깨짐 수정 및 알람 해제 방법 내용 추가 +- 변경사항: 불필요한 구분선 및 빈 불릿 필터링으로 가독성 개선 + +--- + +## [0.1.8] - 2026-02-08 +### Changed +- **설정 화면 전면 개편**: 섹션별 카드 분리, 구분선 및 여백 적용으로 가독성 대폭 개선 +- **알람 화면 UI 고도화**: + - 그라데이션 배경 및 대형 시간 표시로 프리미엄 느낌 강화 + - 스누즈(블루) / 해제(레드) 슬라이더 색상 분리로 직관성 향상 + - 슬라이더 핸들 디자인 고급화 (원형 + 중심 컬러) + +--- + +## [0.1.7] - 2026-02-08 +### Added +- **슬라이더 방식 알람 UI**: 아이폰/갤럭시 스타일의 '밀어서 해제/스누즈' UI 도입 + - **스누즈 (좌→우)**: 상단 슬라이더를 밀어서 잠시 미룸 + - **알람 해제 (우→좌)**: 하단 슬라이더를 밀어서 정지 +- **디자인 고도화**: 시각적인 조작 가이드(트랙 및 핸들)를 적용하여 직관성 및 미관 대폭 개선 + +--- + +## [0.1.6] - 2026-02-08 +### Fixed +- 알람 화면 긴급 수정: 버튼 대신 **스와이프 전용 레이아웃** 도입 (우→좌: 정지, 좌→우: 스누즈) +- 화면 켜짐 보장: 잠금 화면에서도 알람 시 즉시 화면이 켜지도록 로직 강화 +- 논산 야맞 알람 오류: 출근 시간(20:00) 1시간 전인 **19:00**에 알람이 기본 설정되도록 수정 +- 축약어 적용: '다른 조 오늘 근무' 섹션에서도 '야간 맞교대' 대신 **'야맞'**으로 통일 + +### Added +- 알람 화면에 현재 시간 표시 및 스와이프 안내 가이드 추가 + +--- + +## [0.1.5] - 2026-02-08 +### Added +- 알람 스와이프 제스처 기능: **우→좌(알람 정지)**, **좌→우(스누즈)** +- 알람 시 화면 자동 켜짐 및 잠금화면 표시 기능 강화 +- 변경사항(Notice) 화면에 '닫기' 버튼 추가 + +### Changed +- 논산 공장 야간 맞교대(야맞) 기본 시간을 **20:00**으로 조정 및 라벨 업데이트 +- 달력 내 '야간 맞교대' 표기를 **'야맞'**으로 축약하여 가독성 개선 +- 5행 달력의 스크롤을 완전히 고정하여 불필요한 움직임 제거 +- 달력 제목 형식을 연.월(예: 2026.02)로 변경하여 더 깔끔하게 개선 + +### Fixed +- 스누즈 버튼 클릭 시 알람이 즉시 다시 울리던 현상 수정 +- 알람 정지 시 상단 바 알림이 사라지지 않던 문제 해결 + +--- + +## [0.1.4] - 2026-02-08 +### Added +- 고급스러운 디자인 시스템 적용 (카드 곡률, 현대적 컬러 팔레트) +- 알람 테스트 기능 구현 (설정 > 5초 후 테스트 알람) +- 사용설명서 앱 내 뷰어 연동 및 최신 내용 반영 + +### Changed +- 달력 줄 수(5행/6행)에 따른 상하 스크롤 자동 제어 +- 체인지로그 표시 시 불필요한 마크다운 기호를 제거하여 가독성 향상 +- 설정 화면의 '깃허브 다운로드' 버튼 제거 (앱 내 업데이트로 통일) + +### Fixed +- 음력 날짜가 표시되지 않거나 부정확하던 문제 수정 +- 메인 화면 상단 알람 정보의 실시간 반영 로직 개선 + +--- + +## [0.1.3] - 2026-02-08 +### Added +- 설정 내 '변경사항' 메뉴가 실제 CHANGELOG 내용을 표시하도록 연동 +- '직접 입력' 근무 설정 시 알람 시간을 즉시 입력받도록 개선 + +### Changed +- '오늘 다른 조' 표시를 모든 팀(전주 4개, 논산 3개)이 보이도록 복원 +- 일별 근무 변경 시 표준 근무(주간/석간/야간/야맞)는 설정된 시간을 즉시 적용하도록 간소화 +- 야간 맞교대(야맞) 알람 기본 시간을 공장별로 차별화 (논산: 19:00, 전주: 18:00) + +### Fixed +- 야간 맞교대 시간 설정이 저장되지 않던 문제 수정 + +--- + +## [0.1.2] - 2026-02-08 +### Added +- 앱 내 직접 APK 다운로드 및 설치 기능 (진행률 표시 포함) +- 스와이프 제스처로 캘린더 월 탐색 기능 + +### Changed +- '오늘 다른 조' 표시를 현재 보고 있는 팀 제외한 팀만 표시하도록 간소화 +- 캘린더 높이를 항상 6줄(42칸)로 고정하여 일관된 UI 제공 +- 업데이트 다운로드 방식을 웹페이지 이동에서 앱 내 직접 다운로드로 변경 + +### Fixed +- 팀 표시에서 지역명(전주/논산) 제거하여 UI 정리 + +--- + +## [0.1.1] - 2026-02-08 +### Changed +- 릴리즈 저장소 분리 (dakjaba-releases) +- 버전 체크 URL 업데이트 + +--- + +## [0.1.0] - 2026-02-08 +### Added +- 사용설명서(Manual) 메뉴 추가 +- 설정 화면 내 수동 업데이트 메뉴 개선 +- 달력 내 음력 표시 기능 추가 +- 릴리즈 빌드 서명(Signing) 적용 + +### Changed +- 알람 설정 단위를 1분으로 세분화 +- 반 선택 방식을 라디오 버튼에서 드롭다운(Spinner)으로 변경 +- 전주 D반 복구 및 공장별 맞춤형 반 선택 로직 적용 +- 하단 '오늘의 근무' 레이아웃 최적화 + +### Fixed +- 설정 변경 시 달력에 즉시 반영되지 않던 문제 수정 +- 공휴일 텍스트 잘림 현상 개선 + +--- + +## [2026-02-01] + +### Added +- 기본 알람 스케줄 엔진 + +### Fixed +- Doze 모드에서 알람 누락 문제 수정 diff --git a/app/src/main/assets/MANUAL.md b/app/src/main/assets/MANUAL.md new file mode 100644 index 0000000..ba673e5 --- /dev/null +++ b/app/src/main/assets/MANUAL.md @@ -0,0 +1,47 @@ +# 교대링(Shiftring) 상세 사용 가이드 + +본 가이드는 **교대링 v1.1.8**의 주요 기능과 설정을 안내합니다. 별도의 복잡한 설정 없이도 **자신의 반(A/B/C/D)**만 선택하면 즉시 모든 일정과 알람이 세팅됩니다. + +## 1. 스마트 달력 사용법 +- **일정 한눈에 보기**: 달력에 주간(노랑), 석간(연두), 야간(보라), 휴무(빨강) 등 색상별로 근무가 자동 표시됩니다. +- **월 이동 제스처**: 화면을 좌우로 가볍게 밀어서(스와이프) 이전 달이나 다음 달로 빠르게 이동할 수 있습니다. +- **빠른 년/월 이동**: 상단 중앙의 **'2026년 02월'** 텍스트를 터치하면 휠 다이얼을 돌려 원하는 년도와 월로 즉시 이동할 수 있습니다. +- **오늘로 돌아오기**: 상단의 **'오늘'** 버튼을 누르면 언제 어디서든 현재 날짜로 즉시 돌아옵니다. +- **타 조 근무 확인**: 하단의 '오늘의 타 조 근무' 섹션에서 다른 조 이름을 터치하면, 해당 조의 달력 뷰로 잠시 전환됩니다. + +## 2. 근무 변경 및 개인 메모 +기본 스케줄 외의 변경 사항을 달력에 직접 기록하고 관리할 수 있습니다. +- **날짜 선택**: 수정하고 싶은 날짜를 터치하면 상세 설정 팝업이 나타납니다. +- **근무 상태 수정**: 연차, 교육, 월차, 반차 등 해당일의 상태를 선택하세요. 달력에 즉시 반영되며 관련 알람도 자동 조정됩니다. +- **메모장 활용**: 하단 메모란에 내용을 입력하고 저장하면, 달력 날짜 아래에 작은 점(•)이 표시되며 메모 내용을 확인할 수 있습니다. +- **설정 초기화**: 수정한 일정을 원래의 기본 순번대로 되돌리려면 **'원래대로'** 버튼을 누르세요. + +## 3. 프리미엄 알람 시스템 +최신 트렌드를 반영한 아름답고 신뢰할 수 있는 알람 기능을 제공합니다. 교대링은 **3단계 안전장치**를 통해 100% 신뢰도를 지향합니다. +- **자동 예약**: 선택된 근무(주/야/석)에 따라 알람 시간이 자동으로 계산되어 예약됩니다. (향후 30일치 사전 예약) +- **정밀 알람 엔진**: `AlarmClock` API를 통해 절전 모드에서도 정확하게 작동하며, 상단바에 알람 아이콘이 표시되어 작동 여부를 쉽게 확인할 수 있습니다. +- **실시간 동기화**: 근무를 변경하거나 설정에서 알람 시간을 바꾸는 즉시 전체 스케줄이 실시간으로 재구성됩니다. +- **시간 커스텀**: 설정(⚙️) → **알람 설정** 탭에서 각 근무별 기본 알람 시간을 본인의 기상 패턴에 맞게 수정할 수 있습니다. +- **전체 알람 마스터 스위치**: 알람 설정 페이지 좌측 상단의 **'전체 알람 켜짐/꺼짐'** 버튼으로 모든 예약을 일시 정지하거나 활성화할 수 있습니다. +- **럭셔리 디자인**: **글래스모피즘(유리 질감)**과 화려한 그라데이션이 적용된 알람 화면은 가독성과 디자인을 모두 잡았습니다. +- **직관적인 버튼 제어**: + - **다시 울림**: 상단 유리 질감 버튼을 누르면 설정된 간격만큼 알람을 미룹니다. + - **해제**: 중앙의 거대한 원형 버튼을 누르면 알람이 즉시 종료됩니다. (주변에 은은한 오로라 광채 애니메이션이 작동합니다) +- **부드러운 스위치**: 알람 항목의 온/오프 스위치는 가볍고 부드러운 애니메이션을 제공하며, 불필요한 배경 요소를 제거하여 시각적 이질감을 없앴습니다. + +## 4. 물때표 및 특수 설정 +- **물때표 표시**: 설정 → 기타 설정에서 **'물때표 보기'**를 활성화하면 달력 상단에 물때 정보가 나타납니다. +- **지역 전환**: 달력 상단의 지역 이름(군산, 변산, 여수, 태안)을 터치하여 간편하게 지역별 물때를 확인할 수 있습니다. +- **기본 공장 설정**: 본인이 속한 공장(전주 또는 논산)을 선택하여 공장별 특화된 교대 로직을 적용받으세요. + +## 5. 데이터 백업 및 앱 공유 +- **안전한 백업**: 설정 → 기타 설정에서 현재의 근무 기록과 메모를 파일로 저장하거나 다시 불러올 수 있습니다. +- **설치 파일 직접 전송**: **'앱 공유하기'** 기능을 통해 동료들에게 설치 파일(APK)을 직접 보내주어 간편한 설치를 도울 수 있습니다. + +--- + +알람이 누락되지 않도록 앱 실행 시 안내되는 **통합 권한 설정**을 반드시 완료해주세요: +1. 배터리 사용량을 **'제한 없음'**으로 설정 (배터리 최적화 제외) +2. **'정확한 알람 및 리마인더'** 권한 허용 (필수) +3. **'전체화면 알림'** 권한 허용 (잠금 화면 즉시 표시) +4. 알람 볼륨 및 진동 설정 확인 diff --git a/app/src/main/java/com/example/shiftalarm/AlarmActivity.kt b/app/src/main/java/com/example/shiftalarm/AlarmActivity.kt new file mode 100644 index 0000000..bf2851a --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmActivity.kt @@ -0,0 +1,498 @@ +package com.example.shiftalarm + +import android.app.KeyguardManager +import android.content.Context +import android.content.Intent +import android.media.AudioAttributes +import android.media.AudioManager +import android.media.MediaPlayer +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.PowerManager +import android.os.VibrationEffect +import android.os.Vibrator +import android.util.Log +import android.view.MotionEvent +import android.view.View +import android.view.WindowManager +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.activity.enableEdgeToEdge +import com.example.shiftalarm.databinding.ActivityAlarmBinding +import androidx.core.content.ContextCompat +import java.time.LocalDate +import java.time.format.DateTimeFormatter +import kotlin.math.abs + +class AlarmActivity : AppCompatActivity() { + + private lateinit var binding: ActivityAlarmBinding + private var mediaPlayer: MediaPlayer? = null + private var vibrator: Vibrator? = null + private var startX = 0f + + // 5분 후 자동 스누즈 + private val autoStopHandler = Handler(Looper.getMainLooper()) + private val AUTO_STOP_DELAY = 5L * 60 * 1000 + + override fun onCreate(savedInstanceState: Bundle?) { + // 중요: 잠금 화면 위 표시 설정을 가장 먼저 적용 + setupLockScreenFlags() + + super.onCreate(savedInstanceState) + + // ForegroundService가 실행 중이면 먼저 중지 + stopService(Intent(this, AlarmForegroundService::class.java)) + + // Service 중지 후 약간의 지연을 두어 AudioFocus가 완전히 해제되도록 함 + try { + Thread.sleep(100) + } catch (e: InterruptedException) { + // 무시 + } + + enableEdgeToEdge() + binding = ActivityAlarmBinding.inflate(layoutInflater) + binding.root.background = ContextCompat.getDrawable(this, R.drawable.bg_alarm_gradient) + setContentView(binding.root) + + // 추가 윈도우 플래그 설정 + setupWindowFlags() + + val shift = intent.getStringExtra("EXTRA_SHIFT") ?: "근무" + binding.tvShiftType.text = if (shift == "SNOOZE") "다시 울림 알람" else "[$shift] 근무 알람" + + val now = java.util.Calendar.getInstance() + val amPm = if (now.get(java.util.Calendar.AM_PM) == java.util.Calendar.AM) "오전" else "오후" + val hour = now.get(java.util.Calendar.HOUR) + val hourText = if (hour == 0) 12 else hour + val min = now.get(java.util.Calendar.MINUTE) + binding.tvCurrentTime.text = String.format("%s %d:%02d", amPm, hourText, min) + + val today = LocalDate.now() + val dayOfWeek = today.dayOfWeek.getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.KOREAN) + binding.tvDate.text = String.format("%d월 %d일 %s", today.monthValue, today.dayOfMonth, dayOfWeek) + + // 알람 시작 (화면 상태와 무관하게 항상 실행) + startAlarm() + setupControls() + + // 5분 후 자동 스누즈 + autoStopHandler.postDelayed({ + Toast.makeText(this, "알람이 자동으로 다시 울림 설정되었습니다.", Toast.LENGTH_LONG).show() + snoozeAlarm() + stopAlarm() + finish() + }, AUTO_STOP_DELAY) + + // 키가드(잠금화면) 상태 변화 리스너 등록 + registerKeyguardListener() + } + + /** + * 잠금 화면 관련 플래그를 super.onCreate 이전에 설정 + */ + private fun setupLockScreenFlags() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + setShowWhenLocked(true) + setTurnScreenOn(true) + } + } + + private fun setupWindowFlags() { + // ======================================== + // 알람 화면이 패턴/지문보다 먼저 표시되도록 설정 + // ======================================== + // 중요: requestDismissKeyguard()를 호출하면 패턴/지문이 먼저 뜸 + // 알람 화면을 먼저 띄우려면 FLAG_SHOW_WHEN_LOCKED만 사용해야 함 + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + // 1. 가장 먼저: 화면 켜기 + 잠금화면 위에 표시 + setShowWhenLocked(true) + setTurnScreenOn(true) + } + + // 2. 화면 켜짐 유지 + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + + // 3. 하위 호환성: Android 8.0 이하 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) { + @Suppress("DEPRECATION") + window.addFlags( + WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + ) + } + + // 4. Android 14+ 추가 플래그 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN) + window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) + } + + // 5. Android 10+ 레이아웃 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) + } + + // 6. 전체화면 모드 (모든 기기 공통) + setFullscreenMode() + } + + /** + * 전체화면 모드 설정 + */ + private fun isSamsungDevice(): Boolean { + val manufacturer = Build.MANUFACTURER?.lowercase() ?: "" + val brand = Build.BRAND?.lowercase() ?: "" + return manufacturer.contains("samsung") || brand.contains("samsung") + } + + /** + * 전체화면 모드 설정 + */ + private fun setFullscreenMode() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // Android 11+ (API 30+): WindowInsetsController 사용 + window.setDecorFitsSystemWindows(false) + window.insetsController?.let { controller -> + controller.hide(android.view.WindowInsets.Type.statusBars() or android.view.WindowInsets.Type.navigationBars()) + controller.systemBarsBehavior = android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } + } else { + // Android 10 이하: systemUiVisibility 사용 + @Suppress("DEPRECATION") + window.decorView.systemUiVisibility = ( + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or + View.SYSTEM_UI_FLAG_FULLSCREEN or + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or + View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + ) + } + } + + private fun setupControls() { + binding.btnSnooze.setOnClickListener { + handleSnooze() + } + + // Swipe-to-dismiss for Stop Button + var startX = 0f + val dismissBtn = binding.btnDismiss + val maxSwipe = dpToPx(100f).toFloat() + + dismissBtn.setOnTouchListener { v, event -> + when (event.action) { + MotionEvent.ACTION_DOWN -> { + startX = event.rawX + v.animate().cancel() + true + } + MotionEvent.ACTION_MOVE -> { + val dx = event.rawX - startX + val clampedDx = if (dx > 0) dx.coerceAtMost(maxSwipe) else dx.coerceAtLeast(-maxSwipe) + v.translationX = clampedDx + + // Visual feedback: scale up when near trigger + val ratio = abs(clampedDx) / maxSwipe + v.scaleX = 1f + (ratio * 0.15f) + v.scaleY = 1f + (ratio * 0.15f) + v.alpha = 1f - (ratio * 0.3f) + true + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + val dx = event.rawX - startX + if (abs(dx) > maxSwipe * 0.8f) { + // Trigger Dismiss + (getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator)?.vibrate(50) + Toast.makeText(this, "알람 해제 완료", Toast.LENGTH_SHORT).show() + stopAlarm(); finish() + } else { + // Reset + v.animate() + .translationX(0f) + .scaleX(1f) + .scaleY(1f) + .alpha(1f) + .setDuration(300) + .start() + } + true + } + else -> false + } + } + + // Pulse logic with enhanced glow + fun startPulse() { + binding.pulseCircle.scaleX = 0.85f; binding.pulseCircle.scaleY = 0.85f; binding.pulseCircle.alpha = 0.5f + binding.pulseCircle.animate() + .scaleX(1.3f).scaleY(1.3f).alpha(1.0f) + .setDuration(1500) + .withEndAction { + binding.pulseCircle.animate() + .scaleX(0.85f).scaleY(0.85f).alpha(0.5f) + .setDuration(1500) + .withEndAction { if(!isFinishing) startPulse() } + .start() + } + .start() + } + startPulse() + } + + private fun handleSnooze() { + (getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator)?.vibrate(50) + val snoozeRepeat = intent.getIntExtra("EXTRA_SNOOZE_REPEAT", 3) + val text = if (snoozeRepeat == 99) "다시 울림 설정됨" else "다시 울림 (${snoozeRepeat}회 남음)" + Toast.makeText(this, text, Toast.LENGTH_SHORT).show() + snoozeAlarm(); stopAlarm(); finish() + } + + private fun dpToPx(dp: Float): Int { + return (dp * resources.displayMetrics.density).toInt() + } + + private fun startAlarm() { + if (mediaPlayer?.isPlaying == true) { + Log.d("AlarmActivity", "MediaPlayer가 이미 실행 중") + return + } + + val soundUriStr = intent.getStringExtra("EXTRA_SOUND") + val alarmUri = if (!soundUriStr.isNullOrEmpty()) { + Uri.parse(soundUriStr) + } else { + val prefs = getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + val globalUriStr = prefs.getString("alarm_uri", null) + if (globalUriStr != null) Uri.parse(globalUriStr) + else android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI + } + + // AudioAttributes 강화: 화면 켜진 상태에서도 알람음이 울리도록 + val audioAttrs = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_ALARM) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED) // 볼륨 강제 적용 + .build() + + // AudioManager를 통해 알람 볼륨 설정 + val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager + val originalVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM) + val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM) + + // 알람 볼륨을 최대로 설정 (사용자가 나중에 조정 가능) + try { + audioManager.setStreamVolume(AudioManager.STREAM_ALARM, maxVolume, 0) + } catch (e: Exception) { + Log.w("AlarmActivity", "알람 볼륨 설정 실패", e) + } + + var mediaPlayerStarted = false + + try { + mediaPlayer?.release() + mediaPlayer = MediaPlayer().apply { + setAudioAttributes(audioAttrs) + setDataSource(this@AlarmActivity, alarmUri!!) + isLooping = true + setVolume(1.0f, 1.0f) // 최대 볼륨 + prepare() + start() + } + mediaPlayerStarted = true + Log.d("AlarmActivity", "MediaPlayer 시작 성공 (사용자 지정음)") + } catch (e: Exception) { + Log.e("AlarmActivity", "MediaPlayer 시작 실패 (사용자 지정음), fallback 시도", e) + + // Fallback 1: 시스템 기본 알람음 + try { + val fallback = android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI + mediaPlayer = MediaPlayer().apply { + setAudioAttributes(audioAttrs) + setDataSource(this@AlarmActivity, fallback) + isLooping = true + setVolume(1.0f, 1.0f) + prepare() + start() + } + mediaPlayerStarted = true + Log.d("AlarmActivity", "MediaPlayer 시작 성공 (Fallback 1: 시스템 기본)") + } catch (e2: Exception) { + Log.e("AlarmActivity", "Fallback 1 실패", e2) + + // Fallback 2: RingtoneManager에서 기본 알람 가져오기 + try { + val ringtoneUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_ALARM) + mediaPlayer = MediaPlayer().apply { + setAudioAttributes(audioAttrs) + setDataSource(this@AlarmActivity, ringtoneUri) + isLooping = true + setVolume(1.0f, 1.0f) + prepare() + start() + } + mediaPlayerStarted = true + Log.d("AlarmActivity", "MediaPlayer 시작 성공 (Fallback 2: RingtoneManager)") + } catch (e3: Exception) { + Log.e("AlarmActivity", "모든 MediaPlayer 시작 실패", e3) + } + } + } + + // 진동 시작 (알람음과 독립적으로 - 알람음 실패필도 진동은 울림) + vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val vibrationEffect = VibrationEffect.createWaveform(longArrayOf(0, 1000, 500, 1000), 0) + vibrator?.vibrate(vibrationEffect) + } else { + @Suppress("DEPRECATION") + vibrator?.vibrate(longArrayOf(0, 1000, 500, 1000), 0) + } + Log.d("AlarmActivity", "진동 시작 성공") + } catch (e: Exception) { + Log.e("AlarmActivity", "진동 시작 실패", e) + } + + // 알람음 시작 실패 시 토스트 메시지 + if (!mediaPlayerStarted) { + Toast.makeText(this, "알람음 재생에 실패했습니다. 진동으로 알려드립니다.", Toast.LENGTH_LONG).show() + } + } + + private fun snoozeAlarm() { + val snoozeMin = intent.getIntExtra("EXTRA_SNOOZE", 5) + val snoozeRepeat = intent.getIntExtra("EXTRA_SNOOZE_REPEAT", 3) + val soundUriStr = intent.getStringExtra("EXTRA_SOUND") + + if (snoozeRepeat > 0) { + val nextRepeat = if (snoozeRepeat == 99) 99 else snoozeRepeat - 1 + scheduleSnooze(this, snoozeMin, soundUriStr, nextRepeat) + } else { + Toast.makeText(this, "다시 울림 횟수를 모두 소모하여 알람을 종료합니다.", Toast.LENGTH_SHORT).show() + } + } + + private fun stopAlarm() { + stopService(Intent(this, AlarmForegroundService::class.java)) + + try { + mediaPlayer?.let { + if (it.isPlaying) it.stop() + it.release() + } + } catch (e: Exception) {} + mediaPlayer = null + + try { + vibrator?.cancel() + } catch (e: Exception) {} + vibrator = null + + val nm = getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager + nm.cancel(1) + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + setIntent(intent) + val shift = intent.getStringExtra("EXTRA_SHIFT") ?: "근무" + binding.tvShiftType.text = if (shift == "SNOOZE") "다시 울림 알람" else "[$shift] 근무 알람" + + stopAlarm() + startAlarm() + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + // 화면 켜짐 및 잠금 화면 위 표시 재적용 + setupWindowFlags() + } + + override fun onDestroy() { + super.onDestroy() + autoStopHandler.removeCallbacksAndMessages(null) + stopAlarm() + unregisterKeyguardListener() + } + + // ======================================== + // 키가드(잠금화면) 상태 감지 및 알람 해제 처리 + // ======================================== + private var keyguardManager: KeyguardManager? = null + private var keyguardCallback: KeyguardManager.KeyguardDismissCallback? = null + + /** + * 키가드(잠금화면) 상태 변화를 감지하여 알람을 적절히 처리 + * 안드로이드 버전별로 다른 방식으로 처리 + */ + private fun registerKeyguardListener() { + keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as? KeyguardManager + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // Android 8.0+: KeyguardDismissCallback 사용 + keyguardCallback = object : KeyguardManager.KeyguardDismissCallback() { + override fun onDismissError() { + Log.e("AlarmActivity", "Keyguard dismiss error") + } + + override fun onDismissSucceeded() { + Log.d("AlarmActivity", "Keyguard dismissed successfully - 사용자가 패턴/지문으로 해제함") + // 패턴/지문 해제 후 알람 계속 울리게 하려면 여기서 아무것도 하지 않음 + // 알람을 자동으로 멈추려면: stopAlarm(); finish() + } + + override fun onDismissCancelled() { + Log.d("AlarmActivity", "Keyguard dismiss cancelled") + } + } + } + } + + private fun unregisterKeyguardListener() { + keyguardCallback = null + } + + /** + * 현재 키가드(잠금화면)가 잠겨있는지 확인 + */ + private fun isKeyguardLocked(): Boolean { + return keyguardManager?.isKeyguardLocked ?: false + } + + /** + * 현재 키가드(잠금화면)가 보안 잠금(패턴/PIN/지문)을 사용하는지 확인 + */ + private fun isKeyguardSecure(): Boolean { + return keyguardManager?.isKeyguardSecure ?: false + } + + override fun onPause() { + super.onPause() + // 홈 버튼이나 다른 앱으로 전환 시 알람 계속 울리도록 함 + // 사용자가 의도적으로 알람을 해제하지 않았으므로 + Log.d("AlarmActivity", "onPause - 알람 계속 유지") + } + + override fun onStop() { + super.onStop() + // 알람 화면이 백그라운드로 갔을 때 + // 잠금화면이 다시 잠기면 알람을 멈추지 않고 계속 유지 + Log.d("AlarmActivity", "onStop - 알람 계속 유지") + } + + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + if (hasFocus) { + // 알람 화면이 다시 포커스를 받으면 전체화면 모드 재적용 + setFullscreenMode() + Log.d("AlarmActivity", "Window focus regained") + } + } +} diff --git a/app/src/main/java/com/example/shiftalarm/AlarmEventLogger.kt b/app/src/main/java/com/example/shiftalarm/AlarmEventLogger.kt new file mode 100644 index 0000000..6a1c3f8 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmEventLogger.kt @@ -0,0 +1,24 @@ +import android.util.Log + +class AlarmEventLogger { + companion object { + private const val TAG = "AlarmEventLogger" + } + + fun logAlarmEvent(event: String) { + val currentTime = System.currentTimeMillis() + Log.d(TAG, "Alarm Event: $event at $currentTime") + } + + fun logAlarmSet(alarmId: Int, time: String) { + Log.i(TAG, "Alarm set: ID = $alarmId, Time = $time") + } + + fun logAlarmTriggered(alarmId: Int) { + Log.w(TAG, "Alarm triggered: ID = $alarmId") + } + + fun logAlarmCanceled(alarmId: Int) { + Log.e(TAG, "Alarm canceled: ID = $alarmId") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shiftalarm/AlarmForegroundService.kt b/app/src/main/java/com/example/shiftalarm/AlarmForegroundService.kt new file mode 100644 index 0000000..8a957b8 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmForegroundService.kt @@ -0,0 +1,83 @@ +package com.example.shiftalarm + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.app.Service +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.IBinder +import androidx.core.app.NotificationCompat + +class AlarmForegroundService : Service() { + + private val CHANNEL_ID = "SHIFT_ALARM_CHANNEL_V5" + private val NOTIFICATION_ID = 1 + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + val shiftType = intent?.getStringExtra("EXTRA_SHIFT") ?: "근무" + val soundUri = intent?.getStringExtra("EXTRA_SOUND") + val snoozeMin = intent?.getIntExtra("EXTRA_SNOOZE", 5) ?: 5 + val snoozeRepeat = intent?.getIntExtra("EXTRA_SNOOZE_REPEAT", 3) ?: 3 + + // 1. 알림 채널 생성 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + CHANNEL_ID, + "교대링 알람", + NotificationManager.IMPORTANCE_HIGH + ).apply { + description = "알람이 울리는 동안 표시되는 알림입니다." + setSound(null, null) // 소리는 Activity에서 재생 + enableVibration(false) // 진동은 Activity에서 재생 + } + val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + manager.createNotificationChannel(channel) + } + + // 2. 전체화면 실행을 위한 PendingIntent + val fullScreenIntent = Intent(this, AlarmActivity::class.java).apply { + putExtra("EXTRA_SHIFT", shiftType) + putExtra("EXTRA_SOUND", soundUri) + putExtra("EXTRA_SNOOZE", snoozeMin) + putExtra("EXTRA_SNOOZE_REPEAT", snoozeRepeat) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) + } + + val fullScreenPendingIntent = PendingIntent.getActivity( + this, + 100, + fullScreenIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + + // 3. 일원화된 단일 알림 생성 + val contentText = if (shiftType == "SNOOZE") "다시 울림 알람입니다." else "오늘의 근무는 [$shiftType] 입니다." + + val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID) + .setContentTitle("교대링 알람 작동 중") + .setContentText(contentText) + .setSmallIcon(R.drawable.ic_alarm_blue) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setCategory(NotificationCompat.CATEGORY_ALARM) + .setFullScreenIntent(fullScreenPendingIntent, true) + .setContentIntent(fullScreenPendingIntent) + .setOngoing(true) + .setAutoCancel(false) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .build() + + // 4. Foreground 시작 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 14+ + startForeground(NOTIFICATION_ID, notification, android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE) + } else { + startForeground(NOTIFICATION_ID, notification) + } + + return START_NOT_STICKY + } + + override fun onBind(intent: Intent?): IBinder? = null +} diff --git a/app/src/main/java/com/example/shiftalarm/AlarmPermissionUtil.kt b/app/src/main/java/com/example/shiftalarm/AlarmPermissionUtil.kt new file mode 100644 index 0000000..b3eb48a --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmPermissionUtil.kt @@ -0,0 +1,228 @@ +package com.example.shiftalarm + +import android.Manifest +import android.app.Activity +import android.app.AlarmManager +import android.app.AlertDialog +import android.app.NotificationManager +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build +import android.os.PowerManager +import android.provider.Settings +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat + +object AlarmPermissionUtil { + + /** + * 전체 권한 상태를 확인하고 필요한 경우 통합 안내 다이얼로그를 표시합니다. + */ + fun checkAndRequestAllPermissions(activity: ComponentActivity) { + val missingPermissions = mutableListOf() + + // 1. 알림 권한 (Android 13+) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + missingPermissions.add("알림 표시 (알람 울림 확인)") + } + } + + // 2. 정확한 알람 권한 (Android 12+) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val am = activity.getSystemService(Context.ALARM_SERVICE) as AlarmManager + if (!am.canScheduleExactAlarms()) { + missingPermissions.add("정확한 알람 (정시에 울림 보장)") + } + } + + // 3. 배터리 최적화 제외 (Android 6+) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val pm = activity.getSystemService(Context.POWER_SERVICE) as PowerManager + if (!pm.isIgnoringBatteryOptimizations(activity.packageName)) { + missingPermissions.add("배터리 최적화 제외 (절전 모드 무시)") + } + } + + // 4. 전체화면 알림 권한 (Android 14+) + if (Build.VERSION.SDK_INT >= 34) { + val nm = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + if (!nm.canUseFullScreenIntent()) { + missingPermissions.add("전체화면 알림 (잠금 화면에서 즉시 표시)") + } + } + + if (missingPermissions.isNotEmpty()) { + showIntegratedPermissionDialog(activity, missingPermissions) + } + } + + private fun showIntegratedPermissionDialog(activity: ComponentActivity, missing: List) { + val message = StringBuilder("안정적인 알람 작동을 위해 아래 권한들이 필요합니다:\n\n") + missing.forEach { message.append("- $it\n") } + message.append("\n[확인]을 누르면 설정 화면으로 순차적으로 안내합니다.") + + AlertDialog.Builder(activity) + .setTitle("권한 설정 안내") + .setMessage(message.toString()) + .setPositiveButton("확인") { _, _ -> + startPermissionFlow(activity) + } + .setNegativeButton("나중에", null) + .setCancelable(false) + .show() + } + + private fun startPermissionFlow(activity: ComponentActivity) { + // 순차적으로 가장 중요한 것부터 요청 + + // 1. 알림 권한 (시스템 팝업) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 101) + return // 알림 권한 결과 콜백 이후 다음으로 넘어가도록 유도 (혹은 그냥 연달아 띄움) + } + } + + // 2. 배터리 최적화 (시스템 팝업) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val pm = activity.getSystemService(Context.POWER_SERVICE) as PowerManager + if (!pm.isIgnoringBatteryOptimizations(activity.packageName)) { + requestBatteryOptimization(activity) + return + } + } + + // 3. 정확한 알람 (설정 화면) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val am = activity.getSystemService(Context.ALARM_SERVICE) as AlarmManager + if (!am.canScheduleExactAlarms()) { + val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM).apply { + data = Uri.parse("package:${activity.packageName}") + } + activity.startActivity(intent) + return + } + } + + // 4. 전체화면 알림 (설정 화면) + if (Build.VERSION.SDK_INT >= 34) { + val nm = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + if (!nm.canUseFullScreenIntent()) { + try { + val intent = Intent("android.settings.MANAGE_APP_USE_FULL_SCREEN_INTENT").apply { + data = Uri.parse("package:${activity.packageName}") + } + activity.startActivity(intent) + } catch (e: Exception) { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.parse("package:${activity.packageName}") + } + activity.startActivity(intent) + } + } + } + } + + fun requestBatteryOptimization(context: Context) { + try { + val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply { + data = Uri.parse("package:${context.packageName}") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.startActivity(intent) + } catch (e: Exception) { + try { + val intent = Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.startActivity(intent) + } catch (e2: Exception) {} + } + } + + fun requestOverlayPermission(context: Context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION).apply { + data = Uri.parse("package:${context.packageName}") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.startActivity(intent) + } + } + + fun requestFullScreenIntentPermission(context: Context) { + if (Build.VERSION.SDK_INT >= 34) { + try { + val intent = Intent("android.settings.MANAGE_APP_USE_FULL_SCREEN_INTENT").apply { + data = Uri.parse("package:${context.packageName}") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.startActivity(intent) + } catch (e: Exception) { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.parse("package:${context.packageName}") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.startActivity(intent) + } + } + } + + fun isAllPermissionsGranted(context: Context): Boolean { + var allGranted = true + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + allGranted = allGranted && ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + allGranted = allGranted && am.canScheduleExactAlarms() + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager + allGranted = allGranted && pm.isIgnoringBatteryOptimizations(context.packageName) + allGranted = allGranted && Settings.canDrawOverlays(context) + } + if (Build.VERSION.SDK_INT >= 34) { + val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + allGranted = allGranted && nm.canUseFullScreenIntent() + } + return allGranted + } + + fun getBatteryOptimizationStatus(context: Context): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager + return pm.isIgnoringBatteryOptimizations(context.packageName) + } + return true + } + + fun getExactAlarmStatus(context: Context): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + return am.canScheduleExactAlarms() + } + return true + } + + fun getOverlayStatus(context: Context): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return Settings.canDrawOverlays(context) + } + return true + } + + fun getFullScreenIntentStatus(context: Context): Boolean { + if (Build.VERSION.SDK_INT >= 34) { + val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + return nm.canUseFullScreenIntent() + } + return true + } +} diff --git a/app/src/main/java/com/example/shiftalarm/AlarmReceiver.kt b/app/src/main/java/com/example/shiftalarm/AlarmReceiver.kt new file mode 100644 index 0000000..8f3e00d --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmReceiver.kt @@ -0,0 +1,103 @@ +package com.example.shiftalarm + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.PowerManager +import android.util.Log +import kotlinx.coroutines.* + +class AlarmReceiver : BroadcastReceiver() { + + private val TAG = "AlarmReceiver" + + override fun onReceive(context: Context, intent: Intent?) { + Log.d(TAG, "===== 알람 수신 (Receiver) =====") + + val alarmId = intent?.getIntExtra("EXTRA_ALARM_ID", -1) ?: -1 + val isCustom = intent?.getBooleanExtra("EXTRA_IS_CUSTOM", false) ?: false + + // 커스텀 알람인 경우 DB에서 여전히 유효한지 확인 (삭제된 알람이 울리는 문제 해결) + if (isCustom && alarmId != -1) { + val customAlarmId = intent.getIntExtra("EXTRA_UNIQUE_ID", -1) + if (customAlarmId != -1) { + // 비동기로 DB 확인 + val scope = CoroutineScope(Dispatchers.IO) + scope.launch { + val repo = ShiftRepository(context) + val alarms = repo.getAllCustomAlarms() + val alarmExists = alarms.any { it.id == customAlarmId && it.isEnabled } + + if (!alarmExists) { + Log.w(TAG, "삭제된 또는 비활성화된 알람입니다. 무시합니다. (ID: $customAlarmId)") + scope.cancel() + return@launch + } + + // 알람이 유효하면 직접 AlarmActivity 실행 + Foreground Service 시작 + startAlarm(context, intent) + scope.cancel() + } + return + } + } + + // 일반 알람은 바로 직접 실행 + startAlarm(context, intent) + } + + private fun startAlarm(context: Context, intent: Intent?) { + // WakeLock 획득 (화면 켜기 및 Activity 실행 보장) + val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager + val wakeLock = pm.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, + "ShiftAlarm::AlarmWakeLock" + ) + wakeLock.acquire(30 * 1000L) // 30초 - Activity 실행 및 초기화에 충분한 시간 + + try { + // 1. Foreground Service 시작 (알림 표시 및 시스템에 알람 실행 중 알림) + val serviceIntent = Intent(context, AlarmForegroundService::class.java).apply { + putExtra("EXTRA_SHIFT", intent?.getStringExtra("EXTRA_SHIFT") ?: "근무") + putExtra("EXTRA_SOUND", intent?.getStringExtra("EXTRA_SOUND")) + putExtra("EXTRA_SNOOZE", intent?.getIntExtra("EXTRA_SNOOZE", 5) ?: 5) + putExtra("EXTRA_SNOOZE_REPEAT", intent?.getIntExtra("EXTRA_SNOOZE_REPEAT", 3) ?: 3) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(serviceIntent) + } else { + context.startService(serviceIntent) + } + + // 2. AlarmActivity 직접 실행 (알람 화면 표시) + val activityIntent = Intent(context, AlarmActivity::class.java).apply { + putExtra("EXTRA_SHIFT", intent?.getStringExtra("EXTRA_SHIFT") ?: "근무") + putExtra("EXTRA_SOUND", intent?.getStringExtra("EXTRA_SOUND")) + putExtra("EXTRA_SNOOZE", intent?.getIntExtra("EXTRA_SNOOZE", 5) ?: 5) + putExtra("EXTRA_SNOOZE_REPEAT", intent?.getIntExtra("EXTRA_SNOOZE_REPEAT", 3) ?: 3) + // 중요: 새 태스크로 실행 (FLAG_ACTIVITY_NEW_TASK) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // 기존 인스턴스 재사용 및 최상위로 가져오기 + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) + // 잠금 화면 위에 표시 + addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) + // 화면 켜기 + addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) + } + + context.startActivity(activityIntent) + Log.d(TAG, "AlarmActivity 실행 완료") + + } catch (e: Exception) { + Log.e(TAG, "알람 실행 실패", e) + } finally { + // WakeLock은 Activity가 화면을 켜고 나서 해제 + android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({ + if (wakeLock.isHeld) wakeLock.release() + }, 5000) + } + } +} diff --git a/app/src/main/java/com/example/shiftalarm/AlarmSyncManager.kt b/app/src/main/java/com/example/shiftalarm/AlarmSyncManager.kt new file mode 100644 index 0000000..7546b35 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmSyncManager.kt @@ -0,0 +1,299 @@ +package com.example.shiftalarm + +import android.content.Context +import android.util.Log +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.time.LocalDate + +/** + * 알람 동기화 관리자 + * DB와 AlarmManager 간의 실시간 동기화를 보장합니다. + * + * 동기화 전략: + * 1. DB 작업과 AlarmManager 작업을 원자적으로 처리 + * 2. 실패 시 롤백 메커니즘 제공 + * 3. 동기화 상태 추적 및 재시도 + */ +object AlarmSyncManager { + + private const val TAG = "AlarmSyncManager" + private const val PREFS_NAME = "AlarmSyncPrefs" + + /** + * 알람 추가 동기화 + * DB에 추가 후 AlarmManager에 즉시 예약 + */ + suspend fun addAlarm(context: Context, alarm: CustomAlarm): Result = withContext(Dispatchers.IO) { + try { + val repo = ShiftRepository(context) + + // 1. DB에 알람 추가 + val alarmId = repo.addCustomAlarm(alarm) + Log.d(TAG, "알람 DB 추가 완료: ID=$alarmId") + + // 2. AlarmManager에 예약 + val today = LocalDate.now(SEOUL_ZONE) + val customAlarms = repo.getAllCustomAlarms() + val addedAlarm = customAlarms.find { it.id == alarmId.toInt() } + + if (addedAlarm == null) { + Log.w(TAG, "추가된 알람을 DB에서 찾을 수 없음: ID=$alarmId") + return@withContext Result.failure(Exception("알람을 찾을 수 없습니다")) + } + + if (addedAlarm.isEnabled) { + // 향후 30일치 예약 + for (i in 0 until 30) { + val targetDate = today.plusDays(i.toLong()) + val shift = repo.getShift(targetDate, + context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + .getString("selected_team", "A") ?: "A", + context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + .getString("selected_factory", "Jeonju") ?: "Jeonju" + ) + + if (addedAlarm.shiftType == "기타" || addedAlarm.shiftType == shift) { + scheduleCustomAlarm( + context, + targetDate, + addedAlarm.id, + addedAlarm.shiftType, + addedAlarm.time, + addedAlarm.soundUri, + addedAlarm.snoozeInterval, + addedAlarm.snoozeRepeat + ) + } + } + Log.d(TAG, "알람 AlarmManager 예약 완료: ID=$alarmId") + } + + // 3. 동기화 상태 저장 + saveSyncStatus(context, "last_add_alarm", System.currentTimeMillis()) + + Result.success(Unit) + } catch (e: Exception) { + Log.e(TAG, "알람 추가 동기화 실패", e) + Result.failure(e) + } + } + + /** + * 알람 수정 동기화 + * DB 수정 후 기존 AlarmManager 예약 취소 후 재예약 + */ + suspend fun updateAlarm(context: Context, alarm: CustomAlarm): Result = withContext(Dispatchers.IO) { + try { + val repo = ShiftRepository(context) + + // 1. 기존 AlarmManager 예약 취소 + cancelAllCustomAlarmSchedules(context, alarm.id) + Log.d(TAG, "기존 알람 예약 취소 완료: ID=${alarm.id}") + + // 2. DB 업데이트 + repo.updateCustomAlarm(alarm) + Log.d(TAG, "알람 DB 업데이트 완료: ID=${alarm.id}") + + // 3. 활성화된 알람이면 재예약 + if (alarm.isEnabled) { + val today = LocalDate.now(SEOUL_ZONE) + for (i in 0 until 30) { + val targetDate = today.plusDays(i.toLong()) + val shift = repo.getShift(targetDate, + context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + .getString("selected_team", "A") ?: "A", + context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + .getString("selected_factory", "Jeonju") ?: "Jeonju" + ) + + if (alarm.shiftType == "기타" || alarm.shiftType == shift) { + scheduleCustomAlarm( + context, + targetDate, + alarm.id, + alarm.shiftType, + alarm.time, + alarm.soundUri, + alarm.snoozeInterval, + alarm.snoozeRepeat + ) + } + } + Log.d(TAG, "알람 재예약 완료: ID=${alarm.id}") + } + + // 4. 동기화 상태 저장 + saveSyncStatus(context, "last_update_alarm", System.currentTimeMillis()) + + Result.success(Unit) + } catch (e: Exception) { + Log.e(TAG, "알람 수정 동기화 실패", e) + Result.failure(e) + } + } + + /** + * 알람 삭제 동기화 + * AlarmManager 예약 먼저 취소 후 DB에서 삭제 + */ + suspend fun deleteAlarm(context: Context, alarm: CustomAlarm): Result = withContext(Dispatchers.IO) { + try { + val repo = ShiftRepository(context) + + // 1. AlarmManager 예약 취소 (DB 삭제 전에 먼저!) + cancelAllCustomAlarmSchedules(context, alarm.id) + Log.d(TAG, "알람 예약 취소 완료: ID=${alarm.id}") + + // 2. DB에서 삭제 + repo.deleteCustomAlarm(alarm) + Log.d(TAG, "알람 DB 삭제 완료: ID=${alarm.id}") + + // 3. 동기화 상태 저장 + saveSyncStatus(context, "last_delete_alarm", System.currentTimeMillis()) + + Result.success(Unit) + } catch (e: Exception) { + Log.e(TAG, "알람 삭제 동기화 실패", e) + Result.failure(e) + } + } + + /** + * 알람 토글 동기화 (활성화/비활성화) + */ + suspend fun toggleAlarm(context: Context, alarm: CustomAlarm, enable: Boolean): Result = withContext(Dispatchers.IO) { + try { + val repo = ShiftRepository(context) + val updatedAlarm = alarm.copy(isEnabled = enable) + + if (enable) { + // 활성화: DB 업데이트 후 예약 + repo.updateCustomAlarm(updatedAlarm) + val today = LocalDate.now(SEOUL_ZONE) + for (i in 0 until 30) { + val targetDate = today.plusDays(i.toLong()) + val shift = repo.getShift(targetDate, + context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + .getString("selected_team", "A") ?: "A", + context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + .getString("selected_factory", "Jeonju") ?: "Jeonju" + ) + + if (alarm.shiftType == "기타" || alarm.shiftType == shift) { + scheduleCustomAlarm( + context, + targetDate, + alarm.id, + alarm.shiftType, + alarm.time, + alarm.soundUri, + alarm.snoozeInterval, + alarm.snoozeRepeat + ) + } + } + Log.d(TAG, "알람 활성화 완료: ID=${alarm.id}") + } else { + // 비활성화: 예약 취소 후 DB 업데이트 + cancelAllCustomAlarmSchedules(context, alarm.id) + repo.updateCustomAlarm(updatedAlarm) + Log.d(TAG, "알람 비활성화 완료: ID=${alarm.id}") + } + + saveSyncStatus(context, "last_toggle_alarm", System.currentTimeMillis()) + Result.success(Unit) + } catch (e: Exception) { + Log.e(TAG, "알람 토글 동기화 실패", e) + Result.failure(e) + } + } + + /** + * 전체 알람 동기화 (앱 시작 시 호출) + */ + suspend fun syncAllAlarmsWithCheck(context: Context): Result = withContext(Dispatchers.IO) { + try { + Log.d(TAG, "전체 알람 동기화 시작") + + // 1. 기존 모든 알람 취소 + val repo = ShiftRepository(context) + val allAlarms = repo.getAllCustomAlarms() + + for (alarm in allAlarms) { + cancelAllCustomAlarmSchedules(context, alarm.id) + } + Log.d(TAG, "기존 모든 알람 취소 완료: ${allAlarms.size}개") + + // 2. 활성화된 알람만 재예약 + val enabledAlarms = allAlarms.filter { it.isEnabled } + val today = LocalDate.now(SEOUL_ZONE) + val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + val team = prefs.getString("selected_team", "A") ?: "A" + val factory = prefs.getString("selected_factory", "Jeonju") ?: "Jeonju" + + var scheduledCount = 0 + for (alarm in enabledAlarms) { + for (i in 0 until 30) { + val targetDate = today.plusDays(i.toLong()) + val shift = repo.getShift(targetDate, team, factory) + + if (alarm.shiftType == "기타" || alarm.shiftType == shift) { + scheduleCustomAlarm( + context, + targetDate, + alarm.id, + alarm.shiftType, + alarm.time, + alarm.soundUri, + alarm.snoozeInterval, + alarm.snoozeRepeat + ) + scheduledCount++ + } + } + } + + Log.d(TAG, "알람 재예약 완료: ${enabledAlarms.size}개 알람, ${scheduledCount}개 예약") + + // 3. 동기화 상태 저장 + saveSyncStatus(context, "last_full_sync", System.currentTimeMillis()) + + Result.success(SyncResult( + totalAlarms = allAlarms.size, + enabledAlarms = enabledAlarms.size, + scheduledAlarms = scheduledCount + )) + } catch (e: Exception) { + Log.e(TAG, "전체 알람 동기화 실패", e) + Result.failure(e) + } + } + + /** + * 동기화 상태 저장 + */ + private fun saveSyncStatus(context: Context, key: String, timestamp: Long) { + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .edit() + .putLong(key, timestamp) + .apply() + } + + /** + * 마지막 동기화 시간 확인 + */ + fun getLastSyncTime(context: Context, key: String): Long { + return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .getLong(key, 0) + } + + /** + * 동기화 결과 데이터 클래스 + */ + data class SyncResult( + val totalAlarms: Int, + val enabledAlarms: Int, + val scheduledAlarms: Int + ) +} diff --git a/app/src/main/java/com/example/shiftalarm/AlarmUtils.kt b/app/src/main/java/com/example/shiftalarm/AlarmUtils.kt new file mode 100644 index 0000000..be6d2a3 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmUtils.kt @@ -0,0 +1,350 @@ +package com.example.shiftalarm + +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import android.util.Log +import android.widget.Toast +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.ZoneId +import java.util.concurrent.TimeUnit + +val SEOUL_ZONE: ZoneId = ZoneId.of("Asia/Seoul") +const val TAG = "ShiftAlarm" + +// ============================================ +// 알람 ID 생성 +// ============================================ +fun getCustomAlarmId(date: LocalDate, uniqueId: Int): Int { + // Combine date and a unique ID from DB to avoid collisions + // Using (uniqueId % 1000) to keep it within a reasonable range + return 200000000 + (date.year % 100) * 1000000 + date.monthValue * 10000 + date.dayOfMonth * 100 + (uniqueId % 100) +} + +// ============================================ +// 사용자 알람 예약 +// ============================================ +fun scheduleCustomAlarm( + context: Context, + date: LocalDate, + uniqueId: Int, + shiftType: String, + time: String, + soundUri: String? = null, + snoozeMin: Int = 5, + snoozeRepeat: Int = 3 +) { + val alarmId = getCustomAlarmId(date, uniqueId) + val label = "사용자:$shiftType" + + val parts = time.split(":") + if (parts.size != 2) return + val hour = parts[0].toIntOrNull() ?: return + val min = parts[1].toIntOrNull() ?: return + + cancelAlarmInternal(context, alarmId) + + val intent = Intent(context, AlarmReceiver::class.java).apply { + action = "com.example.shiftalarm.ALARM_TRIGGER" + putExtra("EXTRA_SHIFT", label) + putExtra("EXTRA_DATE", date.toString()) + putExtra("EXTRA_TIME", time) + putExtra("EXTRA_ALARM_ID", alarmId) + putExtra("EXTRA_IS_CUSTOM", true) + putExtra("EXTRA_UNIQUE_ID", uniqueId) // DB 검증용 + putExtra("EXTRA_SOUND", soundUri) + putExtra("EXTRA_SNOOZE", snoozeMin) + putExtra("EXTRA_SNOOZE_REPEAT", snoozeRepeat) + } + + val pendingIntent = PendingIntent.getBroadcast( + context, alarmId, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + + val targetDateTime = LocalDateTime.of(date, LocalTime.of(hour, min)) + .withSecond(0).withNano(0) + + val alarmTime = targetDateTime.atZone(SEOUL_ZONE).toInstant().toEpochMilli() + + if (alarmTime > System.currentTimeMillis()) { + setExactAlarm(context, alarmTime, pendingIntent) + Log.d(TAG, "알람 예약 완료: $date $time (ID: $alarmId)") + } +} + +// ============================================ +// 알람 취소 (전체 범위) +// ============================================ +fun cancelCustomAlarm(context: Context, date: LocalDate, uniqueId: Int) { + val alarmId = getCustomAlarmId(date, uniqueId) + cancelAlarmInternal(context, alarmId) +} + +/** + * 특정 알람의 모든 예약을 완전히 취소합니다. + * DB에서 삭제하기 전에 반드시 호출해야 합니다. + * 삭제한 알람이 울리는 문제를 해결하기 위해 365일치 + 과거 알람까지 모두 취소 + */ +fun cancelAllCustomAlarmSchedules(context: Context, uniqueId: Int) { + val today = LocalDate.now(SEOUL_ZONE) + + // 1. 과거 30일치 취소 (혹시 모를 과거 예약) + for (i in -30 until 0) { + val targetDate = today.plusDays(i.toLong()) + cancelCustomAlarm(context, targetDate, uniqueId) + } + + // 2. 향후 365일치 모든 가능한 ID 취소 (1년치 완전 커버) + for (i in 0 until 365) { + val targetDate = today.plusDays(i.toLong()) + cancelCustomAlarm(context, targetDate, uniqueId) + } + + // 3. 스누즈 알람도 취소 (스누즈는 999999 ID 사용) + cancelSnoozeAlarm(context) + + // 4. 테스트 알람도 취소 (테스트는 888888 ID 사용) + cancelTestAlarm(context) + + // 5. 해당 uniqueId와 관련된 모든 가능한 PendingIntent 취소 (추가 안전장치) + cancelAllPendingIntentsForUniqueId(context, uniqueId) + + Log.d(TAG, "알람 예약 완전 취소 완료 (ID: $uniqueId, 범위: -30일 ~ +365일)") +} + +/** + * 특정 uniqueId에 대한 모든 가능한 PendingIntent를 취소합니다. + * 알람 ID 생성 공식의 역연산을 통해 모든 가능성을 커버합니다. + */ +private fun cancelAllPendingIntentsForUniqueId(context: Context, uniqueId: Int) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + + // uniqueId % 100의 모든 가능한 값에 대해 취소 시도 + val baseId = uniqueId % 100 + + // 현재 연도 기준으로 여러 해에 걸친 가능한 ID들 + val currentYear = LocalDate.now(SEOUL_ZONE).year % 100 + val years = listOf(currentYear - 1, currentYear, currentYear + 1) + + for (year in years) { + if (year < 0) continue + for (month in 1..12) { + for (day in 1..31) { + try { + val alarmId = 200000000 + year * 1000000 + month * 10000 + day * 100 + baseId + val intent = Intent(context, AlarmReceiver::class.java) + val pendingIntent = PendingIntent.getBroadcast( + context, alarmId, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + alarmManager.cancel(pendingIntent) + pendingIntent.cancel() + } catch (e: Exception) { + // 무시 - 유효하지 않은 날짜 조합 + } + } + } + } + + Log.d(TAG, "uniqueId $uniqueId 관련 모든 PendingIntent 취소 완료") +} + +/** + * 스누즈 알람 취소 + */ +/** + * 스누즈 알람 취소 - 모든 가능한 스누즈 ID 취소 + */ +fun cancelSnoozeAlarm(context: Context) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + + // 주요 스누즈 ID들 취소 + val snoozeIds = listOf(999999, 999998, 999997, 999996, 999995) + + for (snoozeId in snoozeIds) { + val intent = Intent(context, AlarmReceiver::class.java).apply { + action = "com.example.shiftalarm.SNOOZE" + } + val pendingIntent = PendingIntent.getBroadcast( + context, snoozeId, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + alarmManager.cancel(pendingIntent) + pendingIntent.cancel() + } + + Log.d(TAG, "스누즈 알람 취소 완료") +} + +/** + * 테스트 알람 취소 + */ +private fun cancelTestAlarm(context: Context) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val intent = Intent(context, AlarmReceiver::class.java).apply { + action = "com.example.shiftalarm.ALARM_TRIGGER" + } + val pendingIntent = PendingIntent.getBroadcast( + context, 888888, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + alarmManager.cancel(pendingIntent) + pendingIntent.cancel() + Log.d(TAG, "테스트 알람 취소 완료") +} + +private fun cancelAlarmInternal(context: Context, alarmId: Int) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val intent = Intent(context, AlarmReceiver::class.java) + val pendingIntent = PendingIntent.getBroadcast( + context, alarmId, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + alarmManager.cancel(pendingIntent) + pendingIntent.cancel() +} + +// ============================================ +// 정밀 알람 설정 (setAlarmClock 우선) +// ============================================ +private fun setExactAlarm(context: Context, triggerTime: Long, pendingIntent: PendingIntent) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (!alarmManager.canScheduleExactAlarms()) { + Log.e(TAG, "정확한 알람 권한 없음!") + return + } + } + + // setAlarmClock은 Doze 모드에서도 정확하게 작동하며 상단바 알람 아이콘을 활성화함 (신뢰도 최고) + try { + val viewIntent = Intent(context, MainActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) + } + val viewPendingIntent = PendingIntent.getActivity( + context, 0, viewIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + + val clockInfo = AlarmManager.AlarmClockInfo(triggerTime, viewPendingIntent) + alarmManager.setAlarmClock(clockInfo, pendingIntent) + Log.d(TAG, "setAlarmClock 예약 성공: ${java.util.Date(triggerTime)}") + } catch (e: Exception) { + Log.e(TAG, "setAlarmClock 실패, fallback 사용", e) + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent) + Log.d(TAG, "setExactAndAllowWhileIdle 예약 성공") + } else { + alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent) + Log.d(TAG, "setExact 예약 성공") + } + } catch (e2: Exception) { + Log.e(TAG, "모든 알람 예약 방법 실패", e2) + } + } +} + +// ============================================ +// 스누즈 +// ============================================ +fun scheduleSnooze(context: Context, snoozeMin: Int, soundUri: String? = null, snoozeRepeat: Int = 3) { + val intent = Intent(context, AlarmReceiver::class.java).apply { + action = "com.example.shiftalarm.SNOOZE" + putExtra("EXTRA_SHIFT", "SNOOZE") + putExtra("EXTRA_SOUND", soundUri) + putExtra("EXTRA_SNOOZE", snoozeMin) + putExtra("EXTRA_SNOOZE_REPEAT", snoozeRepeat) + } + val pendingIntent = PendingIntent.getBroadcast( + context, 999999, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + + val triggerTime = System.currentTimeMillis() + (snoozeMin * 60 * 1000) + setExactAlarm(context, triggerTime, pendingIntent) +} + +// ============================================ +// 테스트 알람 (5초 후) +// ============================================ +fun scheduleTestAlarm(context: Context) { + val intent = Intent(context, AlarmReceiver::class.java).apply { + action = "com.example.shiftalarm.ALARM_TRIGGER" + putExtra("EXTRA_SHIFT", "테스트") + } + val pendingIntent = PendingIntent.getBroadcast( + context, 888888, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + val triggerTime = System.currentTimeMillis() + 5000 + setExactAlarm(context, triggerTime, pendingIntent) +} + +// ============================================ +// 전체 동기화 (30일치 예약) +// ============================================ +suspend fun syncAllAlarms(context: Context) { + Log.d(TAG, "===== 전체 알람 동기화 시작 (30일) =====") + val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + val repo = ShiftRepository(context) + + val today = LocalDate.now(SEOUL_ZONE) + val team = prefs.getString("selected_team", "A") ?: "A" + val factory = prefs.getString("selected_factory", "Jeonju") ?: "Jeonju" + + // 1. 기존 알람 모두 취소 (안전장치) + // Custom 알람의 경우 ID가 uniqueId 기반이므로 모든 가능성 있는 ID를 취소하기는 어려움. + // 대신 AlarmManager에서 해당 PendingIntent를 정확히 취소해야 함. + // 하지만 uniqueId를 알 수 없으므로, 모든 날짜 루프에서 취소 시도. + + val customAlarms = repo.getAllCustomAlarms() + + for (i in 0 until 30) { + val targetDate = today.plusDays(i.toLong()) + // 기본 알람 ID 취소 (이제 안 쓰지만 하위 호환/청소용) + val legacyId = 100000000 + (targetDate.year % 100) * 1000000 + targetDate.monthValue * 10000 + targetDate.dayOfMonth * 100 + cancelAlarmInternal(context, legacyId) + + // 커스텀 알람 취소 + customAlarms.forEach { alarm -> + cancelCustomAlarm(context, targetDate, alarm.id) + } + } + + if (!ShiftAlarmDefaults.isMasterAlarmEnabled(prefs)) { + Log.d(TAG, "마스터 알람이 꺼져 있어 예약을 중단합니다.") + return + } + + // 2. 새로운 스케줄 생성 + for (i in 0 until 30) { + val targetDate = today.plusDays(i.toLong()) + val shift = repo.getShift(targetDate, team, factory) + + for (alarm in customAlarms) { + if (!alarm.isEnabled) continue + + // 근무 연동 조건 확인 + if (alarm.shiftType == "기타" || alarm.shiftType == shift) { + scheduleCustomAlarm( + context, + targetDate, + alarm.id, + alarm.shiftType, + alarm.time, + alarm.soundUri, + alarm.snoozeInterval, + alarm.snoozeRepeat + ) + } + } + } + Log.d(TAG, "===== 전체 알람 동기화 완료 =====") +} diff --git a/app/src/main/java/com/example/shiftalarm/AlarmWorker.kt b/app/src/main/java/com/example/shiftalarm/AlarmWorker.kt new file mode 100644 index 0000000..895b22d --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AlarmWorker.kt @@ -0,0 +1,28 @@ +package com.example.shiftalarm + +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import androidx.work.CoroutineWorker +import androidx.work.WorkerParameters +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.ZoneId + + +class AlarmWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { + + override suspend fun doWork(): Result = withContext(Dispatchers.IO) { + try { + syncAllAlarms(applicationContext) + Result.success() + } catch (e: Exception) { + e.printStackTrace() + Result.retry() + } + } +} diff --git a/app/src/main/java/com/example/shiftalarm/AppDatabase.kt b/app/src/main/java/com/example/shiftalarm/AppDatabase.kt new file mode 100644 index 0000000..3ce0004 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AppDatabase.kt @@ -0,0 +1,28 @@ +package com.example.shiftalarm + +import android.content.Context +import androidx.room.* + +@Database(entities = [ShiftOverride::class, DailyMemo::class, CustomAlarm::class], version = 3, exportSchema = false) +abstract class AppDatabase : RoomDatabase() { + abstract fun shiftDao(): ShiftDao + + companion object { + @Volatile + private var INSTANCE: AppDatabase? = null + + fun getDatabase(context: Context): AppDatabase { + return INSTANCE ?: synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + AppDatabase::class.java, + "shift_database" + ) + .fallbackToDestructiveMigration() // Simple for now + .build() + INSTANCE = instance + instance + } + } + } +} diff --git a/app/src/main/java/com/example/shiftalarm/AppUpdateManager.kt b/app/src/main/java/com/example/shiftalarm/AppUpdateManager.kt new file mode 100644 index 0000000..aecc693 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/AppUpdateManager.kt @@ -0,0 +1,187 @@ +package com.example.shiftalarm + +import android.app.Activity +import android.app.ProgressDialog +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.widget.Toast +import androidx.appcompat.app.AlertDialog +import androidx.core.content.FileProvider +import org.json.JSONObject +import java.io.BufferedInputStream +import java.io.File +import java.io.FileOutputStream +import java.net.HttpURLConnection +import java.net.URL + +object AppUpdateManager { + + private const val VERSION_URL = "https://git.webpluss.net/sanjeok77/ShiftRing/raw/branch/main/version.json" + + fun checkUpdate(activity: Activity, silent: Boolean = false) { + val ctx = activity.applicationContext + val versionCheckUrl = "$VERSION_URL?t=${System.currentTimeMillis()}" + + Thread { + try { + val url = URL(versionCheckUrl) + val connection = url.openConnection() as HttpURLConnection + connection.connectTimeout = 5000 + connection.readTimeout = 5000 + connection.requestMethod = "GET" + connection.useCaches = false + + if (connection.responseCode == 200) { + val reader = connection.inputStream.bufferedReader() + val result = reader.readText() + reader.close() + + val json = JSONObject(result) + val serverVersionName = json.getString("versionName") + val apkUrl = json.getString("apkUrl") + val changelog = json.optString("changelog", "버그 수정 및 성능 향상") + + val pInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0) + val currentVersionName = pInfo.versionName ?: "0.0.0" + + if (isNewerVersion(serverVersionName, currentVersionName)) { + activity.runOnUiThread { + showUpdateDialog(activity, serverVersionName, changelog, apkUrl) + } + } else if (!silent) { + activity.runOnUiThread { + Toast.makeText(ctx, "현재 최신 버전을 사용 중입니다. ($currentVersionName)", Toast.LENGTH_SHORT).show() + } + } + } else if (!silent) { + activity.runOnUiThread { + Toast.makeText(ctx, "서버 연결 실패", Toast.LENGTH_SHORT).show() + } + } + } catch (e: Exception) { + e.printStackTrace() + if (!silent) { + activity.runOnUiThread { + Toast.makeText(ctx, "업데이트 확인 중 오류 발생", Toast.LENGTH_SHORT).show() + } + } + } + }.start() + } + + private fun isNewerVersion(server: String, current: String): Boolean { + try { + // Clean version strings (remove non-numeric suffixes if any) + val sClean = server.split("-")[0].split(" ")[0] + val cClean = current.split("-")[0].split(" ")[0] + + val sParts = sClean.split(".").map { it.filter { char -> char.isDigit() }.let { p -> if (p.isEmpty()) 0 else p.toInt() } } + val cParts = cClean.split(".").map { it.filter { char -> char.isDigit() }.let { p -> if (p.isEmpty()) 0 else p.toInt() } } + + val length = Math.max(sParts.size, cParts.size) + for (i in 0 until length) { + val s = if (i < sParts.size) sParts[i] else 0 + val c = if (i < cParts.size) cParts[i] else 0 + if (s > c) return true + if (s < c) return false + } + } catch (e: Exception) { + android.util.Log.e("AppUpdateManager", "Version comparison failed: ${e.message}") + return false + } + return false + } + + private fun showUpdateDialog(activity: Activity, version: String, changelog: String, apkUrl: String) { + com.google.android.material.dialog.MaterialAlertDialogBuilder(activity) + .setTitle("새로운 업데이트 발견 (v$version)") + .setMessage("업데이트 내용:\n$changelog\n\n지금 다운로드하시겠습니까?") + .setPositiveButton("다운로드") { _, _ -> + downloadAndInstallApk(activity, apkUrl, version) + } + .setNegativeButton("나중에", null) + .show() + } + + private fun downloadAndInstallApk(activity: Activity, apkUrl: String, version: String) { + val progressDialog = ProgressDialog(activity).apply { + setTitle("업데이트 다운로드 중") + setMessage("v$version 다운로드 중...") + setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) + setCancelable(false) + max = 100 + show() + } + + Thread { + try { + val url = URL(apkUrl) + val connection = url.openConnection() as HttpURLConnection + connection.connectTimeout = 15000 + connection.readTimeout = 15000 + connection.requestMethod = "GET" + connection.connect() + + val fileLength = connection.contentLength + val inputStream = BufferedInputStream(connection.inputStream) + + val apkFile = File(activity.cacheDir, "update.apk") + val outputStream = FileOutputStream(apkFile) + + val buffer = ByteArray(8192) + var total: Long = 0 + var count: Int + + while (inputStream.read(buffer).also { count = it } != -1) { + total += count + outputStream.write(buffer, 0, count) + + if (fileLength > 0) { + val progress = (total * 100 / fileLength).toInt() + activity.runOnUiThread { + progressDialog.progress = progress + } + } + } + + outputStream.flush() + outputStream.close() + inputStream.close() + connection.disconnect() + + activity.runOnUiThread { + progressDialog.dismiss() + installApk(activity, apkFile) + } + + } catch (e: Exception) { + e.printStackTrace() + activity.runOnUiThread { + progressDialog.dismiss() + Toast.makeText(activity, "다운로드 실패: ${e.message}", Toast.LENGTH_LONG).show() + } + } + }.start() + } + + private fun installApk(activity: Activity, apkFile: File) { + try { + val apkUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + FileProvider.getUriForFile(activity, "${activity.packageName}.provider", apkFile) + } else { + Uri.fromFile(apkFile) + } + + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION + } + activity.startActivity(intent) + } catch (e: Exception) { + e.printStackTrace() + Toast.makeText(activity, "설치 실패: ${e.message}", Toast.LENGTH_LONG).show() + } + } +} diff --git a/app/src/main/java/com/example/shiftalarm/BackupManager.kt b/app/src/main/java/com/example/shiftalarm/BackupManager.kt new file mode 100644 index 0000000..b3ce6d9 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/BackupManager.kt @@ -0,0 +1,178 @@ +package com.example.shiftalarm + +import android.content.Context +import android.net.Uri +import org.json.JSONArray +import org.json.JSONObject +import java.io.InputStreamReader +import java.io.OutputStreamWriter +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +/** + * Handles data backup and restoration (Database + SharedPreferences). + * Format: JSON + */ +object BackupManager { + + suspend fun backupData(context: Context, uri: Uri, dao: ShiftDao) = withContext(Dispatchers.IO) { + val overrides = dao.getAllOverrides() + val memos = dao.getAllMemos() + + val json = JSONObject() + + // 1. Backup Overrides + val overrideArray = JSONArray() + overrides.forEach { + overrideArray.put(JSONObject().apply { + put("date", it.date) + put("shift", it.shift) + put("team", it.team) + put("factory", it.factory) + }) + } + json.put("overrides", overrideArray) + + // 1.5 Backup Custom Alarms + val customAlarms = dao.getAllCustomAlarms() + val customAlarmArray = JSONArray() + customAlarms.forEach { + customAlarmArray.put(JSONObject().apply { + put("time", it.time) + put("shiftType", it.shiftType) + put("isEnabled", it.isEnabled) + put("soundUri", it.soundUri) + put("snoozeInterval", it.snoozeInterval) + put("snoozeRepeat", it.snoozeRepeat) + }) + } + json.put("custom_alarms_v2", customAlarmArray) + + // 2. Backup Memos + val memoArray = JSONArray() + memos.forEach { + memoArray.put(JSONObject().apply { + put("date", it.date) + put("content", it.content) + }) + } + json.put("memos", memoArray) + + // 3. Backup Settings (SharedPreferences) + val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + val settings = JSONObject() + prefs.all.forEach { (key, value) -> + if (value is String) settings.put(key, value) + else if (value is Boolean) settings.put(key, value) + else if (value is Int) settings.put(key, value) + else if (value is Float) settings.put(key, value.toDouble()) + else if (value is Long) settings.put(key, value) + else if (value is Double) settings.put(key, value) + } + json.put("settings", settings) + + json.put("magic", "SHIFTRING_BACKUP_V3") + json.put("timestamp", System.currentTimeMillis()) + + val finalString = json.toString() + val encodedBytes = android.util.Base64.encode(finalString.toByteArray(), android.util.Base64.DEFAULT) + + context.contentResolver.openOutputStream(uri)?.use { os -> + os.write(encodedBytes) + } + } + + suspend fun restoreData(context: Context, uri: Uri, dao: ShiftDao) = withContext(Dispatchers.IO) { + val bytes = context.contentResolver.openInputStream(uri)?.use { + it.readBytes() + } ?: throw Exception("Failed to read file") + + var content = "" + try { + // Try Base64 first (V3) + val decodedBytes = android.util.Base64.decode(bytes, android.util.Base64.DEFAULT) + content = String(decodedBytes) + } catch (e: Exception) { + // Fallback to plain text (V1/V2) + content = String(bytes) + } + + val json = JSONObject(content) + + val magic = json.optString("magic", "") + if (magic != "SHIFTRING_BACKUP_V1" && magic != "SHIFTRING_BACKUP_V2" && magic != "SHIFTRING_BACKUP_V3") { + throw Exception("올바르지 않은 백업 파일 형식입니다.") + } + + // 1. Restore Settings FIRST + if (json.has("settings")) { + val settings = json.getJSONObject("settings") + val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE).edit() + prefs.clear() + val keys = settings.keys() + while(keys.hasNext()) { + val key = keys.next() + if (settings.isNull(key)) continue + + val value = settings.get(key) + when(value) { + is Boolean -> prefs.putBoolean(key, value) + is Int -> prefs.putInt(key, value) + is String -> prefs.putString(key, value) + is Double -> prefs.putFloat(key, value.toFloat()) + is Long -> prefs.putLong(key, value) + } + } + prefs.apply() + } + + val restoredPrefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + val fallbackFactory = restoredPrefs.getString("selected_factory", "Jeonju") ?: "Jeonju" + val fallbackTeam = restoredPrefs.getString("selected_team", "A") ?: "A" + + // 2. Restore Overrides + if (json.has("overrides")) { + dao.clearOverrides() + val arr = json.getJSONArray("overrides") + for (i in 0 until arr.length()) { + val obj = arr.getJSONObject(i) + dao.insertOverride(ShiftOverride( + factory = obj.optString("factory", fallbackFactory), + team = obj.optString("team", fallbackTeam), + date = obj.getString("date"), + shift = obj.getString("shift") + )) + } + } + + // 2.5 Restore Custom Alarms + if (json.has("custom_alarms_v2")) { + dao.clearCustomAlarms() + val arr = json.getJSONArray("custom_alarms_v2") + for (i in 0 until arr.length()) { + val obj = arr.getJSONObject(i) + dao.insertCustomAlarm(CustomAlarm( + time = obj.getString("time"), + shiftType = obj.getString("shiftType"), + isEnabled = obj.optBoolean("isEnabled", true), + soundUri = obj.optString("soundUri", null), + snoozeInterval = obj.optInt("snoozeInterval", 5), + snoozeRepeat = obj.optInt("snoozeRepeat", 3) + )) + } + } + + // 3. Restore Memos + if (json.has("memos")) { + dao.clearMemos() + val arr = json.getJSONArray("memos") + for (i in 0 until arr.length()) { + val obj = arr.getJSONObject(i) + dao.insertMemo(DailyMemo( + obj.getString("date"), + obj.getString("content") + )) + } + } + } +} diff --git a/app/src/main/java/com/example/shiftalarm/BootReceiver.kt b/app/src/main/java/com/example/shiftalarm/BootReceiver.kt new file mode 100644 index 0000000..78c737b --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/BootReceiver.kt @@ -0,0 +1,37 @@ +package com.example.shiftalarm + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.PeriodicWorkRequestBuilder +import androidx.work.WorkManager +import java.util.concurrent.TimeUnit + +class BootReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent?) { + if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { + android.util.Log.d("ShiftAlarm", "[부팅] 기기 부팅 감지, 알람 복구 시작") + + // 1) 즉시 1회 실행 → 당일 알람을 바로 복구 + val immediateWork = OneTimeWorkRequestBuilder().build() + WorkManager.getInstance(context).enqueueUniqueWork( + "BootAlarmRestore", + androidx.work.ExistingWorkPolicy.REPLACE, + immediateWork + ) + + // 2) 24시간 주기 반복 워커 등록 + val periodicWork = PeriodicWorkRequestBuilder(24, TimeUnit.HOURS) + .build() + WorkManager.getInstance(context).enqueueUniquePeriodicWork( + "DailyShiftCheck", + androidx.work.ExistingPeriodicWorkPolicy.KEEP, + periodicWork + ) + + android.util.Log.d("ShiftAlarm", "[부팅] 알람 복구 워커 등록 완료") + } + } +} diff --git a/app/src/main/java/com/example/shiftalarm/CalendarAdapter.kt b/app/src/main/java/com/example/shiftalarm/CalendarAdapter.kt new file mode 100644 index 0000000..0a5ff2a --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/CalendarAdapter.kt @@ -0,0 +1,238 @@ +package com.example.shiftalarm + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import java.time.LocalDate + +data class DayShift( + val date: LocalDate?, + val shift: String?, + val hasMemo: Boolean = false, + val memoContent: String? = null +) + +class CalendarAdapter( + var days: List, + private val listener: OnDayClickListener, + var showHolidays: Boolean = true +) : RecyclerView.Adapter() { + + interface OnDayClickListener { + fun onDayClick(date: LocalDate, currentShift: String) + } + + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val root: View = view.findViewById(R.id.dayRoot) + val dayNumber: TextView = view.findViewById(R.id.dayNumber) + val shiftChar: TextView = view.findViewById(R.id.shiftChar) + val holidayNameSmall: TextView = view.findViewById(R.id.holidayNameSmall) + val memoIndicator: ImageView = view.findViewById(R.id.memoIndicator) + val tvTide: TextView = view.findViewById(R.id.tvTide) + val memoContent: TextView = view.findViewById(R.id.memoContent) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.item_day, parent, false) + return ViewHolder(view) + } + + private fun dpToPx(context: Context, dp: Float): Int { + return (dp * context.resources.displayMetrics.density).toInt() + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val item = days[position] + val context = holder.itemView.context + + if (item.date == null) { + holder.itemView.visibility = View.INVISIBLE + return + } + + holder.itemView.visibility = View.VISIBLE + + // Day Number + holder.dayNumber.text = item.date.dayOfMonth.toString() + + // Holiday / Weekend logic + val isSunday = item.date.dayOfWeek == java.time.DayOfWeek.SUNDAY + val isSaturday = item.date.dayOfWeek == java.time.DayOfWeek.SATURDAY + val fullHolidayName = HolidayManager.getHolidayName(item.date) + val isToday = item.date == LocalDate.now() + + // Day Number Color + if (fullHolidayName != null || isSunday) { + holder.dayNumber.setTextColor(Color.parseColor("#FF5252")) + } else if (isSaturday) { + holder.dayNumber.setTextColor(Color.parseColor("#448AFF")) + } else { + holder.dayNumber.setTextColor(ContextCompat.getColor(context, R.color.text_primary)) + } + + // Tide Display + val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE) + val showTide = prefs.getBoolean("show_tide", false) + val tideLocation = prefs.getString("selected_tide_location", "군산") ?: "군산" + + if (showTide) { + val tide = HolidayManager.getTide(item.date, tideLocation) + if (tide.isNotEmpty()) { + holder.tvTide.visibility = View.VISIBLE + holder.tvTide.text = tide + } else { + holder.tvTide.visibility = View.GONE + } + } else { + holder.tvTide.visibility = View.GONE + } + + + // --- Shift & Holiday Display Logic --- + holder.shiftChar.background = null + holder.shiftChar.text = "" + holder.holidayNameSmall.visibility = View.GONE + holder.shiftChar.textSize = 13f + + // "반월", "반년" (Half-Monthly, Half-Yearly) Special Logic + // These are overrides or specific shifts that user sets. + // User requested: "월", "년" text. Half-filled background (Red + Transparent). + // Check exact string or "startswith" if logic changed? + // Logic in adapter `getShift` might return "반월", "반년". + + if (showHolidays && fullHolidayName != null) { + // Holiday Mode (Priority): Show full holiday name, no circle + holder.shiftChar.text = fullHolidayName + holder.shiftChar.setTextColor(Color.parseColor("#FF5252")) + holder.shiftChar.textSize = 10f + holder.shiftChar.background = null + } else if (item.shift != null && item.shift != "비번") { + // Shift Mode + + // Handle specific "Half" cases first + if (item.shift == "반월" || item.shift == "반년") { + holder.shiftChar.text = if (item.shift == "반월") "월" else "년" + holder.shiftChar.setTextColor(ContextCompat.getColor(context, R.color.black)) // Black for contrast on Half Red/Transparent + holder.shiftChar.textSize = 13f + holder.shiftChar.background = ContextCompat.getDrawable(context, R.drawable.bg_shift_half_red) + } else { + // Standard Logic + val shiftAbbreviation = when (item.shift) { + "주간" -> "주" + "석간" -> "석" + "야간" -> "야" + "주간 맞교대" -> "주맞" + "야간 맞교대" -> "야맞" + "휴무", "휴가" -> "휴" + "월차" -> "월" + "연차" -> "연" + "교육" -> "교" + else -> item.shift.take(1) + } + holder.shiftChar.text = shiftAbbreviation + holder.shiftChar.textSize = 15f + holder.shiftChar.setTypeface(null, android.graphics.Typeface.BOLD) + + val shiftColorRes = when (item.shift) { + "주간" -> R.color.shift_lemon + "석간" -> R.color.shift_seok + "야간" -> R.color.shift_ya + "주간 맞교대" -> R.color.shift_jumat + "야간 맞교대" -> R.color.shift_yamat + "휴무", "휴가", "월차", "연차" -> R.color.shift_red + "교육" -> R.color.primary + else -> R.color.text_secondary + } + val shiftColor = ContextCompat.getColor(context, shiftColorRes) + + if (isToday) { + // Today: Solid Circle + val background = ContextCompat.getDrawable(context, R.drawable.bg_shift_solid_v4) as? android.graphics.drawable.GradientDrawable + background?.setColor(shiftColor) + holder.shiftChar.background = background + holder.shiftChar.backgroundTintList = null + + if (item.shift == "주간" || item.shift == "석간") { + holder.shiftChar.setTextColor(ContextCompat.getColor(context, R.color.black)) + } else { + holder.shiftChar.setTextColor(Color.WHITE) + } + } else { + // Not Today: Stroke Circle + val background = ContextCompat.getDrawable(context, R.drawable.bg_shift_stroke_v4) as? android.graphics.drawable.GradientDrawable + background?.setStroke(dpToPx(context, 1.5f), shiftColor) + background?.setColor(Color.TRANSPARENT) + + holder.shiftChar.background = background + holder.shiftChar.backgroundTintList = null + + holder.shiftChar.setTextColor(shiftColor) + } + } + } + + // Lunar date small display if requested or just default + if (!showHolidays && fullHolidayName != null) { + holder.holidayNameSmall.visibility = View.VISIBLE + holder.holidayNameSmall.text = fullHolidayName + } else { + // Ensure visibility GONE if not needed (e.g. standard day) + holder.holidayNameSmall.visibility = View.GONE + } + + // Double check: if showHolidays=true (Holiday mode), we handled it at top block. + // But if showHolidays=true and NO holiday, we show lunar date? + // User asked: "Overlap date and holiday text". + // My item_day.xml has holidayNameSmall at bottom now. + // If showHolidays=true, CalendarAdapter usually HIDES shiftChar and shows Holiday Name? + // Wait, standard logic (lines 84-91 above): + // If showHolidays && fullHolidayName != null -> shiftChar shows Name. + // If showHolidays && fullHolidayName == null -> shiftChar shows LUNAR DATE? (Old logic had this). + + if (showHolidays && fullHolidayName == null) { + // Show Lunar Date in shiftChar instead of empty? + // Or shiftChar is empty, show small text? + // Previous code: + // holder.shiftChar.text = "" + // holder.holidayNameSmall.visibility = View.VISIBLE + // holder.holidayNameSmall.text = HolidayManager.getLunarDateString(item.date) + + holder.shiftChar.text = HolidayManager.getLunarDateString(item.date) + holder.shiftChar.textSize = 10f + holder.shiftChar.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary)) + holder.shiftChar.background = null + } + + + // Memo Indicator + holder.memoIndicator.visibility = View.GONE // Hide indicator, showing text instead + if (item.hasMemo && !item.memoContent.isNullOrEmpty()) { + holder.memoContent.visibility = View.VISIBLE + holder.memoContent.text = item.memoContent + } else { + holder.memoContent.visibility = View.GONE + } + + // Today Border or Highlight + if (isToday) { + holder.root.setBackgroundResource(R.drawable.bg_grid_cell_today_v4) + } else { + holder.root.setBackgroundResource(R.drawable.bg_grid_cell_v4) + } + + holder.itemView.setOnClickListener { + if (item.date != null && item.shift != null) { + listener.onDayClick(item.date, item.shift) + } + } + } + + override fun getItemCount(): Int = days.size +} diff --git a/app/src/main/java/com/example/shiftalarm/Entities.kt b/app/src/main/java/com/example/shiftalarm/Entities.kt new file mode 100644 index 0000000..5c6256f --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/Entities.kt @@ -0,0 +1,30 @@ +package com.example.shiftalarm + +import androidx.room.* + +@Entity(tableName = "shift_overrides", primaryKeys = ["factory", "team", "date"]) +data class ShiftOverride( + val factory: String, + val team: String, + val date: String, // YYYY-MM-DD + val shift: String +) + +@Entity(tableName = "daily_memos") +data class DailyMemo( + @PrimaryKey + val date: String, // YYYY-MM-DD + val content: String +) + +@Entity(tableName = "custom_alarms") +data class CustomAlarm( + @PrimaryKey(autoGenerate = true) + val id: Int = 0, + val time: String, // HH:MM + val shiftType: String, // 주간, 석간, 야간 ... 기타 + val isEnabled: Boolean = true, + val soundUri: String? = null, + val snoozeInterval: Int = 5, + val snoozeRepeat: Int = 3 +) diff --git a/app/src/main/java/com/example/shiftalarm/FragmentSettingsAdditional.kt b/app/src/main/java/com/example/shiftalarm/FragmentSettingsAdditional.kt new file mode 100644 index 0000000..c59fc88 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/FragmentSettingsAdditional.kt @@ -0,0 +1,218 @@ +package com.example.shiftalarm + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import com.example.shiftalarm.databinding.FragmentSettingsAdditionalBinding +import kotlinx.coroutines.launch +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +class FragmentSettingsAdditional : Fragment() { + private var _binding: FragmentSettingsAdditionalBinding? = null + private val binding get() = _binding!! + + private val PREFS_NAME = "ShiftAlarmPrefs" + private var isUserInteraction = false + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + _binding = FragmentSettingsAdditionalBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + loadSettings() + setupListeners() + } + + private val backupLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("application/json")) { uri -> + uri?.let { + lifecycleScope.launch { + try { + val db = AppDatabase.getDatabase(requireContext()) + BackupManager.backupData(requireContext(), it, db.shiftDao()) + Toast.makeText(requireContext(), "백업이 완료되었습니다.", Toast.LENGTH_SHORT).show() + } catch (e: Exception) { + Toast.makeText(requireContext(), "백업 실패: ${e.message}", Toast.LENGTH_LONG).show() + } + } + } + } + + private val restoreLauncher = registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri -> + uri?.let { + lifecycleScope.launch { + try { + val db = AppDatabase.getDatabase(requireContext()) + BackupManager.restoreData(requireContext(), it, db.shiftDao()) + androidx.appcompat.app.AlertDialog.Builder(requireContext()) + .setTitle("복구 완료") + .setMessage("데이터 복구가 완료되었습니다. 변경사항을 적용하기 위해 앱을 재시작해야 합니다.") + .setPositiveButton("앱 재시작") { _, _ -> + val intent = requireContext().packageManager.getLaunchIntentForPackage(requireContext().packageName) + intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + intent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(intent) + requireActivity().finish() + } + .setCancelable(false) + .show() + loadSettings() + } catch (e: Exception) { + Toast.makeText(requireContext(), "복구 실패: ${e.message}", Toast.LENGTH_LONG).show() + } + } + } + } + + private fun loadSettings() { + val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + // Theme Spinner + val themeOptions = resources.getStringArray(R.array.theme_array) + val themeAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, themeOptions) + themeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + binding.themeSpinner.adapter = themeAdapter + + val themeMode = prefs.getInt("theme_mode", androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) + val themeIndex = when(themeMode) { + androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO -> 1 + androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES -> 2 + else -> 0 + } + binding.themeSpinner.setSelection(themeIndex) + + // Tide Switch + binding.switchTide.isChecked = prefs.getBoolean("show_tide", false) + } + + private fun setupListeners() { + val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + binding.themeSpinner.setOnTouchListener { _, _ -> + isUserInteraction = true + false + } + + binding.themeSpinner.onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: android.widget.AdapterView<*>?, view: View?, position: Int, id: Long) { + if (!isUserInteraction) return + + val themeMode = when(position) { + 1 -> androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO + 2 -> androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES + else -> androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + } + + // Save and Apply + val currentMode = prefs.getInt("theme_mode", -1) + if (currentMode != themeMode) { + prefs.edit().putInt("theme_mode", themeMode).apply() + + // Critical Guard: Only apply if it actually changes the global state + if (androidx.appcompat.app.AppCompatDelegate.getDefaultNightMode() != themeMode) { + androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode(themeMode) + } + } + } + override fun onNothingSelected(parent: android.widget.AdapterView<*>?) {} + } + + // Tide Switch Listener (Fixed: properly saving now) + binding.switchTide.setOnCheckedChangeListener { _, isChecked -> + prefs.edit().putBoolean("show_tide", isChecked).apply() + } + + // Backup/Restore buttons + binding.btnBackup.setOnClickListener { + val dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmm")) + backupLauncher.launch("shiftring_backup_$dateStr.json") + } + + binding.btnRestore.setOnClickListener { + restoreLauncher.launch(arrayOf("application/json")) + } + + binding.btnManual.setOnClickListener { + startActivity(Intent(requireContext(), ManualActivity::class.java)) + } + + binding.btnNotice.setOnClickListener { + startActivity(Intent(requireContext(), NoticeActivity::class.java)) + } + + binding.btnShareApp.setOnClickListener { + lifecycleScope.launch(kotlinx.coroutines.Dispatchers.IO) { + try { + val context = requireContext() + val pm = context.packageManager + val appInfo = pm.getApplicationInfo(context.packageName, 0) + val apkFile = java.io.File(appInfo.sourceDir) + + val cachePath = java.io.File(context.cacheDir, "apks") + cachePath.mkdirs() + val newFile = java.io.File(cachePath, "ShiftRing_Installer.apk") + + apkFile.copyTo(newFile, overwrite = true) + + val contentUri = androidx.core.content.FileProvider.getUriForFile( + context, + "${context.packageName}.provider", + newFile + ) + + val shareIntent = Intent(Intent.ACTION_SEND) + shareIntent.type = "application/vnd.android.package-archive" + shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri) + shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + + kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.Main) { + startActivity(Intent.createChooser(shareIntent, "앱 설치 파일 공유하기")) + } + } catch (e: Exception) { + kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.Main) { + Toast.makeText(requireContext(), "공유 실패: ${e.message}", Toast.LENGTH_SHORT).show() + } + } + } + } + + binding.btnResetOverrides.setOnClickListener { + androidx.appcompat.app.AlertDialog.Builder(requireContext()) + .setTitle("데이터 초기화") + .setMessage("달력에서 개별적으로 바꾼 모든 근무와 알람 설정이 삭제됩니다. 계속하시겠습니까?") + .setPositiveButton("초기화") { _, _ -> + lifecycleScope.launch { + try { + val db = AppDatabase.getDatabase(requireContext()) + val dao = db.shiftDao() + dao.clearOverrides() + + // Immediately re-sync all alarms + syncAllAlarms(requireContext()) + + Toast.makeText(requireContext(), "모든 개별 설정이 삭제되고 알람이 재설정되었습니다.", Toast.LENGTH_SHORT).show() + } catch (e: Exception) { + Toast.makeText(requireContext(), "초기화 실패: ${e.message}", Toast.LENGTH_LONG).show() + } + } + } + .setNegativeButton("취소", null) + .show() + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} diff --git a/app/src/main/java/com/example/shiftalarm/FragmentSettingsAlarm.kt b/app/src/main/java/com/example/shiftalarm/FragmentSettingsAlarm.kt new file mode 100644 index 0000000..4fd3e62 --- /dev/null +++ b/app/src/main/java/com/example/shiftalarm/FragmentSettingsAlarm.kt @@ -0,0 +1,574 @@ +package com.example.shiftalarm + +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.graphics.Color +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import android.widget.TimePicker +import android.widget.Toast +import androidx.appcompat.app.AlertDialog +import com.google.android.material.materialswitch.MaterialSwitch +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import com.example.shiftalarm.databinding.FragmentSettingsAlarmBinding +import kotlinx.coroutines.launch +import org.json.JSONArray +import org.json.JSONObject +import java.time.LocalDate + +class FragmentSettingsAlarm : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener { + + private var _binding: FragmentSettingsAlarmBinding? = null + private val binding get() = _binding!! + private val PREFS_NAME = "ShiftAlarmPrefs" + private lateinit var repository: ShiftRepository + private var customAlarms: MutableList = mutableListOf() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentSettingsAlarmBinding.inflate(inflater, container, false) + repository = ShiftRepository(requireContext()) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + prefs.registerOnSharedPreferenceChangeListener(this) + + setupListeners() + loadSettings() + } + + override fun onResume() { + super.onResume() + refreshAlarmList() + } + + override fun onDestroyView() { + super.onDestroyView() + val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + prefs.unregisterOnSharedPreferenceChangeListener(this) + _binding = null + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + if (key == "master_alarm_enabled") { + sharedPreferences?.let { + updateMasterToggleUI(ShiftAlarmDefaults.isMasterAlarmEnabled(it)) + } + } + } + + private fun loadSettings() { + val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + // Master Toggle Button State + updateMasterToggleUI(ShiftAlarmDefaults.isMasterAlarmEnabled(prefs)) + + // Migrate and Refresh + lifecycleScope.launch { + migrateFromPrefsIfNecessary() + refreshAlarmList() + } + } + + private suspend fun migrateFromPrefsIfNecessary() { + val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + val legacyJson = prefs.getString("custom_alarms", null) + if (legacyJson != null) { + try { + val arr = JSONArray(legacyJson) + for (i in 0 until arr.length()) { + val obj = arr.getJSONObject(i) + val alarm = CustomAlarm( + time = obj.getString("time"), + shiftType = obj.getString("shiftType"), + isEnabled = obj.optBoolean("enabled", true), + soundUri = obj.optString("soundUri", null), + snoozeInterval = obj.optInt("snoozeInterval", 5), + snoozeRepeat = obj.optInt("snoozeRepeat", 3) + ) + repository.addCustomAlarm(alarm) + } + // Clear legacy data + prefs.edit().remove("custom_alarms").apply() + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + private fun refreshAlarmList() { + lifecycleScope.launch { + customAlarms = repository.getAllCustomAlarms().toMutableList() + refreshUI() + } + } + + private val soundTitleCache = mutableMapOf() + + private fun updateMasterToggleUI(isEnabled: Boolean) { + if (isEnabled) { + binding.tvMasterStatus.text = "전체 알람 켜짐" + binding.tvMasterStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.primary)) + binding.tvMasterStatus.backgroundTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#E3F2FD")) + } else { + binding.tvMasterStatus.text = "전체 알람 꺼짐" + binding.tvMasterStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.shift_red)) + binding.tvMasterStatus.backgroundTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#FFEBEE")) + } + } + + private fun setupListeners() { + val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + binding.tvMasterStatus.setOnClickListener { + val isEnabled = !ShiftAlarmDefaults.isMasterAlarmEnabled(prefs) + prefs.edit().putBoolean("master_alarm_enabled", isEnabled).apply() + updateMasterToggleUI(isEnabled) + + val message = if (isEnabled) "전체 알람이 켜졌습니다." else "전체 알람이 꺼졌습니다." + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + + // Resync immediately + lifecycleScope.launch { syncAllAlarms(requireContext()) } + } + + binding.btnAddCustomAlarm.setOnClickListener { + showEditDialog( + title = "새 알람 추가", + currentTime = "07:00", + shiftType = "주간", + existingAlarm = null, + isNew = true + ) + } + + binding.btnTestAlarm.setOnClickListener { + scheduleTestAlarm(requireContext()) + } + } + + private fun refreshUI() { + val container = binding.alarmListContainer + container.removeAllViews() + + for (alarm in customAlarms) { + val item = createAlarmRow(alarm.shiftType, alarm.time, alarm.isEnabled, isCustom = true, snoozeMin = alarm.snoozeInterval, snoozeRepeat = alarm.snoozeRepeat, soundUri = alarm.soundUri) { isToggle, isLongOrShort -> + if (isToggle) { + // AlarmSyncManager를 사용하여 토글 동기화 + lifecycleScope.launch { + val enable = !alarm.isEnabled + val result = AlarmSyncManager.toggleAlarm(requireContext(), alarm, enable) + if (result.isSuccess) { + Log.d("ShiftAlarm", "알람 토글 동기화 성공: ID=${alarm.id}, enabled=$enable") + } else { + Log.e("ShiftAlarm", "알람 토글 동기화 실패", result.exceptionOrNull()) + Toast.makeText(requireContext(), "알람 상태 변경 중 오류가 발생했습니다.", Toast.LENGTH_SHORT).show() + } + refreshAlarmList() + } + } else { + showEditDialog("사용자 알람", alarm.time, alarm.shiftType, existingAlarm = alarm, isNew = false) + } + } + container.addView(item) + } + } + + private fun createAlarmRow( + shiftName: String, + time: String, + isEnabled: Boolean, + isCustom: Boolean, + snoozeMin: Int, + snoozeRepeat: Int, + soundUri: String?, + onAction: (isToggle: Boolean, isLongClick: Boolean) -> Unit + ): View { + val view = layoutInflater.inflate(R.layout.item_alarm_unified, binding.alarmListContainer, false) + view.isFocusable = true + + val shiftIndicator = view.findViewById(R.id.shiftIndicator) + val tvTime = view.findViewById(R.id.tvTime) + val tvAmPm = view.findViewById(R.id.tvAmPm) + val tvSummary = view.findViewById(R.id.tvSummary) + val alarmSwitch = view.findViewById(R.id.alarmSwitch) + val layoutAlarmSwitch = view.findViewById(R.id.layoutAlarmSwitch) + + val shortName = when(shiftName) { + "주간" -> "주" + "석간" -> "석" + "야간" -> "야" + "주간 맞교대" -> "주맞" + "야간 맞교대" -> "야맞" + "기타" -> "기타" + else -> shiftName.take(1) + } + shiftIndicator.text = shortName + + val colorRes = when(shiftName) { + "주간" -> R.color.shift_lemon + "석간" -> R.color.shift_seok + "야간" -> R.color.shift_ya + "주간 맞교대" -> R.color.shift_jumat + "야간 맞교대" -> R.color.shift_yamat + else -> R.color.shift_gray + } + + val context = requireContext() + val color = ContextCompat.getColor(context, colorRes) + val drawable = ContextCompat.getDrawable(context, R.drawable.bg_shift_stroke_v4) as android.graphics.drawable.GradientDrawable + drawable.mutate() + drawable.setStroke(dpToPx(2.5f), color) + shiftIndicator.background = drawable + shiftIndicator.setTextColor(color) + + try { + val parts = time.split(":") + val h24 = parts[0].toInt() + val m = parts[1].toInt() + val h12 = if (h24 % 12 == 0) 12 else h24 % 12 + tvTime.text = String.format("%02d:%02d", h12, m) + tvAmPm.text = if (h24 < 12) "오전" else "오후" + + if (!isEnabled) { + tvTime.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary)) + tvAmPm.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary)) + tvSummary.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary)) + shiftIndicator.alpha = 0.4f + } else { + tvTime.setTextColor(ContextCompat.getColor(context, R.color.text_primary)) + tvAmPm.setTextColor(ContextCompat.getColor(context, R.color.text_secondary)) + tvSummary.setTextColor(ContextCompat.getColor(context, R.color.primary)) + shiftIndicator.alpha = 1.0f + } + } catch (e: Exception) { tvTime.text = time } + + val tvSoundNameView = view.findViewById(R.id.tvSoundName) + val soundName = getSoundTitle(context, soundUri) + tvSummary.text = "${snoozeMin}분 간격, ${if(snoozeRepeat == 99) "계속" else snoozeRepeat.toString() + "회"}" + tvSoundNameView.text = soundName + + val rowContents = view.findViewById(R.id.rowContents) + rowContents.setOnClickListener { onAction(false, false) } + rowContents.setOnLongClickListener { onAction(false, true); true } + + alarmSwitch.isChecked = isEnabled + layoutAlarmSwitch.setOnClickListener { + // onAction will handle the data update and re-sync + onAction(true, false) + } + + return view + } + + private var currentDialogSoundUri: String? = null + private var tvSoundNameReference: android.widget.TextView? = null + + /** + * 새 알람 추가 시 기본음으로 시스템 알람음 설정 + * 무음 문제 해결을 위해 반드시 시스템 기본 알람음을 반환 + */ + private fun getDefaultAlarmUri(context: Context): String { + // 1. 시스템 기본 알람음 (가장 우선) + val defaultUri = android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI + if (defaultUri != null) { + Log.d("ShiftAlarm", "시스템 기본 알람음 URI: $defaultUri") + return defaultUri.toString() + } + + // 2. RingtoneManager에서 알람 타입 기본값 가져오기 + val fallbackUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_ALARM) + if (fallbackUri != null) { + Log.d("ShiftAlarm", "Fallback 알람음 URI: $fallbackUri") + return fallbackUri.toString() + } + + // 3. 마지막 fallback: 알림음이라도 사용 + val notificationUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_NOTIFICATION) + if (notificationUri != null) { + Log.w("ShiftAlarm", "알람음 없음, 알림음 사용: $notificationUri") + return notificationUri.toString() + } + + // 4. 최후의 수단: 벨소리 + val ringtoneUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_RINGTONE) + if (ringtoneUri != null) { + Log.w("ShiftAlarm", "알림음 없음, 벨소리 사용: $ringtoneUri") + return ringtoneUri.toString() + } + + // 이 경우는 거의 없지만, 안전장치 + Log.e("ShiftAlarm", "어떤 기본 소리도 찾을 수 없음") + return "" + } + + private fun showEditDialog( + title: String, currentTime: String, shiftType: String, existingAlarm: CustomAlarm?, isNew: Boolean + ) { + val dialogView = layoutInflater.inflate(R.layout.dialog_alarm_edit_spinner, null) + val dialog = AlertDialog.Builder(requireContext(), android.R.style.Theme_DeviceDefault_Light_NoActionBar_Fullscreen).setView(dialogView).create() + dialog.window?.setBackgroundDrawableResource(android.R.color.transparent) + dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + + val tvTitle = dialogView.findViewById(R.id.dialogTitle) + val timePicker = dialogView.findViewById(R.id.timePicker) + val tvSoundName = dialogView.findViewById(R.id.tvSoundName) + tvSoundNameReference = tvSoundName + + val btnSelectSound = dialogView.findViewById(R.id.btnSelectSound) + val btnDelete = dialogView.findViewById