I am able to get the ANDROID_GET_CONTENT source and load it. Only photos over 2 MB won't load. While I can upload photos up to 2MB without issue, I can't upload to higher size. My code and logs are as follows.
@Multipart
@POST("v1/product...")
suspend fun productImage(
@Part files: MultipartBody.Part,
@Part("imageKey") imageKey: String
): ImageResponse
fun Uri.progressRequestBody(
context: Context?,
percentageHandler: (Int) -> Unit
): MultipartBody.Part? {
val name = getImageNameAndSize(context)
val progressRequestBody = context?.contentResolver?.openInputStream(this)
?.use {
val byte = it.readBytes()
println("ImageUploadLog byte.size: ${byte.size}")
val body = byte.toRequestBody(
contentType = "multipart/form-data".toMediaTypeOrNull()
)
ProgressRequestBody(
requestBody = body,
progressHandler = percentageHandler
)
}
return MultipartBody.Part
.createFormData("files", name?.first, progressRequestBody ?: return null)
}
class ProgressRequestBody(
private val requestBody: RequestBody,
private val progressHandler: (Int) -> Unit
) : RequestBody() {
companion object {
private const val progressUpdatesToSkip = 2
}
private var writeCount = 0
override fun contentType(): MediaType? = requestBody.contentType()
override fun contentLength(): Long = requestBody.contentLength()
override fun writeTo(sink: BufferedSink) {
println("ImageUploadLog writeCount: $writeCount, progressUpdatesToSkip: $progressUpdatesToSkip")
if (writeCount >= progressUpdatesToSkip) {
val countingSink = CountingSink(sink).buffer()
requestBody.writeTo(countingSink)
countingSink.flush()
} else {
requestBody.writeTo(sink)
}
writeCount++
}
private inner class CountingSink(delegate: Sink) : ForwardingSink(delegate) {
private val handler = Handler(Looper.getMainLooper())
private val total = contentLength()
private var uploaded = 0L
init {
println("ImageUploadLog CountingSink init")
}
override fun write(source: Buffer, byteCount: Long) {
println("ImageUploadLog write")
super.write(source, byteCount)
println("ImageUploadLog previous uploaded: $uploaded")
uploaded += byteCount
println("ImageUploadLog new uploaded: $uploaded, byteCount: $byteCount")
handler.post {
val percentage = (100 * (uploaded.toFloat() / total.toFloat())).toInt()
println("ImageUploadLog percentage: $percentage")
progressHandler(percentage)
}
}
}
Photo upload logs:
1) First Image Upload (74 KB) #Success
ImageUploadLog byte.size: 7417
ImageUploadLog writeCount: 0, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 1, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 2, progressUpdatesToSkip: 2
ImageUploadLog CountingSink init
ImageUploadLog write
ImageUploadLog previous uploaded: 0
ImageUploadLog new uploaded: 7417, byteCount: 7417
ImageUploadLog percentage: 100
2) Second Image Upload (4.7 MB) #Fail
ImageUploadLog byte.size: 4788195
ImageUploadLog writeCount: 0, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 1, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 2, progressUpdatesToSkip: 2
ImageUploadLog CountingSink init
ImageUploadLog write