Pick photo/video via intent in Android

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="26"/>
val PICK_MEDIA= 100
private fun openGallery() {
if (Build.VERSION.SDK_INT in 23..26 && ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.READ_EXTERNAL_STORAGE) != 0
) {
requestPermissions(arrayOf<String>(android.Manifest.permission.READ_EXTERNAL_STORAGE),
REQUEST_PERMISSION)
} else {
val gallery = Intent(Intent.ACTION_PICK)
gallery.setType("*/*");
startActivityForResult(gallery, PICK_MEDIA)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != RESULT_OK){
return
}
when(requestCode){
PICK_MEDIA -> {
val selectedImageUri: Uri? = data?.data
if(selectedImageUri == null){
return
}

Log.i(TAG, "selectedImageUri $selectedImageUri")
var mimeType: String? = contentResolver.getType(selectedImageUri)

Log.i(TAG,
"mimeType $mimeType")
//mimeType can be null when select video from google photos. This is //known issue in specific version. In updated versions it is fixed. //I faced this issue when test on emulator so may be, You will never //face this issue because phone always has upadted google photo app
if (mimeType?.contains("video/") == true || (mimeType == null && selectedImageUri.toString().contains("video"))) {
mime = mime?:"video/mp4"
val bitmap = getVideoThumbnail(this, selectedImageUri, imageWidth)
//Save file to upload on server
val file = saveVideo(this, selectedImageUri, mime)
} else if (mime?.contains("image/") == true) {
var stream = contentResolver.openInputStream(uri)
val bitmap = BitmapFactory.decodeStream(stream, null, options)
stream?.close()
//Save file to upload on server
val file = saveBitmapToFile(resultBitmap, "image/jpg", mediaPath?.absolutePath)
}
}
}
}
fun getVideoThumbnail(context: Context, videoUri: Uri, imageWidth: Int, imageHeight: Int): Bitmap? {
var bitmap: Bitmap? = null
if (Build.VERSION.SDK_INT < 27) {
val picturePath = getPath(context, videoUri!!)
Log.i(TAG, "picturePath $picturePath")
if (picturePath == null) {
val mMMR = MediaMetadataRetriever()
mMMR.setDataSource(context, videoUri)
bitmap = mMMR.frameAtTime
} else {
bitmap = ThumbnailUtils.createVideoThumbnail(picturePath!!,
MediaStore.Images.Thumbnails.MINI_KIND)
}
} else {
val mMMR = MediaMetadataRetriever()
mMMR.setDataSource(context, videoUri)
bitmap = mMMR.getScaledFrameAtTime(-1,
MediaMetadataRetriever.OPTION_CLOSEST_SYNC,
imageWidth,
imageHeight)
}

return bitmap
}
fun saveVideo(context: Context, videoUri: Uri?, mimeType: String?): File? {
if(videoUri == null || mimeType == null){
return null
}

val fileName = "capturedVideo.${mime.substring(mime.indexOf("/") + 1)}"

val inputStream = context.contentResolver.openInputStream(videoUri)
val file = File(context.getExternalFilesDir(Environment.DIRECTORY_DCIM), fileName)
file.deleteOnExit()
file.createNewFile()
val out = FileOutputStream(file)
val bos = BufferedOutputStream(out)

val buf = ByteArray(1024)
inputStream?.read(buf)
do {
bos.write(buf)
} while (inputStream?.read(buf) !== -1)

//out.close()
bos.close()
inputStream.close()

return file
}
fun saveBitmapToFile(bitmap: Bitmap?, mimeType: String, absolutePath: String?): File? {
if(absolutePath == null || bitmap == null){
return null
}

val file = File(absolutePath)
val stream = FileOutputStream(file)

if (mimeType.contains("jpg", true) || mimeType.contains("jpeg", true))
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
else if (mimeType.contains("png", true))
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)

stream.close()

return file
}
fun getPath(context: Context, uri: Uri): String? {

// check here to KITKAT or new version
//val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

// DocumentProvider
if (/*isKitKat && */DocumentsContract.isDocumentUri(context, uri)) {

// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":").toTypedArray()
val type = split[0]
if ("primary".equals(type, ignoreCase = true)) {
return (Environment.getExternalStorageDirectory().toString() + "/"
+ split[1])
}
} else if (isDownloadsDocument(uri)) {
val id = DocumentsContract.getDocumentId(uri)
val contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
java.lang.Long.valueOf(id))
return getDataColumn(context, contentUri, null, null)
} else if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":").toTypedArray()
val type = split[0]
var contentUri: Uri? = null
if ("image" == type) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
} else if ("video" == type) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
} else if ("audio" == type) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = "_id=?"
val selectionArgs = arrayOf(split[1])
return getDataColumn(context, contentUri, selection,
selectionArgs)
}
} else if ("content".equals(uri.scheme, ignoreCase = true)) {

// Return the remote address
return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(context,
uri,
null,
null)
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
return uri.path
}
return null
}

/**
* Get the value of the data column for this Uri. This is <span id="IL_AD2" class="IL_AD">useful</span> for MediaStore Uris, and other file-based
* ContentProviders.
*
* @param context
* The context.
* @param uri
* The Uri to query.
* @param selection
* (Optional) Filter used in the query.
* @param selectionArgs
* (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
fun getDataColumn(
context: Context, uri: Uri?,
selection: String?, selectionArgs: Array<String>?,
): String? {
var cursor: Cursor? = null
val column = "_data"
val projection = arrayOf(column)
try {
cursor = context.getContentResolver().query(uri!!, projection,
selection, selectionArgs, null)
if (cursor != null && cursor.moveToFirst()) {
val index: Int = cursor.getColumnIndexOrThrow(column)
return cursor.getString(index)
}
} finally {
if (cursor != null) cursor.close()
}
return null
}

/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri
.authority
}

/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri
.authority
}

/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri
.authority
}

/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
fun isGooglePhotosUri(uri: Uri): Boolean {
return "com.google.android.apps.photos.content" == uri
.authority
}

--

--

--

Mobile App Developer

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

How to Make RecyclerView Items That Expand With Animation

Ultimate Guide to Android Material Design Components

How to Use the Google Drive API With Flutter Apps

Android : Handle Network Requests with Kotlin Coroutines and Retrofit

GameDev : Game Over Text Flicker!

Root Android device Pixel 6

Top Kotlin Blogs To Learn More In Kotlin

Review Process at Trendyol Android Team

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
DKumar

DKumar

Mobile App Developer

More from Medium

Integration of Huawei Account kit, Remote Configuration, Crash kit and IAP Service in Flutter…

Create BEP20 & ERC20 Token Generator Platform Like Cointool App

Web3’s Overton Window

Run a Telegram bot in old Android device