add provider for data directory

This commit is contained in:
qimiko committed 2023-06-03 01:18:31 -07:00
1 parent 5237817b39
commit 6b4616baa1
2 files changed
+126

No files matched your search

+10
View File
@@ -55,6 +55,16 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:authorities="com.geode.launcher.user"
android:name=".UserDirectoryProvider"
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
</application>
</manifest>
@@ -0,0 +1,116 @@
package com.geode.launcher
import android.database.Cursor
import android.database.MatrixCursor
import android.os.CancellationSignal
import android.os.ParcelFileDescriptor
import android.provider.DocumentsContract
import android.provider.DocumentsProvider
import android.webkit.MimeTypeMap
import java.io.File
private const val ROOT = "root"
private val DEFAULT_ROOT_PROJECTION: Array<String> = arrayOf(
DocumentsContract.Root.COLUMN_ROOT_ID,
DocumentsContract.Root.COLUMN_FLAGS,
DocumentsContract.Root.COLUMN_ICON,
DocumentsContract.Root.COLUMN_TITLE,
DocumentsContract.Root.COLUMN_DOCUMENT_ID,
)
private val DEFAULT_DOCUMENT_PROJECTION: Array<String> = arrayOf(
DocumentsContract.Document.COLUMN_DOCUMENT_ID,
DocumentsContract.Document.COLUMN_MIME_TYPE,
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
DocumentsContract.Document.COLUMN_LAST_MODIFIED,
DocumentsContract.Document.COLUMN_FLAGS,
DocumentsContract.Document.COLUMN_SIZE
)
class UserDirectoryProvider : DocumentsProvider() {
private lateinit var rootDir: File
override fun onCreate(): Boolean {
val context = context ?: return false
rootDir = context.filesDir
return true
}
override fun queryRoots(projection: Array<out String>?): Cursor {
val result = MatrixCursor(projection ?: DEFAULT_ROOT_PROJECTION)
// assert context is nonnull
val context = context ?: return result
result.newRow().apply {
add(DocumentsContract.Root.COLUMN_ROOT_ID, ROOT)
add(DocumentsContract.Root.COLUMN_DOCUMENT_ID, ROOT)
add(
DocumentsContract.Root.COLUMN_FLAGS,
DocumentsContract.Root.FLAG_SUPPORTS_CREATE or
DocumentsContract.Root.FLAG_SUPPORTS_RECENTS or
DocumentsContract.Root.FLAG_SUPPORTS_SEARCH
)
add(DocumentsContract.Root.COLUMN_TITLE, context.getString(R.string.app_name))
add(DocumentsContract.Root.COLUMN_ICON, R.drawable.geode_logo)
}
return result
}
override fun queryDocument(documentId: String?, projection: Array<out String>?): Cursor {
return MatrixCursor(projection ?: DEFAULT_DOCUMENT_PROJECTION).apply {
val file = getFileForDocumentId(documentId ?: ROOT)
addDocument(this, file)
}
}
override fun queryChildDocuments(
parentDocumentId: String?,
projection: Array<out String>?,
sortOrder: String?
): Cursor {
return MatrixCursor(projection ?: DEFAULT_DOCUMENT_PROJECTION).apply {
val parent = getFileForDocumentId(parentDocumentId ?: ROOT)
parent.listFiles()?.forEach { file -> addDocument(this, file) }
}
}
override fun openDocument(
documentId: String?,
mode: String?,
signal: CancellationSignal?
): ParcelFileDescriptor {
val file = getFileForDocumentId(documentId ?: ROOT)
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.parseMode(mode))
}
private fun addDocument(cursor: MatrixCursor, file: File) {
cursor.newRow().apply {
add(DocumentsContract.Document.COLUMN_DOCUMENT_ID, getDocumentIdForFile(file))
add(DocumentsContract.Document.COLUMN_MIME_TYPE, typeForFile(file))
add(DocumentsContract.Document.COLUMN_DISPLAY_NAME, file.name)
add(DocumentsContract.Document.COLUMN_LAST_MODIFIED, file.lastModified())
add(DocumentsContract.Document.COLUMN_SIZE, file.length())
}
}
private fun typeForFile(file: File): String {
if (file.isDirectory) {
return DocumentsContract.Document.MIME_TYPE_DIR
}
return MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(file.extension) ?: "application/octet-stream"
}
private fun getFileForDocumentId(documentId: String): File {
return File(rootDir, documentId.removePrefix(ROOT))
}
private fun getDocumentIdForFile(file: File): String {
return ROOT + file.toRelativeString(rootDir)
}
}