Skip to content

Commit 1b43ade

Browse files
committed
Implemented file compatible codes
TOOD: Extension functions
1 parent 28395e0 commit 1b43ade

36 files changed

+852
-60
lines changed

.idea/gradle.xml

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ android.enableJetifier=true
2020
# Kotlin code style for this project: "official" or "obsolete":
2121
kotlin.code.style=official
2222

23-
version=0.1.11
23+
version=0.2
2424

2525
dokka_version=1.4.0-rc
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
package xyz.quaver.io
22

3-
import android.app.Activity
4-
import android.content.Intent
53
import android.net.Uri
6-
import androidx.test.espresso.intent.Intents.intending
7-
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
8-
import androidx.test.platform.app.InstrumentationRegistry
94
import androidx.test.ext.junit.runners.AndroidJUnit4
10-
5+
import androidx.test.platform.app.InstrumentationRegistry
6+
import org.junit.Assert.assertEquals
117
import org.junit.Test
128
import org.junit.runner.RunWith
13-
14-
import org.junit.Assert.*
15-
import java.io.File
9+
import xyz.quaver.io.util.parent
1610

1711
/**
1812
* Instrumented test, which will execute on an Android device.
@@ -27,4 +21,11 @@ class ExampleInstrumentedTest {
2721
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
2822
assertEquals("xyz.quaver.documentfilex.test", appContext.packageName)
2923
}
24+
25+
@Test
26+
fun parent() {
27+
val uri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3Atest1/document/primary%3Atest1%2Ftest2")
28+
29+
assertEquals("content://com.android.externalstorage.documents/tree/primary%3A/document/primary%3Atest1", uri.parent.toString())
30+
}
3031
}

library/src/main/java/xyz/quaver/io/DocumentFileX.kt

+7-2
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,17 @@
2222

2323
package xyz.quaver.io
2424

25+
import android.annotation.SuppressLint
2526
import android.content.Context
2627
import android.net.Uri
2728
import androidx.annotation.RequiresApi
28-
import xyz.quaver.io.util.*
29+
import java.io.File
2930
import java.io.FileFilter
3031
import java.io.FilenameFilter
3132

3233
@RequiresApi(19)
3334
class DocumentFileX : SAFileX {
35+
@SuppressWarnings("unused")
3436
private constructor() : super("") {
3537
throw UnsupportedOperationException("STOP! You violated the law.")
3638
}
@@ -48,7 +50,7 @@ class DocumentFileX : SAFileX {
4850
}
4951

5052
override fun createNewFile() =
51-
throw UnsupportedOperationException("Creating file is not supported on Document URI")
53+
throw UnsupportedOperationException()
5254

5355
override fun getParent() =
5456
throw UnsupportedOperationException()
@@ -76,4 +78,7 @@ class DocumentFileX : SAFileX {
7678

7779
override fun mkdirs() =
7880
throw UnsupportedOperationException()
81+
82+
override fun renameTo(dest: File) =
83+
throw UnsupportedOperationException()
7984
}

library/src/main/java/xyz/quaver/io/FileX.kt

+12-2
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@
2020
* limitations under the License.
2121
*/
2222

23+
@file:SuppressWarnings("unused")
24+
2325
package xyz.quaver.io
2426

27+
import android.annotation.SuppressLint
2528
import android.content.Context
2629
import android.net.Uri
2730
import android.os.Build
2831
import android.provider.DocumentsContract
2932
import androidx.annotation.RequiresApi
33+
import androidx.core.net.toUri
3034
import xyz.quaver.io.util.*
3135
import java.io.File
3236

