Save .txt file on Android Q
Asked Answered
P

2

8

I was trying to save text file using below code

try {
                FileOutputStream fos = new FileOutputStream(TXT_FILE_NAME, true);

                FileWriter fWriter;

                try {
                    fWriter = new FileWriter(fos.getFD());
                    fWriter.write(binding.tvExtractedResult.getText().toString());
                    fWriter.close();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    fos.getFD().sync();
                    fos.close();
                    Toast.makeText(this, "File Saved Successfully", Toast.LENGTH_LONG).show();
                }
            } catch (Exception e) {
                Toast.makeText(this, "Error while saving file", Toast.LENGTH_LONG).show();
                e.printStackTrace();
            }

But the problem is this code doesn't work with Android Q. After this I tried to search the solution and I did this

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ContentValues myContentValues = new ContentValues();
            myContentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, TXT_FILE_NAME);
            String myFolder = "Download/MY_PROJECT";
            myContentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, myFolder);
            myContentValues.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain");
            myContentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);

            Uri extVolumeUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);

            ContentResolver contentResolver = getContentResolver();
            Uri uri = contentResolver.insert(extVolumeUri, myContentValues);

            if (uri == null) {
                Log.e(TAG, "uri is null");
                return;
            }
            Log.e(TAG, "uri=" + uri);

            try {
                FileOutputStream fos = new FileOutputStream(new File(uri.toString()));

                fos.write(binding.tvExtractedResult.getText().toString().getBytes());
                fos.close();
            } catch (Exception e) {
                Log.e(TAG, "error occurred" + e.getMessage());
                e.printStackTrace();
            } finally {
                myContentValues.clear();
                myContentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
                contentResolver.update(uri, myContentValues, null, null);
            }

        }

In above code I'm getting uri == null

Appreciate your help. Thanks.

Posit answered 24/5, 2020 at 10:8 Comment(2)
Have you added android:requestLegacyExternalStorage = true in Manifest?Myelitis
Same problem even with equestLegacyExternalStorage always nullHappygolucky
M
5

Please have a look at this code, it will allow you to save text file below and higher versions of Android Q.

public static void saveFile(Context context, String fileName, String text, String extension) throws IOException{
    OutputStream outputStream;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

        ContentValues values = new ContentValues();

        values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName + extension);   // file name
        values.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain");
        values.put(MediaStore.MediaColumns.RELATIVE_PATH, DIRECTORY);

        Uri extVolumeUri = MediaStore.Files.getContentUri("external");
        Uri fileUri = context.getContentResolver().insert(extVolumeUri, values);

        outputStream = context.getContentResolver().openOutputStream(fileUri);
    }
    else {
        String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).toString() + FOLDER_NAME;
        File file = new File(path, fileName + extension);
        Log.d(TAG, "saveFile: file path - " + file.getAbsolutePath());
        outputStream = new FileOutputStream(file);
    }

    byte[] bytes = text.getBytes();
    outputStream.write(bytes);
    outputStream.close();
}
Minium answered 27/8, 2021 at 6:12 Comment(0)
R
0

The answer provided by @SheikhHasib is correct.

Here, however, is the Kotlin version of his code with small adjustments. This will save "backup.txt" file in the "Download" directory, and the file will contain "Example content". I've tested in on Android 11 and it works perfectly.

@Throws(IOException::class)
private fun saveFile(context: Context, fileName: String, text: String, extension: String) {
    val outputStream: OutputStream? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val values = ContentValues()
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
        values.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")
        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
        val extVolumeUri: Uri = MediaStore.Files.getContentUri("external")
        val fileUri: Uri? = context.contentResolver.insert(extVolumeUri, values)
        context.contentResolver.openOutputStream(fileUri!!)
    } else {
        val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()
        val file = File(path, "$fileName.$extension")
        FileOutputStream(file)
    }

    val bytes = text.toByteArray()
    outputStream?.write(bytes)
    outputStream?.close()
}

And to run it:

CoroutineScope(Dispatchers.IO).launch {
    runCatching{
    val content: String = "Example content"
    saveFile(requireContext(), "backup", content, "txt")
    }
}
Rapture answered 17/5, 2022 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.