0

I'm able to select file, selected pdf file got uri as content://somefile but when i'm sending the file using unirest getting error file not found exception below is my code

 //file chooser
 File file;
 Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
 chooseFile.setType("*/*");
 chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
 startActivityForResult(Intent.createChooser(chooseFile, "Select a File to Upload"),1);
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case 1:
                if (resultCode == -1) {
                    file = new File(data.getData().getPath());
                    
                }

                break;
        }
    }
HttpResponse<String> response = Unirest.post("http://url/")
                            .field("file", file)
Siddhesh Nayak
  • 95
  • 4
  • 11
  • `file = new File(data.getData().getPath())`. getPath() does not deliver a file system path and hence you can not use the File class to access the file behind the uri. Have a look at the values of data.getData().toString() and data.getData().getPath(). No messing around with File class. You can use the uri data.getData() itself to upload the file. – blackapps Apr 02 '21 at 05:58
  • Apparently you did not use file.exist() before you called the upload code. – blackapps Apr 02 '21 at 06:00
  • I'm getting this file content:/com.android.providers.media.documents/document/document%3A32 – Siddhesh Nayak Apr 02 '21 at 09:38
  • That is a nice content scheme. Delevered with uri.toString(). Please add file.exists() in yoru code before you try to upload. Please report. – blackapps Apr 02 '21 at 09:44
  • file should exists as i was able to pick pdf file – Siddhesh Nayak Apr 02 '21 at 10:01
  • Good logic but bad programming.. Add `if (!file.exists()) return ` to your code to see. Also display a Toast() there then to inform the user. – blackapps Apr 02 '21 at 10:15
  • i added now it always returns toast file not exists any solution for that when i have selected pdf the content:/com.android.providers.media.documents/document/document%3A32 file not exists – Siddhesh Nayak Apr 02 '21 at 10:41
  • Repeat: `No messing around with File class. You can use the uri data.getData() itself to upload the file.` Well... if your library allows it. Have a look... – blackapps Apr 02 '21 at 10:54

2 Answers2

0

you have to do the typical method so please use retrofit for saving so much time

file upload example - How to Upload Image file in Retrofit 2

for networking, you have to also visit the official retrofit site https://square.github.io/retrofit/

99% of people recommend retrofit for networking and saving so much time

axar
  • 539
  • 2
  • 17
  • i'm able to make request but the new File(data.getData().getPath()) //here i'm getting content://somefile which is not found i'm able to use lib file chooser "https://github.com/hedzr/android-file-chooser" and file is uploaded ther is drawback with library cannot select pdf file – Siddhesh Nayak Apr 02 '21 at 06:47
  • `data.getData().getPath()) //here i'm getting content://somefile ` No. Not at all. getPath() never starts with content://. Further: compare with the path you get from that file chooser. – blackapps Apr 02 '21 at 09:45
  • Were you able to find a solution to this error? – sb_269 Jan 07 '23 at 18:10
0
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

object SelectedFilePath {
    fun getPath(context: Context, uri: Uri): String? {

    //check here to KITKAT or new version
    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(":").toTypedArray()
            val type = split[0]
            if ("primary".equals(type, ignoreCase = true)) {
                return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
            }
        } else if (isDownloadsDocument(uri)) {
            val id = DocumentsContract.getDocumentId(uri)
            val contentUri = ContentUris.withAppendedId(
                Uri.parse("content://<span id=\"IL_AD1\" class=\"IL_AD\">downloads</span>/public_downloads"),
                java.lang.Long.valueOf(id)
            )
            return getDataColumn(context, contentUri, null, null)
        } else if (isMediaDocument(uri)) {
            val docId = DocumentsContract.getDocumentId(uri)
            val split = docId.split(":").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
            }
            val selection = "_id=?"
            val selectionArgs = arrayOf(
                split[1]
            )
            return getDataColumn(context, contentUri, selection, selectionArgs)
        }
    } else if ("content".equals(uri.scheme, ignoreCase = true)) {

        // Return the remote address
        return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(
            context,
            uri,
            null,
            null
        )
    } else if ("file".equals(uri.scheme, ignoreCase = true)) {
        return uri.path
    }
    return null
}

fun getDataColumn(
    context: Context, uri: Uri?, selection: String?,
    selectionArgs: Array<String>?
): 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)
        }
    } finally {
        cursor?.close()
    }
    return null
}

fun isExternalStorageDocument(uri: Uri): Boolean {
    return "com.android.externalstorage.documents" == uri.authority
}

fun isDownloadsDocument(uri: Uri): Boolean {
    return "com.android.providers.downloads.documents" == uri.authority
}

fun isMediaDocument(uri: Uri): Boolean {
    return "com.android.providers.media.documents" == uri.authority
}

fun isGooglePhotosUri(uri: Uri): Boolean {
    return "com.google.android.apps.photos.content" == uri.authority
}

}

Now onActivityResult use this class

 MY_RESULT_CODE_FILECHOOSER -> if (resultCode == Activity.RESULT_OK) {
                if (data != null) {
                    val fileUri: Uri? = data.data
                    Log.d(LOG_TAG, "Uri: $fileUri")
                    var filePath: String? = null
                    try {
                        filePath = fileUri?.let { SelectedFilePath.getPath(this, it) }
                        uploadFile(filePath)
                    } catch (e: Exception) {
                        Log.e(LOG_TAG, "Error: $e")
                       showToast("Error: $e")
                    }
                    if (filePath != null) {
                        Log.e(LOG_TAG, filePath)
                    }
                }
            }

