DocumentProvider เป็นคลาสนามธรรมของ Android ที่ใช้งานผู้ให้บริการเนื้อหาสำหรับการเข้าถึงไฟล์ผ่าน Storage Access Framework ผู้ให้บริการจะถูกลงทะเบียนใน AndroidManifest.xml และให้ไฟล์แก่แอปพลิเคชันอื่นผ่านตัวเลือกระบบ ตาม Android Developers (2026) DocumentsProvider ต้องการการใช้งานเมธอด queryRoots, queryDocument และ queryChildDocuments เพื่อแสดงโครงสร้างไฟล์ในกล่องโต้ตอบการเลือก
ประเด็นสำคัญ
DocumentsProvider เป็นคลาสพื้นฐานของ Android ที่สืบทอด ContentProvider ซึ่งช่วยให้แอปพลิเคชันสามารถให้ไฟล์ของตนแก่แอปพลิเคชันอื่นผ่านอินเทอร์เฟซ SAF ของระบบ ผู้ให้บริการสร้างระบบไฟล์เสมือนที่ผู้ใช้เห็นในกล่องโต้ตอบการเลือกเอกสาร
ผู้ให้บริการแต่ละรายจัดระเบียบไฟล์เป็น ราก (roots) — จุดเข้าถึงระดับบนสุด ตัวอย่างเช่น Google Drive มีราก “ไดรฟ์ของฉัน” และ “แชร์กับฉัน” ภายในราก ผู้ให้บริการส่งคืนโครงสร้างต้นไม้ของเอกสาร โดยแต่ละเอกสารคือไฟล์หรือไดเรกทอรีที่มีชนิด MIME ขนาด และวันที่เฉพาะ
DocumentProvider เป็นส่วนหนึ่งของแพ็คเกจ android.provider และพร้อมใช้งานตั้งแต่ Android 4.4 (API 19) ผู้ให้บริการถูกใช้โดยบริการคลาวด์ ตัวจัดการรหัสผ่าน แอปจดบันทึก และโปรแกรมใด ๆ ที่เก็บไฟล์ในรูปแบบของตนเอง
การสร้าง DocumentProvider ของคุณเองเริ่มต้นด้วยการสืบทอดคลาส DocumentsProvider และใช้งานเมธอดที่จำเป็นสี่เมธอด ผู้ให้บริการกำหนดโครงสร้างไฟล์ที่ปรากฏในตัวเลือก SAF ของระบบเมื่อเลือกไฟล์
เมธอดแรกคือ queryRoots ซึ่งส่งคืนเคอร์เซอร์ที่มีคอลัมน์ Root.COLUMN_ROOT_ID, Root.COLUMN_TITLE, Root.COLUMN_SUMMARY และ Root.COLUMN_FLAGS แต่ละรากสามารถรองรับแฟล็ก: FLAG_SUPPORTS_CREATE, FLAG_SUPPORTS_SEARCH และ FLAG_SUPPORTS_IS_CHILD
เมธอดที่สองที่จำเป็นคือ queryChildDocuments ซึ่งส่งคืนเอกสารย่อยของ URI ที่ระบุ เมธอดนี้ถูกเรียกเมื่อผู้ใช้เปิดไดเรกทอรีในตัวเลือก แต่ละเอกสารประกอบด้วยคอลัมน์: Document.COLUMN_DOCUMENT_ID, COLUMN_DISPLAY_NAME, COLUMN_MIME_TYPE, COLUMN_SIZE และ COLUMN_LAST_MODIFIED
DocumentsProvider ต้องการการใช้งานสี่เมธอดที่สร้างโครงสร้างไฟล์สำหรับตัวเลือก หากไม่มีเมธอดเหล่านี้ ผู้ให้บริการจะไม่ทำงาน — กล่องโต้ตอบ SAF ของระบบจะไม่สามารถแสดงไฟล์ได้
เพิ่มเติม คุณสามารถใช้งาน createDocument สำหรับสร้างไฟล์ใหม่ deleteDocument สำหรับลบ และ renameDocument สำหรับเปลี่ยนชื่อ เมธอดเหล่านี้ต้องการแฟล็ก FLAG_SUPPORTS_CREATE ในราก
DocumentProvider ถูกลงทะเบียนใน AndroidManifest.xml เป็น ContentProvider ปกติพร้อมตัวกรอง intent และแฟล็กเพิ่มเติม ผู้ให้บริการต้องได้รับการป้องกันจากการเข้าถึงโดยตรงผ่านสิทธิ์ — แนะนำให้ใช้ android:exported="true" พร้อมสิทธิ์ที่ชัดเจน
<provider
android:name=".provider.CustomDocumentProvider"
android:authorities="com.example.app.documents"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action
android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
<meta-data
android:name="android.content.documents.roots"
android:resource="@xml/file_paths" />
</provider>
แฟล็ก grantUriPermissions อนุญาตให้ SAF มอบสิทธิ์การเข้าถึงชั่วคราวให้กับแอปพลิเคชันที่เรียก คุณลักษณะ authorities ต้องไม่ซ้ำกัน — โดยปกติจะใช้ชื่อแพ็คเกจที่มีคำต่อท้าย .documents นอกจากนี้ยังแนะนำให้ระบุ meta-data พร้อมทรัพยากร XML สำหรับกำหนดค่าราก
การใช้งาน DocumentsProvider ต้องการส่งคืน ParcelFileDescriptor จากเมธอด openDocument สำหรับไฟล์ในเครื่องจะใช้ ParcelFileDescriptor.open สำหรับไฟล์คลาวด์ — ParcelFileDescriptor.open พร้อม Pipe สำหรับสตรีมมิ่ง โค้ดต้องจัดการกับข้อผิดพลาดในการเข้าถึงและไฟล์ที่หายไป
class CustomDocumentProvider : DocumentsProvider() {
override fun queryRoots(): Cursor {
val matrix = MatrixCursor(Root.COLUMNS)
matrix.newRow().add(Root.COLUMN_ROOT_ID, "local")
.add(Root.COLUMN_TITLE, "My Files")
.add(Root.COLUMN_SUMMARY, "Local documents")
.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE)
return matrix
}
override fun openDocument(
documentId: String, flags: Int, cursor: CancellationSignal?
): ParcelFileDescriptor {
val file = File(context.filesDir, documentId)
val accessMode = ParcelFileDescriptor.parseMode(flags)
return ParcelFileDescriptor.open(file, accessMode)
}
}
DocumentProvider สามารถส่งคืน ไฟล์เสมือน — เอกสารที่ไม่มีอยู่เป็นไฟล์แยกต่างหากบนดิสก์ ตัวอย่างเช่น บันทึกจากฐานข้อมูลสามารถนำเสนอเป็น PDF เสมือน ซึ่งใช้ชนิด MIME พร้อมแฟล็ก FLAG_VIRTUAL_DOCUMENT และ openDocument จะแปลงข้อมูลเป็นรูปแบบที่ต้องการก่อนส่ง
iOS มีกลไกที่คล้ายกัน — UIDocumentPickerViewController ซึ่งให้อินเทอร์เฟซการเลือกไฟล์แบบรวมศูนย์เช่นกัน อย่างไรก็ตาม ใน iOS ผู้ให้บริการเอกสารถูกใช้งานผ่าน UIDocumentPickerDelegate และส่วนขยายแอป (App Extensions) ชนิด Document Provider
ต่างจาก Android DocumentsProvider, iOS UIDocumentPickerViewController ไม่ต้องการสร้างผู้ให้บริการแบบกำหนดเองสำหรับไฟล์ในเครื่อง — ตัวเลือกระบบรองรับ iCloud Drive และพื้นที่จัดเก็บในเครื่องโดยค่าเริ่มต้น บริการคลาวด์ของบุคคลที่สามลงทะเบียนผ่าน ส่วนขยาย Document Provider ด้วยคีย์ Info.plist NSExtensionFileProviderDocumentInterface
ความแตกต่างหลัก: ใน Android DocumentProvider จะถูก เรียกใช้งาน ผ่าน SAF Intent และต้องใช้งานการนำทางด้วยตนเอง ใน iOS UIDocumentPickerViewController ใช้เบราว์เซอร์ไฟล์ระบบในตัว และผู้ให้บริการส่วนขยายรับผิดชอบเฉพาะการให้เนื้อหาตามคำขอเท่านั้น
คำถามที่พบบ่อย
DocumentsProvider เป็นคลาสนามธรรมของ Android สำหรับสร้างผู้ให้บริการเอกสารแบบกำหนดเอง มันช่วยให้แอปพลิเคชันนำเสนอไฟล์ของตนแก่แอปพลิเคชันอื่นผ่านกล่องโต้ตอบ Storage Access Framework ของระบบ
สี่เมธอดที่จำเป็น: queryRoots (รากพื้นที่จัดเก็บ), queryDocument (เอกสารเดียว), queryChildDocuments (เนื้อหาโฟลเดอร์) และ openDocument (เปิดไฟล์) หากไม่มีเมธอดเหล่านี้ ผู้ให้บริการจะไม่ทำงาน
ผู้ให้บริการถูกลงทะเบียนเป็น <provider> ด้วยชื่อคลาส authorities ที่ไม่ซ้ำกัน ตัวกรอง intent พร้อมการดำเนินการ android.content.action.DOCUMENTS_PROVIDER และ grantUriPermissions="true"
FileProvider สร้าง URI เนื้อหาสำหรับไฟล์เฉพาะของแอปพลิเคชันของคุณ DocumentsProvider สร้างระบบไฟล์ที่สมบูรณ์ซึ่งมองเห็นได้ในตัวเลือก SAF พร้อมรองรับการนำทางและการค้นหา
ใช้แฟล็ก FLAG_VIRTUAL_DOCUMENT ในคอลัมน์ COLUMN_FLAGS และชนิด MIME ที่มีคำนำหน้า “vnd.android.document/” ใน openDocument แปลงข้อมูลเป็นรูปแบบที่ขอโดยใช้ ParcelFileDescriptor พร้อม Pipe
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม