Skip to content

Add UserDefaults.setStandardUserDefaults for Android #5206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

marcprux
Copy link

@marcprux marcprux commented May 5, 2025

This PR adds UserDefaults.setStandardUserDefaults(UserDefaults) to provide the ability for a platform to override the standard defaults.

The existing Linux-specific defaults system doesn't work well on Android, whose "defaults" system are handled by the SharedPreferences Java class in the Android SDK. Rather than adding a JNI bridge here just for an Android-specific implementation, this PR takes the simpler route of just exposing the ability to override the standard user defaults with a public setter, which can be called at initialization time.

@compnerd
Copy link
Member

compnerd commented May 5, 2025

This is adding new API, so I think that this might need a Foundation evolution proposal.

@parkera
Copy link
Contributor

parkera commented May 5, 2025

Is this just emblematic of some larger issue about compatibility of UserDefaults with Android in general?

I don't know as much about it as I would like, so I'm unclear on how this API would be used, who is supposed to call it and when, and other details. In general we try very hard not to expose a platform-specific workaround if we can avoid it.

@marcprux
Copy link
Author

marcprux commented May 5, 2025

Is this just emblematic of some larger issue about compatibility of UserDefaults with Android in general?

The issue is that the file-based Linux implementation — even if it were working — is simply not correct for Android. Android apps expects that user preferences be stored using the SharedPreferences Java API, which is part of the Android SDK. Developers expect to be able to interoperate between the preferences that are used by Java/Kotlin dependencies and those set by Foundation.

I don't know as much about it as I would like, so I'm unclear on how this API would be used, who is supposed to call it and when, and other details.

Many Foundation operations won't work on Android until a series of bootstrapping operations take place. These involve fixing the TimeZone, setting up the FileManager paths application home and cache paths, register custom protocols to handle loading assets from the APK, etc. You can see discussion about this from 2019 on the forums, and you can see the gory details of how Skip does it at AndroidBridgeBootstrap.swift .

This would be one more step in that bootstrapping process: it would call something like UserDefaults.setStandardUserDefaults(BridgedAndroidSharedPreferences()).

Skip currently works around this by having the plugin generate a file with typealias UserDefaults = AndroidUserDefaultsBridge, but that only works when the Swift package has a dependency on Skip.

In general we try very hard not to expose a platform-specific workaround if we can avoid it.

We could always make it available to everyone, since I can imagine that other platforms might have the same need. E.g., Windows might want a UserDefaults that is backed by ApplicationData.LocalSettings. WASM might be able to save their defaults using local storage, etc. But I didn't want to make this into a whole proposal, since it's just a thing that we need for Android right now.

@parkera
Copy link
Contributor

parkera commented May 13, 2025

In the long run, do we want Foundation to use the swift-java bridge to just call into SharedPreferences directly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants