PreferenceFragment NullPointerException - java

public class MyPrefs extends PreferenceActivity {
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyPreferenceFragment frag = new MyPreferenceFragment();
getFragmentManager().beginTransaction().replace(android.R.id.content, frag).commit();
Preference pref;
pref = frag.findPreference("pref_gps_updates");
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
});
}
}
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.preference.Preference.setOnPreferenceChangeListener(android.preference.Preference$OnPreferenceChangeListener)' on a null object reference
I don't understand why I get this crash or what I am doing wrong?
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<EditTextPreference
android:key="pref_gps_updates"
android:inputType="number"
android:title="#string/pref_gps_updates"
android:summary="#string/pref_gps_updates_summary"
android:defaultValue="60" />
</PreferenceScreen>

Preference pref;
pref = frag.findPreference("pref_updates");
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
});
Put this part into your Fragment's onCreate() (NOT in the activities onCreate) and double check if the key pref_updates is used in your xml.
Update:
public class MyPrefs extends PreferenceActivity {
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
Preference pref;
pref = findPreference("pref_gps_updates");
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
});
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyPreferenceFragment frag = new MyPreferenceFragment();
getFragmentManager().beginTransaction().replace(android.R.id.content, frag).commit();
}
}

Instead of creating a PreferenceChangedListener for each preference, it would be better to just have your PreferenceFragment implement the OnSharedPreferenceChangeListener interface.
That way, no matter how many preferences you add, you won't need to add a new listener for each one, and the logic is self-contained in the PreferenceFragment.
It would be something like this:
public class MyPrefs extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyPreferenceFragment frag = new MyPreferenceFragment();
getFragmentManager().beginTransaction().replace(android.R.id.content, frag).commit();
/* remove all of this
Preference pref;
pref = frag.findPreference("pref_gps_updates");
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
});
*/
}
public static class MyPreferenceFragment extends PreferenceFragment
implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("pref_gps_updates")) {
//do something
}
}
}
}

In code you use
pref = frag.findPreference("pref_updates");
but in xml it says
android:key="pref_gps_updates"
change keys need to match to be found.

Try and move the code up before you do the fragment transaction.
MyPreferenceFragment frag = new MyPreferenceFragment();
Preference pref;
pref = frag.findPreference("pref_gps_updates");
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
});
getFragmentManager().beginTransaction().replace(android.R.id.content, frag).commit();
}
}

Related

How do I update the settings display after using external method to change setting

I need to update the Settings display after executing code that changes one of the settings. I can change the preference, but it doesn't update in the display until I leave and come back.
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
final Preference btnLexicon = findPreference("lexicon");
btnLexicon.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
selectLexicon();
return true;
}
});
btnLexicon.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.setSummary(newValue.toString());
return true;
}
});
bindPreferenceSummaryToValue(findPreference("lexicon"));
}
The external method operates with an alert dialog and then update the setting accordingly.
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
SharedPreferences.Editor prefs = settings.edit();
prefs.putString("lexicon", LexData.getLexName());
prefs.apply();
I've tried the suggestion to use
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
}
and
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if ("lexicon".equals(key))
sharedPreferences.getString("lexicon", LexData.getLexName());
}
The solution was to recreate the Settings activity
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if ("lexicon".equals(key))
recreate();
}
You need to actually do something with that String you retrieve in the OnSharedPreferenceChangeListener.
if ("lexicon".equals(key))
findPreference(key).setSummary(sharedPreferences.getString("lexicon", LexData.getLexName()));

Initialize common view in base Activity class

I have a parent activity NavigationActivity and it does something like this:
public class NavigationActivity extends Activity {
protected LinearLayout navigationBar;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
navigationBar = findViewById(R.id.navbar);
}
}
It has one method that sets the visibility of navigationBar:
#Override
protected void setNavbarVisibility(int view) {
if (this.navigationBar != null) {
this.navigationBar.setVisibility(view);
}
}
I have an activity AdventureActivity that extends NavigationActivity:
public class AdventureActivity extends NavigationActivity {
EditText title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstancState);
renderAdventureLayout();
}
public void renderAdventureLayout() {
Handler h = new Handler();
title.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(final View v, boolean hasFocus) {
if (hasFocus) {
h.postDelayed(new Runnable() {
#Override
public void run() {
setNavbarVisibility(View.GONE);
}
}, 200);
} else {
h.postDelayed(new Runnable() {
#Override
public void run() {
setNavbarVisibility(View.VISIBLE);
}
}, 200);
}
}
}
}
}
Now, I didn't have to declare or initialize navigationBar in AdventureActivity, and it's already initially visible. However, the statement setNavbarVisibility(View.GONE); doesn't seem to work in AdventureActivity unless I also initialize navigationBar as it was initialized in NavigationActivity because according the debugger, navigationBar was null when it wasn't initialized in AdventureActivity. I find it redundant having to initialize navigationBar in both activities.
You haven't provided a content view in either of your activities, which results findViewById() method to return null.
If you want to create such an activity hierarchy, that means, that NavigationActivity should have an abstract method, that subclasses should implement:
public abstract class NavigationActivity extends Activity {
...
#LayoutRes
protected abstract int getLayoutId();
}
Then AdventureActivity would become:
public class AdventureActivity extends NavigationActivity {
...
#Override
#LayoutRes
protected int getLayoutId() {
return R.layout.some_activity;
}
}
Now in NavigationActivity#onCreate():
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
navigationBar = findViewById(R.id.navbar);
}
This mandates each of subclasses to provide a layout, where exists a LinearLayout with id navbar, otherwise your navigationBar would end up being null.

