package com.reactnativecompressor.Utils import android.annotation.SuppressLint 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 android.provider.OpenableColumns import androidx.loader.content.CursorLoader import com.facebook.react.bridge.ReactApplicationContext import java.io.File import java.io.FileOutputStream import java.io.IOException import java.util.UUID object RealPathUtil { private const val FIELD_NAME = "name" private const val FIELD_TYPE = "type" private const val FIELD_SIZE = "size" fun getRealPath(context: ReactApplicationContext, fileUri: Uri): String? { val realPath: String? // SDK < API11 realPath = if (Build.VERSION.SDK_INT < 11) { getRealPathFromURI_BelowAPI11(context, fileUri) } else if (Build.VERSION.SDK_INT < 19) { getRealPathFromURI_API11to18(context, fileUri) } else { getRealPathFromURI_API19(context, fileUri) } return realPath } @SuppressLint("NewApi") fun getRealPathFromURI_API11to18(context: Context?, contentUri: Uri?): String? { val proj = arrayOf(MediaStore.Images.Media.DATA) var result: String? = null val cursorLoader = CursorLoader(context!!, contentUri!!, proj, null, null, null) val cursor = cursorLoader.loadInBackground() if (cursor != null) { val column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) cursor.moveToFirst() result = cursor.getString(column_index) cursor.close() } return result } fun getRealPathFromURI_BelowAPI11(context: Context, contentUri: Uri?): String { val proj = arrayOf(MediaStore.Images.Media.DATA) val cursor = context.contentResolver.query(contentUri!!, proj, null, null, null) var column_index = 0 var result = "" if (cursor != null) { column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) cursor.moveToFirst() result = cursor.getString(column_index) cursor.close() return result } return result } /** * Get a file path from a Uri. This will get the the path for Storage Access * Framework Documents, as well as the _data field for the MediaStore and * other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @author paulburke */ @SuppressLint("NewApi") fun getRealPathFromURI_API19(context: ReactApplicationContext, 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] if ("primary".equals(type, ignoreCase = true)) { return Environment.getExternalStorageDirectory().toString() + "/" + split[1] } // TODO handle non-primary volumes } 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,uri) } 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 }else { contentUri = MediaStore.Files.getContentUri("external"); } val selection = "_id=?" val selectionArgs = arrayOf( split[1] ) return getDataColumn(context, contentUri, selection, selectionArgs,uri) } } else if ("content".equals(uri.scheme, ignoreCase = true)) { // Return the remote address return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(context, uri, null, null,uri) } 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 useful 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: ReactApplicationContext, uri: Uri?, selection: String?, selectionArgs: Array?,actualUri: Uri?): 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) } val copyPath=copyFileToLocalStorage(actualUri!!, context) MediaCache.addCompletedImagePath(copyPath) return copyPath } catch (e: Exception) { val copyPath=copyFileToLocalStorage(actualUri!!, context) MediaCache.addCompletedImagePath(copyPath) return copyPath } finally { cursor?.close() } return null } fun getFileExtension(fileName: String): String { return if (fileName.contains(".")) { fileName.substringAfterLast(".") } else { "" } } private fun copyFileToLocalStorage( uri: Uri,context: ReactApplicationContext): String { val returnUri = uri val returnCursor = context.contentResolver.query(returnUri, null, null, null, null) returnCursor?.moveToFirst(); val nameIndex = returnCursor!!.getColumnIndex(OpenableColumns.DISPLAY_NAME) val name = returnCursor!!.getString(nameIndex) val fileExtension=getFileExtension(name) var dir = context.cacheDir // we don't want to rename the file so we put it into a unique location dir = File(dir, UUID.randomUUID().toString()) try { val destPath=Utils.generateCacheFilePath(fileExtension, context) val destFile = File(destPath) val copyPath: Uri = copyFile(context, uri, destFile) return copyPath.toString() } catch (e: java.lang.Exception) { e.printStackTrace() } return uri.toString() } @Throws(IOException::class) fun copyFile(context: Context, uri: Uri?, destFile: File?): Uri { context.contentResolver.openInputStream(uri!!).use { inputStream -> FileOutputStream(destFile).use { outputStream -> val buf = ByteArray(8192) var len: Int while (inputStream!!.read(buf).also { len = it } > 0) { outputStream.write(buf, 0, len) } return Uri.fromFile(destFile) } } } /** * @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 } }