Android write and read to external file

Required permissions. These permissions need to be declared in the manifest file and prompt the user to grant them.



One app writes to external file. The file will be written to /storage/emulated/0/Android/data/com.example.write_external_file/files/test.txt, it will be deleted on app delete.

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
import kotlin.random.Random
import java.io.File
import java.io.FileOutputStream
import java.io.IOException


class MainActivity : AppCompatActivity() {

    private val charPool : List = ('a'..'z') + ('A'..'Z') + ('0'..'9')

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

        btn_write.setOnClickListener {
            val randomString = generateRandomStr()

            val filename = "test.txt"
            val folder = getExternalFilesDir(null)

//            if(!File("/storage/emulated/0/Android/data/test").exists()) {
//                File("/storage/emulated/0/Android/data/test").mkdir()
//                File("/storage/emulated/0/Android/data/test/files").mkdir()
//            }
            val myFile = File(folder, filename)

            writeToFile(myFile, randomString)

            // /storage/emulated/0
            // /storage/emulated/0/Android/data/com.example.write_external_file/files/text.txt
            // /storage/emulated/0/Android/data/com.example.write_external_file/files/test.txt
            //     Content: 7oywMdG2viRK8NxtHQr24ebdFqzHA3EewqzUr8vVqxye4Ne5AphU
            val textToDisplay = "File path: ${myFile.absolutePath}\n Content: $randomString"
            tv_text.text = textToDisplay
            Log.d("Main", textToDisplay)
        }

    }

    private fun writeToFile(file: File, dataStr: String) {
        try {
            val fstream = FileOutputStream(file)
            fstream.write(dataStr.toByteArray())
            fstream.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }

    }

    private fun generateRandomStr(): String {
        val stringSize = Random.nextInt(30, 100)
        return (1..stringSize)
            .map { Random.nextInt(0, charPool.size) }
            .map(charPool::get)
            .joinToString("")
    }

}

Another app reads the file created by the app above, it requires to ask the user for permission to read from external files.

import android.Manifest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.nio.charset.Charset
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import androidx.core.app.ActivityCompat
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    companion object {
        const val TARGET_APP_PACKAGE = "com.example.write_external_file"
        const val TARGET_FILE_NAME = "test.txt"
    }

    private val REQUEST_PERMISSIONS = 100
    private val PERMISSIONS_REQUIRED = arrayOf(
        Manifest.permission.READ_EXTERNAL_STORAGE
    )

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

        if (checkPermission(PERMISSIONS_REQUIRED)) {
            showFileData()
        } else {
            ActivityCompat.requestPermissions(this, PERMISSIONS_REQUIRED, REQUEST_PERMISSIONS)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        Log.d("MainActivity", "requestCode: $requestCode")
        Log.d("MainActivity", "Permissions:" + permissions.contentToString())
        Log.d("MainActivity", "grantResults: " + grantResults.contentToString())

        if (requestCode == REQUEST_PERMISSIONS) {
            var hasGrantedPermissions = true
            for (i in grantResults.indices) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    hasGrantedPermissions = false
                    break
                }
            }

            if (hasGrantedPermissions) {
                showFileData()
            } else {
                finish()
            }

        } else {
            finish()
        }
    }

    private fun showFileData() {
        val externalDirPath = getExternalFilesDir(null)?.absolutePath ?: ""

        val targetDirPath = if (externalDirPath.isNotEmpty()) {
            externalDirPath.replace(packageName, TARGET_APP_PACKAGE)
        } else {
            ""
        }

        val targetFile = File(targetDirPath, TARGET_FILE_NAME)
        val targetFileContent = if (targetFile.exists()) {
            readFile(targetFile)
        } else {
            ""
        }

        val stringBuilder = StringBuilder()
        stringBuilder.append("\n")
        stringBuilder.append("packageName: $packageName")
        stringBuilder.append("\n")
        stringBuilder.append("getExternalStorageDirectory: $externalDirPath")
        stringBuilder.append("\n")
        stringBuilder.append("target dir path: $targetDirPath")
        stringBuilder.append("\n")
        stringBuilder.append("target file path: ${targetFile.absolutePath}")
        stringBuilder.append("\n")
        stringBuilder.append("target file content: $targetFileContent")

        Log.d("file_debug","file info: $stringBuilder")
        tv_result.text = "file info: $stringBuilder"
    }

    private fun readFile(file: File) : String {
        var resultStr = ""
        try {
            val fileInputStream = FileInputStream(file)
            val size = fileInputStream.available()
            val buffer = ByteArray(size)
            fileInputStream.read(buffer)
            resultStr = String(buffer, Charset.forName("UTF-8"))
            fileInputStream.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return resultStr
    }

    private fun checkPermission(permissions: Array): Boolean {
        for (permission in permissions) {
            if (ContextCompat.checkSelfPermission(applicationContext, permission) != PackageManager.PERMISSION_GRANTED) {
                return false
            }
        }
        return true
    }

}

Complete example in Github

Search within Codexpedia

Custom Search

Search the entire web

Custom Search