How To Get Reference of EditTextPreference in my MainActivity?

I am trying to take the value from my edittextpreference and change the font size of the textviews in my mainActivity layout. Please help me with this guys.I must be doing some silly mistake.Help would be appreciated.
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView txt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sp= PreferenceManager.getDefaultSharedPreferences(this);
String str=sp.getString("editTextPref","50");
if(sp!=null)
{
Toast.makeText(this,"String value is "+str,Toast.LENGTH_LONG).show();
txt=(TextView) findViewById(R.id.textView);
txt.setTextSize(Float.parseFloat(str));
}
Toast.makeText(this,"String value is :"+str,Toast.LENGTH_LONG).show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int items=item.getItemId();
switch(items)
{
case R.id.setting:
Toast.makeText(this,"Settings Clicked",Toast.LENGTH_LONG).show();
finish();
Intent i=new Intent(this,Prefs.class);
startActivity(i);
break;
}
return super.onOptionsItemSelected(item);
}
}
Prefs.java
public class Prefs extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
SharedPreferences sp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
// show the current value in the settings screen
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
initSummary(getPreferenceScreen().getPreference(i));
}
}
#Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key));
}
private void initSummary(Preference p) {
if (p instanceof PreferenceCategory) {
PreferenceCategory cat = (PreferenceCategory) p;
for (int i = 0; i < cat.getPreferenceCount(); i++) {
initSummary(cat.getPreference(i));
}
} else {
updatePreference(p);
}
}
private void updatePreference(Preference p)
{
if(p instanceof EditTextPreference)
{
EditTextPreference editTextPreference=(EditTextPreference) p;
p.setSummary(editTextPreference.getText());
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
this.finish();
startActivity(new Intent(Prefs.this,MainActivity.class));
Toast.makeText(this,"Pref activity finished",Toast.LENGTH_LONG).show();
}
}
Prefs.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:enabled="false"
android:key="settingCategory"
android:title="Settings"
>
</PreferenceCategory>
<EditTextPreference
android:id="#+id/editTextPref"
android:dialogMessage="I am Dialog Message"
android:dialogTitle="Dialog Title"
android:hint="e.g 25"
android:icon="#mipmap/ic_launcher"
android:key="fontSize"
android:padding="5dp"
android:selectAllOnFocus="true"
android:singleLine="true"
android:summary="Changes Font Size of Overall App"
android:title="Change Font Size" />
</PreferenceScreen>
You should be reading value for key fontSize not the name of id field of EditTextPreference. Change your code in your MainActivity like this:
SharedPreferences sp= PreferenceManager.getDefaultSharedPreferences(this);
String str=sp.getString("fontSize","50");

fetch value of a Widget in an activity from another Java file in android