@@ -76,7 +80,7 @@ class Cache(private val context: Context, private val uri: Uri) {
7680
abstract class FileX : File {
7781
internal constructor(path: String) : super(path)
7882

79-
protected lateinit var context: Context
83+
internal lateinit var context: Context
8084
lateinit var uri: Uri
8185

8286
var cached = false
@@ -126,4 +130,10 @@ fun FileX(context: Context, uri: String, cached: Boolean = false) =
126130
FileX(context, Uri.parse(uri), cached)
127131

128132
fun FileX(context: Context, parentUri: String, child: String, cached: Boolean = false) =
129-
FileX(context, Uri.parse(parentUri), child, cached)
133+
FileX(context, Uri.parse(parentUri), child, cached)
134+
135+
fun FileX(context: Context, file: File) =
136+
RawFileX(context, file.toUri())
137+
138+
fun FileX(context: Context, file: File, child: String) =
139+
FileX(context, File(file, child))

library/src/main/java/xyz/quaver/io/SAFileX.kt

+41-18
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,16 @@
2222

2323
package xyz.quaver.io
2424

25+
import android.annotation.SuppressLint
2526
import androidx.annotation.RequiresApi
2627
import xyz.quaver.io.util.*
28+
import java.io.File
29+
import java.net.URI
30+
import java.nio.file.Path
2731

2832
@RequiresApi(19)
2933
abstract class SAFileX : FileX {
34+
@SuppressWarnings("unused")
3035
private constructor() : super("") {
3136
throw UnsupportedOperationException("STOP! You violated the law.")
3237
}
@@ -35,12 +40,12 @@ abstract class SAFileX : FileX {
3540

3641
override fun canExecute() = false
3742

38-
override fun canRead() = when {
43+
override fun canRead(): Boolean = when {
3944
cached -> cache.canRead
4045
else -> uri.canRead(context)
4146
}
4247

43-
override fun canWrite() = when {
48+
override fun canWrite(): Boolean = when {
4449
cached -> cache.canWrite
4550
else -> uri.canWrite(context)
4651
}
@@ -57,40 +62,40 @@ abstract class SAFileX : FileX {
5762
return true
5863
}
5964

60-
override fun deleteOnExit() {
65+
override fun deleteOnExit(): Unit =
6166
DeleteOnExitHook.add(uri)
62-
}
6367

64-
override fun exists() = when {
68+
override fun exists(): Boolean = when {
6569
cached -> cache.exists
6670
else -> uri.exists(context)
6771
}
6872

6973
override fun getAbsoluteFile() = canonicalFile
7074
override fun getAbsolutePath() = canonicalPath
7175

72-
override fun getCanonicalFile() = uri.toFile(context)
73-
override fun getCanonicalPath() = canonicalFile?.canonicalPath
76+
override fun getCanonicalFile(): File? = uri.toFile(context)
77+
override fun getCanonicalPath(): String? = canonicalFile?.canonicalPath
7478

75-
override fun getName() = uri.name
76-
override fun getPath() = uri.path
79+
override fun getName(): String? = uri.name
80+
override fun getPath(): String? = uri.path
7781

78-
override fun getFreeSpace() = kotlin.runCatching {
82+
override fun getFreeSpace(): Long = kotlin.runCatching {
7983
canonicalFile?.freeSpace
8084
}.getOrNull() ?: throw UnsupportedOperationException()
8185

82-
override fun getTotalSpace() = kotlin.runCatching {
86+
override fun getTotalSpace(): Long = kotlin.runCatching {
8387
canonicalFile?.totalSpace
8488
}.getOrNull() ?: throw UnsupportedOperationException()
8589

86-
override fun getUsableSpace() = kotlin.runCatching {
90+
@SuppressLint("UsableSpace")
91+
override fun getUsableSpace(): Long = kotlin.runCatching {
8792
canonicalFile?.usableSpace
8893
}.getOrNull() ?: throw UnsupportedOperationException()
8994

90-
override fun hashCode() =
95+
override fun hashCode(): Int =
9196
uri.hashCode()
9297

93-
override fun equals(other: Any?) =
98+
override fun equals(other: Any?): Boolean =
9499
this.hashCode() == other.hashCode()
95100

96101
override fun isAbsolute() = true
@@ -100,18 +105,36 @@ abstract class SAFileX : FileX {
100105
else -> uri.isDirectory(context)
101106
}
102107

103-
override fun isFile() = !isDirectory
108+
override fun isFile(): Boolean = !isDirectory
104109

105-
override fun isHidden() = name?.startsWith('.') ?: false
110+
override fun isHidden(): Boolean = name?.startsWith('.') ?: false
106111

107-
override fun lastModified() = when {
112+
override fun lastModified(): Long = when {
108113
cached -> cache.lastModified
109114
else -> uri.lastModified(context)
110115
} ?: 0L
111116

112-
override fun length() = when {
117+
override fun length(): Long = when {
113118
cached -> cache.length
114119
else -> uri.length(context)
115120
} ?: 0L
116121

122+
override fun setExecutable(executable: Boolean) = throw UnsupportedOperationException()
123+
override fun setExecutable(executable: Boolean, ownerOnly: Boolean) = throw UnsupportedOperationException()
124+
override fun setLastModified(time: Long) = throw UnsupportedOperationException()
125+
override fun setReadOnly() = throw UnsupportedOperationException()
126+
override fun setReadable(readable: Boolean) = throw UnsupportedOperationException()
127+
override fun setReadable(readable: Boolean, ownerOnly: Boolean) = throw UnsupportedOperationException()
128+
override fun setWritable(writable: Boolean) = throw UnsupportedOperationException()
129+
override fun setWritable(writable: Boolean, ownerOnly: Boolean) = throw UnsupportedOperationException()
130+
131+
@RequiresApi(26)
132+
override fun toPath(): Path? =
133+
canonicalFile?.toPath()
134+
135+
override fun toString(): String =
136+
uri.toString()
137+
138+
override fun toURI(): URI = URI(uri.toString())
139+
117140
}

library/src/main/java/xyz/quaver/io/TreeFileX.kt

+21-7
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class TreeFileX : SAFileX {
3939
}
4040

4141
constructor(context: Context, parent: Uri, child: String, cached: Boolean)
42-
: this(context, parent.getChildUri(child), cached)
42+
: this(context, parent.getChildUri(child), cached)
4343

4444
constructor(context: Context, uri: Uri, cached: Boolean) : super(uri.path.let {
4545
it ?: throw NullPointerException("URI path should not be null")
@@ -74,11 +74,13 @@ class TreeFileX : SAFileX {
7474
uri.displayName
7575
} ?: throw Exception("Unable to get name from Uri")
7676

77-
return uri.parent?.create(context, mimeType ?: "application/octet-stream", name) != null
77+
return uri.parent?.create(context, mimeType ?: "application/octet-stream", name)?.let {
78+
this.uri = it
79+
} != null
7880
}
7981

8082
override fun getParent() =
81-
uri.parent.toString()
83+
uri.parent?.toString()
8284

8385
override fun getParentFile() = uri.parent?.let { parent ->
8486
FileX(context, parent, cached)
@@ -125,17 +127,29 @@ class TreeFileX : SAFileX {
125127

126128
val name = this.name ?: return false
127129

128-
return uri.parent?.create(context, DocumentsContract.Document.MIME_TYPE_DIR, name) != null
130+
return uri.parent?.create(context, DocumentsContract.Document.MIME_TYPE_DIR, name)?.also {
131+
this.uri = it
132+
} != null
129133
}
130134

131135
override fun mkdirs(): Boolean {
132136
if (uri.exists(context))
133137
return false
134138

135-
if (parentFile?.mkdirs() != true)
136-
return false
139+
return (this.parentFile?.let {
140+
(it.mkdirs() || it.exists()) && mkdir()
141+
}) ?: false
142+
}
143+
144+
override fun renameTo(dest: File): Boolean {
145+
if (dest !is SAFileX)
146+
throw UnsupportedOperationException("dest should be SAFileX")
147+
148+
val name = dest.name ?: throw Exception("Unable to get name from Uri")
137149

138-
return mkdir()
150+
return DocumentsContract.renameDocument(context.contentResolver, this.uri, name)?.also {
151+
this.uri = it
152+
} != null
139153
}
140154

141155
}

0 commit comments

Comments
 (0)