enum class State {
BEFORE_RECORDING,
ON_RECORDING,
AFTER_RECORDING,
ON_PLAYING
}
<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() //앱 종료
}
}
private var recorder: MediaRecorder? = null
internal은 저장할 앱의 특정 공간을 제공하지 못하기 때문에,
external로 외부 캐시로 진행
private val recordingFilePath: String by lazy { //녹음하는 파일을 저장하는 path
"${externalCacheDir?.absolutePath}/recording.3gp"
}
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
}
drawingAmplitudes.let { amplitudes ->
if (isReplaying) { //녹음한 것을 다시 재생시킬때
amplitudes.takeLast(replayingPosition) //가장 뒤부터 순서대로 가져옴
} else { //녹음 중
amplitudes //현재를 그대로 가져옴
}
}
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초뒤 다시 호출
}
}
fun clearCountTime() {
updateCountTime(0)
}
fun clearVisualization() {
drawingAmplitudes = emptyList() //현재 amplitudes를 비워버림
invalidate()
}
player?.setOnCompletionListener {
stopPlaying()
state = State.AFTER_RECORDING
}
init{
setBackgroundResource(R.drawable.shape_oval_button)
}
tools:src="@drawable/ic_record"
android:padding="25dp"
android:scaleType="fitCenter"