1

FILE is created using URI in cacheDir but when i tried to get the path, image is not found, Logged the URI before creating file and able to see proper URI for image file. Now i had created a File in app cache and tried to retrieve the path of image then not getting full image path, Not sure image is created or not here is my code

 val imagesList = data?.extras?.getStringArray(GligarPicker.IMAGES_RESULT)
                if (!imagesList.isNullOrEmpty()) {
                    val arrayList = ArrayList<MultipartBody.Part>()
                    for (i in 0 until imagesList.size) {
                        Log.e("imagesList.item", imagesList[i])
                        val uri = Uri.parse("file://" + imagesList[i].toString())
                        Log.e("URI", uri.toString())
                        val parcelFileDescriptor: ParcelFileDescriptor? =
                            requireContext().contentResolver.openFileDescriptor(uri, "r")
                        val fileDescriptor: FileDescriptor? = parcelFileDescriptor?.fileDescriptor

                        val file = File(
                            requireContext().cacheDir,
                            requireContext().contentResolver.getFileName(uri!!)
                        )
                        Log.e("File", file.path.toString())

                        val inputStream = FileInputStream(fileDescriptor)
                        val outputStream = FileOutputStream(file)
                        inputStream.copyTo(outputStream)

                        // creates RequestBody instance from file

                        val requestFile: RequestBody =
                            RequestBody.create("multipart/form-data".toMediaTypeOrNull(), file)
                        // requireContext().create("multipart/form-data".toMediaTypeOrNull(), file)

                        val body: MultipartBody.Part? =
                            MultipartBody.Part.createFormData("image", file.name, requestFile)

                        if (body != null) {
                            arrayList.add(body)
                        }
                    }

Tried to log the URI and FILEPATH ,Here is details

URI: file:///storage/emulated/0/DCIM/Camera/IMG_20210131_150237.jpg
File: /data/user/0/com.visilogix.smarttrax/cache

Error logs

  Caused by: java.io.FileNotFoundException: /data/user/0/com.visilogix.smarttrax/cache: open failed: EISDIR (Is a directory)
    at libcore.io.IoBridge.open(IoBridge.java:496)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
    at com.visilogix.smarttrax.ui.performPutAway.GrnLinesFragment.onActivityResult(GrnLinesFragment.kt:283)
    at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
    at android.app.Activity.dispatchActivityResult(Activity.java:8110)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4838)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4886) 
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
 Caused by: android.system.ErrnoException: open failed: EISDIR (Is a directory)
    at libcore.io.Linux.open(Native Method)

Updated code for creating file

  val uri = Uri.parse("file://" + imagesList[i].toString())
                    Log.e("URI", uri.toString())
                    val parcelFileDescriptor: ParcelFileDescriptor? =
                        requireContext().contentResolver.openFileDescriptor(uri, "r")
                    val fileDescriptor: FileDescriptor? = parcelFileDescriptor?.fileDescriptor

                    val uri1 = Uri.parse(imagesList[i].toString())
                    Log.e("File", requireContext().contentResolver.getFileName(uri1!!))
                    val file = File(
                        requireContext().externalCacheDir?.path,
                        requireContext().contentResolver.getFileName(uri1!!)
                    )
                    file.parentFile.mkdir()
                    file.createNewFile()
                    Log.e(
                        "File2",
                        requireContext().contentResolver.getFileName(uri1!!).toString()
                    )

                    val inputStream = FileInputStream(fileDescriptor)
                    val outputStream = FileOutputStream(file)
                    inputStream.copyTo(outputStream)

App is crashing at val outputStream = FileOutputStream(file).

 Caused by: java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.visilogix.smarttrax/cache: open failed: EISDIR (Is a directory)
    at libcore.io.IoBridge.open(IoBridge.java:496)
