用Kotlin实现音频文件上传
做音频类App开发时,经常需要把录音文件传到服务器。比如用户录了一段语音笔记,点个上传就能存到云端。这种功能其实不难,用Kotlin配合OkHttp就能搞定。
假设你已经录好了音频,路径是 /storage/emulated/0/Recordings/test.mp3,现在要把它发到后台接口 https://api.example.com/upload。
添加网络权限和依赖
先在 AndroidManifest.xml 里加上网络权限:
<uses-permission android:name="android.permission.INTERNET" />然后在 build.gradle 加上OkHttp依赖:
implementation 'com.squareup.okhttp3:okhttp:4.12.0'编写上传代码
核心逻辑就是构建一个带文件的表单请求。下面是一个可以直接用的示例:
val file = File("/storage/emulated/0/Recordings/test.mp3")
val requestBody = MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file", file.name, RequestBody.create(MediaType.get("audio/mpeg"), file))
.build()
val request = Request.Builder()
.url("https://api.example.com/upload")
.post(requestBody)
.build()
OkHttpClient().newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
println("上传成功")
}
}
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
})这段代码会把本地音频作为表单字段发送。注意这里设置了正确的MIME类型 audio/mpeg,服务端能更准确地处理。
处理运行时权限
如果目标设备是Android 6.0以上,别忘了申请读取外部存储权限。可以在Activity里这样请求:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
}用户授权后才能访问录音文件。否则程序会因为读不到文件而报错。
显示上传进度
大文件上传时加个进度条体验更好。可以封装一个 ProgressRequestBody 来监听写入过程:
class ProgressRequestBody(private val requestBody: RequestBody, private val listener: (Int) -> Unit) : RequestBody() {
override fun contentType() = requestBody.contentType()
override fun contentLength() = requestBody.contentLength()
override fun writeTo(sink: BufferedSink) {
val countingSink = object : ForwardingSink(sink) {
var bytesWritten = 0L
override fun write(source: Buffer, byteCount: Long) {
super.write(source, byteCount)
bytesWritten += byteCount
val progress = (bytesWritten * 100f / contentLength()).toInt()
listener(progress)
}
}
requestBody.writeTo(BufferedSink(countingSink))
}
}使用时包装原始请求体:
.addFormDataPart("file", file.name, ProgressRequestBody(RequestBody.create(MediaType.get("audio/mpeg"), file)) { progress ->
runOnUiThread { /* 更新进度条 */ }
})这样就能实时看到上传进度了。