Saving switch button state isn't working - android

I have a switch button for setting the sound of the app On and OFF, although it works normally but when I close the app then open it again.. the switch becomes false automatically..!?
I've tried to save the last state via Shared Preference library Hawk , but it not clear to me how to do it right.!?
That's when I've tried to use Hawk
// ....
bool soundON = Hawk.get("sound"); // NPE !!!
if (soundON) {
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(false);
soundSwitch.setSelected(false);
}
soundSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
isSoundEnabled = true;
Hawk.put("sound", true);
} else {
isSoundEnabled = false;
}
Log.i("is checked sound", isChecked + "");
}});
UPDATE - Solution
I used #Shrikant answer, but with just a small change.! I used Boolean instead boolean so I can check for null values which Boolean allows you to do since it can be true or false or null unlike boolean which can be either true or false.
Here's the code
Boolean isSound = Hawk.get("sound");
if (isSound == null) {
// I want the sound to be ON by default so I set it to true
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(isSound);
soundSwitch.setSelected(isSound);
Log.i("Sound State > ", isSound + "");
}

Try this
In onCreate() init that Hawk
Hawk.init(context).build();
after this get your sound value from Hawk and set it to switch
boolean isSound = Hawk.get("some",false);
soundSwitch.setChecked(isSound);
soundSwitch.setSelected(isSound);
there is not to check boolean by if else
soundSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.i("is checked sound", isChecked + "");
Hawk.put("sound", isChecked);
}
});
I have used 2.0.1 version of Hawk.

In onCreate() method you have to check isSoundEnabled from shared preference whether you checked it from your local variable.
try this:
bool soundValue = Hawk.get("sound");
if (soundValue) {
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(false);
soundSwitch.setSelected(false);
}
instead of :
if (isSoundEnabled) {
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(false);
soundSwitch.setSelected(false);
}
in onCreate()

You should save the check state at the time of the setOnCheckedChangeListener call. And get the check state at the time of the onCreate call.

Related

how to verify if checkbox is checked in android studio?

i would like to implement some code under the condition checkbox is checked or not, here is my code:
CheckBox checkBox=findViewById(R.id.checkBox);
if(checkBox.isChecked()){
Log.v("checked","true");
spin.setVisibility(View.VISIBLE);
montant2.setVisibility(View.VISIBLE);
txtVw.setVisibility(View.VISIBLE);
try {
auth3();
} catch (JSONException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
normally i should be able to view the log inside the if condition but nothing appears.
Is the Check Box checked by default? when does the code run?
you're only printing a log when the checkBox is checked, but you won't get any log if the statement is false.
Try to add this line before your if statement:
checkBox.setChecked(true);
If you're getting the log after adding this line, it means that your checkbox is not checked when running the code.
EDIT:
You're running the code in the OnCreate method where the checkBox.getChecked() is set to false by default. To make it work, you need to create a listener that will run the code every time that the checkBox is checked.
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b) {
// Everytime you check the checkBox, the following code will execute:
// Your code here //
}
}
});
Instead of Log, you can use one boolean variable to identify like:
Boolean checkbox = false;
CheckBox checkBox=findViewById(R.id.checkBox);
if(checkBox.isChecked()){
checkbox = true;
}else{
checkbox = false;
}
use this code
public void itemClicked(View yourView) {
CheckBox checkBox = (CheckBox)yourView;
if(checkBox.isChecked()){
}
}

How to disable call inside onChecked change conditionally?

