Can anyone tell me what is wrong with this code. For some reason the OnSharedPreferencesChanged is not being called when changing the value. I am trying to check if the PIN entered is equal to 2 digits or no. But for it just doesnt work..
can anyone help me out.
Thanks.!
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.util.Log;
import android.widget.Toast;
public class PrefsActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
EditTextPreference editPreference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
this.editPreference = ((EditTextPreference) getPreferenceScreen()
.findPreference("userPass"));
Log.d("TAG","before sharedPreferenceChanged");
}
#Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Log.d("TAG","In SharedPreferences");
if (sharedPreferences.getString("userPass", null).length() != 2) {
Log.d("TAG","lenght is less than 1");
Toast.makeText(this, "Pin has to be 2 digits only",
Toast.LENGTH_LONG).show();
this.editPreference.setText(null);
return;
} else {
Toast.makeText(this, "Pin set", Toast.LENGTH_LONG).show();
}
// TODO Auto-generated method stub
}
Try setting the setOnPreferenceChangeListener for your editPreference in onCreate(), put your validation code inside this callback.
Reading the docs, they say OnSharedPreferenceChangeListener is called when the shared preference is changed(is already changed). In the other hand the setOnPreferenceChangeListener is triggered "when this Preference is changed by the user (but before the internal state has been updated)"
Related
I'm trying to make a progress bar where i can increase/reset the value and i did that so far, but i want to be able to somehow save the state of where I left off after I leave the application, I need the progress bar's percentage to stay the same even when i quit it, I've read something about on resume methods and shared preferences but I don't really get how to do it and apply it on my own code, any help will be really appreciated, this is my activity's code:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import me.itangqi.waveloadingview.WaveLoadingView;
public class MainActivity extends AppCompatActivity {
WaveLoadingView waveLoadingView;
SeekBar seekBar;
Button increase,restart;
private int prog = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekBar=findViewById(R.id.seekbar);
waveLoadingView=findViewById(R.id.waveloading);
waveLoadingView.setProgressValue(0);
increase=findViewById(R.id.increase);
restart=findViewById(R.id.restart);
increase.setOnClickListener(v -> {
if(prog<=100){
prog+=10;
updateProgressBar();
}
if(prog<50){
waveLoadingView.setBottomTitle(String.format("%d%%",prog)+"you're drinking too little");
waveLoadingView.setCenterTitle("");
waveLoadingView.setTopTitle("");
}else if(prog<80){
waveLoadingView.setBottomTitle("");
waveLoadingView.setCenterTitle(String.format("%d%%",prog)+"You Are Almost There!");
waveLoadingView.setTopTitle("");
}else{
waveLoadingView.setBottomTitle("");
waveLoadingView.setCenterTitle("");
waveLoadingView.setTopTitle(String.format("%d%%",prog)+"\r\n You've Made It!");
}
if(prog==110){
waveLoadingView.setProgressValue(0);
}
});
restart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
waveLoadingView.setProgressValue(0);
waveLoadingView.setBottomTitle("");
waveLoadingView.setCenterTitle("");
waveLoadingView.setTopTitle("");
prog=0;
}
});
}
private void updateProgressBar() {
waveLoadingView.setProgressValue(prog);
}
}
Use the shared preferences file to save the value and you can read it when you reopen the app.
private void updateProgressBar() {
waveLoadingView.setProgressValue(prog);
getSharedPreferences("nameyourfile" , MODE_PRIVATE). edit(). putInt("progress', prog). apply() ;
}
OnResume
int prog = getSharedPreferences("nameyourfile" , MODE_PRIVATE).getInt("progress', yourdefaultvalueprogress) ;
updateProgressBar(prog) ;
I know similar questions have been asked but none of the solutions to those questions have been working for me.
When I go ahead and try to save the state of my app, the state of the EditText views are not being saved and restored. I went ahead and commented everything out and just put in a temporary string to save but when the app loads up again, the onCreate() method does not print 'Restoring instance state'
package com.fwumdesoft.udppacketsender;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* Posts a UDP message with the given data to the
* target address on the target port.
*/
class UdpPostActivity extends AppCompatActivity {
private static final String TAG = "UdpPostActivity";
private static final String stateTextTargetHost = "com.fwumdesoft#TargetHost";
private static final String stateTextTargetPort = "com.fwumdesoft#TargetPort";
private static final String stateTextHexData = "com.fwumdesoft#HexData";
private static final String stateTextStringData = "com.fwumdesoft#StringData";
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_udp_post);
if (savedInstanceState != null) {
// ((EditText) findViewById(R.id.txtAddress)).setText(savedInstanceState.getString(stateTextTargetHost));
// ((EditText) findViewById(R.id.txtPort)).setText(savedInstanceState.getString(stateTextTargetPort));
// ((EditText) findViewById(R.id.txtData)).setText(savedInstanceState.getString(stateTextHexData));
// ((EditText) findViewById(R.id.txtStringData)).setText(savedInstanceState.getString(stateTextStringData));
String text = savedInstanceState.getString(stateTextStringData);
Log.v(TAG, "Restoring instance state");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// outState.putString(stateTextTargetHost, ((EditText)findViewById(R.id.txtAddress)).getText().toString());
// outState.putString(stateTextTargetPort, ((EditText)findViewById(R.id.txtPort)).getText().toString());
// outState.putString(stateTextHexData, ((EditText)findViewById(R.id.txtData)).getText().toString());
// outState.putString(stateTextStringData, ((EditText)findViewById(R.id.txtStringData)).getText().toString());
super.onSaveInstanceState(outState);
outState.putString(stateTextStringData, "test");
Log.v(TAG, "Saved instance state");
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.v(TAG, "onRestore");
// ((EditText)findViewById(R.id.txtAddress)).setText(savedInstanceState.getString(stateTextTargetHost));
// ((EditText)findViewById(R.id.txtPort)).setText(savedInstanceState.getString(stateTextTargetPort));
// ((EditText)findViewById(R.id.txtData)).setText(savedInstanceState.getString(stateTextHexData));
// ((EditText)findViewById(R.id.txtStringData)).setText(savedInstanceState.getString(stateTextStringData));
}
In the logcat output I get "Saved instance state" and then "onCreate" but I do not get "Restoring instance state" or "onRestore" when restarting the app.
Go to debug mode and see if your onCreate is being called. Do you have android:configChanges set in your manifest?
You should refer to the key you gave in outState when checking if savedInstanceState is not null, like this.
if (savedInstanceState != null) {
String text = savedInstanceState.getString("test");
Log.v(TAG, "Restoring instance state");
}
This documentation may shed some light
https://developer.android.com/guide/components/activities/activity-lifecycle.html
I'm quite new to programming.
I'm trying to make a simple app with two activities, where the second activity can change the text of the first. I know it can be done using intents, but I was wondering if there is a more direct way of doing it, for example using the second activity to call a function from the first activity?
Here's the code I have so far:
The MainActivity, which contains a TextView and a button to open the second activity:
public class MainActivity extends Activity {
TextView textview;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.et2);
button = (Button) findViewById(R.id.b1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, ChangeText.class);
startActivity(intent);
}
});
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
public void changetext(String message) {
textview.setText(message);
}
}
And the second activity, ChangeText, which contains an EditText and a button which should change the text of the TextView in MainActivity and then finish itself:
public class ChangeText extends Activity{
EditText edittext;
Button button;
private MainActivity mainclass;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.change_text);
edittext = (EditText)findViewById(R.id.et2);
button = (Button)findViewById(R.id.b2);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String message = edittext.getText().toString();
mainclass.changetext(message);
finish();
}
});
}
}
As you can see I tried to make the app work by making a public function in MainActivity which receives a string and sets the TextView with it, and then I call this function from the ChangeText activity.
The problem: it keeps crashing! Can anyone tell me how I can make this work?
Seems like I answered almost exactly the same question a week or so ago, so this is probably a duplicate, but I can't seem to find the original question.
The short answer is no - you can't call a method in an Activity from another Activity. The issue is that for normal programming purposes, only one Activity exists at a time*.
If you do something to circumvent this, then you're risking causing some major issues, including high memory usage, null pointer exceptions, etc.
The correct way to do this is indeed through the Intent system.
* Activities may or may not actually get destroyed when they become inactive, depending on things like how you use the back stack.
However, you should always program is if they do get destroyed when they become inactive - read, understand, and respect the Activity lifecycle.
For something as simple as your app, the "most direct" approach is to use the intent and startActivityForResult and them implement an onActivityResult in your main activity.
The problem you'll run into, even if you correctly pass you Activity references around is they are not guaranteed to be running at the same time.
Other ways aside from Intents, is to use a class(s) not involved with the Activity. Either a background service or a static variable in a class that extends Application. I rarely use Application classes anymore in favor of services and binding Activities them.
If I use an EventBus in projects, they can send Sticky events, which will hold the data until cleared.
Android uses a messaging mechanism to communicate between its components. This messaging mechnism is essential to Android, so you should use it. And as you already said, the messaging is implemented by Intents. ;-)
If you want something more complex, use an EventBus or implement a your own subscribe/publish mechanism that does what you want.
Use static variable
Example
In your MainActivity define
public static String msg = null;
then in your ChangeText activity assign changed text to it like
MainActivity.msg = edittext.getText().toString();
now in your main activity override the onResume() methode
if(msg != null){
textview.setText(msg);
msg = null;
}
You must LocalBroadCast Manager to do so
Here is the MainActivity which has the TextView which has to updated by another Activity
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView txt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt=(TextView)findViewById(R.id.txt1);
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String s1= intent.getStringExtra("myString");
getIt(s1);
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
public void getIt(String s)
{
System.out.println(s);
txt.setText(s);
}
public void go(View view)
{
Intent intent = new Intent(this,WriteText.class);
startActivity(intent);
}
}
And This is the Activity which contains the EditText which updates the TextView in the previous activity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
public class WriteText extends Activity {
EditText ed1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_text);
ed1 = (EditText)findViewById(R.id.textView);
}
public void come(View view){
Intent intent = new Intent("custom-event-name");
intent.putExtra("myString", ed1.getText().toString());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
This Worked for me , Hope it works for you too
Consider following code be the settings page of a live wallpaper in Android:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="#string/livewallpaper_settings"
android:key="livewallpaper_settings">
<ListPreference
android:key="livewallpaper_testpattern"
android:title="#string/livewallpaper_settings_title"
android:summary="#string/livewallpaper_settings_summary"
android:entries="#array/livewallpaper_testpattern_names"
android:entryValues="#array/livewallpaper_testpattern_prefix"/>
<CheckBoxPreference android:key="livewallpaper_movement"
android:summary="#string/livewallpaper_movement_summary"
android:title="#string/livewallpaper_movement_title"
android:summaryOn="Moving test pattern"
android:summaryOff="Still test pattern"/>
</PreferenceScreen>
It shows a setting page and everything about showing the settings is ok. How can I save this settings and use them while creating the live wallpaper?
Also, is it true to read the settings in onCreate method or not?
I found the answer :
package ca.jvsh.livewallpaper;
import ca.jvsh.livewallpaper.R;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class LiveWallpaperSettings extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener
{
#Override
protected void onCreate(Bundle icicle)
{
super.onCreate(icicle);
getPreferenceManager().setSharedPreferencesName(LiveWallpaper.SHARED_PREFS_NAME);
addPreferencesFromResource(R.xml.livewallpaper_settings);
getPreferenceManager().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onResume()
{
super.onResume();
}
#Override
protected void onDestroy()
{
getPreferenceManager().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key)
{
}
}
this was the java class for the setting page.
and this is for reading the settings :
TestPatternEngine()
{
...
mPreferences = LiveWallpaper.this.getSharedPreferences(SHARED_PREFS_NAME, 0);
mPreferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(mPreferences, null);
}
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key)
{
mShape = prefs.getString("livewallpaper_testpattern", "smpte");
mMotion = prefs.getBoolean("livewallpaper_movement", true);
readColors();
}
I work with preference xml file as options menu and i use it in my java class like bellwo
but the compiler says its deprecated and add a black line on addpreffrencefromresource(R.xml.mypreff). what is the new way of coding for it? thank you for helping.
package com.bestdiet;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.MenuItem;
public class prefs extends PreferenceActivity{
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.mypref);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
// return super.onOptionsItemSelected(item);
switch(item.getItemId())
{
case R.id.exit:
finish();
break;
case R.id.help:
break;
case R.id.options:
break;
}
return false;
}
xml file:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:title="پخش صدا"
android:defaultValue="true"
android:key="checkbox1"
/>
<CheckBoxPreference
android:title="پخش موسیقی"
android:defaultValue="true"
android:key="checkbox2"/>
</PreferenceScreen>
There is something notable: I just used the same xml preference layout...
But nobody tells you not to use two different files (say prefs_old.xml and prefs_new.xml), to add some of the new features to the (new) PreferenceFragment version of your PreferenceScreen.
This is my PreferenceActivity. It simply checks the build version to see which version of the preferences must be prepared:
package com.example.android.scheduler2;
/* ---------------------------------- Imports ------------------------------- */
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.widget.ListView;
public final class ACT_Prefs
extends PreferenceActivity
implements OnSharedPreferenceChangeListener
{
/* ------------------------------ Objects ------------------------------- */
private Context ctx = null;
/* ----------------------------- Overrides ------------------------------ */
#Override
public final void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ctx = getApplicationContext();
if (Build.VERSION.SDK_INT < 11)
{
createPreference_Activity();
}
else
{
createPreference_Fragment();
}
}
#Override
protected void onPause()
{
// Unregister OnSharedPreferenceChangeListener
PreferenceManager.getDefaultSharedPreferences(ctx).
unregisterOnSharedPreferenceChangeListener(this);
// Call base method
super.onPause();
}
#Override
protected void onResume()
{
// Register OnSharedPreferenceChangeListener
PreferenceManager.getDefaultSharedPreferences(ctx).
registerOnSharedPreferenceChangeListener(this);
// Fire base method
super.onResume();
}
#Override
public void onSharedPreferenceChanged
(final SharedPreferences sharedPreferences, final String key)
{
// ... Do whatever you need to do here ...
System.out.println(key + " changed!!");
}
/* ------------------------------ Methods ------------------------------- */
//#SuppressWarnings("deprecation")
private final void createPreference_Activity()
{
addPreferencesFromResource(R.xml.prefs);
}
#SuppressLint("NewApi")
private final void createPreference_Fragment()
{
getFragmentManager().beginTransaction().replace
(android.R.id.content, new FRG_Prefs()).commit();
getFragmentManager().executePendingTransactions();
}
}
This is FRG_Prefs (the PreferenceFragment)
package com.example.android.scheduler2;
/* ---------------------------------- Imports ------------------------------- */
import android.annotation.SuppressLint;
import android.graphics.PixelFormat;
import android.preference.PreferenceFragment;
import android.view.View;
import android.widget.ListView;
#SuppressLint("NewApi")
public final class FRG_Prefs
extends PreferenceFragment
{
/* ----------------------------- Overrides ------------------------------ */
#Override
public final void onResume()
{
super.onResume();
addPreferencesFromResource(R.xml.prefs);
}
}