초급 7.녹음기

mangyun·2021년 11월 22일
0

초급 앱개발

목록 보기
7/8

정리

먼저 enumclass State

enum class State {
    BEFORE_RECORDING,
    ON_RECORDING,
    AFTER_RECORDING,
    ON_PLAYING
}

아이콘을 변경하는 함수

  • AppCompatImageButton을 상속(AppCompat : 이전버전에서도 새로운 기능을 쓸수있게 함

이미지 지정

  • setImageResource(R.drawable.ic_record)

권한요청

manifests에 녹음 권한

<uses-permission android:name="android.permission.RECORD_AUDIO"/> 

여기서는 앱을 시작하자마자 바로 권한 요청

requestAudioPermission()
후에 요청한 권한에 대한 결과를 받음
 override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        val audioRecordPermissionGranted = requestCode == REQUEST_RECORD_AUDIO_PERMISSION &&
                grantResults.firstOrNull() == PackageManager.PERMISSION_GRANTED
        //부여결과 중에서 arrayOf로 전달했기때문에 firstOrNull로 하나만 전달

        if (!audioRecordPermissionGranted) { //권한이 거부되었다면
            finish() //앱 종료
        }
    }

녹음기능

Format과 Encoder사이에는 서로 사양이 맞는 호환성이 존재

오디오나 비디오같은 파일은 사용하지않을때는 메모리에서 해제해 null을 만드는것이 가장 무난함

private var recorder: MediaRecorder? = null

internal은 저장할 앱의 특정 공간을 제공하지 못하기 때문에,
external로 외부 캐시로 진행

private val recordingFilePath: String by lazy { //녹음하는 파일을 저장하는 path
        "${externalCacheDir?.absolutePath}/recording.3gp"
    }

Format과 Encoder사이에는 (THREE_GPP - AMR_NB)같이 서로 사양이 맞는 호환성이 존재

recorder = MediaRecorder().apply {
            setAudioSource(MediaRecorder.AudioSource.MIC)
            setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
            setOutputFile(recordingFilePath)
            prepare()
        } //녹음할 수 있는 상태를 전부 마침

리셋기능

private var state = State.BEFORE_RECORDING //녹음 전 상태값
set(value) {
field = value

        //리셋버튼의 사용되는 상태는 녹음 후거나, 재생 중일때임
        resetButton.isEnabled = (value == State.AFTER_RECORDING) || (value == State.ON_PLAYING)
 }

private fun bindViews() {
//리셋버튼
resetButton.setOnClickListener {
stopPlaying()//재생중에서도 리셋을 할 수 있게함
state = State.BEFORE_RECORDING
}

음성 시각화기능

곡선이 부드럽게 그려짐

val amplitudePaint = Paint(Paint.ANTI_ALIAS_FLAG)

각 화면에 맞게 사이즈 조절

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    drawingWidth = w
    drawingHeight = h

}

그리기 전, amplitudes 재생할때와 녹음 중일때 조건

drawingAmplitudes.let { amplitudes ->
            if (isReplaying) { //녹음한 것을 다시 재생시킬때
                amplitudes.takeLast(replayingPosition) //가장 뒤부터 순서대로 가져옴
            } else { //녹음 중
                amplitudes //현재를 그대로 가져옴
            }
        }

반복해서 amplitude를 가져와, 20밀리초 뒤에 그리기

    private val visualizeRepeatAction: Runnable = object : Runnable {
        override fun run() {
            if (!isReplaying) {
                val currentAmplitude = onRequestCurrentAmplitude?.invoke() ?: 0
                // main에 onRequestCurrentAmplitude호출해 main의 recorder max값을 가져옴
                drawingAmplitudes = listOf(currentAmplitude) + drawingAmplitudes
                //그릴때는 제일 처음이 오른쪽부터 시작함
            } else {
                replayingPosition += 1
            }

            invalidate() //데이터가 추가되면 갱신을 해야함

            handler?.postDelayed(this, ACTION_INTERVAL)// 자신을 20밀리초 뒤에 다시 실행
        }
    }

시간반영

class CountUpView(
    context: Context,
    attrs: AttributeSet? = null
) : AppCompatTextView(context, attrs) {

    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초뒤 다시 호출
        }
    }

초기화

  • resetButton에 지정
fun clearCountTime() {
        updateCountTime(0)
    }
fun clearVisualization() {
        drawingAmplitudes = emptyList() //현재 amplitudes를 비워버림
        invalidate()

    }

녹음 완료처리 - 현재 전달된 파일을 전부 재생했을 때 발생

        player?.setOnCompletionListener {
            stopPlaying()
            state = State.AFTER_RECORDING

        }

UI마무리

  • 녹음기 버튼을 background하지않고 RecordButton함수에서 바꿈 - 속성을 따로 지정하지않아도 언제든 동그라미 버튼이 됨
init{
        setBackgroundResource(R.drawable.shape_oval_button)
    }

버튼ui 미리보기, 빨간버튼 사이즈 채우기

tools:src="@drawable/ic_record"
android:padding="25dp"
android:scaleType="fitCenter"
profile
기억보다는 기록을 하자.

0개의 댓글