What are things to keep in mind while using Shared Preferences android? - android

I am working on a simple android application.
The application has the functionality of user login which is connected to php.
I am successful in getting login functionality done well. What I want now is to save the username so that I can use it anywhere and anytime in my application. After going through some SO threads I came to know that this is doable using android sharedPreferences.
But prior to implementing them I want to know some stuff that I should keep in mind while using sharedPreferences like
what is basic task of shared preferences?
what things to keep in mind while actually using them?
what is proper way to programatically implement them in code?
and finally how to remove them after they are used?

what is basic task of shared preferences?
SharedPreferences are essentially used when you need your application to store persistent data. I consider using it when a Database is (for the sheer purposes of size / data to be stored) isn't really required.
what things to keep in mind while actually using them?
You can save just about anything that you typically require for your application to perform it's task. For example, in a gaming application, you could store the user's scores. However, since the SharedPreferences file/s can be accessed by anyone on a rooted device, you wouldn't want to store passwords. If you absolutely must store them anyway, you should implement your own algorithm to encrypt it. In an app of mine, I store URL's to a user's profile picture on Facebook and Twitter. That is already in the public domain.
what is proper way to programatically implement them in code?
If you are going to use SharedPreference in say, just one or two Activities, you use something like this to add values to the SharedPreference file:
// THE SHAREDPREFERENCE INSTANCE
SharedPreferences sharedPrefs;
// THE EDITOR INSTANCE
Editor editor;
// A CONSTANT STRING TO PROVIDE A NAME TO THE SHAREDPREFERENCE FILE
private static final String PRIVATE_PREF = "some_file_name";
// INSTANTIATE THE SHAREDPREFERENCE INSTANCE
sharedPrefs = getApplicationContext().getSharedPreferences(PRIVATE_PREF, Context.MODE_PRIVATE);
// INSTANTIATE THE EDITOR INSTANCE
editor = sharedPrefs.edit();
// ADD VALUES TO THE PREFERENCES FILE
editor.putLong(UNIQUE_KEY_NAME, VALUE);
editor.putString(UNIQUE_KEY_NAME, VALUE);
editor.putString(UNIQUE_KEY_NAME, VALUE);
editor.putString(UNIQUE_KEY_NAME, VALUE);
// THIS STEP IS VERY IMPORTANT. THIS ENSURES THAT THE VALUES ADDED TO THE FILE WILL ACTUALLY PERSIST
// COMMIT THE ABOVE DATA TO THE PREFERENCE FILE
editor.commit();
To fetch the values out of the file:
String someString = sharedPrefs.getString(UNIQUE_KEY_NAME, null);
long someLong = sharedPrefs.getLong(UNIQUE_KEY_NAME, 0);
If you need to reuse the contents / values from the SharedPreference file, this here is a nice tutorial on creating a helper class that will let any number of Activites to access the values instead of coding the above in every single one of them: http://megasnippets.com/source-codes/java/sharedpreferences_helper_class_android
and finally how to remove them after they are used?
// INSTANTIATE THE EDITOR INSTANCE
editor = sharedPrefs.edit();
// TO CLEAR A SELECT FEW OF THE VALUES:
editor.remove(KEY_FOR_THE_VALUE_TO_BE_REMOVED);
// ALTERNATIVELY, TO CLEAR ALL VALUES IN THE FILE:
editor.clear();
Note: Any SharedPreferences file/s you may create will be removed when the user manually clears the app data from the device's Settings.
Links For Further Reading:
http://www.vogella.com/articles/AndroidFileBasedPersistence/article.html
http://saigeethamn.blogspot.in/2009/10/shared-preferences-android-developer.html
http://www.mybringback.com/tutorial-series/12260/android-sharedpreferences-example/
http://www.androidhive.info/2012/08/android-session-management-using-shared-preferences/

How to Save/Read 'username' from SharedPreferences Persistent Storage
Basic Task:
Persistent storage.
Keep In Mind:
Is there so much data that you might be better off using a database or flat file storage?
Proper Way to Save and Read "username":
String key = "username";
String value = "John Doe";
// Save
SharedPreferences.Editor editor = context.getSharedPreferences(MY_PREFS_NAME, Context.MODE_PRIVATE).edit();
editor.putString(key, value);
editor.commit();
// Read
String def = "";
SharedPreferences settings = context.getSharedPreferences(MY_PREFS_NAME, Context.MODE_PRIVATE);
if(!settings.contains(key)) {
// Warn user that there is nothing to read and/or return a default value: "def"
}
String value = settings.getString(key, def);

