Last active
February 6, 2023 03:18
-
-
Save yusufceylan/260ae3b072d9a0268c7f15ccef6e05aa to your computer and use it in GitHub Desktop.
Take photo from camera and save it to gallery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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