0

I have an app that can open and edit binary file from external SD card. I want to have possibility to save this file back from where it was opened.

I have added permissions in manifest file and I also ask user for permission. Thanks to those permissions I can open file and get the data but when I want to save file to external SD card there is an error: java.io.FileNotFoundException: /storage/3834-3433/file.bin: open failed: EACCES (Permission denied).

Here is code for granting permission:

public boolean isStoragePermissionGranted() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                return true;
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                return false;
            }
        }
        else {
            return true;
        }
    }

Here is the code for choosing and getting file path:

button.setOnClickListener(v -> {
            intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("*/*");
            startActivityForResult(intent, 200);
        });

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        switch (requestCode) {
            case 200:
                if (resultCode == RESULT_OK) {
                    String filePath = Objects.requireNonNull(data.getData()).getPath();
                    filePathMain = filePath;
                }
                break;
        }
    }

And this is the part of code to save file:

void byteArrayToFile() {
        try (OutputStream out = new FileOutputStream(filePathMain)) {
            out.write(outBytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

I have no idea why it allows me to open file but not to write when I have <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />. I also had to run this app on the real device because when I run this on emulator there is an error that it can't find the file I choose. I could really use some help on this. Thank You.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Luke
  • 21
  • 4
  • "there is an error that it can't find the file I choose" -- your code will not work on the majority of Android devices, because `ACTION_GET_CONTENT` will not return a `file` `Uri`. It will return a `content` `Uri`. See https://stackoverflow.com/questions/49221312/android-get-real-path-of-a-txt-file-selected-from-the-file-explorer and https://stackoverflow.com/questions/48510584/onactivityresults-intent-getpath-doesnt-give-me-the-correct-filename and https://stackoverflow.com/questions/35870825/getting-the-absolute-file-path-from-content-uri-for-searched-images. – CommonsWare Jun 10 '19 at 14:25
  • Beyond that, you do not have arbitrary read/write access to removable storage on Android 4.4+. I recommend that you switch to `ACTION_OPEN_DOCUMENT` on Android 4.4+, and use `ContentResolver`, `openInputStream()`, and `openOutputStream()` to work with the `Uri`. – CommonsWare Jun 10 '19 at 14:27
  • Add the read permission also – Vodet Jun 10 '19 at 14:43

1 Answers1

0

Based on @CommonsWare comment I changed from ACTION_GET_CONTENT to ACTION_OPEN_DOCUMENT to get a file Uri. Also used ContentResolver to read:

InputStream inputStream = getContentResolver().openInputStream(uri);

and write to file:

ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());

And now it's working properly.

Luke
  • 21
  • 4