I am trying to make my app allow users to read pdf files on my app. I have added the uses permission in my manifest file and my code works perfectly fine yet when the runtime permission pops up and I allow for the app to access my device storage no pdf files show up on my app for me to select and to read. Why is this happening and what should I change?
This is the current code in my MainActivity.java class:
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);
}
}
I have also set up my Pdfadapter.java class and pdfviewholder.java class but the pdfs don’t show up in my app. I am trying to make my app usable for sdks between 21 up to the latest version. My compilesdk is 32, min sdk 32 and targetsdk 32 in my gradle file.
2
Answers
First of all, never use the
file API
for fetching the media from device storage except you have a special requirement. It’s slow as hell when you have so many files stored on the device and memory consumption is a thing to consider when making an app.Here, you can read all the media files using
Mediastore API
which is memory efficient and provides many customizations while loading media files.So, all you have to do is get the storage permission and then load PDFs using mediastore like this,
Load all PDFs from device storage including SD card :
Here is the
MediaModel
model class for better access of file details:Check your permission code and try this method and you’ll get it.
And yes, make sure you load the PDFs on
background thread
for better performance and populate the recyclerview onmain thread
.If the files are not created by your app you will not be able to list them on Android 11+ devices.
Not with file.listFiles().
Not with MediaStore queries.