I have an app on both the App Store (iOS - Swift) and Play Store (Android - Java). The app uses UserDefaults.standard for iOS and SharedPreferences for Android to store a few settings.
Both of these implementations work perfectly. The apps can be launched and quit hundreds of times over the course of months and all settings persist.
When I push an update to the stores and install the updates on several devices, the settings are deleted. From what I have read online, UserDefaults and SharedPreferences are supposed to persist between app updates and should only be deleted when the app is uninstalled. However, this is not the case for me. I have also found several posts regarding this issue on many different sites (including this one) but there is never an answer.
Is there some sort of setting, flag, code, or anything else that needs to be set (or not set) in order to ensure that UserDefaults and SharedPreferences persist after an app update?
Are UserDefaults and SharedPreferences what I should be using for this purpose? If not, what should I be using? I have already tried to save a serialized object to file and an xml file but those were deleted after an app update as well. (See: File Deleted After Update)
I do not need any security for these settings. I just need a robust way to have the settings persist between app updates.
Here is the relevant code for iOS followed by Android. After an app update, the tutorial screen is always shown. All other settings are also defaults.
class Settings {
static let shared = Settings()
var tutorialShown = false
private init() {
let defaults = UserDefaults.standard
if defaults.value(forKey: "tutorialShown") == nil {
defaults.set(false, forKey: "tutorialShown")
}
tutorialShown = defaults.bool(forKey:"tutorialShown")
//other settings omitted for brevity
}
func save() {
let defaults = UserDefaults.standard
defaults.set(tutorialShown, forKey:"tutorialShown")
//other settings omitted for brevity
}
}
//somewhere in the code
Settings.shared.tutorialShown = true
Settings.shared.save()
//somewhere in the code
if(Settings.shared.tutorialShown) {
sceneName = "TitleScene"
} else {
sceneName = "WelcomeScene"
}
//And for Android
public class Settings {
//instance
private static Settings instance;
private static Lock instanceLock = new ReentrantLock();
public boolean tutorialShown;
public static Settings getInstance() {
instanceLock.lock();
try {
if (instance == null) {
instance = new Settings();
}
return instance;
} finally {
instanceLock.unlock();
}
}
private Settings() {
Preferences prefs = Gdx.app.getPreferences("packageNameHere");
tutorialShown = prefs.getBoolean("tutorialShown", false);
//other settings omitted for brevity
}
public void save() {
Preferences prefs = Gdx.app.getPreferences("packageNameHere");
prefs.putBoolean("tutorialShown", tutorialShown);
prefs.flush();
}
}
//somewhere in the code
Settings.getInstance().tutorialShown = true;
Settings.getInstance().save();
//somewhere in the code
if(Settings.getInstance().tutorialShown) {
this.setScreen(new TitleScreen(this));
} else {
this.setScreen(new WelcomeScreen(this));
}
-
Even though you referenced a prior post, please restate that you are using libGDX and add in any additional info about frameworks/libraries used. If it was working for you in a published app, update your post to include what version of libGDX was in that version and what version are you using now. Have you created a "hello world" type app/game for testing saving preferences locally and does that work?Morrison Chang– Morrison Chang2025年02月21日 02:38:58 +00:00Commented Feb 21, 2025 at 2:38
-
The reason I didn't include these details is because the app works perfectly. It has been on the app store (and play store) for years and there have been no issues. I and other users have ran the app hundreds of times. The problem only occurred after I published an update. The update did not change any LIBGDX versions or any code. I use SpriteKit in the iOS version. The only thing that changed in the update was level data. The fact that the issue only occurs after the app has been updated (through the app and play stores) make me think I have some sort of app configuration issue somewhere.Roguetroop– Roguetroop2025年02月22日 21:28:30 +00:00Commented Feb 22, 2025 at 21:28
-
Thx for the info. I would still list out the LIBGDX version and prior platform target API versions in which it was working for future readers. If the only changes were to app level data and platform target then the only common is your code. On Android with adb you can test fresh install vs upgrade which should preserve app data: stackoverflow.com/q/39842874/295004 I would build the old working version, install and then upgrade via adb. Use a diff tool on your code between old and new, and check your initial/startup code again to see how it handles low space file storage cases.Morrison Chang– Morrison Chang2025年02月23日 00:04:17 +00:00Commented Feb 23, 2025 at 0:04