Creating Multiple ParcelFileDescriptor for a file from default file picker URI throws File Not Found Exception

183 Views Asked by At

I have targeted Android API level 30 and tried to create multiple file descriptors for a single file from the URI from the default file picker which looks like this.

content://com.android.externalstorage.documents/document/E8A6-89C4%3AMovies%2FTestFile.mp4 

content://com.android.externalstorage.documents/document/primary%3ATestFile.mp4

I am using the below code to create 10 threads to asynchronously access a file with ParcelFileDescriptors.

public class TestActivity extends AppCompatActivity {

    public static final String TAG = "TEST_LOG";
    
    private Button pickFileBtn;
    final int VIDEO_REQUEST_CODE = 111;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        setContentView(R.layout.test_activity);
        pickFileBtn = findViewById(R.id.pick_file);
        pickFileBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                pickFile();        
            }
        });
    }

    private void pickFile() {
        Intent intent = new Intent();
        intent.setType("video/*");
        intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        startActivityForResult(intent, VIDEO_REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == VIDEO_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                loadFrame(data.getData());
            }
        }
    }

    void loadFrame(Uri uri) {
        for (int i = 0; i < 10; i++) {
            new Thread(new CustomRunnable(uri)).start();
        }
    }
}


class CustomRunnable implements Runnable {
    private Uri uri;

    public CustomRunnable(Uri uri) {
        this.uri = uri;
    }

    @Override
    public void run() {
        try {
            ParcelFileDescriptor descriptor = null;
            try {
                descriptor = CustomApplication.appContext.getContentResolver().openFileDescriptor(uri, "r");
                // Working with the descriptor here.
            } catch (Exception e) {
                Log.e(TestActivity.TAG, String.format("Failed to obtain parcelFileDescriptor for %s.%s", uri.toString(), e.getMessage()));
            } finally {
                if (descriptor != null)
                    descriptor.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Failed to obtain r parcelFileDescriptor for content://com.android.externalstorage.documents/document/primary%3ATestFile.mp4.Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/document/primary%3ATestFile.mp4 from pid=6190, uid=12283 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

This can create around 5 descriptors and throws File Not Found Exception for the rest. But, It can successfully create all the required descriptors when I use URI from the media store. And the media store URI looks like this.

content://media/external/video/media/268019

I have tried to reuse the 5 descriptors but when I try to read the files using them, I get an error saying EBML header parsing failed

I have also tried to obtain access to a specific folder using Intent.ACTION_OPEN_DOCUMENT_TREE and then picking a file, but the result is the same, that it only opens 5 descriptors.

Why do opening descriptors from the default file picker only create 5 descriptors and why I can not reuse them.

0

There are 0 best solutions below