[Android] 녹음기(Recorder) App 만들기

🚩 녹음기 App

오늘은 음성을 녹음하는 APP을 만들어본다!
사용자는 녹음된 음성을 재생하여 확인 할 수 있고, 초기화를 통해 재녹음을 할 수 있다.
녹음이 잘 되고 있는지 확인 하기 위해 음성의 변화를 그래프로 보여준다.

사용해 본 기술

  • RECORD AUDIO PERMISSION 체크
  • Audio Visualizing
  • MediaRecorder API
  • Handler

🚩 기능 살펴보기

◾ MediaRecorder API 사용하여 녹음하기

  1. 녹음 권한 요청하기
// Manifest.xml에 추가
<uses-permission android:name="android.permission.RECORD_AUDIO" />
  1. MediaRecorder 객체 생성 및 실행
// MediaRecorder 생성
recorder = MediaRecorder().apply {
	// 오디오 소스 설정
	setAudioSource(MediaRecorder.AudioSource.MIC)
	// 출력 파일 포맷 설정
	setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
	// 오디오 인코더를 설정
	setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
	// 출력 파일 이름 설정
	setOutputFile(recordingFilePath)
	// 초기화 완료
	prepare()
}
recorder?.start() // 녹음 시작

◾ 녹음된 음성 Visualizing 하여 보여주기

  1. 녹음 중인 경우, 음성의 크기를 리스트로 받아온다.
// VisualizeView.kt
var onRequestCurrentAmplitude: (() -> Int)? = null

// MainActivity.kt
visualizerView.onRequestCurrentAmplitude = {
	recorder?.maxAmplitude ?: 0
}
visualizerView.startVisualizing(false)
  1. 이를 그래프로 보여줄 View를 만들어 시각화한다.
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)
}

👩‍💻 결과


++ 설치된 모습


관련 문서 : 안드로이드 공식문서 - MediaRecorder 개요 & 안드로이드 공식 문서 - Visualizer
Git 바로가기

좋은 웹페이지 즐겨찾기