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?
Related
I want rename file and when use bellow code and rename file successful but after I don't see that file on my phone and the file is deleted. I requested 2 permissions READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE successful
My code to get all image in device and rename function
MainActivity{
getAllImages()
btn_rename.setOnClickListener{
var old_file=listImageFile.get(pos_selected)
var new_file=File(old_file.parent,new_name)
var check:Boolean=old_file.renameTo(new_file)
if(check){
// check return true
}
}
}
fun getAllImages() {
listImageFile= arrayListOf()
val allImages = arrayListOf<Uri>()
val imageProjection = arrayOf(
MediaStore.Images.Media.DATA,
)
val cursor = requireActivity().contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
imageProjection,
null,
null
)
cursor.use {
if (cursor != null) {
val data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
while (cursor.moveToNext()) {
var path = cursor.getString(data)
var file=File(path)
if(file.exists()){
listImageFile.add(
FileData(
file,
false
)
)
}
}
}
}
}
Whenever you create/rename/delete file, you must refresh the system files.
Try this below solution after rename the file:
btn_rename.setOnClickListener{
var old_file=listImageFile.get(pos_selected)
var new_file=File(old_file.parent,new_name)
var check:Boolean=old_file.renameTo(new_file)
if(check){
// check return true
MediaScannerConnection.scanFile(context, arrayOf(old_file.absolutePath),null,null)
MediaScannerConnection.scanFile(context, arrayOf(new_file.absolutePath),null,null)
}
}
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
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.
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.
I don't want my app to require any permissions, but I want the user to be able to select a file for reading. My app doesn't need arbitrary access to the filesystem. However, all openfiledialog implementations I have researched so far seem to assume permission to access external storage.
One workaround I can think of is to configure my app to be among the list of apps to open a certain type of file. I haven't tried this, but I hope this would work without permission to access external storage. However, user guidance would be less then ideal in this case. I would prefer a solution with a dialog and have the user pick the file.
I think this requirement does not undermine security, because the user has full control over the file my app can read. Is this possible somehow?
However, all openfiledialog implementations I have researched so far seem to assume permission to access external storage.
Set your minSdkVersion to 19, then use ACTION_OPEN_DOCUMENT, part of the Storage Access Framework.
Or, if you need your minSdKVersion to be below 19, use ACTION_GET_CONTENT on the older devices.
You will get a Uri back via onActivityResult(). Use a ContentResolver and methods like openInputStream() to consume the content identified by that Uri.
I haven't tried this, but I hope this would work without permission to access external storage
Only if you exclude file: Uri values. For example, an <intent-filter> that supports only content: Uri values would work.
Android 11 Resolve file access issue without use of MANAGE_EXTERNAL_STORAGE.
I have added code for get doc file and Upload to server.
AndroidManifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:preserveLegacyExternalStorage="true"
android:requestLegacyExternalStorage="true"
</application>
Now, Add this lib in your project
https://github.com/FivesoftCode/FilePicker
Add below code to Activity/Fragment
FilePicker.from(activity)
.setFileTypes(FilePicker.IMAGE, FilePicker.VIDEO) //Set file types you want to pick.
.setAllowMultipleFiles(true) //Allow user to select multiple files
.setListener { files -> //Wait for results
if (files != null && files.size > 0) {
//Do something with uris.
for (items in files) {
val extension: String = getMimeType(activity!!,items)!!
if (extension == "pdf") {
val cacheDir: String = context!!.cacheDir.toString()
val getCopyFilePath = copyFileToInternalStorage(context!!,items,cacheDir)
Log.e("TAG", "getPathToUploadDoc: " + getCopyFilePath )
}
}
} else {
//Add msg here...
}
}
.setTitle("Pick a file from My Files")
.pick() //Open file picker
Add below method for get Mime Type
fun getMimeType(context: Context, uri: Uri): String? {
val extension: String?
//Check uri format to avoid null
extension = if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
//If scheme is a content
val mime = MimeTypeMap.getSingleton()
mime.getExtensionFromMimeType(context.contentResolver.getType(uri))
} else {
//If scheme is a File
//This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(uri.path)).toString())
}
return extension
}
fun getFiledetails(uri: Uri,context: Context,getCopyFilePath:String): NormalFile? {
// var result: String? = null
if (uri.scheme == "content") {
val cursor: Cursor = context.contentResolver.query(uri,
FileLoader.FILE_PROJECTION, null, null, null)!!
try {
if (cursor != null && cursor.moveToFirst()) {
// result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
val path: String = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA))
if (path != null && path != "") {
//Create a File instance
cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID))
// cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID)).toInt()
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.TITLE))
// cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA))
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.SIZE))
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_ADDED))
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE))
}
}
} finally {
cursor.close()
}
}
/*if (result == null) {
result = uri.path
val cut = result!!.lastIndexOf('/')
if (cut != -1) {
result = result.substring(cut + 1)
}
}*/
return file
}
fun copyFileToInternalStorage(context: Context?,uri: Uri, newDirName: String): String? {
val returnCursor = context!!.contentResolver.query(
uri, arrayOf(
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
), null, null, null
)
/*
* Get the column indexes of the data in the Cursor,
* * move to the first row in the Cursor, get the data,
* * and display it.
* */
val nameIndex = returnCursor!!.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE)
returnCursor.moveToFirst()
val name = returnCursor.getString(nameIndex)
val size = java.lang.Long.toString(returnCursor.getLong(sizeIndex))
val output: File
output = if (newDirName != "") {
val dir = File(/*context!!.filesDir.toString() + "/" +*/ newDirName)
if (!dir.exists()) {
dir.mkdir()
}
File(/*context!!.filesDir.toString() + "/" +*/ newDirName + "/" + name)
} else {
File(context!!.filesDir.toString() + "/" + name)
}
try {
val inputStream: InputStream? = context!!.contentResolver.openInputStream(uri)
val outputStream = FileOutputStream(output)
var read = 0
val bufferSize = 1024
val buffers = ByteArray(bufferSize)
while (inputStream?.read(buffers).also { read = it!! } != -1) {
outputStream.write(buffers, 0, read)
}
inputStream?.close()
outputStream.close()
} catch (e: Exception) {
Log.e("Exception", e.message!!)
}
return output.path
}
For upload Doc
implementation 'net.gotev:uploadservice:2.1'
var uploadId = UUID.randomUUID().toString()
val url = ServerConfig.MAIN_URL
uploadReceiver.setDelegate(this)
uploadReceiver.setUploadID(uploadId)
val data = MultipartUploadRequest(mContext, uploadId, url)
.addFileToUpload(path, "attachment")
.addHeader("Authentication", getMD5EncryptedString())
.addParameter(USER_ID,1)
.setMaxRetries(5)
.startUpload()
fun getMD5EncryptedString(): String {
val encTarget = ServerConfig.AUTHENTICATE_VALUE //Any pwd
var mdEnc: MessageDigest? = null
try {
mdEnc = MessageDigest.getInstance("MD5")
} catch (e: NoSuchAlgorithmException) {
println("Exception while encrypting to md5")
e.printStackTrace()
}
mdEnc!!.update(encTarget.toByteArray(), 0, encTarget.length)
var md5 = BigInteger(1, mdEnc.digest()).toString(16)
while (md5.length < 32) {
md5 = "0$md5"
}
return md5
}