I have toggle(Switch) buttons inside my fragment.After coming on the fragment I am reading BLE values and setting the toggle buttons.
#Override
public void sosStatus(boolean sosvalue, BluetoothGattCharacteristic sosCharac) {
if (sosvalue) {
byte[] charValue = sosCharac.getValue();
String valueOfCharInstring = StringUtils.byteToHex(charValue[0]);
Log.d("+++++SosStatus",""+sosCharac.getUuid().toString() + " " + valueOfCharInstring);
if (sosCharac.getUuid().toString().equalsIgnoreCase(BLEConstants._BUTTON_CHARACTERISTIC)) {
if (valueOfCharInstring.equalsIgnoreCase(BLEConstants.EnableCharacInString)) {
setButtonStatus(touchButton,R.id.switch_btn_device_touch,"Enabled");
// touchButton.setChecked(true);
// tvTouchButtonAction.setText("Enabled");
} else if (valueOfCharInstring.equalsIgnoreCase(BLEConstants.DisableCharacInString)) {
setButtonStatus(touchButton,R.id.switch_btn_device_touch,"Disabled");
// touchButton.setChecked(false);
// tvTouchButtonAction.setText("Disabled");
}
}
if (characList.size() > 0) {
gattclientCallBack.readCharacteristicMain(UUID.fromString(characList.remove(characList.size() - 1)));
} else {
useOnCheckedChangeMethod = true;
showProgress(false);
}
} else {
useOnCheckedChangeMethod = true;
showProgress(false);
HandleCharacListData(true,false,"");
}
}
Now since Switch widget is used, what is happening is that when I read the values programatically for first time, it works fine.but when I toggle the button with touch, onCheckChanged is repeatedly getting called as if I set some value, it keeps on calling itself in infinite loop. This is my oncheckchanged code.
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
try {
if (useOnCheckedChangeMethod) {
switch (compoundButton.getId()) {
case R.id.switch_btn_device_touch:
touchButton.setOnCheckedChangeListener(null);
//showProgress(true);
HandleCharacListData(true,false,"");
HandleCharacListData(false,false,BLEConstants.TOUCH_BUTTON_CHARACTERISTIC);
if(characList!=null && characList.size()>0) {
if(b) {
gattclientCallBack.writeCharacteristic(characList.remove(characList.size() - 1), BLEConstants.DisableCharac);
}
else {
gattclientCallBack.writeCharacteristic(characList.remove(characList.size() - 1), BLEConstants.EnableCharac);
}
}
Log.d("Touch++++", "+++");
break;
}
So it continuously keep on toggling as on and off due to the check if(b). :)
what can I do to ensure that the onCheckChange methos only gets called once after the value is set ?
Things that I have also tried
1) Use onClick listener and disable call in oncheckchanged and enable on click.
2) Use onTouch
Thank you :)
That interesting, because inside of setChecked() it actually checks to see if it's in the middle of broadcasting and returns...
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
return;
}
mBroadcasting = true;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
mBroadcasting = false;
}
}
The only solution I know of is un-registering the callback before calling setChecked() and register the callback again after your call returns. This works because the callback isn't called asynchronously but instead, called immediately inside of setChecked().
Hey I got my answer in the link below to a question framed little differently . Thanks to this guy :)
onCheckedChanged called automatically

Android: onPreferenceChange with validation

