개발을 미루고 미루다가 어느덧 마지막 글을 올린 날에서 3달 가량이 지나버렸다.
꾸준히 개발해왔으면 지금쯤 거의 다 완성돼있었을텐데 그렇게 하지 않고 게으름 피운 나에게 화가 난다.
이제 와서 다시 해봐야 늦었다는 생각도 늘지만 지금부터라도 다시 시작해보려 한다.
구현할 기능
기능 구현에 앞서 시나리오는 다음과 같다.
- 다른 앱 (Ex. 디스코드, 카카오톡) 에서 내가 알람을 켜둔 아이템의 이름이 메시지에 포함된 Notification 감지
- 해당 아이템의 알람 세부설정 확인 (Ex. 알림음, 볼륨, 반복 횟수, 반복 간격)
- 세부설정에 따라 알람 재생
이 중에서 3번의 역할을 하는 클래스를 구현했다.
알람 서비스 구현
알람 서비스는 알람을 재생/정지하고, 알람을 재생할 때 현재 음소거 모드와 볼륨을 변경하는 역할을 한다.
UI가 표시되고 있는지와 상관없이 동작해야 하기 때문에 Activity가 아닌 Service로 만들었다.
우선 서비스에 보낼 Intent 관련 상수를 정의했다.
// Alarm
const val ACTION_ALARM_ON: String = "com.devjaewoo.itsmywaye.extra.ACTION_ALARM_ON"
const val ACTION_ALARM_OFF: String = "com.devjaewoo.itsmywaye.extra.ACTION_ALARM_OFF"
const val EXTRA_ALARM_URI: String = "com.devjaewoo.itsmywaye.extra.EXTRA_ALARM_URI"
const val EXTRA_ALARM_VOLUME: String = "com.devjaewoo.itsmywaye.extra.EXTRA_ALARM_VOLUME"
const val EXTRA_ALARM_REPEAT: String = "com.devjaewoo.itsmywaye.extra.EXTRA_ALARM_REPEAT"
const val EXTRA_ALARM_INTERVAL: String = "com.devjaewoo.itsmywaye.extra.EXTRA_ALARM_INTERVAL"
이제 onStartCommand에서 action을 통해 알람을 켜야 하는지, 꺼야 하는지 알 수 있다.
아래와 같이 Intent에서 알람 정보를 받아와 처리해주면 된다.
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if(intent != null) {
if(intent.action == ACTION_ALARM_ON) {
uri = intent.getStringExtra(EXTRA_ALARM_URI) ?: ""
volume = intent.getIntExtra(EXTRA_ALARM_VOLUME, 100)
repeatTimes = intent.getIntExtra(EXTRA_ALARM_REPEAT, 3)
interval = intent.getIntExtra(EXTRA_ALARM_INTERVAL, 5)
playRingtone()
}
else {
stopRingtone()
}
}
return super.onStartCommand(intent, flags, startId)
}
그 다음 실제 알람을 켜고 끄는 코드를 작성했다.
처음엔 Ringtone 클래스를 사용하려 했으나, 원하는 기능 중 하나가 잘 동작하지 않아 MediaPlayer 클래스로 바꿨다.
MediaPlayer를 통한 소리 제어 방법은 다음에 따로 올려야겠다.
Ringtone은 이전에 올려둔게 있다.
[Android] Ringtone 재생 및 목록 가져오기
Ringtone 재생 val ringtoneUri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM) val ringtone: Ringtone = RingtoneManager.getRingtone(context, ringtoneUri) ringtone.play() ringtoneUri..
devjaewoo.tistory.com
if (mediaPlayer == null || !(mediaPlayer!!.isPlaying)) {
if(RingtoneManager.getRingtone(applicationContext, Uri.parse(uri)) == null) {
Log.w(TAG, "onStartCommand: Cannot find ringtone at $uri. Setting uri to default alarm ringtone.")
uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM).toString()
}
mediaPlayer = MediaPlayer.create(this, Uri.parse(uri)).apply {
stop()
isLooping = true
setAudioAttributes(AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()) //알람 볼륨으로 소리 켬
prepare()
}
playRingtone()
}
코드를 간단히 설명하자면 현재 알람을 켤 수 있는 상태일 경우 알람 스트림으로 지정된 uri의 알림음을 틀어주는 코드이다.
안드로이드에는 소리를 내보낼 수 있는 스트림이 여러개 있는데, 그중 하나가 알람 스트림이다.
전화벨 소리는 벨소리 볼륨, 게임이나 유튜브는 미디어, 통화는 통화 볼륨 스트림으로 출력된다.
아까 Ringtone으로 하려다가 안됐다고 했던게 바로 이거였다.
알람이 나오는 것은 확인했지만, 볼륨이 너무 작았다.
웨이가 떠서 알람이 정상적으로 울렸는데 하필 내가 음소거 모드로 설정해둬서 알람음을 못들어 웨이를 못먹으면 그만큼 억울한것도 없을것이다.
이런 불상사를 방지하기 위해 알람이 울릴 때 음소거를 해제하고, 알람 볼륨을 설정한 값으로 높여주고, 알람을 끌 때 다시 이전 값으로 되돌아가도록 코드를 작성했다.
lateinit var audioManager: AudioManager
private var savedVolume: Int = 0
private var savedRingerMode: Int = 0
override fun onCreate() {
super.onCreate()
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
}
private fun changeAudioState(volume: Int) {
savedRingerMode = audioManager.ringerMode
savedVolume = audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION)
Log.d(TAG, "changeAudioState: " +
"SavedVolume: $savedVolume " +
"MaxVolume: ${audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION)} " +
"CurrentVolume: ${(audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION) * (volume / 100.0)).toInt()}")
audioManager.ringerMode = AudioManager.RINGER_MODE_NORMAL
audioManager.setStreamVolume(
AudioManager.STREAM_NOTIFICATION,
(audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION) * (volume / 100.0)).toInt(),
0)
}
private fun restoreAudioState() {
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, savedVolume, 0)
audioManager.ringerMode = savedRingerMode
}
이제 작성한 아래의 함수들을 통해 아래의 시나리오에 맞게 핸드폰을 제어할 수 있다.
- 음소거 해제, 볼륨 변경
- 알람 켜기
- 알람 끄기
- 음소거, 볼륨 원상복구
작동영상은 따로 올리지 않겠다.
'Projects > It's My Waye' 카테고리의 다른 글
[It's My Waye] 12. 알람 DB 구조 수정 (0) | 2022.05.17 |
---|---|
[It's My Waye] 11. 알람 기능 구현 - 알람 제어 (0) | 2022.04.27 |
[It's My Waye] 9. 알람 화면 기능 구현 (0) | 2022.02.09 |
[It's My Waye] 8. 알람 UI 구현 (0) | 2022.02.09 |
[It's My Waye] 7. 메인화면 UI 구현 (DrawerLayout) (0) | 2022.01.23 |