Search code examples
androidfilekotlinio

Android Programming: Cannot read file from file picker Intent


I am creating a simple Android app where when a user clicks on a button, a file picker appears in which a user selects a file, and the app reads the contents of the file. However, in my code below, I get a FileNotFound following error after selecting a file (at the line where the File object is instantiated):

EXCEPTION: java.io.FileNotFoundException: /document/6471 (No such file or directory)

Below is my code:

// File picker implementation
private fun chooseFile(view:View) {
    println("chooseFile activated!");
    var selectFile = Intent(Intent.ACTION_GET_CONTENT)
    selectFile.type = "*/*"
    selectFile = Intent.createChooser(selectFile, "Choose a file")
    startActivityForResult(selectFile, READ_IN_FILE)
}


/* After startActivityForResult is executed, when the selectFile Intent is completed, onActivityResult is executed with
   the result code READ_IN_FILE.*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == READ_IN_FILE) { // Step 1: When a result has been received, check if it is the result for READ_IN_FILE
        if (resultCode == Activity.RESULT_OK) { // Step 2: Check if the operation to retrieve thea ctivity's result is successful
            // Attempt to retrieve the file
            try {
                // Retrieve the true file path of the file
                var uri: Uri? = data?.getData();
                // Instantiate a File object from the file name
                var file:File = File(uri?.getPath());

                // Read the file, line by line
                file.forEachLine { println(it) }
            } catch (e: Exception) { // If the app failed to attempt to retrieve the error file, throw an error alert
                println("EXCEPTION: " + e.toString());
                Toast.makeText(this, "Sorry, but there was an error reading in the file", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    var file1:Button = findViewById(R.id.file1);
    file1.setOnClickListener(::chooseFile)
}

Below is my XML code (activity_main.xml):

<Button
    android:id="@+id/file1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="sans-serif"
    android:text="File 1"
    android:textAllCaps="false"
    android:textSize="16sp" />

Solution

  • // File picker implementation
    private fun chooseFile(view:View) {
        //only the below specified mime type is allowed in the picker
        val mimeTypes = arrayOf(
            "application/msword",
            "application/vnd.ms-powerpoint",
            "application/vnd.ms-excel",
            "text/plain",
            "application/pdf"
        )
        println("chooseFile activated!");
        var selectFile = Intent(Intent.ACTION_GET_CONTENT)
        selectFile.type = if (mimeTypes.size == 1) mimeTypes[0] else "*/*"
            if (mimeTypes.isNotEmpty()) {
                selectFile.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
            }
        selectFile = Intent.createChooser(selectFile, "Choose a file")
        startActivityForResult(selectFile, READ_IN_FILE)
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 200) { // Step 1: When a result has been received, check if it is the result for READ_IN_FILE
            if (resultCode == Activity.RESULT_OK) { // Step 2: Check if the operation to retrieve thea ctivity's result is successful
                // Attempt to retrieve the file
                try {
                    data?.data?.let {
                        contentResolver.openInputStream(it)
                    }?.let {
                        val r = BufferedReader(InputStreamReader(it))
                        while (true) {
                            val line: String? = r.readLine() ?: break
                            println(line)
                        }
                    }
    
                } catch (e: Exception) { // If the app failed to attempt to retrieve the error file, throw an error alert
                    Toast.makeText(
                        this,
                        "Sorry, but there was an error reading in the file",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        }
    }