Skip to content

[#255] 소리 및 진동 선택 시 반응 없음 이슈 수정#256

Open
jieeeunnn wants to merge 5 commits intodevelopfrom
fix/sound-vibration-not-responding#255
Open

[#255] 소리 및 진동 선택 시 반응 없음 이슈 수정#256
jieeeunnn wants to merge 5 commits intodevelopfrom
fix/sound-vibration-not-responding#255

Conversation

@jieeeunnn
Copy link
Member

@jieeeunnn jieeeunnn commented Feb 3, 2026

#️⃣연관된 이슈

📝작업 내용

  • 소리 및 진동 선택 시 각 선택에 대한 피드백을 줄 수 있도록 수정하였습니다.
    (마이페이지, 온보딩 화면에서 모두 수정했습니다~)

PR 발행 전 체크 리스트

  • 발행자 확인
  • 프로젝트 설정 확인
  • 라벨 확인
  • 코드 린트 확인

스크린샷 (선택)

💬리뷰 요구사항(선택)

  • 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 알람 유형 선택 시 음성 및 진동 피드백 추가
    • 볼륨 조정 시 실시간 음성 피드백 제공
    • 알람 설정 화면에서 음향 효과 미리 듣기 기능 통합

@jieeeunnn jieeeunnn self-assigned this Feb 3, 2026
@jieeeunnn jieeeunnn linked an issue Feb 3, 2026 that may be closed by this pull request
1 task
@jieeeunnn jieeeunnn added the fix label Feb 3, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

개요

사운드 및 진동 피드백 시스템을 도입하여 볼륨 변경 및 알람 타입 선택 시 UI 상호작용에 대한 오디오/촉각 피드백을 추가합니다. 새로운 SoundSamplePlayer 클래스가 VolumeBottomSheet 콜백과 함께 통합됩니다.

변경사항

Cohort / File(s) 요약
사운드 피드백 인프라
app/src/main/java/com/depromeet/team6/presentation/ui/mypage/SoundSamplePlayer.kt
ToneGenerator를 통한 볼륨 샘플 재생, 시스템 알림음 재생, Android 버전별 진동 처리(VibratorManager/Vibrator)를 포함한 새로운 SoundSamplePlayer 클래스 추가. 리소스 정리를 위한 생명주기 관리(release())를 제공합니다.
볼륨 컴포넌트 확장
app/src/main/java/com/depromeet/team6/presentation/ui/common/sound/VolumeBottomSheet.kt
onVolumeChanged: (Int) -> Unit 콜백 매개변수를 추가하여 외부 호출자가 볼륨 변경 이벤트를 처리할 수 있도록 활성화합니다.
화면 통합
app/src/main/java/com/depromeet/team6/presentation/ui/mypage/MypageAlarmScreen.kt, app/src/main/java/com/depromeet/team6/presentation/ui/onboarding/component/OnboardingAlarmSelector.kt
SoundSamplePlayer 인스턴스를 메모이제이션하고 DisposableEffect로 정리합니다. 알람 타입 선택(ALL/SOUND/VIBRATION)과 볼륨 변경 시 해당 사운드/진동 피드백을 트리거합니다.

주요 검토 포인트

성능 및 리소스 관리:

  • ToneGenerator 재생 시 이전 인스턴스 정리 로직이 구현되어 있으나, 빠른 연속 볼륨 변경(예: 슬라이더 드래그)에서 ToneGenerator 생성 오버헤드 검토 권장
  • DisposableEffect 정리 타이밍이 정확한지 확인 필요

안정성:

  • vibrateSample()이 진동 기능 부재 시 조용히 반환하여 graceful degradation 처리
  • 알림음(Ringtone) 중복 실행 시 먼저 중지 후 재시작하여 리소스 누수 방지

아키텍처:

  • SoundSamplePlayerContext 의존성을 요구하며, 컴포저블에서 생성/정리 책임이 분산됨. 불필요한 재생성을 피하기 위해 remember로 메모이제이션된 점은 적절함

예상 코드 리뷰 노력

🎯 3 (Moderate) | ⏱️ ~20분

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경 사항의 핵심을 명확하게 요약하고 있습니다. 소리 및 진동 선택 시 반응이 없던 이슈를 수정하는 것이 정확히 무엇을 했는지 명확히 전달됩니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/sound-vibration-not-responding#255

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/depromeet/team6/presentation/ui/mypage/SoundSamplePlayer.kt`:
- Around line 38-52: playVolumeSample currently calls toneGenerator.release()
and recreates a new ToneGenerator on every call, causing heavy resource churn
when the slider fires many events; change this to reuse a single ToneGenerator
instance (toneGenerator) and update its volume instead of releasing/recreating,
or implement a short debounce on playVolumeSample to limit calls during slider
drags. Specifically, keep a single ToneGenerator created lazily (use the
existing toneGenerator field), avoid calling release() on each invocation, and
only call startTone(ToneGenerator.TONE_PROP_BEEP, 120) when volume actually
changes after debounce; ensure any final cleanup still calls
toneGenerator.release() when the component is destroyed.
- Around line 1-2: SoundSamplePlayer is placed under presentation.ui.mypage but
is reused by onboarding; move the class to a shared package (e.g.,
presentation.ui.common or presentation.util) by changing its package declaration
in SoundSamplePlayer and updating all import sites (references in onboarding and
mypage code) to the new package; ensure any visibility modifiers remain
public/internal as appropriate and run a project-wide import/compile fix to
update imports and resolve references to SoundSamplePlayer.
- Around line 17-21: getRingtone(...) can return null so storing it as a
non-null Ringtone causes NPEs when you later call notificationRingtone.isPlaying
or notificationRingtone.play(); change the field to a nullable type
(notificationRingtone: Ringtone?), assign the result of
RingtoneManager.getRingtone(...) directly, and everywhere you use
notificationRingtone (e.g., in play/stop methods in SoundSamplePlayer) add null
checks or safe calls (?.isPlaying, ?.play(), ?.stop()) or provide a fallback
no-op behavior so calls are safe when getRingtone() returned null.

Comment on lines +1 to +2
package com.depromeet.team6.presentation.ui.mypage

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

SoundSamplePlayer 패키지 위치 재검토 필요

SoundSamplePlayermypage 패키지에 위치하지만 onboarding에서도 사용됩니다. 재사용 가능한 유틸리티 클래스이므로 common 또는 util 패키지로 이동하는 것이 아키텍처적으로 적절합니다.

Also applies to: 13-15

🤖 Prompt for AI Agents
In
`@app/src/main/java/com/depromeet/team6/presentation/ui/mypage/SoundSamplePlayer.kt`
around lines 1 - 2, SoundSamplePlayer is placed under presentation.ui.mypage but
is reused by onboarding; move the class to a shared package (e.g.,
presentation.ui.common or presentation.util) by changing its package declaration
in SoundSamplePlayer and updating all import sites (references in onboarding and
mypage code) to the new package; ensure any visibility modifiers remain
public/internal as appropriate and run a project-wide import/compile fix to
update imports and resolve references to SoundSamplePlayer.

Comment on lines +17 to +21
private val notificationRingtone: Ringtone =
RingtoneManager.getRingtone(
context,
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

RingtoneManager.getRingtone()은 null을 반환할 수 있음

기본 알림음이 설정되지 않은 기기에서 getRingtone()이 null을 반환하면 이후 notificationRingtone.isPlayingplay() 호출 시 NPE가 발생합니다.

🛡️ Null 안전성 처리 제안
-    private val notificationRingtone: Ringtone =
-        RingtoneManager.getRingtone(
+    private val notificationRingtone: Ringtone? =
+        RingtoneManager.getRingtone(
             context,
             RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
         )

     fun playNotificationSample() {
-        if (notificationRingtone.isPlaying) {
-            notificationRingtone.stop()
+        notificationRingtone?.let { ringtone ->
+            if (ringtone.isPlaying) {
+                ringtone.stop()
+            }
+            ringtone.play()
         }
-        notificationRingtone.play()
     }

     fun release() {
         toneGenerator.release()
-        if (notificationRingtone.isPlaying) {
-            notificationRingtone.stop()
-        }
+        notificationRingtone?.takeIf { it.isPlaying }?.stop()
     }
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/depromeet/team6/presentation/ui/mypage/SoundSamplePlayer.kt`
around lines 17 - 21, getRingtone(...) can return null so storing it as a
non-null Ringtone causes NPEs when you later call notificationRingtone.isPlaying
or notificationRingtone.play(); change the field to a nullable type
(notificationRingtone: Ringtone?), assign the result of
RingtoneManager.getRingtone(...) directly, and everywhere you use
notificationRingtone (e.g., in play/stop methods in SoundSamplePlayer) add null
checks or safe calls (?.isPlaying, ?.play(), ?.stop()) or provide a fallback
no-op behavior so calls are safe when getRingtone() returned null.

Comment on lines +38 to +52
fun playVolumeSample(volume: Float) {
val scaled = (kotlin.math.sqrt(volume) * 100)
.coerceAtLeast(10f)
.toInt()

// 이전 톤 정리
toneGenerator.release()

toneGenerator = ToneGenerator(
AudioManager.STREAM_NOTIFICATION,
scaled
).apply {
startTone(ToneGenerator.TONE_PROP_BEEP, 120)
}
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

ToneGenerator 빈번한 재생성으로 인한 리소스 부하

슬라이더를 드래그할 때마다 ToneGenerator를 release() 후 재생성하는 방식은 리소스 낭비가 될 수 있습니다. 슬라이더 드래그 중 수십 번 호출될 수 있으므로, 디바운싱을 고려하거나 단일 인스턴스를 재사용하는 방식을 검토해 보세요.

🤖 Prompt for AI Agents
In
`@app/src/main/java/com/depromeet/team6/presentation/ui/mypage/SoundSamplePlayer.kt`
around lines 38 - 52, playVolumeSample currently calls toneGenerator.release()
and recreates a new ToneGenerator on every call, causing heavy resource churn
when the slider fires many events; change this to reuse a single ToneGenerator
instance (toneGenerator) and update its volume instead of releasing/recreating,
or implement a short debounce on playVolumeSample to limit calls during slider
drags. Specifically, keep a single ToneGenerator created lazily (use the
existing toneGenerator field), avoid calling release() on each invocation, and
only call startTone(ToneGenerator.TONE_PROP_BEEP, 120) when volume actually
changes after debounce; ensure any final cleanup still calls
toneGenerator.release() when the component is destroyed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Fix] 소리 및 진동 선택 시 반응 없는 이슈 수정

1 participant

Comments