sri
  • 73
  • 1
  • 11
  • The message tells you that you try to open a directory instead of a file. Probably you created the directory with file.mkdirs() before you changed that to file.getParentFile().mkdirs();. – blackapps Feb 27 '21 at 10:09
  • @blackapps file.mkdirs() added but no luck – sri Feb 27 '21 at 10:21
  • You should not have tried that of course. Please reread my message and delete the directory. Or use another name. – blackapps Feb 27 '21 at 10:29
  • `requireContext().contentResolver.getFileName(uri1!!)` We cannot see which file name that would be or if it is empty. Please use a hard coded file name. Also tell the value of file.getAbsolutePath(). – blackapps Feb 27 '21 at 10:31
  • filepath recieved from imagePicker is : /storage/emulated/0/DCIM/Camera/IMG_20210131_150237.jpg By using this tried to create file as shown above – sri Feb 27 '21 at 10:44
  • 1
    A normal image picker does not give such a file system path but a content scheme uri. But i ment not that one of course. Of the one you try to create. Of the one you have problems with. – blackapps Feb 27 '21 at 10:46
  • By using this /storage/emulated/0/DCIM/Camera/IMG_20210131_150237.jpg only i had tried to create file , getAbsolutePath is crashing as file is not found – sri Feb 27 '21 at 10:48
  • `requireContext().externalCacheDir?.path` That will not give you that path which you now mentioned twice. Read what i asked. – blackapps Feb 27 '21 at 10:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/229283/discussion-between-sri-and-blackapps). – sri Feb 27 '21 at 10:56
  • @blackapps read your comment and tried it , I had mentioned details in chat. Could you please come to chat in above link – sri Feb 27 '21 at 11:14
  • I will not chat. – blackapps Feb 27 '21 at 11:19
  • Hard coded file name and File absolute path returning : /storage/emulated/0/Android/data//cache – sri Feb 27 '21 at 11:29

2 Answers2

1

Using "externalCacheDir" instead of "cacheDir" while creating file might solve the problem.

requireContext().externalCacheDir?.let {
            val file = File(
                    it.path,
                    requireContext().contentResolver.getFileName(uri!!)
            )
            file.createNewFile()

        }
NRUSINGHA MOHARANA
  • 1,489
  • 8
  • 13
  • Didn't fix it. here is path of file using externalCacheDir : /storage/emulated/0/Android/data/com.visilogix.smarttrax/cache – sri Feb 27 '21 at 06:26
  • Sorry, I have missed "getPath()" calling in "requireContext().externalCacheDir". Calling "requireContext().externalCacheDir.path" creates file and I am getting proper URI. – NRUSINGHA MOHARANA Feb 27 '21 at 06:45
  • Caused by: java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.visilogix.smarttrax/cache: open failed: EISDIR (Is a directory) facing the same issue with updated changes – sri Feb 27 '21 at 06:54
  • Ok if this not working, Could you please help me with creating file using URI in kotlin – sri Feb 27 '21 at 07:03
  • 1
    try with "file.createNewFile()" just after creating the file, because file is not getting created due to no content is available. – NRUSINGHA MOHARANA Feb 27 '21 at 07:25
  • Could you please see the updated code at bottom of my question – sri Feb 27 '21 at 07:39
  • Sorry did not get your query creating file using URI ?? I mean if you know URI that means file has been already created. Do you mean copying a file uri from different app to your app private folder ? – NRUSINGHA MOHARANA Feb 27 '21 at 07:45
  • Those are selected images URIs from image picker , Now i want to get those images to app private folder ( i'm sending these images to server using multi part) – sri Feb 27 '21 at 07:50
  • You could do one thing, if you are not saving images to your local database, then direct send byte array to server. Are you using OkHttp ? – NRUSINGHA MOHARANA Feb 27 '21 at 07:55
  • I'm using retrofit multi part ( yes OkHttp) , No local DB . – sri Feb 27 '21 at 07:59
  • I am achieving uploading image to php server using below code. I use Coroutine and Lambda expression which follows best practises. If you want then I can share. – NRUSINGHA MOHARANA Feb 27 '21 at 08:17
  • If you are using multipart while sending images to server then please share details – sri Feb 27 '21 at 08:23
  • 1
    Kindly check it out. I post this as another answer to this question. Good luck ! – NRUSINGHA MOHARANA Feb 27 '21 at 08:31
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/229280/discussion-between-nrusingha-moharana-and-sri). – NRUSINGHA MOHARANA Feb 27 '21 at 09:12
1

