Flutter - How to use shared_preferences and Settings.bundle for iOS (and what about Android?)
Asked Answered
S

2

6

So we have a Flutter app - and it has a bunch of user preferences. To date, we've been using shared_preferences plugin to handle them (like everyone else in Flutter-land). Life was happy.

Now, our iOS users want to see some of these Preferences in the Settings.app area for our Application. Currently, only the system standard ones are showing.

We created (via Xcode) a Settings.bundle file for a couple of new Preferences (before adding the other ones) -- and voila -- we see them in Settings for our app .. However, we are NOT seeing them in the actual Flutter app -- we still only see the "other" preferences that are managed within the app itself.

We basically are doing a "dump" of the Preferences keys and values in debug mode .. and all we see are the ones we've defined in the app..

So two questions:

1) Are we missing something? Looking at the internal code for shared_preferences it appears to use the same "storage" area that Settings.bundle uses .. So why we're not seeing these Settings Preferences in the app is confusing.. yet we're seeing the other ones.

2) What is the equivalent methodology in Android to set app preferences without having to launch the app? One of our preferences only makes sense to set PRIOR to app launch .. and to be honest, I'm just not a prolific Android developer ..

Cheers!

Siegbahn answered 27/2, 2019 at 17:16 Comment(0)
S
6

Here is a partial answer, suitable for iOS only. Still no idea on how to handle this on Android (or if even possible).

If you want to setup Preferences that are viewable and changeable in the Settings app for your application, there is basically one extra step you need to do. The general overall steps are:

-- Create your Flutter Preferences like you normally would. -- Within the iOS folder create a new TOP level folder called "Settings.bundle". There is already one of these at the Runner folder but that's not too useful for us.

-- Within the Settings.bundle folder you need another sub-folder called "en.lproj" (or any other languages you want). Within THAT sub-folder you need a file called "Root.strings".

-- At the same level as the en.lproj is another file called "Root.plist". So the structure looks basically like:

main_app/
    iOS/
        ...
        Settings.bundle/
            en.lproj/
                Root.strings
            Root.plist

Root.plist

Here is where the magic (mostly) lives. As it turns out flutter automatically adds the prefix "flutter." all Preference names you use. That's the secret. So here is a sample of a Root.plist. Note the flutter.XXXX key names!

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>StringsTable</key>
    <string>Root</string>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>Type</key>
            <string>PSGroupSpecifier</string>
            <key>Title</key>
            <string>Data Location</string>
        </dict>
        <dict>
            <key>Type</key>
            <string>PSMultiValueSpecifier</string>
            <key>Title</key>
            <string>Region</string>
            <key>Key</key>
            <string>flutter.dataSourceRegionV2</string>
            <key>DefaultValue</key>
            <string>0</string>
            <key>Titles</key>
            <array>
                <string>US/World</string>
                <string>EU</string>
                <string>Advanced</string>
            </array>
            <key>Values</key>
            <array>
                <integer>1</integer>
                <integer>2</integer>
                <integer>3</integer>
            </array>
        </dict>
        <dict>
            <key>Type</key>
            <string>PSTextFieldSpecifier</string>
            <key>Title</key>
            <string>Server</string>
            <key>Key</key>
            <string>flutter.dataSourceServerURLV2</string>
            <key>DefaultValue</key>
            <string></string>
            <key>IsSecure</key>
            <false/>
            <key>KeyboardType</key>
            <string>URL</string>
            <key>AutocapitalizationType</key>
            <string>None</string>
            <key>AutocorrectionType</key>
            <string>No</string>
        </dict>
    </array>
</dict>
</plist>

Root.strings

This contains the translated strings to use in the Settings file for the app based on the language. It's pretty straightforward. Again, from the same sample:

/* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */

"Data Location" = "Data Location";
"Region" = "Region";
"Server" = "Adv. URL";
"none given" = "none given";
"Authorization" = "Authorization";
"Username" = "Username";
"Password" = "Password";
"Advanced" = "Advanced";
"US/World" = "USA";
"EU" = "European Union";

From within your flutter app you use the normal shared_preferences usage -- just remember to remove the "flutter." prefix from within your application.

Here is a link to a decent article that has more info about iOS settings in general: iOS Settings

Hope this helps and gets you past this little conundrum! Now if we could figure out Android!

Siegbahn answered 28/4, 2019 at 16:15 Comment(0)
S
0

For Android, You'll need to go into the android/app/src/main/res folder and create a folder called xml. once you do that, you'll need to create a preferences.xml file.

Scriabin answered 4/4, 2022 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.