2

我的目标是Android API 级别 30,并尝试从默认文件选择器的 URI为单个文件创建多个文件描述符,如下所示。

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

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

我正在使用下面的代码创建 10 个线程来使用 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();
        }
    }
}

无法获取 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 要求您使用 ACTION_OPEN_DOCUMENT 或相关 API 获取访问权限

这可以创建大约 5 个描述符并为其余的引发File Not Found Exception 。但是,当我使用URI from the media store. 媒体存储 URI 看起来像这样。

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

我试图重用这 5 个描述符,但是当我尝试使用它们读取文件时,我收到一条错误消息EBML header parsing failed

我还尝试使用然后选择一个文件来访问特定文件夹Intent.ACTION_OPEN_DOCUMENT_TREE,但结果是一样的,它只打开 5 个描述符。

为什么从默认文件选择器打开描述符只创建 5 个描述符,为什么我不能重用它们。

4

0 回答 0