Khiem Luong
Khiem Luong

Reputation: 5

Files created from Intent.ACTION_OPEN_DOCUMENT is 0 byte (Storage Access Framework)

I am trying to create a file manager app but I am running into issues with creating new files.

I am able to open and read files from the app using Intent.ACTION_VIEW and I have implemented a function that sets the Mime Type, so incorrect directories are not the issue.

But I wanted to save that file to another directory, so I added another Intent for creating files using the Storage Access Framework (SAF). As seen below:

public void createFile(File url) {
    Uri uri = Uri.fromFile(url);
    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    USBUtils.intentUriFilter(url, intent);

    intent.putExtra(Intent.EXTRA_TITLE, url.getName());

    intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri);
    startActivityForResult(intent, CREATE_FILE);
}

Again, I dynamically set the Mime Type from the URL that was passed in and the SAF popup does appear allowing me to choose where the file is downloaded. In the example below I tried to save a copy of 0005.jpg as 0005b.jpg, as seen in the Emulator display below.

The file is created, but the file itself is empty; 0 byte.

Is there a way to write a byte array to this intent file similar to Files.write(outputFile.toPath(), dataForWriting), where dataForWriting is the byte array? Or maybe move the file created from Files.write() using Intent, not Files.move() or Files.copy()?

Some caveats from my attempts at solving this issue:

  1. Files.write() does work, however I want the user to be able to specify where the written file goes through the SAF.
  2. With Android 10/API 29 (My target version) I have to deal with scoped storage, so I passed in these flags in the AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and

android:requestLegacyExternalStorage="true"

in the application tag. I also have a permission check function which states that I do have write and read external storage permission. This means that Files.write() did not work on some directories, and I have to create files through the SAF.

  1. I am trying to write data to a USB drive that's connected to the phone (this is basically an app that manages files on a USB). With that being said, Files.write() does not have permission to write directly to a USB, because USBs don't have an "emulated" folder.

Upvotes: 0

Views: 576

Answers (1)

Khiem Luong
Khiem Luong

Reputation: 5

Using CommonsWare suggestions, I created an onActivityResult() and passed in the CREATE_FILE request code from createFile(File url) like so.

   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (requestCode == CREATE_FILE) {
            Uri uri = intent.getData();
            final ContentResolver resolver = getContentResolver();
            try {
                OutputStream os = resolver.openOutputStream(uri);
                if (os != null)
                    os.write(encryptedFileBytes);
                os.close();


            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Thanks!

Upvotes: 1

Related Questions