How to load Shared Preferences on first Application start - android

I'm using an activity called SettingsActivity that extends PreferenceFragmentCompat. When the application starts for the very first time MainActivity, I try to get the preferences through getDefaultSharedPreferences(getApplicationContext()) but without success because they are only loaded when I start the Settings activity.
To prove this, I checked the file shared_preferences.xml and it's filled only when I open the SettingsActivity.
In this sense, how can I force the loading of the preferences in the MainActivity?
MainActivity
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Map<String, ?> allPreferences = getDefaultSharedPreferences(MainActivity.applicationContext).getAll();
Log.d(Class.forName(), allPreferences.isEmpty()); //prints true
Intent intent_settings = new Intent(activityContext, SettingsActivity.class);
startActivity(intent_settings);
}
}
SettingsActivity
public class SettingsActivity extends PreferenceFragmentCompat {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
setPreferencesFromResource(R.xml.preferences, rootKey);
Map<String, ?> allPreferences = getPreferenceManager().getSharedPreferences().getAll();
Log.d(Class.forName, allPreference.isEmpty()); // prints false
}
}

In your activity's onCreate place the following code
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
reference Android Developers Docs

Related

How to create dynamic Splash Screen in Android Studio using Shared Preferences to set TextView

I'm trying to get my Android app's initial screen to update a TextView whenever a SharedPreference is changed in the settings menu, but I'm not sure exactly where to go from here.
This is a method that I added to my initial screen code to see if it would change when the preference was changed in the settings, but it never gets called according to my debugging efforts. Other parts of our application (mainly the search function) call this successfully.
public class initialScreen extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_initial_screen);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
String nameOfPref = "test";
if (key.equals("instance")){
nameOfPref = sharedPreferences.getString("instance","test");
}
TextView tv = (TextView) findViewById(R.id.title);
tv.setText(nameOfPref);
}
// ... plus some other StartActivity(intent) methods that don't matter here
}
Which the preference is set by a different class like this:
public class mySettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
}
}
I guess I'm trying to figure out how to make my initial screen dynamic and 'always listening' for that preference to change.

Apply style setting in Activity immediately

I have an Activity containing a PreferenceFragment. The user can change the app's style (light theme or dark theme) in this Activity. Now I want the change being visible immediately. That means, I want the style of the Activity changing when the user changes the style setting in the PreferenceFragment.
My idea was to listen for the preference change with OnSharedPreferenceChangeListener in the PreferenceFragment and recreate the Activity.
But I do not think this is the right way. So, what is best practice here? Thanks in advance.
UPDATE
Activity:
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadSettings();
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
private void loadSettings() {
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(this);
boolean darkTheme =
sharedPreferences.getBoolean(getText(R.string.pref_theme_key).toString(), false);
if (darkTheme) {
setTheme(R.style.DarkTheme);
}
}
}
PreferenceFragment:
public class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(getText(R.string.pref_theme_key))) {
// recreate Activity
}
}
}
Preferences:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="false"
android:key="#string/pref_theme_key"
android:title="#string/pref_theme" />
</PreferenceScreen>
I think your approach is correct. Listen for that preference change and then recreate your activity.
Editing for more context:
You should be saving this as a light/dark variant in your preferences and then when your activity is created call setTheme based on this before calling setContentView.

Confused on Reading SharedPreferences Without a PreferenceActivity

