在 Release APK 中使用 Intent.ACTION_OPEN_DOCUMENT 读取大型文本文件时出现 IOException EBADF(错误的文件描述符)

IOException EBADF (Bad file descriptor) when reading large text files using Intent.ACTION_OPEN_DOCUMENT in Release APK

在我的 android 应用程序中,我提供了一个菜单,用于通过 Intent.ACTION_OPEN_DOCUMENT 导入文本文件(它包含我稍后使用 gson 处理的一些 Json 数据)。这些文件可能很大,有 5 MB 或更大。

问题:当我直接从 phone 上的 Android Studio 启动应用程序时一切正常,对于大文件也是如此。然而,对于发布的 apk,如果文件大于大约 500kb(异常由 readLine 抛出),我将获得一个 IOException EBADF(错误的文件描述符)。如果我从 google 驱动器或下载中读取文件,就会出现这种情况。

我使用以下方法阅读代码(从我的 Activity 调用):

private void importCollection() {
    // Fetch text file
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("text/*");
    startActivityForResult(intent, IMPORT_COLLECTION_CODE);
}

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

    if (data != null) {
        if (requestCode == IMPORT_COLLECTION_CODE) {
            // Fetch elements
            Uri uri = data.getData();

            StringBuilder sb = new StringBuilder();

            BufferedReader bufferedReader = null;

            try {
                ParcelFileDescriptor pfd = getContentResolver().
                        openFileDescriptor(uri, "r");
                BufferedReader bufferedReader =
                        new BufferedReader(new FileReader(pfd.getFileDescriptor()));

                String line;

                while((line = bufferedReader.readLine()) != null) { // <-- Exception here
                    sb.append(line);
                    sb.append("\n");
                }

                // ... do something with sb
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if(bufferedReader != null) {
                        bufferedReader.close();
                    }
                } catch(IOException e) {
                    // ignore
                }
            }
        }
    }
}

我还尝试将读取文件的代码放入 AsyncTask(无论如何这是个好主意),并将 FileReader 直接传递给 gson 的 fromJson 方法,但我仍然获得同样的错误。

Whosebug 上报告了一些类似的案例,其中人们在读取更多数据之前不小心关闭了 reader,但在我的代码中并非如此。

我的明显问题:有人知道为什么会发生这种情况 and/or 解决方法吗?

greenapps 在评论中回答了我的问题:Following the official documentation 我应该使用 InputStream:

    InputStream inputStream = getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(
        inputStream));

然后就可以正常工作了。