为什么READ_EXTERNAL_STORAGE不允许在我的Android Studio应用中显示PDF?

wfsdck30  于 2023-05-21  发布在  Android
关注(0)|答案(2)|浏览(142)

我试图让我的应用程序允许用户在我的应用程序上阅读PDF文件。我已经在我的清单文件中添加了uses权限,我的代码运行得很好,但当运行时权限弹出时,我允许应用程序访问我的设备存储,没有pdf文件显示在我的应用程序上供我选择和阅读。为什么会发生这种情况,我应该改变什么?
这是我的www.example.com类中的当前代码MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private PdfAdapter pdfAdapter;
    private List<File> pdfList;
    private RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        runtimePermission();
    }

    private void runtimePermission() {
        Dexter.withContext(MainActivity.this).withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse permissionGrantedResponse) {
                        displayPdf();
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse permissionDeniedResponse) {
                        Toast.makeText(MainActivity.this, "Permission is Required", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(PermissionRequest permissionRequest, PermissionToken permissionToken) {
                        permissionToken.continuePermissionRequest();
                    }
                }).check();

    }

    public ArrayList<File> findPdf (File file)
    {
        ArrayList<File> arrayList = new ArrayList<>();
        File[] files = file.listFiles();

        for (File singleFile: files)
        {
            if (singleFile.isDirectory() && singleFile.isHidden()) {
                arrayList.addAll(findPdf(singleFile));
            }
            else {
                if (singleFile.getName().endsWith(".pdf")){
                    arrayList.add(singleFile);
                }
            }
        }
        return arrayList;
    }

    private void displayPdf() {
        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        pdfList = new ArrayList<>();
        pdfList.addAll(findPdf(Environment.getExternalStorageDirectory()));
        pdfAdapter = new PdfAdapter(this, pdfList);
        recyclerView.setAdapter(pdfAdapter);
    }
}

我还设置了我的Pdfadapter.java类和pdfviewholder.java类,但PDF文件不显示在我的应用程序中。我正试图使我的应用程序可用于21到最新版本之间的sdk。我的compilesdk是32,min sdk是32,gradle文件中的targetsdk是32。

kyvafyod

kyvafyod1#

首先,切勿使用file API从设备存储中获取介质,除非您有特殊要求。当你有这么多文件存储在设备上时,它会慢得像地狱一样,而内存消耗是制作应用程序时要考虑的一件事。

在这里,您可以使用Mediastore API读取所有媒体文件,这是内存效率,并提供了许多自定义,同时加载媒体文件。
所以,你所要做的就是获得存储权限,然后像这样使用mediastore加载PDF,

从设备存储(包括SD卡)加载所有PDF:

public ArrayList<MediaModel> getAllPDFFromStorage(Context ctx) {
        ArrayList<MediaModel> pdfList = new ArrayList<>();

        String[] projection = {
                MediaStore.Files.FileColumns._ID,
                MediaStore.Files.FileColumns.DISPLAY_NAME,
                MediaStore.Files.FileColumns.DATA,
                MediaStore.Files.FileColumns.DISPLAY_NAME,
                MediaStore.Files.FileColumns.DATE_MODIFIED,
                MediaStore.Files.FileColumns.MIME_TYPE,
                MediaStore.Files.FileColumns.SIZE
        };

        String sortOrder = MediaStore.Files.FileColumns.DATE_MODIFIED + " DESC";

        String selection = MediaStore.Files.FileColumns.MIME_TYPE + " = ?";

        String mimeTypePdf = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
        String[] selectionArgs = {mimeTypePdf};

        Uri collection;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            collection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
        } else {
            collection = MediaStore.Files.getContentUri("external");
        }

        Cursor cursor = ctx.getContentResolver().query(collection, projection, selection, selectionArgs, sortOrder);
        if (cursor != null && cursor.moveToFirst()) {

            do {
                long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID));
                String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA));
                String dirName = "";
                String parent = new File(path).getParent();
                if (!parent.isEmpty()) {
                    dirName = new File(parent.toString()).getName();
                }
                String name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME));
                long date = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATE_MODIFIED));
                String size = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.SIZE));
                Uri contentUri;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    contentUri = ContentUris.withAppendedId(
                            MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), id
                    );
                } else {
                    contentUri = ContentUris.withAppendedId(
                            MediaStore.Files.getContentUri("external"), id
                    );
                }

                if (size != null && new File(path).exists()) {
                    MediaModel mediaModel = new MediaModel();
                    mediaModel.setFileName(name);
                    mediaModel.setFilePath(path);
                    mediaModel.setUri(contentUri);
                    mediaModel.setDateAdded(date);
                    mediaModel.setFileSize(Long.parseLong(size));
                    mediaModel.setDirName(dirName);
                    pdfList.add(mediaModel);
                }
            } while (cursor.moveToNext());

            cursor.close();
        }

        return pdfList;
    }

下面是MediaModel模型类,可以更好的获取文件细节:

class MediaModel {
    String fileName;
    String filePath;
    Uri uri;
    long dateAdded;
    long fileSize;
    String dirName;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public Uri getUri() {
        return uri;
    }

    public void setUri(Uri uri) {
        this.uri = uri;
    }

    public long getDateAdded() {
        return dateAdded;
    }

    public void setDateAdded(long dateAdded) {
        this.dateAdded = dateAdded;
    }

    public long getFileSize() {
        return fileSize;
    }

    public void setFileSize(long fileSize) {
        this.fileSize = fileSize;
    }

    public String getDirName() {
        return dirName;
    }

    public void setDirName(String dirName) {
        this.dirName = dirName;
    }
}

检查您的权限代码,然后尝试此方法,您将获得它。

是的,确保在background thread上加载PDF以获得更好的性能,并在main thread上填充recyclerview。

m3eecexj

m3eecexj2#

如果这些文件不是由您的应用创建的,您将无法在Android 11+设备上列出它们。
不使用file.listFiles()。
不支持MediaStore查询。

相关问题