mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-21 08:19:33 +00:00
add provider for data directory
This commit is contained in:
2 files changed
+126
No files matched your search
@@ -55,6 +55,16 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</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>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user