How should I fetch value of a Checkbox which is in an Activity and in its onCreate there is findviewbyId method.
public class abc extends Activity {
Checkbox mon;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
}
public boolean check()
{
if (mon.isChecked())
return true;
else
return false;
}}
Now, there is another java class, in which I am passing the activity class object and calling that method which returns the value.
abc a =new abc();
a.check();
But it is not working. I think there is problem with findviewbyid statement.
And also, if the acitivity is not being opened , I want it to show the defualt value which I set in the xml file
android:checked="false"
Set a static variable and assign the value of CheckBox:
public class abc extends Activity {
Checkbox mon;
public static boolean checkBoxValue; //here
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
}
public boolean check()
{
if (mon.isChecked())
checkBoxValue = true; //here
return true;
else
checkBoxValue = false; //here
}}
Another class:
public class AnotherClass {
.....
public boolean value = abc.checkBoxValue;
.......
}
Another way
abc Activity:
public boolean check()
{
if (mon.isChecked())
Intent intent = new Intent(this, anotherClass.class);
intent.putExtra("value", true);
startActivity(intent);
return true;
.....
.......
another Activty:
public class AnotherClass extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.anotherclass);
boolean value = getIntent().getBooleanExtra("value");
}
}
Boolean with static modifier would be enough for your case.
public static boolean monValue = false // as you mention the default is false
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
mon.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton btn, boolean b) {
monValue = b;
}
});
}
Then you just need to boolean x = abc.monValue in other class.
But I really want to suggest another way to communicate between class within android lifecycle.
With EventBus
Create class that wraps event data
public class MyCheckboxEvent {
public final boolean checked;
public MyCheckboxEvent(boolean checked) {
this.checked = checked;
}
}
Then add EventBus.getDefault().post(new MyCheckboxEvent(booleanValue)); on you abc activity
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
mon.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton btn, boolean b) {
EventBus.getDefault().post(new MyCheckboxEvent(b));
}
});
}
Add the handler on any class that subscribe the abc Checkbox event data
#Subscribe
public void handleMyAbcCheckbox(MyCheckboxEvent event) {
boolean x = event.checked;
}
Then register and unregister the subscriber according to the lifecycle
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}

Activity.this cannot be referenced from a static context

Well, the question is something which is similar to already asked questions on the forum but I couldn't find a suitable answer to my problem.My usersettingactivity class-
public class UserSettingActivity extends PreferenceActivity implements View.OnClickListener,
SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen screen = getPreferenceScreen();
PreferenceCategory langCategory=(PreferenceCategory)findPreference("change_lang");
if(PrefSettings.getInstance().getUserCountry().equalsIgnoreCase("NA"))
screen.removePreference(langCategory);
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
LayoutInflater.from(this).inflate(R.layout.user_preference_layout, root, true);
Toolbar toolbar = (Toolbar) root.findViewById(R.id.toolbar);
toolbar.setNavIconClickListener(this);
TextView version = (TextView) root.findViewById(R.id.build_version);
version.setText("v" + BuildConfig.VERSION_NAME);
getFragmentManager().beginTransaction().replace(R.id.fragment, new MyPreferenceFragment()).commit();
}
#Override
public void onClick(View v) {
finish();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
AppTracker.btnClicked(key);
if ("prefNotification".equals(key)) {
Utils.configureServiceAlarm(this);
}
}
public static class MyPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
#Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference.getKey().contains("whitelist_paths")) {
startActivity(new Intent(getActivity(), FolderChooserActivity.class));
}
if(preference.getKey().contains("change_language"))
LanguageDialog languageDialog=new LanguageDialog(UserSettingActivity.this); //Here is the problem
languageDialog.langDialogFragment();
return true;
}
}}
My LanguageDialog class-
public class LanguageDialog {
private Activity a = null;
HashMap<String, String> lang;
public LanguageDialog(Activity activity){
a=activity;
}
public void langDialogFragment()
{
lang = new HashMap<String, String>();
lang.put("English","en");
lang.put("Bengali","bn");
lang.put("Hindi","hi");
lang.put("Kannada","kn");
lang.put("Marathi","mr");
lang.put("Tamil","ta");
lang.put("Telugu","te");
final CharSequence[] inlang = {"English","Hindi","Bengali","Kannada","Marathi","Tamil","Telugu"};
AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(a, R.style.AlertDialog));
builder.setTitle(R.string.select_language)
.setIcon(R.mipmap.ic_launcher)
.setSingleChoiceItems(inlang, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String lang_code=lang.get(inlang[which].toString());
Logger.d(inlang[which].toString());
updateLocale(lang_code);
}
})
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Utils.navigateToActivity(a);
a.finish();
}
})
.show();
}
public void updateLocale(String lang)
{
Locale locale;
if(lang.equalsIgnoreCase("en")) {
locale = new Locale(lang,"US");
PrefSettings.getInstance().setUserlanguage(lang);
}
else {
locale = new Locale(lang,"IN");
PrefSettings.getInstance().setUserlanguage(lang);
}
Logger.d(lang);
Locale.setDefault(locale);
Configuration config = a.getResources().getConfiguration();
config.locale = locale;
a.getBaseContext().getResources().updateConfiguration(config,
a.getBaseContext().getResources().getDisplayMetrics());
} }
The problem is occurring in the UserSettingActivity where I am not able to create a object of LanguageDialog in the fragment class. It is showing the error -
UserSettingActivity cannot be referenced from a static context. I have already tried all the possible answers to the questions similar to this problem but none could help me out.Thanks in advance for the help!
You can try getActivity() instead of using .this
your
MyPreferenceFragment is static, you cannot refer a non- static class from static fragment
public static class MyPreferenceFragment extends PreferenceFragment remove static from here

Categories