i developed app can read all documents like pdf, and office PowerPoint, excel, word
and the main activity i want to show a list of all documents available on device so user can open any document inside app and not only browsing files from storage
i tried this code but not working and tried another multiple solutions in stackoverflow and other websites and nothing work at end.
my code
mainactivity
before on create
private static final int PDF_SELECTION_CODE = 200;
private static final int PERMISSION_REQUEST_CODE = 100;
private RecyclerView recyclerView;
private DocumentAdapter documentAdapter;
private ArrayList<File> documentList;
inside on create
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
loadDocuments();
} else {
loadDocuments();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Scoped Storage
loadDocumentsWithScopedStorage();
} else {
// Legacy Storage
loadDocumentsWithScopedStorage();
}
loadDocumentsWithMediaStore();
after on create
private void getDocuments(@NonNull File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
getDocuments(file);
} else if (file.getName().endsWith(".pdf") ||
file.getName().endsWith(".doc") ||
file.getName().endsWith(".docx") ||
file.getName().endsWith(".txt")) {
documentList.add(file);
}
}
}
}
private void loadDocumentsWithScopedStorage() {
documentList = new ArrayList<>();
Uri collection = MediaStore.Files.getContentUri("external");
String[] projection = {
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DISPLAY_NAME
};
// Filter for specific document types
String selection = MediaStore.Files.FileColumns.MIME_TYPE + " IN (?, ?, ?, ?)";
String[] selectionArgs = new String[]{
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"text/plain"
};
Cursor cursor = getContentResolver().query(collection, projection, selection, selectionArgs, null);
if (cursor != null) {
int dataIndex = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
while (cursor.moveToNext()) {
String filePath = cursor.getString(dataIndex);
File file = new File(filePath);
documentList.add(file);
}
cursor.close();
}
documentAdapter = new DocumentAdapter(documentList, file -> {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(android.net.Uri.fromFile(file), "*/*");
startActivity(intent);
});
recyclerView.setAdapter(documentAdapter);
}
private void loadDocumentsWithMediaStore() {
documentList = new ArrayList<>();
Uri collection = MediaStore.Files.getContentUri("external");
String[] projection = {
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DISPLAY_NAME
};
String selection = MediaStore.Files.FileColumns.MIME_TYPE + " IN (?, ?, ?, ?)";
String[] selectionArgs = new String[]{
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"text/plain"
};
try (Cursor cursor = getContentResolver().query(collection, projection, selection, selectionArgs, null)) {
if (cursor != null) {
int dataIndex = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
while (cursor.moveToNext()) {
String filePath = cursor.getString(dataIndex);
File file = new File(filePath);
documentList.add(file);
}
}
}
documentAdapter = new DocumentAdapter(documentList, file -> {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(android.net.Uri.fromFile(file), "*/*");
startActivity(intent);
});
recyclerView.setAdapter(documentAdapter);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
loadDocuments();
} else {
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
}
}
}
Document Adapter
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.io.File;
import java.util.ArrayList;
public class DocumentAdapter extends RecyclerView.Adapter<DocumentAdapter.DocumentViewHolder> {
private final ArrayList<File> documentList;
private final OnDocumentClickListener listener;
public DocumentAdapter(ArrayList<File> documentList, OnDocumentClickListener listener) {
this.documentList = documentList;
this.listener = listener;
}
@NonNull
@Override
public DocumentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
return new DocumentViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull DocumentViewHolder holder, int position) {
File document = documentList.get(position);
holder.textView.setText(document.getName());
holder.itemView.setOnClickListener(v -> listener.onDocumentClick(document));
}
@Override
public int getItemCount() {
return documentList.size();
}
public interface OnDocumentClickListener {
void onDocumentClick(File file);
}
static class DocumentViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public DocumentViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(android.R.id.text1);
}
}
}
i tried all solution from browsing stackoverflow questions and searching google and asking gemini and chatgpt
code is not working and not showing a list of documents files
no code error shown and when i run app only output a toast message "Permission Denied".
2
Answers
i am afraid you cannot achieve what you want,because google make changes on file system access permission from Android 10.your app can only access its own private folders and shared folders on device like Downloads,Document,DCIM,Pictures.to access other folders is not allowed any more,unless your app is specifically used for file management or a system app.
even if the files in shared folders you can access must be type of media,other types are also forbidden.so you have to use the file browsing app in the system to read document on the device. your app cannot read all the documents on device.
you can know more about the permission changes from here google android developer
Solution: Access All Documents with MANAGE_EXTERNAL_STORAGE Permission (Android 10 and higher)
– Add the MANAGE_EXTERNAL_STORAGE Permission in the Manifest:
In your AndroidManifest.xml, you need to declare the MANAGE_EXTERNAL_STORAGE permission to allow your app to request access to all files on the device:
– Request the MANAGE_EXTERNAL_STORAGE Permission at Runtime:
Starting from Android 10 (API 29), to access files outside of scoped storage, you need to request MANAGE_EXTERNAL_STORAGE permission at runtime. This is different from regular file access permissions.
Here’s how you can check and request it:
The ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION intent opens the system settings where users can grant access to all files on the device. Once granted, your app will be able to access documents in directories beyond the scope of scoped storage.
– Load Documents After Permission is Granted:
Once the permission is granted, you can access all files on the device.