Choosing file using Intent.ACTION_OPEN_DOCUMENT and uploading to server using Retrofit2

164 views Asked by At

There are some related questions about choosing and uploading files from Android. But those answers are outdated and most of the methods in those responses are gone/deprecated.

I am trying to get a file from the local storage using Intent.ACTION_OPEN_DOCUMENT and uploading that to the server using Retrofit. But I am unable to convert Uri to File instance. Also, I am not able to upload that file using Retrofit.

Here is the code I have used to get a file:

    class MainActivity : AppCompatActivity() {

    private val DEVICE_PATH: Int = 398
    private val BASE_URL = "https://pdftoworder.com/"
    private lateinit var pdfClient: PDFClient

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val logging = HttpLoggingInterceptor()
        logging.level = (HttpLoggingInterceptor.Level.BODY)

        val okHttpClient = OkHttpClient
                .Builder()
                .addInterceptor(logging)
                .build()

        val retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(okHttpClient)
                .addConverterFactory(MoshiConverterFactory.create())
                .build()

        pdfClient = retrofit.create(PDFClient::class.java)


        getPath.setOnClickListener { getFileUri() }
    }


    fun getFileUri(){
        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
        //intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.type = "*/*"
        intent.type = "application/pdf"
        startActivityForResult(intent, DEVICE_PATH)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {


        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == DEVICE_PATH && resultCode == Activity.RESULT_OK) {
            data?.data?.let {uri ->
                Log.d("PATHURL", "${uri.path} ${File(uri.path!!).name}")

                lifecycleScope.launch {
                    //val api_key =  RequestBody.create(MediaType.parse("text/plain"), "somevalue")
                    try {
                        val api_key = "DzkpCKjktggtCT1ZE8bFqca7anmmkpOcg975".toRequestBody("text/plain".toMediaTypeOrNull())
                        val tool_uid = "PR5".toRequestBody("text/plain".toMediaTypeOrNull())


                        val a = getRealPathFromURI(uri)
                        val file: File = File(uri.path!!)

                        val requestFile: RequestBody = file.asRequestBody("application/pdf".toMediaTypeOrNull())
                        val multipartBody: MultipartBody.Part = MultipartBody.Part.createFormData("input", file.name, requestFile)

                        val result = pdfClient.convert(
                                input = multipartBody,
                                api_key = api_key,
                                tool_uid = tool_uid
                        )




                        Log.d("PATHURL", "${uri.path}")
                    }catch (ex: Exception){
                        Log.d("PATHURL", "fatal ${ex.message}")
                    }
                }
            }
        }
    }

    fun getPath(context: Context, uri: Uri): String? {
        // DocumentProvider
        if (DocumentsContract.isDocumentUri(context, uri)) {
            System.out.println("getPath() uri: " + uri.toString())
            System.out.println("getPath() uri authority: " + uri.getAuthority())
            System.out.println("getPath() uri path: " + uri.getPath())
            // ExternalStorageProvider
            if ("com.android.externalstorage.documents" == uri.getAuthority()) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                println("getPath() docId: " + docId + ", split: " + split.size + ", type: " + type)
                // This is for checking Main Memory
                return if ("primary".equals(type, ignoreCase = true)) {
                    if (split.size > 1) {
                        Environment.getExternalStorageDirectory().toString() + "/" + split[1] + "/"
                    } else {
                        Environment.getExternalStorageDirectory().toString() + "/"
                    }
                    // This is for checking SD Card
                } else {
                    "storage" + "/" + docId.replace(":", "/")
                }
            }
        }
        return null
    }

    fun getRealPathFromURI(contentUri: Uri?): String? {
        val proj = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = contentResolver.query(contentUri!!, proj, null, null, null) ?: return null
        val column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
        cursor.moveToFirst()
        return cursor.getString(column_index)
    }
}


interface PDFClient {

    @POST("api/convert")
    @Multipart
    suspend fun convert(
            @Part input: MultipartBody.Part,
            @Part("api_key") api_key: RequestBody,
            @Part("tool_uid") tool_uid: RequestBody
    ): ResponseBody
}

The error I am getting is:

document/raw:/storage/emulated/0/Download/Question_Bank/26_9_day_CSE_summer_final_2018_Wireless Programming.pdf (No such file or directory)
Here my goals are:
  • Get file from android
  • Upload that file to server using retrofit
  • Download File from server
  • Save that file to the local storage

Any little help would be appreciated. I have also created a GitHub Repo to reproduce the issue.

0

There are 0 answers