Because I want an AppCompat Action Bar on all of my settings submenus, I had to implement a workaround and my Settings Activity extends AppCompatActivity, not PreferenceActivity. I'm using a PreferenceFragment in the activity to handle the preferences, and each PreferenceScreen has its own xml file, which the PreferenceFragment switches out for each submenu in the settings. All of this was necessary to get the Action Bar to stay put through all of my submenus.
I'm trying to read a string value from the shared preferences file from within my MainActivity, and I've tried three different methods for getting that information, none of which have worked:
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String btSelectPref = sharedPref.getString(getString(R.string.bt_select_key), "");
,
SharedPreferences sharedPref = getSharedPreferences(name, MODE_PRIVATE);
String btSelectPref = sharedPref.getString(getString(R.string.bt_select_key), "");
and
SharedPreferences sharedPref = getPreferences(MODE_PRIVATE);
String btSelectPref = sharedPref.getString(getString(R.string.bt_select_key), "");
Here is the relevant section of my preferences.xml:
<PreferenceCategory
android:title="Bluetooth"
android:key="pref_bt">
<Preference
android:title="Select Bluetooth Device"
android:key="#string/bt_select_key"
android:defaultValue="0">
</Preference>
</PreferenceCategory>
This should fill the btSelectPref string with a "0", but it's always empty when I test it. I have included PreferenceManager.setDefaultValues(this, R.xml.preferences, false); in onCreate in my MainActivity, so the default values should be set.
I'm not sure which of these methods I should be using since I have multiple resource files for my settings, but none of them seem to be working for me. In the case of getSharedPreferences(name, MODE_PRIVATE), I have no idea what the name parameter should be referencing, since I've never named my shared preferences file.
EDIT: It turns out my issue was not related to getting values from the shared preferences file. I just had the wrong xml tag on the preference I was trying to check the value of. I changed it from a generic <Preference> tag to a <ListPreference> and my code started working with PreferenceManager.getDefaultSharedPreferences().
What you want to do and what you are doing differs. If you just want to put default shared preference for a key then consider this example. If your whole activity has just one shared pref file then you need not specify any name. It will automatically get it.
public MainActivity extends AppCompatActivity {
SharedPreferences mPrefs;
int test;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_counter);
mPrefs = this.getPreferences(Context.MODE_PRIVATE);
test = mPrefs.getInt("pref_bt_select", 0);}
}
For the above example you can define the key and default value in your strings.xml and then you can refer to it while looking for the prefs you want.
Hey I have used AppCompat for my preference screen too.I did this because I wanted to use Vintage Chroma and this was the only way. But I am able to use PreferenceManager.getDefaultSharedPreference() without any errors.
Also if you want to use default shared preferences in the Fragment you can use :
SharedPreferences preferences = this.getActivity().getSharedPreferences("pref", Context.MODE_PRIVATE);
Here is my full code :
public class PreferencesActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new PreferencesScreen())
.commit();
ActionBar toolbar = getSupportActionBar();
if (toolbar != null) {
toolbar.setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
public static class PreferencesScreen extends PreferenceFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_xml);
}
}
}
Here is my code snippet for MAinActivity
Just the initial part where I set the default text theme.
`public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
AutoCompleteTextView mytextview;
public static String[] list;
ArrayList<String> recent = new ArrayList<String>();
public int recent_index = 0;
Menu mMenu;
#Override
protected void onCreate(Bundle savedInstanceState) {
/*Setting default theme.*/
SharedPreferences Sp= PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
int firstRun=Sp.getInt("firstRun",0);
if(firstRun==0)
{
SharedPreferences.Editor editor=Sp.edit();
editor.putInt("paragraphFontColor", Color.parseColor("#ffffff"));
editor.putInt("headingFontColor",Color.parseColor("#DE5246"));
editor.putInt("subheadingFontColor",Color.parseColor("#597d5e"));
editor.putInt("hyperlinksFontColor",Color.parseColor("#A5D8F5"));
editor.putInt("bodyColor",Color.parseColor("#2b2b2b"));
editor.putString("paragraphFont","PrintClearly.otf");
editor.putString("headingFont","PrintBold.otf");
editor.putString("subheadingFont","PrintBold.otf");
editor.putString("hyperlinkFont","PrintBold.otf");
editor.putString("paragraphFontStyle","normal");
editor.putString("headingFontStyle","normal");
editor.putString("subheadingFontStyle","normal");
editor.putString("hyperlinkFontStyle","normal");
editor.putString("actionBarColor","#597d5e");
editor.putString("paragraphFontSize","20px");
editor.putString("headingFontSize","30px");
editor.putString("subheadingFontSize","20px");
editor.putString("hyperlinkFontSize","20px");
editor.putString("firstRun",0);
editor.commit();
}
`

Starting a fragment calls activity's onCreate()

I have an AppCompatPreference SettingsActivity with a PreferenceFragment, like this:
public class SettingsActivity extends AppCompatPreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "activity onCreate called");
setupActionBar();
String userString = getIntent().getStringExtra(LoginActivity.USER);
Log.v(TAG, "UserString: " + userString);
...
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "GeneralPreferenceFragment onCreate called");
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
}
}
}
When I start the app, a LoginActivity authenticates with a server and passes user data (userString) to the SettingsActivity. It then starts a service with that data.
Everything is peachy and the service starts with no problem.
D/SettingsActivity: activity onCreate called
V/SettingsActivity: UserString: {some string of JSON user data}
But then I tap on General Preferences. As soon as I do so, this gets logged:
D/SettingsActivity: activity onCreate called
V/SettingsActivity: UserString: null
Because it logs activity onCreate called instead of GeneralPreferenceFragment onCreate called, it seems like the wrong onCreate() is being called. The app then crashes with a NullPointException trying to start the service with a null user.
I am trying to figure this out. Maybe the entire activity is restarting for some reason? Any suggestions on diagnosing this problem would help.
As your log shows, a new instance of activity is created.
This is the expected behaviour of the PreferenceActivity on a phone. Tablets use a two-pane layout and keep a single activity. But phones start a new activity.
AppCompat behaves the same.
You can however pass more data to the fragment with
public class MySettingsActivity extends PreferenceActivity {
#Override
public void onBuildHeaders(List<Header> target) {
super.onBuildHeaders(target);
// You can build with xml settings that don't depend from UserString
loadHeadersFromResource(R.xml.preferences, target);
// For Settings that depend on UserString:
Header userHeader = new Header();
userHeader.title = ""; // TODO
user.fragment = UserFragment.class;
Bundle args = new Bundle(1);
// TODO Pass a User parcelable instead
args.putString(EXTRA_USER, userString);
userHeader.fragmentArguments = args;
}
}

Using Multiple SharedPreferences in Android

I have an android app with its own SharedPreferences file called "settings.xml". It is stored under res folder:
public class PreferencesActivity extends PreferenceActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(my_package.R.xml.settings);
}
}
I use a library that has its own SharedPreferences file called library_settings.xml:
public class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(library_package.R.xml.library_settings);
}
}
However, when I deploy my app. Only one of them is copied. I am able to use my own settings.xml using:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GlobalApplication.getAppContext());
return prefs.getBoolean("some_key", true);
How do I programmatically access library_settings.xml SharedPreferences values? Also, library_settings.xml is not getting copied to the app folder i.e., /data/PACKAGE_NAME/shared_prefs/

Categories

Resources