I'm trying to get list of images from a folder using this function
var gpath:String = Environment.getExternalStorageDirectory().absolutePath
var spath = "testfolder"
var fullpath = File(gpath + File.separator + spath)
var list = imageReader(fullpath)
fun imageReader(root : File):ArrayList<File>{
val a : ArrayList<File> ? = null
val files = root.listFiles()
for (i in 0..files.size){
if (files[i].name.endsWith(".jpg")){
a?.add(files[i])
}
}
return a!!
}
but i have these exceptions :
java.lang.ArrayIndexOutOfBoundsException:length=3;index=3
kotin.kotlinNullPointerException
I've read about this problem but i have no idea how to fix it,
any help please?
For Null Pointer you may need to change and pass fullpath instead of path inside var list = imageReader(path).
Wrong
var fullpath = File(gpath + File.separator + spath)
var list = imageReader(path)
Right
var gpath:String = Environment.getExternalStorageDirectory().absolutePath
var spath = "testfolder"
var fullpath = File(gpath + File.separator + spath)
var list = imageReader(fullpath)
EDIT 1
I have made few changes to function and apply it inside override fun onCreate as below.
var gpath: String = Environment.getExternalStorageDirectory().absolutePath
var spath = "Download"
var fullpath = File(gpath + File.separator + spath)
Log.w("fullpath", "" + fullpath)
imageReaderNew(fullpath)
Function
fun imageReaderNew(root: File) {
val fileList: ArrayList<File> = ArrayList()
val listAllFiles = root.listFiles()
if (listAllFiles != null && listAllFiles.size > 0) {
for (currentFile in listAllFiles) {
if (currentFile.name.endsWith(".jpeg")) {
// File absolute path
Log.e("downloadFilePath", currentFile.getAbsolutePath())
// File Name
Log.e("downloadFileName", currentFile.getName())
fileList.add(currentFile.absoluteFile)
}
}
Log.w("fileList", "" + fileList.size)
}
}
Logcat Output
W/fullpath: /storage/emulated/0/Download
E/downloadFilePath: /storage/emulated/0/Download/download.jpeg
E/downloadFileName: download.jpeg
E/downloadFilePath: /storage/emulated/0/Download/images.jpeg
E/downloadFileName: images.jpeg
E/downloadFilePath: /storage/emulated/0/Download/images (1).jpeg
E/downloadFileName: images (1).jpeg
fun imageReader(root : File):ArrayList<File>{
val a : ArrayList<File> ? = null
val files = root.listFiles()
for (i in 0..files.size-1){
if (files[i].name.endsWith(".jpg")){
a?.add(files[i])
}
}
return a!!
}
The above answer is right but it declares a as null and then in loop uses null save. Therefore it detects images but does not add them to the list and the list returns null.
fun imageReader(root: File): ArrayList < File > {
val a: ArrayList < File > = ArrayList()
if (root.exists()) {
val files = root.listFiles()
if (files.isNotEmpty()) {
for (i in 0..files.size - 1) {
if (files[i].name.endsWith(".jpg")) {
a.add(files[i])
}
}
}
}
return a!!
}
By using MediaStore we can achieve count of image inside a folder and we will add one more check to prevent getting image of subfolders of current folder.
fun getImageCountInDirectory(context: Context, directoryPath: String): Int {
var imageCount = 0
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val sortOrder = MediaStore.Images.Media.DATE_MODIFIED + " DESC"
val selection = "${MediaStore.Images.Media.DATA} like ? and ${MediaStore.Images.Media.DATA} not like ?"
val selectionArgs = arrayOf("$directoryPath/%", "$directoryPath/%/%") // use % as a wildcard character to select all files inside the directory, and exclude subdirectories
val cursor = context.contentResolver.query(
uri,
null,
selection,
selectionArgs,
sortOrder
)
if (cursor != null) {
imageCount = cursor.count
cursor.close()
}
return imageCount
}
This function will return an integer value and it is the total number of image files inside the folder. And we are using the not like operator and adding %/% to the selectionArgs array to select all files whose path doesn't contain a subdirectory.
Related
The following code is used to save files from the app to downloads:
Uri collection = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
ContentValues values = new ContentValues();
values.put(MediaStore.Downloads.DISPLAY_NAME, filename);
values.put(MediaStore.Downloads.MIME_TYPE, mimeType);
values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
ContentResolver contentResolver = context.getApplicationContext().getContentResolver();
Uri uri = contentResolver.insert(collection, values);
OutputStream outputStream = context.getApplicationContext().getContentResolver().openOutputStream(uri, "w");
Everything is saved, however, if you delete the file from downloads manually, and then try to download it again from the application, an error appears:
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: files._data (code 2067 SQLITE_CONSTRAINT_UNIQUE[2067])
Is there a way to fix this or will I have to use unique names for each download?
This error happens because the machanism of OS: if we delete manually a file (media), its database will not be deleted immediately. Until we restart device.
Have a approach for this problem (still not be optimized - hope receiving sharing from people), such as:
Step 1: Get info of file via its name
Step 2: Ask OS to update its database via MediaScannerConnection.scanFile
Step 3: Use current code that has above problem
Codes for steps (collected on internet)
Step 1:
fun findByFileName(fileName: String): MutableList<FileInfo> {
val files = mutableListOf<FileInfo>()
val collection =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
val projection = arrayOf(
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.DATA
)
val selection = "${MediaStore.Video.Media.DISPLAY_NAME} LIKE ?"
val selectionArgs = arrayOf(
fileName
)
// Display videos in alphabetical order based on their display name.
val sortOrder = "${MediaStore.Video.Media.DISPLAY_NAME} ASC"
val query = context.contentResolver.query(
collection,
projection,
selection,
selectionArgs,
sortOrder
)
query?.use { cursor ->
// Cache column indices.
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
val nameColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)
val durationColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)
val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)
val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)
while (cursor.moveToNext()) {
// Get values of columns for a given video.
val id = cursor.getLong(idColumn)
val name = cursor.getString(nameColumn)
val duration = cursor.getInt(durationColumn)
val size = cursor.getInt(sizeColumn)
val data = cursor.getStringOrNull(dataColumn)
val contentUri: Uri = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
id
)
// Stores column values and the contentUri in a local object
// that represents the media file.
files += FileInfo(contentUri, name, duration, size, data)
}
}
return files
}
data class FileInfo(
val uri: Uri,
val name: String,
val duration: Int,
val size: Int,
val data: String? = null
)
Step 2 + Step 3:
val exitedData = findByFileName(fileName = name)
if (exitedData != null) {
MediaScannerConnection.scanFile(context, arrayOf(exitedData.first().data.toString()), null, object: MediaScannerConnection.OnScanCompletedListener {
override fun onScanCompleted(path: String?, uri: Uri?) {
// Step 3
// Use current code have this problem
...
}
}
} else {
// Save file normally
// Use current code have this problem
...
}
I am saving a file inside the Downloads directory of the device (Android 11) to be viewed later by my app. I'm allowing multiple file types like pdf, word etc. I was able to save the file like this: (I got this code sample from here)
#TargetApi(29)
private suspend fun downloadQ(
url: String,
filename: String,
mimeType: String
) =
withContext(Dispatchers.IO) {
val response = ok.newCall(Request.Builder().url(url).build()).execute()
if (response.isSuccessful) {
val values = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, filename)
put(MediaStore.Downloads.MIME_TYPE, mimeType)
put(MediaStore.Downloads.IS_PENDING, 1)
}
val resolver = context.contentResolver
val uri =
resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
uri?.let {
resolver.openOutputStream(uri)?.use { outputStream ->
val sink = outputStream.sink().buffer()
response.body()?.source()?.let { sink.writeAll(it) }
sink.close()
}
values.clear()
values.put(MediaStore.Downloads.IS_PENDING, 0)
resolver.update(uri, values, null, null)
} ?: throw RuntimeException("MediaStore failed for some reason")
} else {
throw RuntimeException("OkHttp failed for some reason")
}
}
But when I tried to retrieve the file, I tried with the following ways that did not work:
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID)
val id = cursor.getLong(idColumn)
Log.d("uri id ","$id")
val contentUri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI,id)
This approach threw an exception:
java.lang.IllegalArgumentException: Failed to find configured root that contains /external/downloads/78
I got this ID (here 78) from the query and cursor from ContentResolver.query() and I hoped it to return the Uri from which I could get the File.
The second approach was this:
val uri = MediaStore.Downloads.getContentUri("external",id)
uri.path?.let { filePath ->
Log.d("uri path ",filePath)
val file = File(filePath)
} ?: Log.d("uri path ","null")
I used external as the directory based on this answer, but this approach also threw the same exception
java.lang.IllegalArgumentException: Failed to find configured root that contains /external/downloads/78
At the end what ended up working was hardcoding something like this after I used a file explorer app to view the exact directory path:
val file = File("storage/emulated/0/Download/$name.$extension")
So my question is, how do I get the value of this path dynamically, and is this path the same for all devices that can be used like this way?
EDIT: I also wanted to know if I am using the filename and it's extension to view the file, then if user downloads another file with same name then how do I make sure that correct file is opened? (even if i make a separate directory for my app inside Download, user could still download the same file twice that has a name like storage/emulated/0/Download/myDir/file(2).extension )
Try with the following code it will help you.
private fun readFile(){
val FILENAME = "user_details.txt"
val dir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.toString() + "/" + "folderName"
)
} else {
File(
Environment.getExternalStorageDirectory()
.toString() + "/${Environment.DIRECTORY_DOWNLOADS}/" + "folderName"
)
}
dir.apply {
if(this.exists()) File(this, FILENAME).apply {
FileInputStream(this).apply {
val stringBuffer = StringBuffer()
var i: Int
while (this.read().also { i = it } != -1) {
stringBuffer.append(i.toChar())
}
close()
}
}
}
}
You can use
{Environment.DIRECTORY_DOWNLOADS} + "/folderName/file_name.mime_type"
/storage/emulated/0/Download/12d82c65-00a5-4c0a-85bc-238c28005c33.bin
In my Android application I have a feature of renaming files. I have implemented this feature by creating a new file with new name on same path and then copying the content of original file to new file after all that I delete the file with old name.
The problem here is that the timestamp of the original file is not retained and the renamed file gets created with time when it was renamed.
What I have tried so far
1- I used file.renameTo() function.
2- 1 never works so I used setLastModified method for new file and passed it the last modified date of original file. Got this last modified date by using existingFile.lastModified().
3- After that in function where i am fetching files using Media Store I sorted the files by DATE_MODIFIED
4- Point 3 doesn't worked properly as it keeps showing renamed file on top with original file date, so I removed Sort by DATE_MODIFIED from media store and tried fetchedFiles.sortByDescending { it.getMFileDate() }
5- Point 4 also have same issue the renamed file shows up on top.
Code for renameTo function usage that didn't work properly
try {
val existingFile = File(selectedFile.getMAbsolute_path())
val separator = "."
val arrValues: Array<String> =
selectedFile.getMAbsolute_path()?.split(separator)!!.toTypedArray()
val newFileName = inputText
val newFilePath =
selectedFile.getMParent_file() + "/$newFileName.${arrValues[arrValues.size - 1]}"
val newFile = File(newFilePath)
existingFile.renameTo(newFile)
} catch (e: Exception) {
e.printStackTrace()
}
The above code renames the file on device version 8 but on Android version 7 it just removes the file. It doesn't shows up same results on different devices
Below is my current code:
Permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.READ_PHONE_STATE" />
UPDATED [23-12-2020]
I have made changes to proceedRenaming function, first i created new file object then copied it, after that i have set lastModified and at the end Media Store scan is called.
This is the right call hierarchy. It works fine on devices greater than or equal to Android Version 8 (OREO).
I have figured out the setLastModified function is not working on devices below Android Version 8 (OREO). It keeps on setting the current date to new file.
Rename Function
private fun proceedRenaming(
context: Context,
selectedFile: MyFileModel,
positionOfDeleted: Int,
inputText: String,
isFileShortcutCreated: Boolean
) {
try {
//delete shortcut if exists
deleteFileShortCut(context, selectedFile, positionOfDeleted)
val existingFile = File(selectedFile.getMAbsolute_path())
val separator = "."
val arrValues: Array<String> =
selectedFile.getMAbsolute_path()?.split(separator)!!.toTypedArray()
val newFileName = inputText
val newFilePath = selectedFile.getMParent_file() + "/$newFileName.${arrValues[arrValues.size - 1]}"
val newFile = File(newFilePath)
copy(existingFile, newFile)
//print the original last modified date
val sdf = SimpleDateFormat("MM/dd/yyyy")
val date1 = "" + sdf.format(existingFile.lastModified())
Log.d("Origina Date :", date1)
//set this date
//need convert the above date to milliseconds in long value
val newDate: Date = sdf.parse(date1)
newFile.setLastModified(newDate.time)
//print the latest last modified date
val date2 = "" + sdf.format(newFile.lastModified())
Log.i("Lastest Date : ", date2)
context?.sendBroadcast(
Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(newFile)
)
)
if (existingFile.exists()) {
existingFile.delete()
existingFile.canonicalFile.delete()
if (existingFile.exists()) {
BaseApplication.applicationContext()
.deleteFile(existingFile.getName())
}
}
MediaScannerConnection.scanFile(
context,
arrayOf<String>(selectedFile.getMAbsolute_path().toString()),
null
) { path, uri ->
Log.i("ExternalStorage", "Scanned $path:")
Log.i("ExternalStorage", "-> uri=$uri")
context?.contentResolver
?.delete(uri, null, null)
}
selectedFile.setOldFileName(selectedFile.getMFile_name()!!)
selectedFile.setOldFileParentFileh(selectedFile.getMParent_file()!!)
selectedFile.setOldFilePath(selectedFile.getMAbsolute_path()!!)
selectedFile.setMAbsolute_path(newFilePath)
selectedFile.setMFile_name(newFileName)
selectedFile.setPosition(positionOfDeleted)
renamedFile.postValue(selectedFile)
if (isFileShortcutCreated) {
createFileShortCut(context, selectedFile, positionOfDeleted)
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(
context,
context?.getString(R.string.text_rename_error),
Toast.LENGTH_SHORT
).show()
}
}
Copy Function
#Throws(IOException::class)
fun copy(src: File?, dst: File?) {
val inStream = FileInputStream(src)
val outStream = FileOutputStream(dst)
val inChannel: FileChannel = inStream.getChannel()
val outChannel: FileChannel = outStream.getChannel()
inChannel.transferTo(0, inChannel.size(), outChannel)
inStream.close()
outStream.close()
}
Function Where I am fetching files from MediaStore
private fun readFiles(
args: Array<String?>,
where: String
): ArrayList<MyFileModel> {
val fetchedFiles = ArrayList<MyFileModel>()
var fileCursorExternal: Cursor? = null
var fileCursorInternal: Cursor? = null
try {
//Tables
val tableExternal = MediaStore.Files.getContentUri("external")
val tableInternal = MediaStore.Files.getContentUri("internal")
//Column
val column = arrayOf(
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.MediaColumns.DATA,
MediaStore.MediaColumns.TITLE,
MediaStore.MediaColumns.SIZE,
MediaStore.Files.FileColumns.DATE_MODIFIED
)
//Sort by date
val orderBy = MediaStore.Files.FileColumns.DATE_MODIFIED
fileCursorExternal = context.contentResolver.query(
tableExternal,
column,
where,
args, "$orderBy DESC"
)
while (fileCursorExternal!!.moveToNext()) {
fetchedFiles.add(setMyFileModel(fileCursorExternal))
}
fileCursorInternal = context.contentResolver.query(
tableInternal,
column,
where,
args,
"$orderBy DESC"
)
while (fileCursorInternal!!.moveToNext()) {
fetchedFiles.add(setMyFileModel(fileCursorInternal))
}
} catch (ex: java.lang.Exception) {
ex.printStackTrace()
} finally {
fileCursorExternal?.close()
fileCursorInternal?.close()
}
//fetchedFiles.sortByDescending { it.getMFileDate() } //commented as not working
return fetchedFiles
}
Function Where the data from cursor is converted to MyFileModel class object
private fun setMyFileModel(cursor: Cursor): MyFileModel {
val MyFileModel = MyFileModel()
if (cursor != null) {
try {
MyFileModel.setMFileDate(
getReadableDate(
cursor.getLong(
cursor.getColumnIndexOrThrow(
MediaStore.Files.FileColumns.DATE_MODIFIED
)
)
)
)
MyFileModel.setMAbsolute_path(
cursor.getString(
cursor.getColumnIndexOrThrow(
MediaStore.MediaColumns.DATA
)
)
)
MyFileModel.setMFile_name(
cursor.getString(
cursor.getColumnIndexOrThrow(
MediaStore.MediaColumns.TITLE
)
)
)
MyFileModel.setMFile_size(
getReadableSize(
cursor.getLong(
cursor.getColumnIndexOrThrow(
MediaStore.MediaColumns.SIZE
)
)
)
)
MyFileModel.setFileType(getFileType(MyFileModel.getMAbsolute_path()).name)
if (MyFileModel.getMAbsolute_path() != null) {
val file = File(MyFileModel.getMAbsolute_path())
MyFileModel.setMParent_file(file.parent)
}
} catch (ex: Exception) {
ex.printStackTrace()
}
}
return MyFileModel
}
Function to convert long date to string
private fun getReadableDate(dateVal: Long): String {
try {
var date = dateVal
date *= 1000L
return SimpleDateFormat("dd MMM yyyy").format(Date(date))
} catch (ex: Exception) {
ex.printStackTrace()
}
return ""
}
Required Output
1- On renaming a file, new file should be created old file should be deleted.
2- New file should have timestamp of old file so that sorting is not disturbed.
What can I try to resolve this?
I am using below code to save image data into local directory from Uris obtained through pick intent.
private fun sendImages(uriString: String, messageBody: String, uriList: ArrayList<Uri>) {
val pathList = mutableListOf<String>()
val fileNameList = mutableListOf<String>()
var fieSize = 0
var multiSize = 0
if(uriList.isEmpty() && uriString.isNotEmpty())
uriList.add(Uri.parse(uriString))
val localId: String = "localId"
for(i in 0 until uriList.size) {
val uri = uriList[i]
val path = FileUtils.getPath(application, uri)!!
val fullName = path.substring(path.lastIndexOf("/") + 1)
val name = "some function call that returns unique name for file"
val file = File(requireActivity().applicationContext.filesDir, localId + name)
file.createNewFile()
var bitmapdata: ByteArray? = null
var inputStream: InputStream? = null
try {
val ei = ExifInterface(path)
val orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
var bitmap: Bitmap? = null
bitmap = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
ImageDecoder.decodeBitmap(ImageDecoder.createSource(requireActivity().applicationContext.contentResolver, uri))
}
else MediaStore.Images.Media.getBitmap(requireActivity().applicationContext.contentResolver, uri)
val newBitmap = FunctionUtil.rotateImage(bitmap, orientation)
bitmapdata = FileUtils.getCompressedBitmapForUpload(newBitmap!!)
FunctionUtil.recycleBitmap(newBitmap)
} catch (e: Exception) {
return
}
}
requireActivity().applicationContext.openFileOutput(file.name, Context.MODE_PRIVATE).use {
it.write(bitmapdata)
}
val localPath = FunctionUtil.getMediaStorePath(requireActivity().application)
val completePath = requireActivity().application.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)!!
var outFile =File(localPath+"/"+file.name)
org.apache.commons.io.FileUtils.copyFile(file,outFile)
Logger.log("PATH ${ outFile.absolutePath} ${ outFile.path}")
pathList.add(outFile.absolutePath)
fileNameList.add(file.name)
//... Do something with this data
}
}
In the same code, if single file is copied to local directory, it is getting saved & i am able to send it . But whenever i try to save multiple files, the files are becoming empty when i try to send them.
I am not able to find what issue is there. Please help
Some Android phones will encounter such a problem :
the file does exist, but the 'fd' returned by the 'c++ open()' method is -1, and the 'strerror' showing 'No such file or directory".
The phones I have come across are as follows:
vivo
V2055A V2073A V2241A
huawei
GIA-AN00 JLH-AN00 CMA-AN00 HPB-AN00 NTN-AN20 CMA-AN40
oppo
LE2110
In the source code of the Android System, a similar phenomenon can also be found :
The above is a comment added in 2017, and only the common 'bmp' and 'ico' formats are written.
In face, this problem also occurs with pictures in 'heif/heic' format.
Finally,
Using 'FileInputStream' will be ok.
I have searched high and low and not found an answer to my particular question, I hope someone can help.
I am developing this for Android 9 and above, the code I use for older releases works fine.
It's quite simple, I have stored an image in the MediaStore, I have found the image in the media store, I return its path, I check the path exists and it does, it also has a correct size and is visible in the android Gallery. So why when I try to open it with
val bitmap2 = BitmapFactory.decodeFile(fullPath)
bitmap2 comes back as null - no errors are generated by the above command. The parseAllImages function was taken from the web and tweaked slightly but seems to work ok as far as I can tell.
sample code
private fun setPic() {
if (mediaPath.isNotEmpty()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val content = GalleryAdd.parseAllImages(requireActivity(), mediaPath)
val fullPath = content
if (File(fullPath).exists()) {
val tester = File(fullPath).length()
val bitmap2 = BitmapFactory.decodeFile(fullPath)
viewModel.setBitmap(bitmap2)
}
}
}
}
fun parseAllImages(act : Activity, name : String) : String {
try {
val projection =
arrayOf(MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID)
val cursor = act.contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null, // Return all rows
null,
null
)
val size: Int = cursor!!.getCount()
/******* If size is 0, there are no images on the SD Card. */
if (size == 0) {
} else {
val thumbID = 0
if (cursor != null) {
while (cursor.moveToNext()) {
val file_ColumnIndex: Int =
cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
/**************** Captured image details */
/***** Used to show image on view in LoadImagesFromSDCard class */
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
val path: String = cursor.getString(file_ColumnIndex)
val fileName =
path.substring(path.lastIndexOf("/") + 1, path.length)
if (fileName == name)
{
return path
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
return ""
}
Code snippet I use to write to the media store
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver: ContentResolver = activity.contentResolver
val contentValues = ContentValues()
contentValues.put(
MediaStore.MediaColumns.DISPLAY_NAME,
fileName
)
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
contentValues.put(
MediaStore.MediaColumns.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES + File.separator + "fishy"
)
val imageUri: Uri? =
resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
val tester = imageUri.toString() + File.separator + Environment.DIRECTORY_PICTURES + File.separator + "fishy" + File.separator + fileName
scanLoc = fileName
fos = resolver.openOutputStream(imageUri!!)!!
val file = File(currentPhotoPath)
val ins: InputStream = file.inputStream()
ins.copyTo(fos)
}
Any help or can someone point me to sample code that can read a jpg image from the mediastore given it's name? It's not production ready so please forgive lack of error checks.
Thanks
Lee.