Quick overview:
I have built validation that works with onPreferenceChanged on a sample project designed just to test settings and how they're saved and such. The functionality is all there and works as I desire it to. I was hoping to be able to move this functionality over into the default generated SettingsActivity class since it appears to provide solid functionality and much needed headers for the expansion of the program.
The code itself I would like to implement is what's been provided below. Very briefly I have a check which decides if a specific verification or not needs to be implemented and if so it attaches the specific one, otherwise it attaches a generic one. I believe this to be a hacky method and would like an alternative if possible.
// Type of verification checking to attach
public void attachOnPreferenceChangedListener(Preference dsp_pref) {
if (dsp_pref.getKey().equals("et_targetPref")) {
attachTargetVerifier(dsp_pref);
} else { // Any non verifier specific is given a generic listen with summary updater
attachGenericVerifier(dsp_pref);
}
}
private void attachGenericVerifier(Preference dsp_pref) {
dsp_pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
updatePrefSummary(preference);
return true;
}
});
}
private void attachTargetVerifier(Preference dsp_pref) {
dsp_pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Pattern dsl_pattern = Pattern.compile(URL_REGEX,Pattern.CASE_INSENSITIVE);
Matcher dsl_matcher = dsl_pattern.matcher(newValue.toString());
if (!dsl_matcher.matches()) {
Toast.makeText(getActivity(), "Invalid URL. Example: http://example.com/target", Toast.LENGTH_LONG).show();
} else if (dsl_matcher.group(1).toLowerCase().endsWith("/target")) {
Toast.makeText(getActivity(), "Preference Saved", Toast.LENGTH_LONG).show();
updatePrefSummary(preference);
return true;
} else if(dsl_matcher.group(2) == null) {
Toast.makeText(getActivity(), "URL must start with 'http://'", Toast.LENGTH_LONG).show();
} else {
}
return false;
}
});
}
What the default SettingsActivity provides is just a simple and straightforward OnPreferenceChange override, which probably means validation checking needs to be integrated here unless a more elegant method exists, in which case I'm all ears:
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone display
// name.
String name = ringtone.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
Appreciate any advice on how this can be done without it becoming unmanageable
The solution, for those interested, while not complete and 100% is to place the small validation block at the top, if validation fails a return false is carried out:
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
///////////////////////////////////////////////////////////////////
// Preference Validation Section
///////////////////////////////////////////////////////////////////
// URL Check: http://whatev.er/targetstore
if (preference.getKey().equals("connect_url")) {
Pattern dsl_pattern = Pattern.compile(URL_REGEX,Pattern.CASE_INSENSITIVE);
Matcher dsl_matcher = dsl_pattern.matcher(stringValue);
if (dsl_matcher.matches() && // Match!
dsl_matcher.group(1).toLowerCase().endsWith("/targetstore")) { // Confirmed validity
Toast.makeText(dsl_context, "Preference Saved", Toast.LENGTH_LONG).show();
} else { // No match - don't save data.
Toast.makeText(dsl_context, "Invalid URL. Example: http://example.com/targetstore", Toast.LENGTH_LONG).show();
return false; // Stops result from saving
}
}
if (preference instanceof ListPreference) {
//List Pref setSummary
} else if (preference instanceof RingtonePreference) {
//Ringtone Pref setSummary
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
There is still an issue whenever the settings are loaded, a "Preference Saved" prompt will be shown. Some check verifying whether data is being read and not set might help solve this, I have no knowledge of such a check however.

Run Service only when on Wifi if user wants to

I made an app whos purpose is to download and set wallpaper in set intervals.
User can choose to do that only when connected to wifi or not.
Relevant code:
mWallpaperButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mSwitchWifi.isChecked()) {
mConnectivity = mConnectionDetector.isConnectedToWifi();
} else {
mConnectivity = mConnectionDetector.isConnectedToInternet();
}
if (mConnectivity) {
my code here
}
The code above works fine for setting the wallpaper the first time.
My problem is, I need the Service to check if the user wants to update wallpaper only over WIFI before doing so. At the moment, wallpaper is updated regardless of mSwitchWifi state. (which is bad, because it can use mobile data and user sometimes doesn't want that.)
I tried running similar Switch code in Service but I can't because it must be called in a UI Thread.
I also tried couple of workarounds and Intent.putExtra but I get exception:
NullPointerException: Attempt to invoke virtual method on a null object reference
Any idea how to check network state in service?
My service code atm:
public static class Service extends IntentService {
public Service() {
super("wallpaperchanger-download");
}
#Override
protected void onHandleIntent(Intent intent) {
if (url == null) {
SharedPreferences sharedPreferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
String getUrl = sharedPreferences.getString(pref_urlKey, null);
if (getUrl != null) {
url = getUrl;
}
}
wm = WallpaperManager.getInstance(this);
try {
InputStream input = new URL(url).openStream();
Log.v(TAG, url);
wm.setStream(input);
input.close();
} catch (Exception e) {
e.printStackTrace();
}
loading = false;
Log.v(TAG, "Service Running Url " + url);
}
}
If you question is how to access the user selection inside a service/runnable/thread then you can use shared preferences to achieve this. So in your case when the user selects the choice for the first time you want to do something like this:
if(mSwitchWifi.isChecked()) { // i guess this is no wifi
SharedPreferences sharedPreferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
Editor editor = sharedPeredences.edit()
editor.putBoolean("isWifi", false)
} else { // guessing this is wifi
SharedPreferences sharedPreferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
Editor editor = sharedPeredences.edit()
editor.putBoolean("isWifi", true)
}
This is this code to check if it is true or false:
mWallpaperButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Boolean isWifi = isWifi()
if (!isWifi) { // i guess this is if not wifi
mConnectivity = mConnectionDetector.isConnectedToWifi();
} else if (isWifi) { // guessing this is wifi
mConnectivity = mConnectionDetector.isConnectedToInternet();
}
}
}
public Boolean isWifi() { // you can call this inside your service
SharedPreferences sharedPreferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
Boolean wifiState = sharedPreferences.getBoolean("isWifi", true)
return wifiState;
}
This is just a very rough implementation to give an idea of how you can do it, you can improve this many ways. For example you could put the if statement thats inside the onClickListener in the isWifi() function and just call isWifi() inside your runnable/thread...
you can set list preferences to auto update functions based on the network ....
You can create separate class to check the connectivity and from that class you can select the preferences like auto update only on wifi or when connected to network or do not auto update ....

