SharedPreferenceUtil
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.SharedPreferences;
import android.util.Base64;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Map;
/**
* Created by yangshuai on 2015/9/30 0030.
*/
public class SharedPreferenceUtil {
private static SharedPreferences sharedPreferences;
private static SharedPreferences.Editor editor;
public static void init(Activity context) {
if (sharedPreferences == null) {
sharedPreferences = context.getPreferences(Context.MODE_PRIVATE);
}
if (editor == null) {
editor = sharedPreferences.edit();
}
}
public static void saveIntData(String key, int data){
editor.putInt(key, data);
editor.commit();
}
public static int getIntData(String key){
return sharedPreferences.getInt(key, 0);
}
public static int getIntData(String key, int defaultValue){
return sharedPreferences.getInt(key, defaultValue);
}
public static void saveStringData(String key, String data){
editor.putString(key, data);
editor.commit();
}
public static String getStringData(String key){
return sharedPreferences.getString(key, "");
}
public static String getStringData(String key, String defaultValue){
return sharedPreferences.getString(key, defaultValue);
}
public static void saveBooleanData(String key, boolean data){
editor.putBoolean(key, data);
editor.commit();
}
public static boolean getBooleanData(String key){
return sharedPreferences.getBoolean(key, false);
}
public static boolean getBooleanData(String key, boolean defaultValue){
return sharedPreferences.getBoolean(key, defaultValue);
}
public static void saveFloatData(String key, float data){
editor.putFloat(key, data);
editor.commit();
}
public static float getFloatData(String key){
return sharedPreferences.getFloat(key, 0);
}
public static float getFloatData(String key, float defaultValue){
return sharedPreferences.getFloat(key, defaultValue);
}
public static Map<String, ?> getAllData(){
return sharedPreferences.getAll();
}
/* 存储一个序列化(实现 Serializable接口)的对象 */
public static void saveSerializableObject(String key, Object object) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
saveStringData(key, Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT));
}
/* 获取序列化对象 */
public static Object getSerializableObject(String key) throws IOException {
byte[] base64Bytes = Base64.decode(getStringData(key).getBytes(), Base64.DEFAULT);
ByteArrayInputStream bais = new ByteArrayInputStream(base64Bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
try {
return ois.readObject();
} catch (ClassNotFoundException e) {
return null;
}
}
}
使用文件流读取 SharedPreferences 数据文件
SharedPreferences 保存的数据文件存放在内部存储卡中,路径为:
/data/data/【包名】/shared_prefs
.
public static String useFileStreamReadSharedPreferencesData(Context context) {
String content = "";
String path = android.os.Environment.getDataDirectory().getAbsolutePath()
+ "/data/" + context.getPackageName() + "/shared_prefs/abc.xml";
try {
FileInputStream fileInputStream = new FileInputStream(path);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
content = bufferedReader.readLine();
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
修改 SharedPreferences 的保存路径
代码
public void saveToSDcard(Context context) {
try {
/* 获取 ContextWrapper 对象中的 mBase 变量 */
Field field = ContextWrapper.class.getDeclaredField("mBase");
field.setAccessible(true);
/* 获取mBase变量的值 */
Object object = field.get(context);
/* 获取 ContextImpl.mPreferencesDir 变量 */
field = object.getClass().getDeclaredField("mPreferencesDir");
field.setAccessible(true);
/* 创建自定义路径 */
File file = new File("/sdcard");
/* 修改 mPreferencesDir 变量的值 */
field.set(object, file);
/* 执行该语句,在 /sdcard 目录中创建一个 save_data.xml 文件 */
SharedPreferences sharedPreferences = context.getSharedPreferences("save_data", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("afra55", "AAA啊哈");
editor.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
分析源码:
ContextWrapper.java
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return mBase.getSharedPreferences(name, mode);
}
getSharedPreferences 调用 mBase.getSharedPreferences(name, mode) 返回SharedPreferences 对象。
public class ContextWrapper extends Context {
Context mBase;
......
}
跟踪 Context 类,找到了抽象方法:
public abstract SharedPreferences getSharedPreferences(String name,
int mode);
在这里可以看到getSharedPreferences 方法肯定被某个类实现了,那么用mBase变量获取该类的名称。
try {
Field field = ContextWrapper.class.getDeclaredField("mBase");
field.setAccessible(true);
Object object = field.get(context);
object.getClass().getName(); // 获取到名字
} catch (Exception e) {
e.printStackTrace();
}
知道了实现抽象方法的类是 android.app.ContextImpl, 在ContextImpl 中找到了实现方法:
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
SharedPreferencesImpl sp;
synchronized (ContextImpl.class) {
if (sSharedPrefs == null) {
sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>();
}
final String packageName = getPackageName();
ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);
if (packagePrefs == null) {
packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
sSharedPrefs.put(packageName, packagePrefs);
}
// At least one application in the world actually passes in a null
// name. This happened to work because when we generated the file name
// we would stringify it to "null.xml". Nice.
if (mPackageInfo.getApplicationInfo().targetSdkVersion <
Build.VERSION_CODES.KITKAT) {
if (name == null) {
name = "null";
}
}
sp = packagePrefs.get(name);
if (sp == null) {
File prefsFile = getSharedPrefsFile(name); // 这里-----
sp = new SharedPreferencesImpl(prefsFile, mode);
packagePrefs.put(name, sp);
return sp;
}
}
if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
// If somebody else (some other process) changed the prefs
// file behind our back, we reload it. This has been the
// historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly();
}
return sp;
}
@Override
public File getSharedPrefsFile(String name) {
return makeFilename(getPreferencesDir(), name + ".xml");
}
private File getPreferencesDir() {
synchronized (mSync) {
if (mPreferencesDir == null) {
mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
}
return mPreferencesDir;
}
}
可以看到 ContextImpl 中有个变量 mPreferencesDir 保存存储路径,因此通过反射修改该变量即可。
private File mPreferencesDir;
以下为新的更好的一种形式
BaseSharePreference
public class BaseSharePreference {
public static final String PREFERENCE = "base_" + AppCache.getContext().getResources().getString(R.string.app_name) + "_SharePreference";
private static BaseSharePreference instance = null;
private SharedPreferences mPreference;
public static BaseSharePreference getInstance() {
if (instance == null) {
instance = new BaseSharePreference();
}
return instance;
}
public BaseSharePreference() {
if (AppCache.getContext() != null) {
try {
mPreference = AppCache.getContext().getSharedPreferences(PREFERENCE, Context.MODE_PRIVATE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public SharedPreferences getPreference() {
return mPreference;
}
public void setValue(String key, Object value) {
if (value == null) {
return;
}
if (value instanceof String) {
mPreference.edit().putString(key, (String) value).apply();
} else if (value instanceof Boolean) {
mPreference.edit().putBoolean(key, (Boolean) value).apply();
} else if (value instanceof Integer) {
mPreference.edit().putInt(key, (Integer) value).apply();
} else if (value instanceof Long) {
mPreference.edit().putLong(key, (Long) value).apply();
} else if (value instanceof Float) {
mPreference.edit().putFloat(key, (Float) value).apply();
} else if (value instanceof Set) {
//noinspection unchecked
mPreference.edit().putStringSet(key, (Set<String>) value).apply();
}
}
public boolean getBooleanValue(String key, boolean... value) {
if (value != null && value.length > 0) {
boolean result = value[0];
return mPreference.getBoolean(key, result);
}
return mPreference.getBoolean(key, false);
}
public float getFloatValue(String key, Float... value) {
if (value != null && value.length > 0) {
float result = value[0];
return mPreference.getFloat(key, result);
}
return mPreference.getFloat(key, 0f);
}
public int getIntValue(String key, int... value) {
if (value != null && value.length > 0) {
int result = value[0];
return mPreference.getInt(key, result);
}
return mPreference.getInt(key, 0);
}
public long getLongValue(String key, Long... value) {
if (value != null && value.length > 0) {
long result = value[0];
return mPreference.getLong(key, result);
}
return mPreference.getLong(key, 0l);
}
public String getStringValue(String key, String... value) {
if (value != null && value.length > 0) {
String result = value[0];
return mPreference.getString(key, result);
}
return mPreference.getString(key, "");
}
public Set<String> getSetValue(String key) {
return mPreference.getStringSet(key, null);
}
public void setBaseBean(BaseBean update) {
try {
String info = JSONObject.toJSONString(update);
setValue("base_bean", info);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setObject(String key, Object obj) {
String info = JSONObject.toJSONString(obj);
setValue(key, info);
}
public Object getObject(String key, Class cls) {
if (!getStringValue(key, "").equals("")) {
return JSONObject.parseObject(getStringValue(key, ""), cls);
}
return null;
}
public BaseBean getBaseBean() {
try {
if (!getStringValue("base_bean", "").equals("")) {
BaseBean info = JSONObject.parseObject(getStringValue("appUpdateinfo", ""), BaseBean.class);
return info;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void clearAll() {
try {
mPreference.edit().clear().apply();
} catch (Exception e) {
e.printStackTrace();
}
}
}
AppSharePreference
public class AppSharePreference extends BaseSharePreference {
private static String SHARED_KEY_SETTING_GROUPS_SYNCED = "SHARED_KEY_SETTING_GROUPS_SYNCED";
private static String SHARED_KEY_SETTING_CONTACT_SYNCED = "SHARED_KEY_SETTING_CONTACT_SYNCED";
private static String SHARED_KEY_SETTING_BALCKLIST_SYNCED = "SHARED_KEY_SETTING_BALCKLIST_SYNCED";
private static AppSharePreference instance = null;
public static AppSharePreference getInstance() {
if (instance == null) {
synchronized (AppSharePreference.class) {
instance = new AppSharePreference();
}
}
return instance;
}
private AppSharePreference() {
super();
}
public void setIsChina(boolean isChina) {
setValue("isChina", isChina);
}
public boolean isChina() {
return getBooleanValue("isChina", false);
}
public void setBlacklistSynced(boolean synced) {
setValue(SHARED_KEY_SETTING_BALCKLIST_SYNCED, synced);
}
public boolean isBacklistSynced() {
return getBooleanValue(SHARED_KEY_SETTING_BALCKLIST_SYNCED, false);
}
public void setGroupsSynced(boolean synced) {
setValue(SHARED_KEY_SETTING_GROUPS_SYNCED, synced);
}
public boolean isGroupsSynced() {
return getBooleanValue(SHARED_KEY_SETTING_GROUPS_SYNCED, false);
}
public void setContactSynced(boolean synced) {
setValue(SHARED_KEY_SETTING_CONTACT_SYNCED, synced);
}
public boolean isContactSynced() {
return getBooleanValue(SHARED_KEY_SETTING_CONTACT_SYNCED, false);
}
public boolean isAPKAlreadyOpen(String path) {
return getBooleanValue("APK_ALREADY_OPED" + path, false);
}
public void setAPKAlreadyOpen(String path, boolean value) {
setValue("APK_ALREADY_OPED" + path, value);
}
public void saveLastGetVCodeTime(long mills) {
setValue("LAST_VCODE_GET", mills);
}
public long getLastGetVCodeTime() {
return getLongValue("LAST_VCODE_GET", 0L);
}
}