Download files in storage – Android kotlin

Previously, we created a tutorial to show you how you can download an image in your storage using Java. In this tutorial, we will show you how you can download any file in your android phone’s storage using Kotlin. First, you need to create a file named “DownloadImageTask.kt” and write the following code in it:

class DownloadImageTask(
    var imagePath: String?,
    var fileName: String?
) : AsyncTask<Void, Void, Void>() {

    var cachePath: String = ""

    override fun doInBackground(vararg voids: Void?): Void? {
        try {
            val root =
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
            val directoryPath = File(root.absolutePath + "/")
            if (!directoryPath.exists()) {
                directoryPath.mkdir()
            }
            val cachePath = File("$directoryPath/$fileName")
            cachePath.createNewFile()
            val buffer = ByteArray(1024)
            var bufferLength: Int
            val url = URL(imagePath)
            val urlConnection = url.openConnection() as HttpURLConnection
            urlConnection.requestMethod = "GET"
            urlConnection.doOutput = false
            urlConnection.connect()
            val inputStream = urlConnection.inputStream
            val fileOutput = FileOutputStream(cachePath)
            while (inputStream.read(buffer).also { bufferLength = it } > 0) {
                fileOutput.write(buffer, 0, bufferLength)
            }
            fileOutput.write(buffer)
            fileOutput.close()
            inputStream.close()

            this.cachePath = cachePath.toString()
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (e: ProtocolException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return null
    }

    override fun onPostExecute(aVoid: Void?) {
        // when the operation is done
        // you can use this.cachePath here
    }
}

Now, whenever you want to download any file, you just need to run the following line passing the file’s absolute path in the first parameter. And the file name as the second parameter. The second parameter file name will be the name that will be saved in your phone’s storage.

DownloadImageTask("https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/thumbnails/image/stsci-01gfnn3pwjmy4rqxkz585bc4qh.png", "nasa.png")
                .execute()

That’s how you can download any HTTP file in your android phone’s storage using Kotlin. If you face any problem in following this, kindly do let me know in the comments section below.

Select file from internal storage – Android kotlin

To select a file from internal storage in android using Kotlin, first, you have to start an intent with a request code.

val intent = Intent(Intent.ACTION_PICK)
intent.type = "*/*"
startActivityForResult(intent, 565)

After that, when the image is selected from the gallery by the user, it will be received in the onActivityResult method. So we need to create the following methods in our activity:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (resultCode == Activity.RESULT_OK && requestCode == 565) {
        val uri: Uri? = data?.data

        var base64: String = ""
        try {
            val bytes = uri?.let { contentResolver.openInputStream(it)?.readBytes() }
            base64 = Base64.encodeToString(bytes, Base64.URL_SAFE)
        } catch (e1: IOException) {
            e1.printStackTrace()
        }

        var attachmentName: String = uri?.let { getFileName(it, contentResolver) }.toString()

        var extension: String = uri?.let {
            getMimeType(
                applicationContext,
                it
            )
        }.toString()

        Log.i("mylog, base64 = ", base64)
        Log.i("mylog, attachment = ", attachmentName)
        Log.i("mylog, extension = ", extension)
    }
}

fun getFileName(uri: Uri, contentResolver: ContentResolver): String {
    val returnCursor: Cursor = contentResolver.query(uri, null, null, null, null)!!
    val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
    returnCursor.moveToFirst()
    val name = returnCursor.getString(nameIndex)
    returnCursor.close()

    return name
}

fun getMimeType(context: Context, uri: Uri): String? {
    return if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
        //If scheme is a content
        val mime = MimeTypeMap.getSingleton()
        mime.getExtensionFromMimeType(context.contentResolver.getType(uri))
    } else {
        //If scheme is a File
        //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
        MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(uri.path)).toString())
    }
}

Run the app now, you will be able to select any file from your internal or external storage (if you have external storage). After you select the file, you will see its base64 content, file name, and its extension in the logcat of android studio.