Created
June 22, 2020 07:13
-
-
Save hitesh-dhamshaniya/9569317b8e9f878392466e21f81c220a to your computer and use it in GitHub Desktop.
File URI Utils. kt is used full get exact path of selected file from intent
This file contains 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
import android.content.ContentUris | |
import android.content.Context | |
import android.database.Cursor | |
import android.net.Uri | |
import android.os.Build | |
import android.os.Environment | |
import android.provider.DocumentsContract | |
import android.provider.MediaStore | |
import java.io.File | |
import java.io.FileOutputStream | |
import java.io.IOException | |
import java.io.InputStream | |
import java.io.OutputStream | |
/** | |
* This file was taken from | |
* https://gist.github.com/HBiSoft/15899990b8cd0723c3a894c1636550a8 | |
* | |
* Later on it was modified from the below resource: | |
* https://raw.githubusercontent.com/iPaulPro/aFileChooser/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java | |
* https://raw.githubusercontent.com/iPaulPro/aFileChooser/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java | |
*/ | |
object FileUriUtils { | |
fun getRealPath(context: Context, uri: Uri): String? { | |
var path = getPathFromLocalUri(context, uri) | |
if (path == null) { | |
path = getPathFromRemoteUri(context, uri) | |
} | |
return path | |
} | |
private fun getPathFromLocalUri(context: Context, uri: Uri): String? { | |
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(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() | |
val type = split[0] | |
// This is for checking Main Memory | |
return if ("primary".equals(type, ignoreCase = true)) { | |
if (split.size > 1) { | |
Environment.getExternalStorageDirectory().toString() + "/" + split[1] | |
} else { | |
Environment.getExternalStorageDirectory().toString() + "/" | |
} | |
// This is for checking SD Card | |
} else { | |
val path = "storage" + "/" + docId.replace(":", "/") | |
if (File(path).exists()) { | |
path | |
} else { | |
"/storage/sdcard/" + split[1] | |
} | |
} | |
} else if (isDownloadsDocument(uri)) { | |
val fileName = getFilePath(context, uri) | |
if (fileName != null) { | |
return Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName | |
} | |
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(":".toRegex()).dropLastWhile { it.isEmpty() }.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) | |
} // MediaProvider | |
// DownloadsProvider | |
} 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 | |
} // File | |
// MediaStore (and general) | |
return null | |
} | |
private 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.contentResolver.query(uri!!, projection, selection, selectionArgs, null) | |
if (cursor != null && cursor.moveToFirst()) { | |
val index = cursor.getColumnIndexOrThrow(column) | |
return cursor.getString(index) | |
} | |
} catch (ex: Exception) { | |
} finally { | |
cursor?.close() | |
} | |
return null | |
} | |
private fun getFilePath(context: Context, uri: Uri): String? { | |
var cursor: Cursor? = null | |
val projection = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME) | |
try { | |
cursor = context.contentResolver.query(uri, projection, null, null, null) | |
if (cursor != null && cursor.moveToFirst()) { | |
val index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME) | |
return cursor.getString(index) | |
} | |
} finally { | |
cursor?.close() | |
} | |
return null | |
} | |
private fun getPathFromRemoteUri(context: Context, uri: Uri): String? { | |
// The code below is why Java now has try-with-resources and the Files utility. | |
var file: File? = null | |
var inputStream: InputStream? = null | |
var outputStream: OutputStream? = null | |
var success = false | |
try { | |
val extension = getImageExtension(uri) | |
inputStream = context.contentResolver.openInputStream(uri) | |
file = FileUtil.getImageFile(context.cacheDir, extension) | |
if (file == null) return null | |
outputStream = FileOutputStream(file) | |
if (inputStream != null) { | |
inputStream.copyTo(outputStream, bufferSize = 4 * 1024) | |
success = true | |
} | |
} catch (ignored: IOException) { | |
} finally { | |
try { | |
inputStream?.close() | |
} catch (ignored: IOException) { | |
} | |
try { | |
outputStream?.close() | |
} catch (ignored: IOException) { | |
// If closing the output stream fails, we cannot be sure that the | |
// target file was written in full. Flushing the stream merely moves | |
// the bytes into the OS, not necessarily to the file. | |
success = false | |
} | |
} | |
return if (success) file!!.path else null | |
} | |
/** @return extension of image with dot, or default .jpg if it none. | |
*/ | |
private fun getImageExtension(uriImage: Uri): String { | |
var extension: String? = null | |
try { | |
val imagePath = uriImage.path | |
if (imagePath != null && imagePath.lastIndexOf(".") != -1) { | |
extension = imagePath.substring(imagePath.lastIndexOf(".") + 1) | |
} | |
} catch (e: Exception) { | |
extension = null | |
} | |
if (extension == null || extension.isEmpty()) { | |
// default extension for matches the previous behavior of the plugin | |
extension = "jpg" | |
} | |
return ".$extension" | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is ExternalStorageProvider. | |
*/ | |
private 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. | |
*/ | |
private 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. | |
*/ | |
private 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. | |
*/ | |
private fun isGooglePhotosUri(uri: Uri): Boolean { | |
return "com.google.android.apps.photos.content" == uri.authority | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment