I have a newly created android-18 app, with a PreferenceScreen that's too obvious & simple to list.
And I also have an automated test [fixed to convert the questions into the answers].
public class MyPreferenceTest extends ActivityUnitTestCase<MyPreference> {
Intent intent;
MyPreference activity;
public MyPreferenceTest() {
super(MyPreference.class);
}
#Override
protected void setUp() throws Exception {
Context targetContext = getInstrumentation().getTargetContext();
intent = new Intent(targetContext, MyPreference.class);
super.setUp();
}
private void assembleActivity() {
startActivity(intent, null, null);
activity = getActivity();
}
private void assemblePreferences(String device, String userName, String password) {
Context targetContext = getInstrumentation().getTargetContext();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(targetContext);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("smart_phin_bluetooth_devices", device);
editor.putString("username", userName);
editor.putString("password", password);
editor.commit();
}
public void test_empty_userNames_dont_reflect_into_the_summary() {
assemblePreferences("", "", "");
assembleActivity();
activity.onResume();
EditTextPreference userName = (EditTextPreference) activity.findPreference("username"); // FIXME userName
assertEquals("", userName.getEditText().getText().toString());
assertEquals("", userName.getText());
assertEquals("Enter your user name", userName.getSummary().toString());
}
public void test_full_userNames_reflect_into_the_summary() {
assemblePreferences("", "BookerT", "");
assembleActivity();
activity.onResume(); // We must call this bc Android does but the test rig does not...
EditTextPreference userName = (EditTextPreference) activity.findPreference("username");
assertEquals("username", userName.getKey());
assertEquals("BookerT", String.valueOf(userName.getText().toString());
// assertEquals("BookerT", userName.getEditText().getText().toString());
assertEquals("BookerT", userName.getSummary().toString());
}
} // end of class MyPreferenceTest
The commented-out assertion would fail because nothing has invoked that EditText view yet.
The test now checks that new code in onResume() updates the Summary from generic verbiage to reflect the Preference's current value.
You have a bug in your tests.
private void assemblePreferences(String device, String userName, String password)
Note that the order of values here is device, userName, password.
assemblePreferences("BookerT", "", "");
Hence device is BookerT, not userName.
Related
I'm trying to save a string to shared preferences and then start an activity and retrieve it but doesn't work. What am I doing wrong?
First I set the shared preference key then I start the activity:
SharedPreferences.Editor editor =
getSharedPreferences("PaymentStatus",MODE_PRIVATE).edit();
editor.putString("payment_status","success");
editor.apply();
Intent i = new Intent(getBaseContext(), ProfileActivity.class);
startActivity(i);
and on the ProfileActivity class I trying to retrieve the key:
SharedPreferences prefs = getSharedPreferences("PaymentStatus",
MODE_PRIVATE);
String payment_status = prefs.getString("payment_status", null);
if(payment_status == "success"){
Log.i("payment status", "success");
}
I can't see the payment status success in the logcat.
The issue with the code you have given is not with how you done it with shared preferences (you did that correctly btw)
Your issue is that you are comparing strings via == as this compares the string reference and not the string value. Use .equals() or .contains() instead.
if (payment_status.equals("success")) {
Log.i("payment status", "success");
}
This is my experience in used SharedPreferens.
Perhaps this approach will solve the problem:
public class UserData {
UserData(MainActivity mainActivity){this.mainActivity = mainActivity;}
private static UserData userData;
private final MainActivity mainActivity;
private SharedPreferences sPref;
private SharedPreferences.Editor editor;
final private String USER_ID = "user_id";
public static void create(MainActivity activity) {
if (userData == null) userData = new UserData(activity);
}
public static UserData getUserData() {
return userData;
}
void createUser() {
sPref = mainActivity.getSharedPreferences("UserData", Context.MODE_PRIVATE);
editor = sPref.edit();
// Если user id уже есть, выходим из метода
if(sPref.contains(USER_ID)) return;
editor.putString(USER_ID, createUserId());
editor.apply();
Toast.makeText(mainActivity,"UserId created", Toast.LENGTH_SHORT).show();
}
// id формируется на основе текущей даты и времени
private String createUserId() {
Date currentDate = new Date();
DateFormat dateFormat = new SimpleDateFormat("ddMMyyyyHHmmss", Locale.getDefault());
return dateFormat.format(currentDate);
}
public String getUserId() {
return sPref.getString(USER_ID, "");
}
}
First of, allow me to point out that am new to android development and at this very moment am trying to store a user login session using SharedPreferences and having done a bit to create myself a class SessionManager to handle that, i got no error anyways but, each time i logged in, am quickly redirected to the LoginActivty again.
SessionManager.java
package com.example.drawerlayout;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import java.util.HashMap;
public class SessionManager {
SharedPreferences sharedPreferences;
public SharedPreferences.Editor editor;
public Context context;
int PRIVATE_MODE = 0;
private static final String PREF_NAME = "LOGIN";
private static final String LOGIN = "IS_LOGIN";
public static final String NAME = "NAME";
public static final String EMAIL = "EMAIL";
public static final String TYPE = "TYPE";
public SessionManager(Context context) {
this.context = context;
sharedPreferences = context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
editor = sharedPreferences.edit();
}
public void createSession(String name, String email, String type){
editor.putBoolean(PREF_NAME, true);
editor.putString(NAME, name);
editor.putString(EMAIL, email);
editor.putString(TYPE, type);
editor.apply();
}
public boolean isLoggedIn(){
return sharedPreferences.getBoolean(LOGIN, false);
}
public void checkLoggin(){
if (!this.isLoggedIn()){
Intent i = new Intent(context, LoginActivity.class);
context.startActivity(i);
((MainActivity) context).finish();
}
}
public HashMap<String, String> getUserDetails(){
HashMap<String, String> user = new HashMap<>();
user.put(NAME, sharedPreferences.getString(NAME, null));
user.put(EMAIL, sharedPreferences.getString(EMAIL, null));
user.put(TYPE, sharedPreferences.getString(TYPE, null));
return user;
}
public void logOut(){
editor.clear();
editor.commit();
Intent i = new Intent(context, LoginActivity.class);
context.startActivity(i);
((MainActivity) context).finish();
}
}
and SessionManager.java is used in LoginActivity like so:
String name = details.getString("username").trim();
String email = details.getString("email").trim();
String type = details.getString("type").trim();
//CREATE SESSION
sessionManager.createSession(name,email,type);
and in MainActivity.java like
sessionManager = new SessionManager(this);
sessionManager.checkLoggin();
You are updating wrong key in createSession method.
Replace PREF_NAME with LOGIN in createSession. And your code will work as expected.
public void createSession(String name, String email, String type){
// Check below line...
editor.putBoolean(LOGIN, true);
editor.putString(NAME, name);
editor.putString(EMAIL, email);
editor.putString(TYPE, type);
editor.apply();
}
See your String variable names once again!
String PREF_NAME is for getting the preference.
String LOGIN is for addressing the value to check if the user is logged in or not
Your Mistake:
Function createSession(String name, String email, String type)
You are updating the value of String PREF_NAME instead of String LOGIN
Solution:
Function createSession(String name, String email, String type)
Updating the value of String LOGIN instead of String PREF_NAMEin line no 29 of SessionManager.java
Most probably you have forgotten to put a boolean field LOGIN in your session manager's create session.. modify createSession Method as below
public void createSession(String name, String email, String type,Boolean isLoggedIn){
editor.putString(NAME, name);
editor.putString(EMAIL, email);
editor.putString(TYPE, type);
editor.putBoolean(LOGIN,isLoggedIn)
editor.apply();
}
And then if login success in login activity then call like this
String name = details.getString("username").trim();
String email = details.getString("email").trim();
String type = details.getString("type").trim();
//CREATE SESSION
sessionManager.createSession(name,email,type,true);
alright sharedpreference values are saving in xml file which contain its key and value so each of value will be generate on first attempt of login so why don't you check if any value is exists in sharedpreference or not by this way.. put this code to your sessionHandler
public static boolean preferenceExists(String key){
return sharedPreferences.contains(key);
}
it will return boolean flag if any value is exists there or not so simply do check if preferenceExists() or not.... if not then redirect it do login activity else redirect where you want
suggestion : create splashscreen where you can verify these things
I can't obtain data from SharedPreferences.. After I click on a button, it executes AsyncTask in a different class named Background.
public class Background extends AsyncTask<Integer,Void,String>{
private Context context;
private AsyncResponse listener;
public Background(Context context,AsyncResponse listener) {
this.context = context;
this.listener=listener;
}
AsyncResponse is an interface that I've created to inform my MainMactivity that background work has been finished. It's just:
package com.example.pablo.zad3;
public interface AsyncResponse {
void TaskCompleted();
}
Then I want to pass the result to SharedPreferences:
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
SharedPreferences prefs = this.context.getSharedPreferences("MyPrefs",Context.MODE_PRIVATE);
prefs.edit().putString("A", s);
prefs.edit().commit();
listener.TaskCompleted();
}
But in my MainActivity I can't get the resulting string, it's like there was no A key in SharedPreferences (I always get "NO DATA"):
#Override
public void TaskCompleted() {
SharedPreferences prefs = this.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
if(prefs != null) {
String text = prefs.getString("A", "NO DATA");
editText2.setText(text);
}
}
I don't know what I'm doing wrong, can u help me?
The problem are those two lines:
prefs.edit().putString("A", s);
prefs.edit().commit();
at the first one you are opening SharedPreferences for edit and do the changes ...
now at the second line you are opening it again ... which causing the previous changes rollback ...
As the "family" of putXXX(...) method of the SharedPreferences.Editor class returns Editor itself you should do something like:
prefs.edit().putString("A", s).putXXX(...).putXXX(...).commit();
(by putXXX(...) I mean puting other preferences fx putInt("Z", 666))
now the changes will be saved
Use this for writing to preferences:
//Write to preferences
String s = "this is a test.";
SharedPreferences prefs = this.getSharedPreferences("MyPrefs",this.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("A", s);
editor.apply();
And this for retrieving information
//Fetch from preferences
SharedPreferences prefs2 = this.getSharedPreferences("MyPrefs", this.MODE_PRIVATE);
if(prefs2 != null) {
String text2 = prefs.getString("A","");
Log.d(LOG_TAG, "This is the string: "+text2);
}
The only thing that you missed is an editor.
I've been getting null returns from getting strings from my saved preferences. I'm not sure how savedpreferences worked but my understanding was that when call a sharedpreferences, it creates the keypair file on the phone so you can come back to it later.
My program is essentially a string creation application. When you press a button, it creates a string to send as an sms. My settings activity page has four edittexts that save whatever is inside them with a buttonclick and returns to the main activity. The final button creates a String by getting the value from the keyvalue pair and constructs the message. However, I've always gotten null for each of the values.
Heres the code for the settings page and then the main page. Please ask if I could add more, I didn't add ALL of the code, just the sharedpreferences portions.
public SharedPreferences sp;
public Editor e;
public void savethethings(){ //run this when enter is pressed/savew
EditText smsintro_hint = (EditText) findViewById(R.id.settings_smsintro_hint);
EditText smsbody_hint = (EditText) findViewById(R.id.settings_smsbody_hint);
EditText checkboxbody_hint = (EditText) findViewById(R.id.settings_checkboxbody_hint);
EditText checkboxbody_description_hint = (EditText) findViewById(R.id.settings_checkboxbody_description_hint);
String introstring = smsintro_hint.getText().toString();
String bodystring = smsbody_hint.getText().toString();
String checkboxbodystring = checkboxbody_hint.getText().toString();
String checkboxdescriptionstring = checkboxbody_description_hint.getText().toString();
e.putString("intro", introstring);
e.commit(); // you forgot to commit
if(!bodystring.isEmpty())
{
e.putString("body", bodystring);
e.commit();
}
if(!checkboxbodystring.isEmpty())
{
e.putString("checkbody", checkboxbodystring);
e.commit();
}
if(!checkboxdescriptionstring.isEmpty())
{
e.putString("checkboxdescr", checkboxdescriptionstring);
e.commit();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.settingmenu);
//SP
sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); // forget about
// named preferences - get the default ones and finish with it
e = sp.edit();
Button tt = (Button)findViewById(R.id.savebutton);
tt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
public void save(View view)
{
//THINGS HAPPEN HERE WITH SHARED PREFERENCES :(
savethethings();
this.finish();
return;
}
public String finishedtext(String userstring)
{
smsintroduction = (sp.getString("intro", ""));
smsbody = (sp.getString("body", ""));
checkboxtext = (sp.getString("checkbody", ""));
checkboxmessage = (sp.getString("checkboxdescr", ""));
if(smsintroduction.isEmpty())
{
if(smsbody.isEmpty())
{
if(checkboxtext.isEmpty())
{
if(checkboxmessage.isEmpty()) //topkek for most AND statements Ive ever put in in if/then form
{
//Essentially the DEFAULT if they're ALL null
smsbody = "Hi "+ userstring +"! This is coming from jake's phone and it wants to send a text so we can talk or whatever. ";
}
}
}
}
Toast.makeText( this, "Creating text, then press send!", Toast.LENGTH_LONG).show();
String thetext = "";
thetext = smsintroduction + " " + smsbody + " " + checkboxtext;
return thetext;
}
public void savethethings(){ //run this when enter is pressed/savew
EditText smsintro_hint = (EditText) findViewById(R.id.settings_smsintro_hint);
EditText smsbody_hint = (EditText) findViewById(R.id.settings_smsbody_hint);
EditText checkboxbody_hint = (EditText) findViewById(R.id.settings_checkboxbody_hint);
EditText checkboxbody_description_hint = (EditText) findViewById(R.id.settings_checkboxbody_description_hint);
String introstring = smsintro_hint.getText().toString();
String bodystring = smsbody_hint.getText().toString();
String checkboxbodystring = checkboxbody_hint.getText().toString();
String checkboxdescriptionstring = checkboxbody_description_hint.getText().toString();
// if(!introstring.isEmpty()) //if the fields are NOT empty, they should get saved.
// {
e.putString("intro", introstring);
e.commit(); // you forgot to commit
if(!bodystring.isEmpty())
{
e.putString("body", bodystring);
e.commit();
}
if(!checkboxbodystring.isEmpty())
{
e.putString("checkbody", checkboxbodystring);
e.commit();
}
if(!checkboxdescriptionstring.isEmpty())
{
e.putString("checkboxdescr", checkboxdescriptionstring);
e.commit();
}
}
Create java class named SessionManger and put all your methods for setting and getting SharedPreferences values. When you want to save value use the object of this class and set and get the values.
Sample code given below.
public class SessionManager {
SharedPreferences pref;
SharedPreferences.Editor editor;
Context _context;
int PRIVATE_MODE = 0;
public SessionManager(Context context) {
this._context = context;
pref = _context.getSharedPreferences("name_that_you_use", PRIVATE_MODE);
editor = pref.edit();
editor.apply();
}
public void setIntroMessage(String data) {
editor.putString("intro", data);
editor.commit();
}
public String getIntroMessage() {
return pref.getString("intro", null);
}
}
Yesterday, I built a SettingsActivity for my Android app where the user can enter the URL of a webservice-server. I save this using:
editor = sharedPref.edit();
editor.putString(
getString(R.string.SAVED_URL_MOBILEHELPER), lvsURL_mobilehelper);
editor.commit();
in the SharedPreferences after the "save" button is pressed.
In the onStart() I read the setting to set the saved value into the belonging text-field:
// line 29
String lvsURL_mobilehelper = sharedPref.getString(
getString(R.string.SAVED_URL_MOBILEHELPER), "");
This also worked well yesterday; the last string I entered and successfully read from the settings was "testURL12345".
Today, I was trying to add user-authentication around my application and since that, I get a ClassCastException when I open the SettingsActivity:
Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to
java.lang.String
at android.app.SharedPreferencesImpl.getString(SharedPreferencesImpl.java:224)
at de.unibonn.sdb.wissappmobile.activities.SettingsActivity.onResume(
SettingsActivity.java:29)
Does anyone have an idea why this all worked fine yesterday and now it doesn't?
Note: I don't want to store the user credentials in an AccountManager or persistent in my preferences, because the app shall be used on a "business tablet" and not a "personal tablet". The user credentials are needed for HTTP-Basic authentication. So my idea is to check in the parent Activity if the user is "logged in" and not inactive for more than 1800 seconds.
SettingsActivity:
/*
* Activity for settings page (webservice URL)
*/
public class SettingsActivity extends AppFragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
}
#Override
protected void onResume() {
super.onResume();
// Fill content
// URL of the Mobile Helper
String lvsURL_mobilehelper = sharedPref.getString(
getString(R.string.SAVED_URL_MOBILEHELPER), "");
EditText dfsURLMobileHelper = (EditText) findViewById(R.id.dfsURLMobileHelper);
dfsURLMobileHelper.setText(lvsURL_mobilehelper);
}
/*
* Action called when pressing the "Save"-Button
*
* Saves the entered Data in a local file.
*/
public void ClickBtnSave(View view) {
EditText dfsURLMobileHelper = (EditText) findViewById(R.id.dfsURLMobileHelper);
TextView txtError = (TextView) findViewById(R.id.txtError);
String lvsURL_mobilehelper = dfsURLMobileHelper.getText().toString();
String Eceptiontext = "";
Boolean success = false;
// Write to file
try {
editor = sharedPref.edit();
editor.putString(getString(R.string.SAVED_URL_MOBILEHELPER), lvsURL_mobilehelper);
editor.commit();
success = true;
} catch (Exception e) {
success = false;
Eceptiontext = e.getLocalizedMessage();
}
if (success) {
txtError.setText(getString(R.string.SAVING_SUCCESS));
} else {
txtError.setText(getString(R.string.SAVING_FAILED) + " : " + Eceptiontext);
}
}
/*
* Action called when pressing the "Back"-Button
*
* Opens the Search-Acitivity
*/
public void ClickBtnBack(View view) {
// Back to SearchActivity
Intent intent = new Intent(this, SearchActivity.class);
startActivity(intent);
}
}
Parent AppFragmentActivity:
/**
* Class to handle global Callbacks (e.g. user credentials)
*/
public class AppFragmentActivity extends FragmentActivity {
protected SharedPreferences sharedPref;
protected SharedPreferences.Editor editor;
protected String WebServiceUsername;
protected String WebServicePassword;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_appfragmentactivity);
}
#Override
protected void onResume () {
super.onResume();
// Check if user is "logged in".
// Meaning: Are there given user credentials and are they valid of was the user inactive for too long?
// We only do this "onResume" because this callback is the only one, which is called everytime an user
// starts/restarts/resumes an application
checkForUserCredentials();
// Set new "last action" now "now"
setLastAction(new Date().getTime());
}
#Override
protected void onStart () {
// Fill content
super.onStart();
// Set global sharedPreferences
sharedPref = getSharedPreferences(
getString(R.string.FILE_settings_file), Context.MODE_PRIVATE);
}
/*
* Checks if user credentials are valid meaning if they are set and not too old
*/
private void checkForUserCredentials() {
// Get filehandle to PreferencesFile
long TimeLastAction = sharedPref.getLong(
getString(R.string.SETTINGS_USER_LAST_ACTION), 0);
long TimeNow = new Date().getTime();
// Ask for User credentials when last action is too long ago
if(TimeLastAction < (TimeNow - 1800)) {
// Inactive for too long
// Set credentials back
setUsernameAndPassword("", "");
} else {
WebServiceUsername = sharedPref.getString(
getString(R.string.SETTINGS_USER_USERNAME), "");
WebServicePassword = sharedPref.getString(
getString(R.string.SETTINGS_USER_PASSWORD), "");
}
}
/*
* Saves the given last action in the sharedPreferences
* #param long LastAction - Time of the last action
*/
private void setLastAction(long LastAction) {
editor = sharedPref.edit();
editor.putLong(getString(R.string.SETTINGS_USER_LAST_ACTION), LastAction);
editor.commit();
}
/*
* Saves the given username and userpassword sharedPreferences
* #param String username
* #param String password
*/
private void setUsernameAndPassword(String username, String password) {
editor = sharedPref.edit();
editor.putString(
getString(R.string.SETTINGS_USER_USERNAME), username);
editor.putString(
getString(R.string.SETTINGS_USER_PASSWORD), username);
editor.commit();
WebServiceUsername = username;
WebServicePassword = password;
}
/*
* Method called when pressing the OK-Button
*/
public void ClickBtnOK(View view) {
// Save User-Creentials
EditText dfsUsername = (EditText) findViewById(R.id.dfsUsername);
String lvsUsername = dfsUsername.getText().toString();
EditText dfsPassword = (EditText) findViewById(R.id.dfsPassword);
String lvsPassword = dfsPassword.getText().toString();
if(lvsUsername.equals("") || lvsPassword.equals("")) {
TextView txtError = (TextView) findViewById(R.id.txtError);
txtError.setText(getString(R.string.ERR_Name_or_Password_empty));
} else {
// Save credentials
setUsernameAndPassword(lvsUsername, lvsPassword);
setLastAction(new Date().getTime());
// open Searchactivity
Intent intent = new Intent(this, SearchActivity.class);
startActivity(intent);
}
}
#Override
protected void onPause() {
super.onPause();
setLastAction(new Date().getTime());
}
#Override
protected void onStop() {
super.onStop();
setLastAction(0);
setUsernameAndPassword("", "");
}
}
Well, if Long, probably because of you put long there. Because of you are using R.string. sometimes it messes up resources ids, so need for clean project, or you have same string values for these ids in your string.xml. Simply saying, somewhere in logic you put long in same key
p.s. I think best practice is to use public static final String MY_PREFERENCE_KEY = "my_preference_key";