Does anybody here us a KMP library for Android and...
# multiplatform
d
Does anybody here us a KMP library for Android and iOS/Native that provides file system access? Specifically, being able to load a list of files from a directory and also read/write file streams? I've been trying to use KmpIO but it's not working for me; i.e., it doesn't seem to be able to even read the list of files in a directory.
j
kotlinx.io can do it if you can tolerate its API instability, otherwise Okio.
Both APIs are the same, currently.
๐Ÿ‘ 2
d
Does kotlinx.io build on Okio? That seems to ring a bell, but I may be misremembering.\
j
It is a derivative
A successor
d
Gotcha. So would you say it's preferred over Okio, even given the changing APIs?
j
I would say it's less capable but I like its design changes from Okio. I use it where possible, but sometimes Okio is simply needed due to its maturity.
d
kk, ty. I was just poking around on klibs.io and saw another option: fleeksoft-io, but it seems to be prety new.
Thanks for the input. I appreciate it!
@jw One more question: can you point me to a decent example of kotlinx.io for reading a directory's contents?
d
Perfect! Thanks again!
One more question: does the app need to request or ask for any permissions in the AndroidManifext.xml file? I swapped out KmpIO for KotlinX.io and I'm still not able to read the contents of the download directory (/storage/emulated/0/Download) from my app. I've got the following in AndroidManifest.xml:
Copy code
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="<http://schemas.android.com/apk/res/android>">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
j
Oh yeah support for that has long disappeared. You need to use the storage access framework, not a regular File I/O API
At least that's my understanding. I haven't had to read anything outside an app's private files in like a decade.
d
I'm pretty much a neophyte still WRT Android development. What do I need to do for that?
j
I don't know anything about it beyond its name
So we're on the same page
๐Ÿ™ƒ 1
d
How do you grant permission in your app to read/write files?
j
Support is completely removed unless your app's primary function is as a file manager
d
To be clear, the app isn't using a file picker or anything. It's just going to one directory to load its contents on startup, then uses KfsWatch to reload the directory if any files are added, removed, or modified.
j
If it's just for a debug feature the details are here: https://developer.android.com/training/data-storage/manage-all-files
I know literally nothing about this. I have just googled those two links. I have never read them beyond their titles.
๐Ÿ™Œ 1
I just know of the policy change a few years back and that SAF is the new thing.
d
No, it's more than that. The app is ultimately an OPDS reader that's targeting iOS and Android devices. I've written the parts of the app to manage server details and navigate the OPDS tree. Now I want to have it list the files in a directory so I can then have it download to that directory and load the files.
j
Note that the download directory is specifically called out as unsupported for that API.
d
Hrm, that would be a big cause for what I'm seeing then. Let me try another directory and see if it works.
j
It's a massive privacy hole to allow arbitrary apps to monitor that
d
Fair enough. This code is going to live in the common module for my project, so I'm guessing it can't have anything Android-specific as far as making calls, etc.
Sorry to persist, but even with KotlinX.io I'm not able to read files. I changed the directory to one I created ("/storage/emulated/0/Variant") and copied some files into it. But still when the code tries to read the contents SystemFileSystem.list(Path("/storage/emulated/0/Variant")) returns no files. ๐Ÿ˜ž
But I seem to be able to access the parent directory.
j
It has nothing to do with kotlinx.io. You simply cannot read from that location without going through SAF.
๐Ÿซค 1
d
Is there anything I can use as a reference for KMP for granting my app access to a single directory for it to read and write its files? Someplace where it can store publications pulled from a server?
j
What's wrong with your app's private directories?
p
There's a layer of permission and access I don't think kotlinx.io can't help there. Perhaps look for a more high level library. https://github.com/vinceglb/FileKit Or https://github.com/Wavesonics/compose-multiplatform-file-picker Orhttps://github.com/irgaly/kfswatch
d
I don't know about them. ๐Ÿ˜‰ I'm relatively new to Android development, and am really on the steep part of the learning curve.
๐Ÿ‘ 1
@Pablichjenkov I'm using KfsWatch currently to monitor a directory on this feature branch, but I need to also (re)load the list of files there as the contents change over time.
๐Ÿ‘ 1
j
https://developer.android.com/reference/android/content/Context#getFilesDir() will give you a entire folder tree that you can do whatever you want with
โ˜๏ธ 1
d
Hrm, that's Android specific, though, isn't it? The code I'm using is in the common library for my KMP project, so it needs to be able to read stuff using cross-platform APIs.
d
And, to be clear, I'm not looking for anything to popup a file picker or directory picker, nothing like that. Ultimately I would like the app to have its own directory where it can write and read files, and have it be visible to the user so they can manually copy files into it or delete files from it as need be.
j
"Visible to the user" implies SAF on Android, or something like the documents directory, maybe. 15 years ago you could write wherever you wanted, but no one wants that anymore. It's a privacy disaster. iOS doesn't even have the concept, you have to share in and out of applications period.
โ˜๏ธ 1
d
Hrm, I use an app currently called Chunky that does what I want to do with my project. When I installed it, in my iCloud account, it created a directory named "Chunky" that shows up in the root. I can copy files to it from my MBP and they show up almost immediately in Chunky.
I want to have Variant do the same thing, but on both Android and iOS: create a directory for its content and expose it to the user so they can manually copy publications into it, as well as connect to an OPDS server and download files into it, so Variant can load them for reading.
I'm just trying to figure out how to do that in a cross-platform way so as to not have to maintain two codebases.
j
You cannot
d
Which part?
j
You have to write two codebases and expose it as a single API for the rest of your common code.
It is wildly unlikely there exists anything to magically do that very specific shape of commonization of each platform's file handling mechanisms.
d
I was hoping I could using KotlinX.io or KmpIO to do this. They seem to claim they can provide a cross-platform way of reading and writing files.
j
The problem has nothing to do with reading or writing files, though.
You are interacting with the OS and platform-specific services
d
I mean, ignore the exposing the directory to iCloud: if something can just read the contents of a directory and let me write to it right now would be a good start.
j
Using
getFilesDir()
and
NSHomeDirectory()
will get you that. Just keep in mind that what seems like a simple evolution to "expose to the user" actually is a massive architectural shift because of the modern OS privacy sandboxing landscape.
d
So there's no way I could use KotlinX.io or KmpIO to read a directory's contents and write files across iOS and Android?
j
To the private app file system, yes, you can do that.
Those two APIs will give you the respective paths for each OS, and regular File I/O to those paths will work.
d
"...the private app file system..." sounds like what I'm wanting; i.e., if for now Variant manages the content of that directory then that's good enough for an MVP. Especially if the contents are deleted if the app is removed.
Is there a KMP representation of the app file system?
j
I have no idea. You can pass in the path from platform-specific code to your common code pretty trivially when initializing things, so I'm not sure you really need one.
๐Ÿ‘ 1
d
And that would be where, for Android, using the Context object would provide what I'm wanting?
j
Yes
โค๏ธ 1
d
kk - ty. I'll get to looking into that now.
I appreciate all of your patience with my questions, guys.
๐Ÿ‘ 1
Just wanted to share that I've now had some success with this. Turns out that I was trying to access a directory that I guess isn't available to apps. Using the Context object, I see that the app (on Android at least) is allowed to view files in (for my app) /data/data/org.comixedproject.variant.android
๐ŸŽ‰ 1
d
Looks like kotlinx-io already provides a property that points to a dir you can write to so you don't have to do your own expect/actual: https://github.com/Kotlin/kotlinx-io/blob/master/core/common/src/files/FileSystem.kt#L184-L189
๐Ÿ†’ 1
โœจ 1