오늘은 음성을 녹음하는 APP을 만들어본다!
사용자는 녹음된 음성을 재생하여 확인 할 수 있고, 초기화를 통해 재녹음을 할 수 있다.
녹음이 잘 되고 있는지 확인 하기 위해 음성의 변화를 그래프로 보여준다.
// Manifest.xml에 추가
<uses-permission android:name="android.permission.RECORD_AUDIO" />
// MediaRecorder 생성
recorder = MediaRecorder().apply {
// 오디오 소스 설정
setAudioSource(MediaRecorder.AudioSource.MIC)
// 출력 파일 포맷 설정
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
// 오디오 인코더를 설정
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
// 출력 파일 이름 설정
setOutputFile(recordingFilePath)
// 초기화 완료
prepare()
}
recorder?.start() // 녹음 시작
// VisualizeView.kt
var onRequestCurrentAmplitude: (() -> Int)? = null
// MainActivity.kt
visualizerView.onRequestCurrentAmplitude = {
recorder?.maxAmplitude ?: 0
}
visualizerView.startVisualizing(false)
private val amplitudePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = context.getColor(R.color.purple_500)
strokeWidth = LINE_WIDTH
strokeCap = Paint.Cap.ROUND // 라인의 양끝을 둥글게 표현
}
// 뷰 그리기
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas ?: return
val centerY = drawingHeight / 2f // 그래프의 중앙을 센터로 설정
var offsetX = drawingWidth.toFloat()
drawingAmplitudes.let {
if (isReplaying) {
it.takeLast(replayingPosition) //
} else {
it
}
}.forEach { amplitude ->
val lineLength =
amplitude / MAX_AMPLITUDE * drawingHeight * 0.8F // 꽉차는 것 보단 조금 여백을 주기 위해 *0.8
offsetX -= LINE_SPACE // X축의 어느 부분에 그릴 것인지
if (offsetX < 0) // 뷰를 벗어난다면!
return@forEach
canvas.drawLine(offsetX, centerY - lineLength / 2F, offsetX, centerY + lineLength / 2F, amplitudePaint)
}
}
AppCompatImageButton를 상속받은 클래스 RecordButton.kt
class RecordButton(
context: Context,
attrs: AttributeSet
) : AppCompatImageButton(context, attrs) {
fun updateIconWithState(state: State){
when(state){
State.BEFORE_RECORDING->{
setImageResource(R.drawable.ic_baseline_fiber_manual_record_24)
}
State.AFTER_RECORDING ->{
setImageResource(R.drawable.ic_baseline_play_arrow_24)
}
State.ON_PLAYING -> {
setImageResource(R.drawable.ic_baseline_stop_24)
}
State.ON_RECORDING -> {
setImageResource(R.drawable.ic_baseline_stop_24)
}
}
}
}
AppCompatTextView를 상속받은 클래스 CountUpTextView.kt
private var starttimestamp: Long = 0L
private val countUpAction: Runnable = object : Runnable {
override fun run() {
val currentTimeStamp = SystemClock.elapsedRealtime()
val countTimeSeconds = ((currentTimeStamp - starttimestamp) / 1000L).toInt()
updateCountTime(countTimeSeconds)
handler?.postDelayed(this, 1000L) // 1초에 한번 전달
}
}
fun startCountUp() {
starttimestamp = SystemClock.elapsedRealtime()
handler?.post(countUpAction)
}
fun stopCountUp() {
handler?.removeCallbacks(countUpAction)
}
fun clearCountUp(){
updateCountTime(0)
}
private fun updateCountTime(countTimeSeconds: Int) {
val minutes = countTimeSeconds / 60
val seconds = countTimeSeconds % 60
text = "%02d:%02d".format(minutes, seconds)
}
++ 설치된 모습