Knowledge hub
Knowledge hub

Reputation: 51

How to fetch all pdf file from all directories in my Android app

I want to know how to fetch all PDF files from internal storage. Files can be in any directory, like some in DCIM folders or some in Downloads folder, and so on and so forth.

Note: I am using Android Studio (language: Java).

Upvotes: 2

Views: 7774

Answers (3)

shobhan
shobhan

Reputation: 1518

This is improvised answer of @Shay Kin.

As we know in latest android versions we have many restrictions to access files in external storage.

MediaStore api and Storage Access Framework apis provides access to shared files. This is explained clearly in this video.

Coming to the answer, in Shay Kin's answer we can able to fetch all pdf files which are there in the shared files but ignores downloads.

Permissions required

READ_EXTERNAL_STORAGE

if api is Q plus you also need MANAGE_EXTERNAL_STORAGE

please find the below code to fetch all pdf files.

protected List<String> getPdfList() {
    List<String> pdfList = new ArrayList<>();

    final String[] projection = new String[]{
            MediaStore.Files.FileColumns.DISPLAY_NAME,
            MediaStore.Files.FileColumns.DATE_ADDED,
            MediaStore.Files.FileColumns.DATA,
            MediaStore.Files.FileColumns.MIME_TYPE,
    };

    final String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " DESC";

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

    final String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
    final String[] selectionArgs = new String[]{mimeType};
    
    Uri collection = MediaStore.Files.getContentUri("external");
    pdfList.addAll(getPdfList(collection, projection, selection, selectionArgs, sortOrder));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        collection = MediaStore.Downloads.getContentUri("external");
        pdfList.addAll(getPdfList(collection,projection, selection, selectionArgs, sortOrder));
    }
    
    return pdfList;
}

private List<String> getPdfList(Uri collection, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    List<String> pdfList = new ArrayList<>();

    try (Cursor cursor = getContentResolver().query(collection, projection, selection, selectionArgs, sortOrder)) {
        assert cursor != null;

        if (cursor.moveToFirst()) {
            int columnData = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
            do {
                pdfList.add((cursor.getString(columnData)));
                Log.d(TAG, "getPdf: " + cursor.getString(columnData));
                //you can get your pdf files
            } while (cursor.moveToNext());
        }
    }
    return pdfList;
}

Hope this works.

Upvotes: 0

Anil Dhiman
Anil Dhiman

Reputation: 1429

i have search almost all the ans but it was not working in Android 11. so i have a short solution for picking up all file for example image, video, pdf, doc, audio etc. there was a github library which was recently created

Click [here] https://github.com/HBiSoft/PickiT

and if you want to do all this without dependency

Code Below

  • do it in orderwise

var mimeTypes = arrayOf(
    "application/msword",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",  // .doc & .docx
    "application/vnd.ms-powerpoint",
    "application/vnd.openxmlformats-officedocument.presentationml.presentation",  // .ppt & .pptx
    "application/vnd.ms-excel",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",  // .xls & .xlsx
    "application/pdf"
)

 findViewById<Button>(R.id.btnclick).setOnClickListener {

        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            addCategory(Intent.CATEGORY_OPENABLE)
            type = "*/*"
            putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);

            // mimeTypes = mimeTypes
        }

        startActivityForResult(intent, 100)

    }

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    Log.e(">>>>>>", "check")

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        getFile(this,intentToDocumentFiles(data)[0])
    }
}

 private fun intentToDocumentFiles(intent: Intent?): List<DocumentFile> {
    val uris = intent?.clipData?.run {
        val list = mutableListOf<Uri>()
        for (i in 0 until itemCount) {
            list.add(getItemAt(i).uri)
        }
        list.takeIf { it.isNotEmpty() }
    } ?: listOf(intent?.data ?: return emptyList())

    return uris.mapNotNull { uri ->
        if (uri.isDownloadsDocument && Build.VERSION.SDK_INT < 28 && uri.path?.startsWith("/document/raw:") == true) {
            val fullPath = uri.path.orEmpty().substringAfterLast("/document/raw:")
            DocumentFile.fromFile(File(fullPath))
        } else {
            fromSingleUri(uri)
        }
    }.filter { it.isFile }
}

@RequiresApi(Build.VERSION_CODES.R)
fun getFile(context: Context, document: DocumentFile): File? {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
        return null
    }
    try {
        val volumeList: List<StorageVolume> = context
            .getSystemService(StorageManager::class.java)
            .getStorageVolumes()
        if (volumeList == null || volumeList.isEmpty()) {
            return null
        }

        // There must be a better way to get the document segment
        val documentId = DocumentsContract.getDocumentId(document.uri)
        val documentSegment = documentId.substring(documentId.lastIndexOf(':') + 1)
        for (volume in volumeList) {
            val volumePath: String
            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
                val class_StorageVolume = Class.forName("android.os.storage.StorageVolume")
                val method_getPath: Method = class_StorageVolume.getDeclaredMethod("getPath")
                volumePath=method_getPath.invoke(volume).toString()
            } else {
                // API 30
                volumePath=volume.directory!!.path
            }
            val storageFile = File(volumePath + File.separator + documentSegment)

            // Should improve with other checks, because there is the
            // remote possibility that a copy could exist in a different
            // volume (SD-card) under a matching path structure and even
            // same file name, (maybe a user's backup in the SD-card).
            // Checking for the volume Uuid could be an option but
            // as per the documentation the Uuid can be empty.
            val isTarget = (storageFile.exists()
                    && storageFile.lastModified() == document.lastModified()
                    && storageFile.length() == document.length())
            if (isTarget) {
                Log.e(">>>>>>>",storageFile.absolutePath)
                return storageFile
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    Log.e(">>>>>>>","null")
    return null
}

Upvotes: 4

Shay Kin
Shay Kin

Reputation: 2647

You can use MediaStore to fetch all PDF Files ,this is an example how to get all your PDF files :

   protected ArrayList<String> getPdfList() {
    ArrayList<String> pdfList = new ArrayList<>();
    Uri collection;

    final String[] projection = new String[]{
            MediaStore.Files.FileColumns.DISPLAY_NAME,
            MediaStore.Files.FileColumns.DATE_ADDED,
            MediaStore.Files.FileColumns.DATA,
            MediaStore.Files.FileColumns.MIME_TYPE,
    };

    final String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " DESC";

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

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

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


    try (Cursor cursor = getContentResolver().query(collection, projection, selection, selectionArgs, sortOrder)) {
        assert cursor != null;

        if (cursor.moveToFirst()) {
            int columnData = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
            int columnName = cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME);
            do {
                pdfList.add((cursor.getString(columnData)));
                Log.d(TAG, "getPdf: " + cursor.getString(columnData));
                //you can get your pdf files
            } while (cursor.moveToNext());
        }
    }
    return pdfList;
}

Upvotes: 3

Related Questions