Skip to content

Instantly share code, notes, and snippets.

@yusufceylan
Last active February 6, 2023 03:18
Show Gist options
  • Save yusufceylan/260ae3b072d9a0268c7f15ccef6e05aa to your computer and use it in GitHub Desktop.
Save yusufceylan/260ae3b072d9a0268c7f15ccef6e05aa to your computer and use it in GitHub Desktop.
Take photo from camera and save it to gallery
// Take photo from camera and save it to public gallery
// Before Q and After Q implementations
// Answer riginally taken from this SO answer
// https://stackoverflow.com/a/59482148/5695091
private val REQUEST_TAKE_PHOTO = 101
private val REQUEST_PICK_PHOTO = 102
private var photoURI : Uri? = null
// ------------------------------------------------------------------------------
/**
* Get Image File Uri based on Android Version
*/
private fun getImageFileUri() : Uri? {
return try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
createUriAfterQ()
} else {
createUriForPreQ()
}
} catch (e : Exception) {
// Error occurred while creating the File
LogUtils.d("Error occurred while creating the Uri: ${e.localizedMessage}")
null
}
}
/**
* Create File Uri for Pre Q devices
* With using File Provider
*/
@Throws(IOException::class)
private fun createUriForPreQ(): Uri? {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
// getExternalFilesDir method makes taken images private for our app, it will not allow to display it in gallery
// so we will not use requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
// instead use public external storage directory for pre Q devices
val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val mFile = File.createTempFile(
"JPEG_${timeStamp}_", /* prefix */
".jpg", /* suffix */
storageDir /* directory */
)
return FileProvider.getUriForFile(
requireContext(),
getString(R.string.file_provider_authorities),
mFile
)
}
/**
* Create File Uri for after Q Devices
* With using Media Store
*/
@RequiresApi(Build.VERSION_CODES.Q)
private fun createUriAfterQ(): Uri? {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val fileName = "IMG_${timeStamp}.jpg"
val resolver = requireContext().contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
}
val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
return uri
}
/**
* Open Camera and saved taken photo to previously created Uri
*/
private fun openCameraAndSavePhoto() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
// Ensure that there's a camera activity to handle the intent
takePictureIntent.resolveActivity(requireContext().packageManager)?.also {
// Create Uri where the photo should go
photoURI = getImageFileUri()
photoURI?.let {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, it)
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO)
}
}
}
}
/**
* Open Gallery for pick image
*/
private fun openGallery() {
val galleryIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(galleryIntent, REQUEST_PICK_PHOTO)
}
// ------------------------------------------------------------------------------
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_TAKE_PHOTO -> {
when (resultCode) {
Activity.RESULT_OK -> {
LogUtils.d("User confirm taken photo")
// Show uri in image view
cameraImage.load(photoURI)
}
Activity.RESULT_CANCELED -> {
LogUtils.d("User denied taken photo")
}
}
}
REQUEST_PICK_PHOTO -> {
when (resultCode) {
Activity.RESULT_OK -> {
LogUtils.d("User confirm pick photo")
// Get content uri and show in imageView
val contentURI = data?.data
contentURI?.let {
cameraImage.load(it)
}
}
Activity.RESULT_CANCELED -> {
LogUtils.d("User denied pick photo")
}
}
}
}
}
// ------------------------------------------------------------------------------
// Manifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="@string/file_provider_authorities"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
// ------------------------------------------------------------------------------
// xml/file_paths
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external"
path="."/>
<external-files-path
name="external_files"
path="."/>
<cache-path
name="cache"
path="."/>
<external-cache-path
name="external_cache"
path="."/>
<files-path
name="files"
path="."/>
</paths>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment