보통 Retrofit 를 통해 RequestBody 를 만들어 서버로 보낼 때,
Bitmap -> file 저장 -> file 을 RequestBody 로 변경하여 서버로 보내는 예제들이 간혹 보입니다.
contentUri 도 마찬가지로 file 로 저장하고 RequestBody 로 변경하여 서버로 보내곤합니다.
그리고 코드도 올바르게 동작합니다.
하지만 해당 과정에는 파일로 저장할 필요가 없는 케이스도 있습니다.
해당 케이스의 경우 아마 위의 방식을 사용하면 이후에 파일을 삭제하는 로직 혹은 버전이 올라가면 해당 파일을 포함한 폴더를 비워주는 작업들이 필요하게 됩니다. 이런 경우 불필요한 파일 IO 작업을 생략할 수 있는 방법들이 있습니다.
1. Bitmap 의 경우
class BitmapRequestBody(private val bitmap: Bitmap) : RequestBody() {
override fun contentType(): MediaType? = "image/jpeg".toMediaType()
override fun writeTo(sink: BufferedSink) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 99, sink.outputStream())
}
}
2. ContentUri 의 경우
비공식 클럽하우스 안드로이드 앱, 다른 예제 등에서도 해당 방식으로 많이 사용하고 있습니다.
class ContentUriRequestBody(context: Context, private val uri: Uri) : RequestBody() {
private val contentResolver = context.contentResolver
private var fileName = ""
private var size = -1L
init {
contentResolver.query(
uri,
arrayOf(MediaStore.Images.Media.SIZE, MediaStore.Images.Media.DISPLAY_NAME),
null,
null,
null
)?.use { cursor ->
if (cursor.moveToFirst()) {
size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE))
fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME))
}
}
}
private fun getFileName() = fileName
override fun contentLength(): Long = size
override fun contentType(): MediaType? =
contentResolver.getType(uri)?.toMediaTypeOrNull()
override fun writeTo(sink: BufferedSink) {
contentResolver.openInputStream(uri)?.source()?.use { source ->
sink.writeAll(source)
}
}
}
처럼 사용하면 됩니다.
뿐만 아니라, contentType 을 명시하고, contentLength 를 넣어주고 writeTo 의 sink 에 데이터를 담아주기만 하면 텍스트 파일, 이미지, 동영상 등등 많은 부분에서 활용될 수 있습니다.
'Android > Development Tips' 카테고리의 다른 글
Google login errorCode 12500 인 경우 (0) | 2021.06.07 |
---|---|
Proguard 로 난독화 된 코드 복호화 (0) | 2021.05.31 |
Hilt 수박 겉핥기 (0) | 2021.05.07 |
DialogFragment 를 상속하는 다이얼로그에서 dismiss 할 때 Tips (0) | 2021.01.10 |
java.lang.IllegalStateException: Software rendering doesn't support hardware bitmaps 에러 수정하기 (1) | 2021.01.10 |