About the basic task : you can read on Storage Options at developer.android.com.
About the keep in mind : try to avoid saving sensetive data to your application in shared preferences,because user can easily access the data.
You can find your shared preferences xml file in /data/data/your_application.package.name/shared_prefs/shared_prefs_name.xml
Implementation :
Usualy I am creating class with static methods like this :
public class MySharedPreferences {
private static final String APP_SHARED_PREFS = "my_prefs";
private static final String KEY_LOGIN = "username";
public static void setUsername(Context context, String username) {
SharedPreferences sharedPreferences = context.getSharedPreferences(APP_SHARED_PREFS, Activity.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();
editor.putString(KEY_USERNAME, login);
editor.commit();
}
public static String getUsername(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(APP_SHARED_PREFS, Activity.MODE_PRIVATE);
return sharedPreferences.getString(KEY_USERNAME, null);
}
}

Related

Reading SharedPreferences stored by Activity in a Service?

I am using a class to create a background service which runs all the time. When using the Android app the user can enter data which are stored via SharedPreferences. The storing works well and the stored data are available in the activity which stores it. I am using SharedPreferences like this:
SharedPreferences mPrefs = getSharedPreferences("Identifier",Context.MODE_PRIVATE);
In the service I am trying to access to this values that are stored in the activity. Therefore I am using the SharedPreferences the same way:
SharedPreferences mPrefs = getSharedPreferences("Identifier",Context.MODE_PRIVATE);
I am storing an object this way in the activity:
Gson gson = new Gson();
SharedPreferences.Editor prefsEditor = mPrefs.edit();
String json = gson.toJson(myObject);
prefsEditor.putString("value",json);
prefsEditor.commit();
And try to read it this way, but json returns null:
Gson gson = new Gson();
String json = mPrefs.getString("value",null);
Any idea what might be wrong? Is the context wrong? But how should it be?
Try to use a default shared preferences instance, which is shared across all your Activity and Service classes, use below method.
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this/*context*/);
This is the best way for storing primitives datatype(like booleans) or serializable objects. However, if you're capturing a lot of JSON data, you might consider using an SQLite database instead.
The problem was that the service is running in a different process. Therefore I used tray which works perfectly for multiple processes: https://github.com/grandcentrix/tray.

Not getting value from Shared Preferences instantly

