Q:

Application crashes while uploading image captured from camera using retrofit multipart on KitKat 4.4.4 API 19

As per the requirement, The user of the app clicks an image from device camera and then uploads it to server. Everything is working fine when I test my APK on Lollipop and above but when I test it on below Lollipop(specifically on KitKat 4.4.4 API 19) the app crashes with the exception java.io.FileNotFoundException: /: open failed: EISDIR (Is a directory).
Before passing the intent to Camera I am creating a File and passing it the Uri.Also during File creation I am saving the file path in some variable.
Later on onActivityResult(), I create a new file with the path(saved in variable) and then pass it to server using retrofit multipart.
This is how I pass Intent to Camera
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
                        takePictureIntent.resolveActivity(packageManager)?.also {
                            val photoFile = try {
                                createImageFile()
                            } catch (e: Exception) {
                                null
                            }

                            Log.e("file tag", photoFile!!.absolutePath)

                            photoFile?.also {
                                val photoUri = FileProvider.getUriForFile(this@PrintActivity, "$packageName.fileprovider", it)
                                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
                                if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
                                    takePictureIntent.clipData = ClipData.newRawUri("", photoUri)
                                    takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                                }
                                startActivityForResult(takePictureIntent, REQUEST_CAMERA)
                            }
                        }
                    }

The createImageFile() method is as follows :
@Throws(IOException::class)
    private fun createImageFile(): File {
        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(Date())
        val storageDir = getExternalFilesDir("Allocation")
        return File.createTempFile("JPEG_${timeStamp}_", ".jpg", storageDir).apply {
            printImageFilePath = absolutePath
        }
    }

This is the file_paths I provided
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/$packageName/files/Allocation" />
</paths>

This is how I declared Provider in my AndroidManifest under the application tag
<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="$packageName.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

This is the method OnActivityResult()
 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CAMERA && resultCode == Activity.RESULT_OK) {
            try {
                val printedImageFile = File(printImageFilePath)
                doImageUpload(printedImageFile)
            } catch (e: Throwable) {
                e.stackTrace
            }
        }
}

This is my doImageUpload() method
private fun doImageUpload(printedImageFile: File?) {
        if (networkUtil.isConnected()) {
            try {
                launch(UI) {
                    val response = dataManager.uploadImage(printedImageFile)
                    Log.v("ImageUploadSuccess", response.body())

}catch(e:Exception){

}

    }

This is my dataManager.uploadImage(printedImageFile) method
suspend fun uploadImage(printImageFile: File?): Response<String> {

        val printImageBody: RequestBody
        val printImagePart: MultipartBody.Part

            printImageBody = 
 RequestBody.create(MediaType.parse("multipart/formdata"),printImageFile)
            printImagePart = MultipartBody.Part.createFormData("my_file1", printImageFile.name, printImageBody)
            restService.uploadImage(printImagePart).await()
}

And Finally this is my retrofit multipart interface method,
@Multipart
    @POST
    fun uploadImage(@Part myFile2: MultipartBody.Part?): Deferred<Response<String>>

This is the crash log I am receiving
E/AndroidRuntime: FATAL EXCEPTION: main
Process: $packageName, PID: 24339
java.io.FileNotFoundException: /: open failed: EISDIR (Is a directory)
    at libcore.io.IoBridge.open(IoBridge.java:409)
    at java.io.FileInputStream.<init>(FileInputStream.java:78)
    at okio.Okio.source(Okio.java:168)
    at okhttp3.RequestBody$3.writeTo(RequestBody.java:119)
    at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.java:173)
    at okhttp3.MultipartBody.writeTo(MultipartBody.java:114)
    at com.readystatesoftware.chuck.ChuckInterceptor.intercept(ChuckInterceptor.java:154)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    at java.lang.Thread.run(Thread.java:841)
 Caused by: libcore.io.ErrnoException: open failed: EISDIR (Is a directory)
    at libcore.io.IoBridge.open(IoBridge.java:398)
    at java.io.FileInputStream.<init>(FileInputStream.java:78) 
    at okio.Okio.source(Okio.java:168) 
    at okhttp3.RequestBody$3.writeTo(RequestBody.java:119) 
    at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.java:173) 
    at okhttp3.MultipartBody.writeTo(MultipartBody.java:114) 
    at com.readystatesoftware.chuck.ChuckInterceptor.intercept(ChuckInterceptor.java:154) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) 
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254) 
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200) 
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
    at java.lang.Thread.run(Thread.java:841)

A:

After a lot of trial and error and with some help of my senior and this, I finally resolved the respective issue.
The issue was, as soon as I used to capture photo from back camera the android system was killing my respective Activity class in order to conserve resources. When the camera was closed and returned to my Activity, the  Activity was being re-created due to which the instance variable which was used to save the file path of the captured image was null. As a result the application used to crash.
So in order to preserve the instance variable I used onSaveInstanceState(outState: Bundle?) method as follows, in my PrintActivity class(the Activity from which the Camera Intent was fired),
override fun onSaveInstanceState(outState: Bundle?) {
    super.onSaveInstanceState(outState)
    outState?.putString(Constants.PRINT_IMAGE_FILE_PATH,printImageFilePath) 
  // printImageFilePath is the path of the image file , 
 //  Constants.PRINT_IMAGE_FILE_PATH is my key for the bundle

}

And then in my PrintActivity inside the onCreate(savedInstanceState: Bundle?)  I re-assign instance variable like this,
override fun onCreate(savedInstanceState: Bundle?) {
    if(savedInstanceState?.get(Constants.PRINT_IMAGE_FILE_PATH)!=null){
    printImageFilePath = 
    savedInstanceState.get(Constants.PRINT_IMAGE_FILE_PATH)
  }
}

