I am a beginner of the android and I try to making a simple flashlight app with preferences activity. So my problem is; I want to make light and sound settings are optional with checkboxes.
settings.xml
<PreferenceCategory
android:title="#string/sct_behaviour">
<CheckBoxPreference
android:key="pref_light"
android:title="#string/st_pref_light"
android:summary="#string/ss_pref_light"
android:defaultValue="true"
/>
<CheckBoxPreference
android:key="pref_switch_sound"
android:title="#string/st_pref_sound"
android:summary="#string/ss_pref_sound"
android:defaultValue="true"
/>
<CheckBoxPreference
android:key="pref_notification_sound"
android:title="#string/st_pref_notification_sound"
android:summary="#string/ss_pref_notification_sound"
android:defaultValue="true"
/>
settings.java
public class Settings extends PreferenceActivity{
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
CheckBoxPreference pLight = (CheckBoxPreference)getPreferenceManager().findPreference("pref_light");
pLight.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean myValue = (Boolean) newValue;
if(myValue){
}
//NEED SOME HELP IN THERE
return true;
}
});
my turnOnFlash function;
private void turnOnFlash() {
if (!isFlashOn) {
if (camera == null || params == null) {
return;
}
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
isFlashOn = true;
// changing button/switch image
toggleButtonImage();
// play sound
playSound();
}
}
onStart function
#Override
protected void onStart() {
super.onStart();
if(VERBOSE) Log.v(TAG, "++ ON START ++");
// on starting the app get the camera params
getCamera();
turnOnFlash(value);
}
I want to set this true or false value to onStart cycle by the user choice. and don't know how to make this implementation.
if i understand correctly you should get preferences onResume() and act accordingly :
protected void onResume() {
super.onResume();
if(VERBOSE) Log.v(TAG, "++ ON START ++");
// on starting the app get the camera params
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean lightPref = prefs.getBoolean("pref_light", true);
getCamera();
turnOnFlash(lightPref);
}
I think you should use; clicklistener
Preference pLight = (Preference)findPreference("pref_light");
Preference pSwitchSound = (Preference)findPreference("pref_switch_sound");
Preference pNotificationSound = (Preference)findPreference("pref_notification_sound");
pLight.setOnPreferenceClickListener(this);
pSwitchSound.setOnPreferenceClickListener(this);
pNotificationSound.setOnPreferenceClickListener(this);
Related
I want to implement in my app Dark mode. In default I wish it been following by the system, so in Main Activity I've placed:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
It works fine, but I if user wants to change its mind and select certain option in my app menu to toggle off/on dark mode, activity is restarting and app's still following system rules. How can I change that?
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_color_mode) {
if(AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
else
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES);
return true;
}
Code responsible for option you mentioned, is within onCreate(). Mechanism that allows user to change mode is not within onCreate()
public class MainActivityextends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
}
When you explicitly change the dark mode, Android recreates the activity and hence calls onCreate again.
So, after you change the dark mode you won't notice a change, as AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM is called again when onCreate is called by the system.
To make this works you can save a value into SharedPreference that can be checked in onCreate before setting the system dark mode.
This can be a boolean that you can toggle when you want to manually change the dark mode.
Here is a sample
public class MainActivityextends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean isSystem = prefs.getBoolean("IS_SYSTEM", true);
if (isSystem) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_color_mode) {
if(AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
else
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putBoolean("IS_SYSTEM", false).apply();
return true;
}
}
UPDATE
that works perfect, but when I quit application and then launch again, default system mode is active although I've switched it. Is possible here to make it works in that way?
You can use another SharedPreference boolean to be saved permanently
public class MainActivityextends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean isSystem = prefs.getBoolean("IS_SYSTEM", true);
boolean isNight = prefs.getBoolean("IS_NIGHT", false);
if (isSystem) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
} else if (isNight) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_color_mode) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
prefs.edit().putBoolean("IS_NIGHT", false).apply();
} else {
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES);
prefs.edit().putBoolean("IS_NIGHT", true).apply();
}
prefs.edit().putBoolean("IS_SYSTEM", false).apply();
return true;
}
}
I made settings activity from Android Studio, not manually. I want to make a switch that applies a dark mode in the app. The problem is that when I click the switch there is no animation for movement, only a blink from the app. When I go back in my Main Activity I see that the theme is applied(I have tried earlier only with the main activity), but when I try to go back in the settings everything is frozen! Nothing can be clicked, no reaction at all.
This is my Java code:
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
public class SettingsActivity extends AppCompatActivity {
private SwitchPreference darkModeSwitch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
SwitchPreference darkModeSwitch = (SwitchPreference) findPreference("darkmode");
assert darkModeSwitch != null;
darkModeSwitch.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
return false;
}
});
}
}
}
This is root_preferences.xml:
<PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:title="General">
<SwitchPreference
app:key="darkmode"
app:title="Dark mode"/>
</PreferenceCategory>
And this is the Logcat after applying the theme:
avc: denied { getattr } for path="/proc/1" dev="proc" ino=3924 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:r:init:s0 tclass=dir permissive=0
I think that it may be because I have not started the activity again after applying the theme, because when I tried the dark mode in main_activity, there were two lines, which in my settings activity cannot be placed, because the class is static... Please help!
public void onClick(View v) {
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
//These two
finish();
startActivity(new Intent(MainActivity.this, MainActivity.this.getClass()));
}
});
Put this in your preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<SwitchPreferenceCompat
app:defaultValue="false"
app:key="#string/key_night_mode"
app:summaryOff="#string/summary_night_mode_off"
app:summaryOn="#string/summary_night_mode_on"
app:title="#string/title_night_mode" />
</PreferenceScreen>
Then in your SettingsFragment.java which extended PreferenceFragmentCompat inside the onCreatePreference() method:
SwitchPreferenceCompat switchPreferenceCompat = findPreference(getString(R.string.key_night_mode));
switchPreferenceCompat.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = false;
if (newValue instanceof Boolean)
isChecked = (Boolean) newValue;
if (isChecked) {
//these lines so that the preference persists
getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(R.string.key_night_mode), true).apply();
//you do not need to finish and recreate activity
//it takes care of any such things that needs to be done
//automatically
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(R.string.key_night_mode), false).apply();
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
return true;
}
});
These lines of codes are working for me.
Note:
AppTheme should extends from Theme.AppCompat.DayNight or Theme.MaterialComponents.DayNight if you want to be dependent on platform for your night theme. Otherwise, you can create your separate Day and Night theme which extends from Theme.MaterialComponents.Light and Theme.MaterialComponents respectively(AppCompat has similar set of themes too).
Every time the app starts, it needs to respect the user's preferences and start in the user setted theme accordingly. To achieve this, you can check the preference and set theme in the MyApplication class as follows:
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean nightMode = sharedPreferences.getBoolean(getString(R.string.key_night_mode), false);
if (nightMode)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
else {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
else
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
I'm creating a PreferenceFragment based on the developer guide but I get a NullPointerException at the getDefaultSharedPreferences() call in onCreate() when I try to restore saved user preferences. I inflate the PreferenceFragment from xml and I set default values too. The exception is thrown at getDefaultSharedPreferencesName() within getDefaultSharedPreferences().
Here is the PreferenceFragment class:
public class SettingsFragment extends PreferenceFragment implements
OnSharedPreferenceChangeListener {
public static final String KEY_MAX_WALK_DISTANCE_PREFERENCE = "max_walk_distance_preference";
public static final String KEY_MAX_SEARCH_TIME_PREFERENCE = "max_search_time_preference";
Context context = getActivity();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
// load user preferences
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
if (sharedPreferences != null) {
Preference walkDistance = findPreference(KEY_MAX_WALK_DISTANCE_PREFERENCE);
if (walkDistance != null) {
walkDistance.setSummary(sharedPreferences.getString(
KEY_MAX_WALK_DISTANCE_PREFERENCE, "")
+ getResources().getString(
R.string.max_walk_distance_postfix));
}
Preference searchTime = findPreference(KEY_MAX_SEARCH_TIME_PREFERENCE);
if (searchTime != null) {
searchTime.setSummary(sharedPreferences.getString(
KEY_MAX_SEARCH_TIME_PREFERENCE, "")
+ getResources().getString(
R.string.max_search_time_postfix));
}
}
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(KEY_MAX_WALK_DISTANCE_PREFERENCE)) {
Preference walkDistance = findPreference(key);
// Set summary to be the user-description for the selected value
walkDistance.setSummary(sharedPreferences.getString(key, "")
+ getResources().getString(
R.string.max_walk_distance_postfix));
} else if (key.equals(KEY_MAX_SEARCH_TIME_PREFERENCE)) {
Preference searchTime = findPreference(key);
// Set summary to be the user-description for the selected value
searchTime.setSummary(sharedPreferences.getString(key, "")
+ getResources()
.getString(R.string.max_search_time_postfix));
}
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
}
Here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<EditTextPreference
android:dialogTitle="#string/max_walk_distance_dialogtitle"
android:key="max_walk_distance_preference"
android:summary="#string/max_walk_distance_summary"
android:title="#string/max_walk_distance_title"
android:inputType="number"
android:defaultValue="500" />
<EditTextPreference
android:dialogTitle="#string/max_search_time_dialogtitle"
android:key="max_search_time_preference"
android:summary="#string/max_search_time_summary"
android:title="#string/max_search_time_title"
android:inputType="number"
android:defaultValue="10"/>
</PreferenceScreen>
Context context = getActivity();
Your fragment is not associated with any activity when the object is instantiated and getActivity() returns null. Hence the NPE when trying to get preferences with a null Context.
Postpone the getActivity() to e.g. your onCreate() (which is called after onAttach()).
getActivity returns untill onAttach is called. Change
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context)
with
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(getActivity())
When I click the "Settings" page, my CheckBoxPreference shows exactly how I want it to at this stage, however when I select it, the state does not change (i.e. from Unchecked to Checked).
It seems to be retaining the value of false (default) and still running onPreferenceChanged with false as the value passed. I am running code inside my onPreferenceChangedListener that is dependent on the value of the preference that is changed. As it stands I only have one preference in here.
activity_preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceScreen>
<CheckBoxPreference
android:summaryOn="true"
android:summaryOff="false"
android:key="isReg"
android:title="Receive Push Messages"
android:selectable="true"
android:enabled="true"
android:persistent="true" />
</PreferenceScreen>
</PreferenceScreen>
PrefsActivity.java:
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import com.google.android.gcm.GCMRegistrar;
public class PrefsActivity extends PreferenceActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.activity_preferences);
Preference isReg = (Preference) findPreference("isReg");
isReg.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
public boolean onPreferenceChange(Preference pref, Object arg1) {
boolean isReg = getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("isReg", false);
if (isReg){
ServerUtilities.register(getApplicationContext(), GCMRegistrar.getRegistrationId(getApplicationContext()));
}
else {
ServerUtilities.unregister(getApplicationContext(), GCMRegistrar.getRegistrationId(getApplicationContext()));
}
return isReg;
}
});
}
}
You are using the wrong preference widget as per in the code sample,
Preference isReg = (Preference) findPreference("isReg");
It should have been CheckBoxPreference as in
CheckBoxPreference isReg = (CheckBoxPreference) findPreference("isReg");
Edit
One thing I noticed, you're not handling the preference activity properly...consider this code, always, call the preference's commit method in order to save it!
public class PrefsActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener{
CheckBoxPreference isReg;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.activity_preferences);
PreferenceManager.setDefaultValues(this,R.xml.activity_preferences, false);
isReg = (CheckBoxPreference)findPreference("isReg");
if (isReg != null){
isReg.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
#Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
boolean blnIsReg = Boolean.getBoolean(newValue.toString());
Editor e = _prefs.edit();
e.putBoolean("isReg", blnIsReg);
e.commit();
return true;
}
});
}
}
}
#Override
public void onStart(){
super.onStart();
_prefs = PreferenceManager.getDefaultSharedPreferences(this);
}
The listener that is implemented must be in this fashion, which is how the changes are effective:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "onSharedPreferenceChanged; key = " + key);
}
By incorporating the listener, the logcat will show that the preference's key is indeed being changed, i.e. "isReg".
Update the values from the shared preferences in onResume()
method
SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(PrefsActivity.this);
boolean isReg = prefs.getBoolean("isReg", false);
Hope Try This it will help You
I'm writing an app for the Sony Smartwatch, using their SDK. Here's part of the main activity:
class SmartTickerActivity extends ControlExtension {
private Handler mHandler;
SmartTickerActivity(final String hostAppPackageName, final Context context, Handler handler) {
super(context, hostAppPackageName);
if (handler == null) {
throw new IllegalArgumentException("handler == null");
}
}
#Override
public void onStart() {
//do some stuff
PreferenceManager.setDefaultValues(mContext, R.xml.preference, false);
}
The problem is that the saved preferences aren't being applied on the Smartwatch when the application launches. Nor are the default preference values from XML. However, if I click on any of the app's preferences on the phone, the saved preference values are immediately applied to the Smartwatch.
Note that the main class has no onCreate() method, and that's throwing me for a loop.
Here's part of the Preference activity:
public class MyPreferenceActivity extends PreferenceActivity {
private OnSharedPreferenceChangeListener mListener = new OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry().toString());
}
if (pref instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
pref.setSummary(editTextPref.getText().toString());
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preference);
setSummaries();
setTypeface(SmartTickerActivity.mainLayout);
if (previewLayout != null) setTypeface(previewLayout);
// Handle read me
Preference readMe = findPreference(getText(R.string.preference_key_read_me));
readMe.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference readMe) {
showDialog(DIALOG_READ_ME);
return true;
}
});
// Handle about
Preference about = findPreference(getText(R.string.preference_key_about));
about.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference about) {
showDialog(DIALOG_ABOUT);
return true;
}
});
// Handle preview
Preference preview = findPreference(getText(R.string.preference_key_preview_dialog));
preview.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preview) {
showDialog(DIALOG_PREVIEW);
return true;
}
});
}
I'm rather inexperienced at Android development, so the problem might very well have nothing to do whatsoever with the Sony SDK. Can anyone help?
You are correct, the preferences of the official sample extensions are not loaded until the PreferenceActivity is shown for the first time. If you use correct default values when accessing the preferences, this should not be a problem.
If you would like for the preferences to be loaded when the extension is initiated the first time, you could extend the android.app.Application class, and the onCreate method.
For example:
public class MySmartWatchApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
PreferenceManager.setDefaultValues(this, R.xml.app_preferences, false);
}
}