content:// access and sandboxed Apple apps lose their security scope. bookmarkData() turns a PlatformFile into bytes you can store, and PlatformFile.fromBookmarkData(bytes) gives the file back, with its access, on the next launch.
Usage
nonWebMain
nonWebMain. bookmarkData() is a suspend function. Bookmark bytes are platform-specific: don’t share them between operating systems or apps.
Restore a bookmark safely
A bookmark breaks when the user deletes the file, revokes your app’s access, or (on path-based platforms) moves it. Handle failure and ask the user to pick the file again. This helper stores one bookmark in your app’s files directory:nonWebMain
resolveBookmarkData returns a BookmarkResolution with the file and two flags:
Refreshing is best effort: the old bytes may still work, and
bookmarkData() can fail if the file disappeared or macOS already revoked access. Use fromBookmarkData when you only need the file.
Platform notes
On Android,
releaseBookmark() releases the persisted URI permission. Android limits how many URI permissions an app can persist, so release the ones you no longer need.
Set up the macOS App Sandbox
FileKit reads your app’s App Sandbox entitlement at runtime. When it is present, FileKit creates security-scoped bookmarks and reports a failure instead of falling back to a bookmark that can’t restore access.1
Enable the sandbox and user-selected file access
Add these entitlements to the signed app:
entitlements.plist
2
Test the packaged app
Entitlements only apply to a signed build. Pick a file, quit, relaunch, and restore the bookmark.
Keep security-scoped access
On iOS and in sandboxed macOS apps, a file outside your container is readable only while its security-scoped access is active. FileKit starts and stops access around its own operations, and keeps it active until returned sources and sinks are closed. Derive files from the restoredPlatformFile with /, resolve(), or list() so they share its access:
nonWebMain
PlatformFile rebuilt from a path string or toKotlinxIoPath() loses that access, and so does one restored by PlatformFileSerializer, which stores only the path. Persist bookmark data instead.
When you hand a file to another library, wrap the call in withScopedAccess. It calls startAccessingSecurityScopedResource() and stopAccessingSecurityScopedResource() for you, and is a no-op on platforms without security scopes:
releaseBookmark() once you are done with a restored bookmark and every file derived from it. Already-open sources and sinks still close cleanly, but new scoped operations then throw a FileKitException.
Upgrading from older versions
Upgrading from older versions
- macOS bookmark format: new bookmarks on macOS (native and JVM) are wrapped in a versioned FileKit format. Unwrapped Kotlin/Native bookmarks and JVM path bytes written by earlier versions remain readable, and
resolveBookmarkDatareportsshouldRefresh = truefor them. - iOS security scope: restored bookmarks now keep the security-scoped URL for the bookmarked item and its descendants, including after a device restart. Stored bookmarks get this behavior without a migration.
- iOS
releaseBookmark(): it was a no-op in FileKit 0.15.0 and 0.16.0 and now releases access. CallingstartAccessingSecurityScopedResource()on a released bookmark throws instead of returningfalse. fromBookmarkDatais not deprecated.resolveBookmarkDatawas added for refresh metadata.
Related
- Directory picker to let users pick a folder worth bookmarking.
- App directories for files your app owns, which need no bookmark.