if else statement with Checkbox not executing as expected

I have problems when using a CheckBox in an else if statement. I have a CheckBox list like:
cbapel, cbmangga, cbjeruk, cbbelimbing.
when I tick the checkBoxes cbapel, cbmangga, and cbjeruk the result is "2" instead of "4". What's the solution?
if(MainActivity.cbapel.isChecked() && MainActivity.cbbelimbing.isChecked()) {
tx.setText("1");}
else if(MainActivity.cbapel.isChecked() && MainActivity.cbjeruk.isChecked()) {
tx.setText("2");}
else if(MainActivity.cbapel.isChecked() && MainActivity.cbmangga.isChecked()) {
tx.setText("3");}
else if(MainActivity.cbapel.isChecked() && MainActivity.cbmangga.isChecked() && MainActivity.cbjeruk.isChecked()) {
tx.setText("4");}
else {
tx.setText("NOT FOUND");
}
You are really overlooking the simple solution here, by far (assuming you are just counting the number of checked boxes)
int checked = 0;
if (MainActivity.cbapel.isChecked()) {
checked++;
}
if (MainActivity.cbbelimbing.isChecked()) {
checked++;
}
if (MainActivity.cbmangga.isChecked()) {
checked++;
}
if (MainActivity.cbjeruk.isChecked()) {
checked++;
}
if (checked == 0) {
tx.setText("NOT FOUND");
} else {
tx.setText(String.valueOf(checked));
}
If you aren't looking to count the checkboxes, then I think this follows the same logic as what you tried in your question, but accounts for one condition ever being entered.
String value = "";
boolean bool1 = MainActivity.cbapel.isChecked();
boolean bool2 = MainActivity.cbbelimbing.isChecked();
boolean bool3 = MainActivity.cbmangga.isChecked();
boolean bool4 = MainActivity.cbjeruk.isChecked();
if (bool1) {
if (bool3 && bool4) {
value = "4";
} else if (bool3 && !bool4) {
value = "3";
} else if (!bool3 && bool4) {
value = "2";
}
if (value.isEmpty() && bool2) {
value = "1";
}
} else {
value = "NOT FOUND";
}
tx.setText(value.isEmpty() ? "NOT FOUND" : value);
else if(MainActivity.cbapel.isChecked() && MainActivity.cbjeruk.isChecked()) {
Let's look at this...
Is MainActivity.cbapel.isChecked()? Yes
Is MainActivity.cbjeruk.isChecked()? Yes
So this evaluates to true and so it won't check any of the other conditional statements.
There are many different ways for this logic to flow. But, to know what is best for your situation, depends on what these variables actually mean and what you are doing.
The best advice I could give you from what you have provided is to check the most filtered situation first. So...
if(MainActivity.cbapel.isChecked() && MainActivity.cbmangga.isChecked()
&& MainActivity.cbjeruk.isChecked()) {
tx.setText("4");
}
then add the else ifs after that for the other checks.
Also, cricket has a good suggestion in his comment you are checking the same condition every time so you can remove that and wrap it all in one if to remove some duplication.
Use this listener to each check box and set your conditions accordingly
class CheckboxListeners implements CompoundButton.OnCheckedChangeListener {
private CheckBox checkbox;
CheckboxListeners(CheckBox checkbox) {
this.checkbox = checkbox;
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checkbox.setChecked(isChecked);
}
}

Categories

Resources