'Save image to internal storage using ActivityResultContracts.GetContent(). - (Kotlin/Java/Android)
I'm new to file storage. My main goal is to take a picture with the camera, store it with good quality, then display it in an ImageView. I want to avoid asking for user permission (to use camera and external storage), and want to make this as simple as possible.
To take a picture, I'm using
val capturePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { it: Boolean -> }
.
I don't know how to get the bitmap from this function or if I should. To my understanding I should send the uri when calling capturePicture.launch(uri)
.
My question is if this is correct, also how do I get the URI, save it to internal storage (.openFileOutput()
), then load it from internal storage.
I prefer the answer in Kotlin but Java is fine too. An explanation on how paths work in internal storage could be helpful too.
Solution 1:[1]
I followed this medium article tutorial, adjusted it and added more functionality for my use case.
Saved images in the cache directory
To take the picture:
private val takeImageResult =
registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
if (isSuccess) {
latestTmpUri?.let { uri ->
loadPhotosFromInternalStorageIntoRecyclerView()
}
}
}
To call take picture, save it, and get the uri:
private var latestTmpUri: Uri? = null
private fun takeImage() {
lifecycleScope.launchWhenStarted {
getTmpFileUri().let { uri ->
latestTmpUri = uri
takeImageResult.launch(uri)
}
}
}
private fun getTmpFileUri(): Uri {
val tmpFile = File.createTempFile("tmp_image_file", ".jpg", requireActivity().cacheDir).apply {
createNewFile()
deleteOnExit()
}
return FileProvider.getUriForFile(requireActivity().applicationContext, "${BuildConfig.APPLICATION_ID}.provider", tmpFile)
}
To load the picture (loads the first picture in the list of pictures):
private fun loadPhotosFromInternalStorage(): List<InternalStoragePhoto> {
val files = requireActivity().cacheDir.listFiles()
return files?.filter {
it.canRead() && it.isFile && it.name.endsWith(".jpg")
}?.map {
InternalStoragePhoto(it.name, it.toUri())
} ?: listOf()
}
private fun displayImage() {
Glide.with(photoImg.context)
.load(loadPhotosFromInternalStorage()[0].uri)
.into(photoImg)
}
Here's the custom object for the images:
data class InternalStoragePhoto(
val name: String,
val uri: Uri?
)
This is a simplified version of my code, here's the source code for the test app github repo
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | extremeoats |