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.
CodePudding user response:
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