Sending image to php server using Okhttp: First covert all images to byte array and put it in "backupData" list. Then call "backupOneByOne()" method.

private var client: OkHttpClient = OkHttpClient()

init {
    client.setReadTimeout(5, TimeUnit.MINUTES)
    client.setConnectTimeout(5, TimeUnit.MINUTES)
}
val backupData: MutableList<ByteArray> = mutableListOf()

private suspend fun backupOneByOne(currentPosition: Int, byteArray: ByteArray) {
    val backupResponse = doBackupMultiPartData("merchantKey", byteArray)

    when (backupResponse) {
        is ResponseResult.Success -> {
            Log.d("nm==>>", "Menu Item backup successful !!! AND current item position= $currentPosition")
            if (currentPosition < backupData.size - 1) {
                backupOneByOne(currentPosition + 1, backupData[currentPosition + 1])
            } else {
                Log.d("nm==>>", "Backup of all items is done. Current position= $currentPosition")
            }
        }
        is ResponseResult.Error -> {
            Log.d("nm==>>", "Error while backup of Advance table : \n ${backupResponse.msg.errorMsg}")
        }
        else -> {
        }
    }
}
suspend fun doBackupMultiPartData(apiKey: String, imageData: ByteArray?): ResponseResult<ResponseWrapper<String>> {
    val requestBody = MultipartBuilder().type(MultipartBuilder.FORM)
    //requestBody.addFormDataPart("id",2) put other form data fields
    if (imageData != null) {
        requestBody.addFormDataPart(
                "file", "Logo.png", RequestBody.create(
                MediaType.parse(
                        "image/png"
                ), imageData
        )
        )
    }

    val request = Request.Builder()
            .header("api_key", apiKey) // getting api key from backend
            .url("put url here....")
            .post(requestBody.build())
            .build()
    try {
        val result = apiRequest(request)
        Log.d("nm==>>", "Result: $result")
        return if (result != null) {
            val jsonObject = JSONObject(result)
            if (jsonObject.getBoolean("isSuccessful")) {
                ResponseResult.Success(ResponseWrapper("success", null))
            } else {
                ResponseResult.Error(
                        ResponseWrapper(null, "Back end code error: \n $result")
                )
            }
        } else {
            ResponseResult.Error(
                    ResponseWrapper(
                            null, "Getting NULL as result"
                    )
            )
        }
    } catch (jsonException: JSONException) {
        Log.d("nm==>>", "Restore JSON exception::: \n ${jsonException.localizedMessage}")
        return ResponseResult.Error(
                ResponseWrapper(
                        null,
                        "Restore Json Exception"
                )
        )
    } catch (exception: Throwable) {
        //Log.d("nm==>>", "Network exception::: \n ${exception.localizedMessage}")
        return ResponseResult.NoInternet
    }
}

private suspend fun apiRequest(request: Request): String? = suspendCancellableCoroutine { cancellableContinuation ->
    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(request: Request?, e: IOException?) {
            cancellableContinuation.resumeWith(Result.failure(Throwable("API failed.....${e?.localizedMessage}")))
        }

        override fun onResponse(response: Response?) {
            cancellableContinuation.resumeWith(Result.success(response?.body()?.string()))
        }
    })
}
sealed class ResponseResult<out T> {
    object Loading:ResponseResult<Nothing>()
    object Empty:ResponseResult<Nothing>()
    data class Success<T>(val result:T): ResponseResult<T>()
    data class Error<T>(val msg:T): ResponseResult<T>()
    object NoInternet:ResponseResult<Nothing>()
}
data class ResponseWrapper<out T>(val data: T?, val errorMsg: String?)
NRUSINGHA MOHARANA
  • 1,489
  • 8
  • 13