I am storing the data in the Shared Preferences by
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("menu_bar","abcd");
editor.apply();
and I am fetching the data from Shared Preferences in fragment by
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
String name = preferences.getString("menu_bar","");
if(!name.equalsIgnoreCase("")){
Toast.makeText(getActivity(), name, Toast.LENGTH_SHORT).show();
It is working when the app is removed from the stack.
But on the first time it is not working. Getting NULL in the first time but working fine from the second time. I also tried with editor.commit() when saving it.
Use getSharedPreferences("MyPref", Context.MODE_PRIVATE) and then commit to reflect changes instantly
SharedPreferences preferences = getSharedPreferences("MyPref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("menu_bar","abcd");
editor.commit();
Official Documentation
Commit your preferences changes back from this Editor to the SharedPreferences object it is editing. This atomically performs the requested modifications, replacing whatever is currently in the SharedPreferences.
Note that when two editors are modifying preferences at the same time, the last one to call apply wins.
Unlike commit(), which writes its preferences out to persistent storage synchronously, apply() commits its changes to the in-memory SharedPreferences immediately but starts an asynchronous commit to disk and you won't be notified of any failures. If another editor on this SharedPreferences does a regular commit() while a apply() is still outstanding, the commit() will block until all async commits are completed as well as the commit itself.
As SharedPreferences instances are singletons within a process, it's safe to replace any instance of commit() with apply() if you were already ignoring the return value.
You don't need to worry about Android component lifecycles and their interaction with apply() writing to disk. The framework makes sure in-flight disk writes from apply() complete before switching states.
The SharedPreferences.Editor interface isn't expected to be implemented directly. However, if you previously did implement it and are now getting errors about missing apply(), you can simply call commit() from apply().
Try using the same instance of SharedPreferences. Easiest would be an explicitly named one:
class MyActivity {
private static final String PREFS_NAME = "myActivityPrefs";
private static SharedPreferences sharedPrefs = null;
public static SharedPreferences prefs(Context context) {
if (sharedPrefs == null) {
sharedPrefs = context.getSharedPreferences(PREFS_NAME, 0);
}
return sharedPrefs;
}
}
You then use it in the activity like this:
prefs(this).edit().putString("menu_bar","abcd").apply()
And in the fragment:
String name = MyActivity.prefs(getActivity()).getString("menu_bar","");
This is a recommended mode of operation that would give you good performance without waiting for I/O on your main thread - apply() does that for you but requires using the same instance to be consistent.
To use separate instances (sometimes you're forced to - for example through separate processes) always use commit(), which can freeze your main thread at times, and still doesn't guarantee consistency due to how filesystems work, I've seen instances where commit()ed data wasn't immediately available to a separate process, often on specific devices that had a FS configuration quirk.

Best place for storing user login credentials in Android

I am creating an android app, and i cannot(?) find any information on authenticating a user of the app on Google App Engine (without using the user's Google Account).Is it good practice to store username and password on the android device and then store the data used by the app on Google App Engine?
You should NOT use SharedPreferences, despite how secure Google will tell you they are, for the simple fact that rooting habits are widespread by both power and wannabe-power users.
In rooted systems, authorized apps will be able to access the internal storage /system partition, thus access the root-owned encrypted XML files where Android stores SharedPreferences, WHICH BECOME CLEARTEXT FOR ROOT-AUTHORIZED APPS. So if a compromised phone happens to have an app that stores such data and the user has a habit of abusing same email/password for different services, the attack vector is pretty straightforward to compromise credentials for multiple services, despite whatever warnings the user dismissed when rooting his phone or giving the app such permissions, because, well, those warnings just aren't clear enough.
Alternatives are manual encryption of persistent storage for credentials, using custom, variable seed, salted algorithms. secure-preferences lib is a great alternative which pretty much does everything for you in a transparent way, with the added benefit of implementing Android's SharedPreferences interface, keeping most functionality of default sprefs with minor tweaking (look at their samples).
2016 Edit: I just felt I needed to come back to this question in 2016 and add a nice reference to the Apple vs FBI drama to alter the OS in the San Bernardino assailant's phone. So, imagine you have a phone that is easily rootable, like most Android's, and that might even be rooted by default or doesn't need to wipe data to root. The FBI doesn't have to demand anything from Google or your company if they wan't to get your credentials. By using stuff like secure-preferences, you place the same type of responsibility Apple decided to undertake by only making your own system (in this case, your app) able to access those credentials. You do get to be annoyed by the FBI if they so desire, but giving your users the sense that you, not the underlying OS, is the only authority having direct control over those credentials, is something I'd rather have in my product.
2022 Edit: Android has Encrypted Preferences natively now, so make use of that instead I would say (unless someone points out something it doesn't do better than secure-preferences)
You can save the user credentials in shared preference. You can use this preference value at any of your activity. The saved value will remains even after the exit from application.
The sample code for shared preferences are here. It is recommended to keep your preferences code in your application utils class to keep your code organized.
public static String KEY = "SESSION";
public static void saveUserName(String userid, Context context) {
Editor editor = context
.getSharedPreferences(KEY, Activity.MODE_PRIVATE).edit();
editor.putString("username", userid);
editor.commit();
}
public static String getUserName(Context context) {
SharedPreferences savedSession = context.getSharedPreferences(KEY,
Activity.MODE_PRIVATE);
return savedSession.getString("username", "");
}
Consider SharedPreferences for this, like...
public class PrefUtils {
public static final String PREFS_LOGIN_USERNAME_KEY = "__USERNAME__" ;
public static final String PREFS_LOGIN_PASSWORD_KEY = "__PASSWORD__" ;
/**
* Called to save supplied value in shared preferences against given key.
* #param context Context of caller activity
* #param key Key of value to save against
* #param value Value to save
*/
public static void saveToPrefs(Context context, String key, String value) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences.Editor editor = prefs.edit();
editor.putString(key,value);
editor.commit();
}
/**
* Called to retrieve required value from shared preferences, identified by given key.
* Default value will be returned of no value found or error occurred.
* #param context Context of caller activity
* #param key Key to find value against
* #param defaultValue Value to return if no data found against given key
* #return Return the value found against given key, default if not found or any error occurs
*/
public static String getFromPrefs(Context context, String key, String defaultValue) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
try {
return sharedPrefs.getString(key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
return defaultValue;
}
}
}
Simply use these methods like,
// Saving user credentials on successful login case
PrefUtils.saveToPrefs(YourActivity.this, PREFS_LOGIN_USERNAME_KEY, username);
PrefUtils.saveToPrefs(YourActivity.this, PREFS_LOGIN_PASSWORD_KEY, password);
// To retrieve values back
String loggedInUserName = PrefUtils.getFromPrefs(YourActivity.this, PREFS_LOGIN_USERNAME_KEY);
String loggedInUserPassword = PrefUtils.getFromPrefs(YourActivity.this, PREFS_LOGIN_PASSWORD_KEY);
I think its much clearer now...:)

Where is the best place to store globals (auth token) in Android

I'm pretty new to android. I want to know where the best place is to store something like a auth token that I get from logging in on my server. With every subsequent request, I will have to post this auth token. Sure I could keep a global class somewhere, but I just want to know what a good / standard way is to store data that persists across activities and intents. Thanks!
SharedPreferences is the way to go.
See doc here: https://developer.android.com/reference/android/content/SharedPreferences.html
Some example code is like below.
To save the token:
SharedPreferences settings = PreferenceManager
.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = settings.edit();
editor.putString(some_key, your_auth_token_string);
editor.commit();
To get the token:
SharedPreferences settings = PreferenceManager
.getDefaultSharedPreferences(context);
String auth_token_string = settings.getString(some_key, ""/*default value*/);

Can I get data from shared preferences inside a service?

I'm developing an android application. I'm using android 2.2
In my application I am capturing GPS data and sending it to service with the 1 hour time interval. If user exits from application it's also working (it is required).
I'm using 2 services (User defined), one for capturing GPS data and other for sending to the server.
Here my doubt
In service, can we use shared preferences.
If we store any data in shared preferences in any activity of the application, will we be able to use that data in service with the help of shared preferences?
You can access the default shared preferences instance, which is shared across all your Activity and Service classes, by calling PreferenceManager.getDefaultSharedPreferences(Context context):
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
This is great for storing simple primitives (like booleans) or serializable objects. However, if you're capturing a lot of location data, you might consider using a SQLite database instead.
I find the solution.
Inside a service we call the following method to get the shared preferences
myapp.bmodel.getApplicationContext().getSharedPreferences("myPrefs_capture_gps_per_hour", Context.MODE_PRIVATE);
In the above code myapp is a object of the application class which is derived from Application
You need a context to get access to shared preferences. The best way is to create MyApplication as a descendant of Application class, instantiate there the preferences and use them in the rest of your application as MyApplication.preferences:
public class MyApplication extends Application {
public static SharedPreferences preferences;
#Override
public void onCreate() {
super.onCreate();
preferences = getSharedPreferences( getPackageName() + "_preferences", MODE_PRIVATE);
For example, if you need access to your preferences somewhere else, you may call this to read preferences:
String str = MyApplication.preferences.getString( KEY, DEFAULT );
Or you may call this to save something to the preferences:
MyApplication.preferences.edit().putString( KEY, VALUE ).commit();
(don't forget to call commit() after adding or changing preferences!)
Yes Shivkumar, you can use your share preferences in any kind of services as normal as you are using in your Activity.
same like
SharedPreferences preferences = getSharedPreferences("<PrefName>",
MODE_PRIVATE);
There are two ways to create instance of SharedPreference:
Case 1:
SharedPreferences preferences = activity.getSharedPreferences("<PrefName>", MODE_PRIVATE);
Case 2:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Notice if you create a preference with the same name (case 1) or same context (case 2) even at different places, it's still the same, and can share data, obviously.

Categories

Resources