Full code is:

 private fun askPermissionAndBrowseFile() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Level 23

            // Check if we have Call permission
            val permisson: Int = ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_EXTERNAL_STORAGE
            )
            if (permisson != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(
                    arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                    MY_REQUEST_CODE_PERMISSION
                )
                return
            }
        }
        browseFiles()
    }

    private fun browseFiles() {
        var chooseFileIntent = Intent(Intent.ACTION_GET_CONTENT)
        chooseFileIntent.type = "*/*"
        chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE)

        chooseFileIntent = Intent.createChooser(chooseFileIntent, "Choose a file")
        startActivityForResult(chooseFileIntent, MY_RESULT_CODE_FILECHOOSER)
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            MY_REQUEST_CODE_PERMISSION -> {


                // Note: If request is cancelled, the result arrays are empty.
                // Permissions granted (CALL_PHONE).
                if (grantResults.size > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED
                ) {
                    Log.d(LOG_TAG, "Permission granted!")
                    showToast("Permission granted!")
                    browseFiles()
                } else {
                    Log.i(LOG_TAG, "Permission denied!")
                    showToast("Permission denied!")
                }
            }
        }
    }


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            MY_RESULT_CODE_FILECHOOSER -> if (resultCode == Activity.RESULT_OK) {
                if (data != null) {
                    val fileUri: Uri? = data.data
                    Log.d(LOG_TAG, "Uri: $fileUri")
                    var filePath: String? = null
                    try {
                        filePath = fileUri?.let { SelectedFilePath.getPath(this, it) }
                        uploadFile(filePath)
                    } catch (e: Exception) {
                        Log.e(LOG_TAG, "Error: $e")
                       showToast("Error: $e")
                    }
                    if (filePath != null) {
                        Log.e(LOG_TAG, filePath)
                    }
                }
            }
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    private fun uploadFile(filePath: String?) {
        val myData = Data.Builder().putString(AppConstants.FILE_TO_UPLOAD, filePath).build()
        val oneTimeWorkRequest = OneTimeWorkRequest.Builder(UploadFileWorker::class.java)
            .setInputData(myData)
            .build()
        WorkManager.getInstance(this).enqueue(oneTimeWorkRequest)
        Toast.makeText(this, resources.getString(R.string.file_will_be_uploaded), Toast.LENGTH_SHORT).show()
    }
enter code here

Upload worker class :

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.thirdeyegen.mr_workspace.R
import com.thirdeyegen.mr_workspace.constants.AppConstants
import com.thirdeyegen.mr_workspace.network.ProgressRequestBody
import com.thirdeyegen.mr_workspace.network.RestClient
import okhttp3.MultipartBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.File

 infix fun Int.hasReached(limit: Int): Boolean {
    return this == limit
}

class UploadFileWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
    private var isSuccess = true
    private val TAG = "UPLOAD_FILE_WORKER==>"
    val PROGRESS_MAX = 100
    var PROGRESS_CURRENT = 0
    val mContext = context
    private lateinit var builder: NotificationCompat.Builder
    private lateinit var notificationManager: NotificationManager
    override fun doWork(): Result {
        Log.d(TAG, "DO_WORK")
        createNotificationChannel()
        return startUploading()

    }

    private fun startUploading(): Result {
        val filePath = inputData.getString(AppConstants.FILE_TO_UPLOAD)
        if (filePath != null) {
            val file = File(filePath)
            val fileBody = ProgressRequestBody(file, "*", object : ProgressRequestBody.UploadCallbacks {
                override fun onFinish() {
                    if (PROGRESS_CURRENT hasReached 100) {
                        notificationManager.cancel(1)
                    }
                }

                override fun onProgressUpdate(percentage: Int) {
                    PROGRESS_CURRENT = percentage
                    builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
                    notificationManager.notify(1, builder.build());
                    if (percentage hasReached 100) {
                        notificationManager.cancel(1)
                    }
                    Log.d(TAG, "UPLOAD_PROGRESS====> $percentage")
                }

                override fun onError() {
                    notificationManager.cancel(1)
                    Log.d(TAG, "UPLOAD_ERROR===>")
                }
            })
            val filePart: MultipartBody.Part = MultipartBody.Part.createFormData("file", file.name, fileBody)
            RestClient.apiInterfaceForUploader.uploadVideo(filePart, "record").enqueue(object : Callback<Any?> {
                override fun onResponse(call: Call<Any?>, response: Response<Any?>) {
                    Toast.makeText(applicationContext, R.string.msg_file_uploaded_successfully, Toast.LENGTH_LONG).show()
                    isSuccess = true
                }

                override fun onFailure(call: Call<Any?>, t: Throwable) {
                    Toast.makeText(applicationContext, R.string.msg_error_while_uploading_file, Toast.LENGTH_SHORT).show()
                    isSuccess = false
                }
            })
        }

        return if (isSuccess) {
            Result.success()
        } else {
            Result.failure()
        }
    }


    private fun createNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name: CharSequence = "My Channel"
            val description = mContext.getString(R.string.upload_file_text)
            val importance: Int = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel("upload_worker", name, importance)
            channel.description = description
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            val notificationManager: NotificationManager = mContext.getSystemService(NotificationManager::class.java)
            notificationManager.createNotificationChannel(channel)
        }
        setupNotification(mContext)
    }

    private fun setupNotification(context: Context) {
        builder = NotificationCompat.Builder(context, "upload_worker").apply {
            setContentTitle(context.getString(R.string.file_upload_text))
            setOngoing(false)
            setAutoCancel(true)
            setContentText(context.getString(R.string.upload_in_progress))
            setSmallIcon(R.drawable.ic_files)
            setSound(null)
            setNotificationSilent()
            priority = NotificationCompat.PRIORITY_LOW
        }
        notificationManager = mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.notify(1, builder.build())
        builder.setOngoing(true)
    }
}
Diksha Pruthi
  • 276
  • 2
  • 5