tus is a protocol based on HTTP for resumable file uploads. Resumable means that an upload can be interrupted at any moment and can be resumed without re-uploading the previous data again. An interruption may happen willingly, if the user wants to pause, or by accident in case of a network issue or server outage.

//Add on AndroidManifest 
<uses-permission android:name="android.permission.INTERNET" />
dependencies {
    val tusVersion="0.5.0"
    val tusAndroidVersion="0.1.11"
    implementation("io.tus.java.client:tus-java-client:$tusVersion")
    implementation("io.tus.android.client:tus-android-client:$tusAndroidVersion")
}
    private var uploader: TusUploader? = null
    private var isCancelled = false

    fun loadFile(file:File,fileType:String){
        isCancelled=false
        CoroutineScope(Dispatchers.IO).launch {
            Log.e("TusManager","loadFile")
            val headers: MutableMap<String, String> = HashMap()//if you want
            headers[KEY_HEADER_1] = "HEADER 1"
            headers[KEY_HEADER_2] = "HEADER 2"
            headers[KEY_HEADER_3] = "HEADER 3"

            val metaData: MutableMap<String, String> = HashMap()//if you want
            metaData["filename"] = file.name
            metaData["filetype"] = fileType
            metaData["duration"] = file.totalSpace.toString()

            val client = TusClient()
            client.uploadCreationURL = URL("TUS_SERVER_URI")
            client.headers = headers

            val upload = TusUpload(file)
            upload.metadata=metaData

            Log.e("TusManager","Starting upload...")
            val executor: TusExecutor = object : TusExecutor() {
                @Throws(ProtocolException::class, IOException::class)
                override fun makeAttempt() {
                    try {
                        uploader = client.createUpload(upload)
                        uploader?.chunkSize = 1024 //blocksize

                        do {
                            if (isCancelled) {
                                Log.e("TusManager", "Upload cancelled in loop.")
                                return
                            }

                            val totalBytes = upload.size
                            val bytesUploaded = uploader!!.offset
                            val progress = bytesUploaded.toDouble() / totalBytes * 100
                            val percent = progress.toInt()
                            Log.e("TusManager", "Upload at $percent%")
                        } while (uploader!!.uploadChunk() > -1)

                        uploader!!.finish()
                        Log.e("TusManager", "Upload finished.")
                        Log.e("TusManager", "Result => "+uploader.uploaderURL)
                    } catch (e: Exception) {
                        Log.e("TusManager", "Upload error: ${e.localizedMessage}")
                    }
                }
            }

            executor.makeAttempts()
        }
    }
    fun cancelUpload(){
        isCancelled = true
        uploader?.let {
            try {
                it.finish()
            } catch (e: Exception) {
                Log.e("TusManager", "Cancel exception: ${e.message}")
            }
        }
        Log.e("TusManager", "Upload cancelled by user.")
    }