record相关

AudioRecorder.kt

1
2
3
4
5
6
import java.io.File

interface AudioRecorder {
fun start(outputFile: File)
fun stop()
}

AndroidAudioRecorder.kt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import android.content.Context
import android.media.MediaRecorder
import android.os.Build
import android.provider.MediaStore.Audio.Media
import java.io.File
import java.io.FileOutputStream

class AndroidAudioRecorder(
private val context: Context
): AudioRecorder {

private var recorder: MediaRecorder? = null

private fun createRecorder(): MediaRecorder {
return if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
MediaRecorder(context)
} else MediaRecorder()
}

override fun start(outputFile: File) {
createRecorder().apply {
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
setOutputFile(FileOutputStream(outputFile).fd)

prepare()
start()

recorder = this
}
}

override fun stop() {
recorder?.stop()
recorder?.reset()
recorder = null
}
}

playback相关

AudioPlayer.kt

1
2
3
4
5
6
import java.io.File

interface AudioPlayer {
fun playFile(file: File)
fun stop()
}

AndroidAudioPlayer.kt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import android.content.Context
import android.media.MediaPlayer
import androidx.core.net.toUri
import java.io.File

class AndroidAudioPlayer(
private val context: Context
): AudioPlayer {

private var player: MediaPlayer? = null

override fun playFile(file: File) {
MediaPlayer.create(context, file.toUri()).apply {
player = this
start()
}
}

override fun stop() {
player?.stop()
player?.release()
player = null
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import android.Manifest
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.app.ActivityCompat
import java.io.File

class MainActivity : ComponentActivity() {

private val recorder by lazy {
AndroidAudioRecorder(applicationContext)
}

private val player by lazy {
AndroidAudioPlayer(applicationContext)
}

private var audioFile: File? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.RECORD_AUDIO),
0
)
setContent {
AudioRecorderTheme {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(onClick = {
File(cacheDir, "audio.mp3").also {
recorder.start(it)
audioFile = it
}
}) {
Text(text = "Start recording")
}
Button(onClick = {
recorder.stop()
}) {
Text(text = "Stop recording")
}
Button(onClick = {
player.playFile(audioFile ?: return@Button)
}) {
Text(text = "Play")
}
Button(onClick = {
player.stop()
}) {
Text(text = "Stop playing")
}
}
}
}
}
}