음성파일 가져오기
개념 : 파일을 byteArray로 만들어 서버에 전송 하려고한다.
- 당연하지만 만든다는건 변경한다는 의미가 아닌 copy의 의미 (단순히 읽는것임)
1. 파일로 만든다
File() : URI도 가능하고 경로String도 가능
2. InputStream에 넣는다 ( FileInputStream )
3. 파일을 읽어서 byteArray형태로 가져온다
val fis = FileInputStream(File(speakingDirectory))
val byteArray = fil.readBytes()
코틀린 익스텐션 readBytes를 활용했는데
내부를 보면 Outstream도 만들어 주고, 알아서 처리해주니 너무 편리!!
public fun InputStream.readBytes(): ByteArray {
val buffer = ByteArrayOutputStream(maxOf(DEFAULT_BUFFER_SIZE, this.available()))
copyTo(buffer)
return buffer.toByteArray()
}
public fun InputStream.copyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE): Long {
var bytesCopied: Long = 0
val buffer = ByteArray(bufferSize)
var bytes = read(buffer)
while (bytes >= 0) {
out.write(buffer, 0, bytes)
bytesCopied += bytes
bytes = read(buffer)
}
return bytesCopied
}
- API 인터페이스
@Multipart
@POST(")
fun sendFile(
@Part file: MultipartBody.Part
): Completable
@MultiPart 어노테이션, MultipartBody.Part 타입
bytesArray를 MutipartBody.Part 타입으로 변경
sendFile(
file = MultipartBody.Part.createFormData(
name = "file",
filename = "file.wav",
body = bytes.toRequestBody(contentType = "audio/wav".toMediaTypeOrNull())
)
)
ByteArray 재생하기
val path = File(fileDirectory)
val fileOutputStream = FileOutputStream(path).use{
it.write(bytes)
}
player = MediaPlayer()
.apply {
setDataSource(fileDirectory)
prepare()
}
player?.start()
파일들을 HEADER로부터 해당 파일의 타입을 정의할 수 있다 ( audio 인지 video인지 )
만약 이런 헤더가 없다면 단순 파일 ( 확장자 없는 흰 A4용지 아이콘 )이 된다.
단순히 녹음을 끝내고 생성한 File(directory) 에는 HEADER가 들어가 있지 않다. (단순 파일)
그래서 정의된 HEADER 를 임의로 추가해야 한다.
해당 헤더정보를 파일에 정해진 위치에 추가해야 한다.
val header = getWavFileHeaderByteArray(...)
val randomAccessFile = RandomAccessFile(File(filePath), "rw").use{
it.seek(0)
it.write(header)
}
private fun getWavFileHeaderByteArray(
totalAudioLen: Long, totalDataLen: Long, longSampleRate: Long,
channels: Int, byteRate: Long, bitsPerSample: Int
): ByteArray {
val header = ByteArray(44)
header[0] = 'R'.toByte()
header[1] = 'I'.toByte()
header[2] = 'F'.toByte()
header[3] = 'F'.toByte()
header[4] = (totalDataLen and 0xff).toByte()
header[5] = (totalDataLen shr 8 and 0xff).toByte()
header[6] = (totalDataLen shr 16 and 0xff).toByte()
header[7] = (totalDataLen shr 24 and 0xff).toByte()
header[8] = 'W'.toByte()
header[9] = 'A'.toByte()
header[10] = 'V'.toByte()
header[11] = 'E'.toByte()
header[12] = 'f'.toByte()
header[13] = 'm'.toByte()
header[14] = 't'.toByte()
header[15] = ' '.toByte()
header[16] = 16
header[17] = 0
header[18] = 0
header[19] = 0
header[20] = 1
header[21] = 0
header[22] = channels.toByte()
header[23] = 0
header[24] = (longSampleRate and 0xff).toByte()
header[25] = (longSampleRate shr 8 and 0xff).toByte()
header[26] = (longSampleRate shr 16 and 0xff).toByte()
header[27] = (longSampleRate shr 24 and 0xff).toByte()
header[28] = (byteRate and 0xff).toByte()
header[29] = (byteRate shr 8 and 0xff).toByte()
header[30] = (byteRate shr 16 and 0xff).toByte()
header[31] = (byteRate shr 24 and 0xff).toByte()
header[32] = (channels * (bitsPerSample / 8)).toByte()
header[33] = 0
header[34] = bitsPerSample.toByte()
header[35] = 0
header[36] = 'd'.toByte()
header[37] = 'a'.toByte()
header[38] = 't'.toByte()
header[39] = 'a'.toByte()
header[40] = (totalAudioLen and 0xff).toByte()
header[41] = (totalAudioLen shr 8 and 0xff).toByte()
header[42] = (totalAudioLen shr 16 and 0xff).toByte()
header[43] = (totalAudioLen shr 24 and 0xff).toByte()
return header
}
추가 ImageView의 이미지를 파일로 만들기
ByteArrayOutputStream().use { bos ->
(view as ImageView).drawable.toBitmap()
.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos)
imageFile.outputStream().use{
it.write(bos.toByteArray())
it.flush()
}
}
그 파일의 URI 가져오기
val imageUri =
FileProvider.getUriForFile(
this,
"dev.hadrosaur.draganddropsample.images",
imageFile
)
'Android' 카테고리의 다른 글
액티비티간, fragment간 값 전달 하기 (ViewModel X) (0) | 2022.02.12 |
---|---|
쿠키로 Auth인증하는 방법 (Interceptor 첨부) (0) | 2022.02.12 |
DiffUtil 사용시 정렬후 스크롤 Top 으로 이동하기 (0) | 2021.12.29 |
시간 간격 계산하여 x분전, x시간 전으로 변형하기 (0) | 2021.12.24 |
API Response Map 형태로 받기 ( Retrofit ) (0) | 2021.10.04 |