我的目标是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 个描述符,为什么我不能重用它们。