Skip to content

Commit

Permalink
Add requiresWriteAccess to DocumentFileCompat.from*()
Browse files Browse the repository at this point in the history
  • Loading branch information
anggrayudi committed Jul 21, 2021
1 parent 3387a7b commit 03511dc
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 20 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ android.enableJetifier=true
kotlin.code.style=official
GROUP=com.anggrayudi
POM_ARTIFACT_ID=storage
VERSION_NAME=0.10.0-SNAPSHOT
VERSION_NAME=0.11.0-SNAPSHOT
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,16 @@ object DocumentFileCompat {
storageId: String = PRIMARY,
basePath: String = "",
documentType: DocumentFileType = DocumentFileType.ANY,
requiresWriteAccess: Boolean = false,
considerRawFile: Boolean = true
): DocumentFile? {
if (storageId == DATA) {
return DocumentFile.fromFile(context.dataDirectory.child(basePath))
}
return if (basePath.isEmpty()) {
getRootDocumentFile(context, storageId, considerRawFile)
getRootDocumentFile(context, storageId, requiresWriteAccess, considerRawFile)
} else {
val file = exploreFile(context, storageId, basePath, documentType, considerRawFile)
val file = exploreFile(context, storageId, basePath, documentType, requiresWriteAccess, considerRawFile)
if (file == null && basePath.startsWith(Environment.DIRECTORY_DOWNLOADS) && storageId == PRIMARY) {
val downloads = context.fromTreeUri(Uri.parse(DOWNLOADS_TREE_URI))?.takeIf { it.canRead() } ?: return null
downloads.child(context, basePath.substringAfter('/', ""))?.takeIf {
Expand All @@ -149,14 +150,15 @@ object DocumentFileCompat {
context: Context,
fullPath: String,
documentType: DocumentFileType = DocumentFileType.ANY,
requiresWriteAccess: Boolean = false,
considerRawFile: Boolean = true
): DocumentFile? {
return if (fullPath.startsWith('/')) {
// absolute path
fromFile(context, File(fullPath), documentType, considerRawFile)
fromFile(context, File(fullPath), documentType, requiresWriteAccess, considerRawFile)
} else {
// simple path
fromSimplePath(context, fullPath.substringBefore(':'), fullPath.substringAfter(':'), documentType, considerRawFile)
fromSimplePath(context, fullPath.substringBefore(':'), fullPath.substringAfter(':'), documentType, requiresWriteAccess, considerRawFile)
}
}

Expand All @@ -176,17 +178,18 @@ object DocumentFileCompat {
context: Context,
file: File,
documentType: DocumentFileType = DocumentFileType.ANY,
requiresWriteAccess: Boolean = false,
considerRawFile: Boolean = true
): DocumentFile? {
return if (file.canRead() && (considerRawFile || file.isExternalStorageManager(context))) {
return if (file.checkRequirements(context, requiresWriteAccess, considerRawFile)) {
if (documentType == DocumentFileType.FILE && !file.isFile || documentType == DocumentFileType.FOLDER && !file.isDirectory)
null
else
DocumentFile.fromFile(file)
} else {
val basePath = file.getBasePath(context).removeForbiddenCharsFromFilename().trimFileSeparator()
exploreFile(context, file.getStorageId(context), basePath, documentType, considerRawFile)
?: fromSimplePath(context, file.getStorageId(context), basePath, documentType, considerRawFile)
exploreFile(context, file.getStorageId(context), basePath, documentType, requiresWriteAccess, considerRawFile)
?: fromSimplePath(context, file.getStorageId(context), basePath, documentType, requiresWriteAccess, considerRawFile)
}
}

Expand All @@ -209,9 +212,7 @@ object DocumentFileCompat {
if (subFile.isNotEmpty()) {
rawFile = File("$rawFile/$subFile".trimEnd('/'))
}
if (rawFile.canRead() && (considerRawFile || rawFile.isExternalStorageManager(context))
&& (requiresWriteAccess && rawFile.isWritable(context) || !requiresWriteAccess)
) {
if (rawFile.checkRequirements(context, requiresWriteAccess, considerRawFile)) {
return DocumentFile.fromFile(rawFile)
}

Expand Down Expand Up @@ -484,7 +485,7 @@ object DocumentFileCompat {
return null
}
}
return currentDirectory.takeIf { requiresWriteAccess && it.isWritable(context) || !requiresWriteAccess }
return currentDirectory.takeIfWritable(context, requiresWriteAccess)
}

/**
Expand Down Expand Up @@ -545,7 +546,7 @@ object DocumentFileCompat {
}
}
results.indices.forEach { index ->
results[index] = results[index]?.takeIf { requiresWriteAccess && it.isWritable(context) || !requiresWriteAccess }
results[index] = results[index]?.takeIfWritable(context, requiresWriteAccess)
}
return results
}
Expand Down Expand Up @@ -652,10 +653,11 @@ object DocumentFileCompat {
storageId: String,
basePath: String,
documentType: DocumentFileType,
requiresWriteAccess: Boolean,
considerRawFile: Boolean
): DocumentFile? {
val rawFile = File(buildAbsolutePath(context, storageId, basePath))
if ((considerRawFile || storageId == DATA) && rawFile.canRead()) {
if ((considerRawFile || storageId == DATA) && rawFile.canRead() && rawFile.shouldWritable(context, requiresWriteAccess)) {
return if (documentType == DocumentFileType.ANY || documentType == DocumentFileType.FILE && rawFile.isFile
|| documentType == DocumentFileType.FOLDER && rawFile.isDirectory
) {
Expand All @@ -665,7 +667,7 @@ object DocumentFileCompat {
}
}
val file = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
getRootDocumentFile(context, storageId, considerRawFile)?.child(context, basePath) ?: return null
getRootDocumentFile(context, storageId, requiresWriteAccess, considerRawFile)?.child(context, basePath) ?: return null
} else {
val directorySequence = getDirectorySequence(basePath).toMutableList()
val parentTree = ArrayList<String>(directorySequence.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,7 @@ fun DocumentFile.toRawDocumentFile(context: Context): DocumentFile? {
fun DocumentFile.toTreeDocumentFile(context: Context): DocumentFile? {
return if (isRawFile) {
DocumentFileCompat.fromFile(context, toRawFile(context) ?: return null, considerRawFile = false)
} else {
this
}
} else takeIf { it.isTreeDocumentFile }
}

fun DocumentFile.toMediaFile(context: Context) = if (isTreeDocumentFile) null else MediaFile(context, uri)
Expand Down Expand Up @@ -291,7 +289,7 @@ fun DocumentFile.child(context: Context, path: String, requiresWriteAccess: Bool
}
currentDirectory
}
file?.takeIf { requiresWriteAccess && it.isWritable(context) || !requiresWriteAccess }
file?.takeIfWritable(context, requiresWriteAccess)
}
else -> null
}
Expand Down Expand Up @@ -333,6 +331,16 @@ fun DocumentFile.quickFindTreeFile(context: Context, resolver: ContentResolver,
return null
}

@RestrictTo(RestrictTo.Scope.LIBRARY)
fun DocumentFile.shouldWritable(context: Context, requiresWriteAccess: Boolean) = requiresWriteAccess && isWritable(context) || !requiresWriteAccess

@RestrictTo(RestrictTo.Scope.LIBRARY)
fun DocumentFile.takeIfWritable(context: Context, requiresWriteAccess: Boolean) = takeIf { it.shouldWritable(context, requiresWriteAccess) }

@RestrictTo(RestrictTo.Scope.LIBRARY)
fun DocumentFile.checkRequirements(context: Context, requiresWriteAccess: Boolean, considerRawFile: Boolean) = canRead() &&
(considerRawFile || isExternalStorageManager(context)) && shouldWritable(context, requiresWriteAccess)

/**
* @return File path without storage ID. Returns empty `String` if:
* * It is the root path
Expand Down
13 changes: 12 additions & 1 deletion storage/src/main/java/com/anggrayudi/storage/file/FileExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package com.anggrayudi.storage.file
import android.content.Context
import android.os.Build
import android.os.Environment
import androidx.annotation.RestrictTo
import androidx.annotation.WorkerThread
import androidx.core.content.ContextCompat
import androidx.documentfile.provider.DocumentFile
Expand Down Expand Up @@ -100,7 +101,7 @@ val File.mimeType: String?
@JvmOverloads
fun File.getRootRawFile(context: Context, requiresWriteAccess: Boolean = false) = getRootPath(context).let {
if (it.isEmpty()) null else File(it).run {
if (canRead() && (requiresWriteAccess && isWritable(context) || !requiresWriteAccess)) this else null
if (canRead()) takeIfWritable(context, requiresWriteAccess) else null
}
}

Expand All @@ -111,6 +112,16 @@ fun File.canModify(context: Context) = canRead() && isWritable(context)
val File.isEmpty: Boolean
get() = isFile && length() == 0L || isDirectory && list().isNullOrEmpty()

@RestrictTo(RestrictTo.Scope.LIBRARY)
fun File.shouldWritable(context: Context, requiresWriteAccess: Boolean) = requiresWriteAccess && isWritable(context) || !requiresWriteAccess

@RestrictTo(RestrictTo.Scope.LIBRARY)
fun File.takeIfWritable(context: Context, requiresWriteAccess: Boolean) = takeIf { it.shouldWritable(context, requiresWriteAccess) }

@RestrictTo(RestrictTo.Scope.LIBRARY)
fun File.checkRequirements(context: Context, requiresWriteAccess: Boolean, considerRawFile: Boolean) = canRead() &&
(considerRawFile || isExternalStorageManager(context)) && shouldWritable(context, requiresWriteAccess)

fun File.createNewFileIfPossible(): Boolean = try {
isFile || createNewFile()
} catch (e: IOException) {
Expand Down

0 comments on commit 03511dc

Please sign in to comment.