0

I'm quite new to Android development, and I've looked at the similar posts but I still can't get this to work. I can't retrieve SharedPreferences when specifying a preference file, which I try to do in PrefFragment and that's where SharedPreferences.getAll().size() returns 0.

src/main/res/xml/things.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
                  xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory app:title="things_category">
        <SwitchPreference
                app:key="thing"
                app:title="thing"
                />
        <Preference
                app:fragment="org.thing.appo.PrefFragment2"
                app:key="more_things_menu"
                android:title="more things menu"/>
    </PreferenceCategory>

</PreferenceScreen>

src/main/res/xml/more_things.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
                  xmlns:android="http://schemas.android.com/apk/res/android">

    <SwitchPreference
            app:key="more_things"
            app:title="more things"
            />
</PreferenceScreen> 

src/main/res/values/strings.xml

<resources>
    <string name="app_name">appo</string>
    <string name="things">things</string>
    <string name="more_things">more_things</string>
</resources>

MainActivity

public class MainActivity extends AppCompatActivity implements
        PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (findViewById(R.id.fragment_container) != null) {
            if (savedInstanceState != null) {
                return;
            }

            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.fragment_container, new PrefFragment())
                    .commit();
        }
    }

    @Override
    public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
        final Fragment fragment = getSupportFragmentManager().getFragmentFactory().instantiate(
                getClassLoader(),
                pref.getFragment());

        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, fragment)
                .addToBackStack(null)
                .commit();
        return true;
    }
}

PrefFragment

public class PrefFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String key) {
        setPreferencesFromResource(R.xml.things, key);
        Map<String, ?> things = getActivity().getSharedPreferences(getString(R.string.things), Context.MODE_PRIVATE).getAll();
        System.out.println("things.size() = " + things.size()); // returns 0

        Map<String, ?> moreThings = getActivity().getSharedPreferences(getString(R.string.more_things), Context.MODE_PRIVATE).getAll();
        System.out.println("moreThings = " + moreThings.size()); // returns 0

        Map<String, ?> all = PreferenceManager.getDefaultSharedPreferences(getActivity()).getAll();
        System.out.println("all.size() = " + all.size()); // But here it returns 2
    }
}

PrefFragment2

public class PrefFragment2 extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String key) {
        setPreferencesFromResource(R.xml.more_things, key);
    }
}
yinder
  • 17
  • 1
  • 7
  • You preferences screen associated with getDefaultSharedPreferences preferences by default, why do you need to have several shared preferences? – Bracadabra Dec 23 '19 at 13:55
  • The code here is simplified, but I want to access preferences from another preference screen because I need to update a few (displayed) values on the original preference screen from a db - and I need to access some settings that are associated with the sub preference screen. Uhm it's likely bad design, but I'd really love to get it working anyway. – yinder Dec 23 '19 at 15:30
  • You can get all your settings from getDefaultSharedPreferences on both screens – Bracadabra Dec 23 '19 at 15:35
  • Yes, but the problem is that, in one method on the first pref screen, I need to iterate the prefs only associated with the sub pref screen. – yinder Dec 23 '19 at 15:57
  • 1
    You can set custom file for preferences http://idlesun.blogspot.com/2012/12/how-to-make-preferenceactivity-use-non.html or just store the list of keys you need to iterate. – Bracadabra Dec 23 '19 at 16:20
  • 1
    "or just store the list of keys you need to iterate." Store lists in SharedPreferences... Oh, forgot to google that THANK YOU!! Found a great answer here https://stackoverflow.com/a/27872280/8120495 suggesting to store lists as JSON strings! That should work in my case! :) – yinder Dec 23 '19 at 17:27

1 Answers1

0

With help from the comments, I googled a bit and found this https://stackoverflow.com/a/27872280/8120495. Problem solved. :)

EDIT: Finally got it working by being able to access preferences from the child PreferencesScreen. Also, I had not really understood how SharedPreferences differs from Preferences and what Preferences gets saved to ShardPreferences. To get only the prefs from the child PreferenceScreen:

PreferenceScreen preferenceScreen = getPreferenceManager().inflateFromResource(getActivity(), R.xml.more_things.xml, null);
int count = preferenceScreen.getPreferenceCount();

for (int i = 0; i < count; i++) {
        String key = preferenceScreen.getPreference(i).getKey();

        //In this case, the child PreferenceScreen only has a single SwitchPreference, so now that we have its key, we can check its value
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        boolean switchValue = sharedPreferences.getBoolean(key, false);
    }
yinder
  • 17
  • 1
  • 7