Skip to content

Instantly share code, notes, and snippets.

@SeanZoR
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SeanZoR/9152434 to your computer and use it in GitHub Desktop.
Save SeanZoR/9152434 to your computer and use it in GitHub Desktop.
Android - Manage your shared preference with a strings resource file (and secure strings)
import android.content.Context;
import android.provider.Settings;
import android.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
/**
* This is a simple encrypt/decrypt way. It's not 100% secured but gives some security
* Idea from : http://stackoverflow.com/questions/785973/what-is-the-most-appropriate-way-to-store-user-settings-in-android-application
*/
public class BasicStringSecurity implements SecuredPreferenceUtil.SecureStringHandler{
public static final String UTF8 = "utf-8";
private final char[] mSerkit;
/***
* @param serkit The key used when encrypting/decrypting. You will need to reuse this key when encrypting and decrypting
* so make sure you init this value with a persistent value between app initializations, otherwise you will
* lose track of the real values you have used
*
*/
public BasicStringSecurity(char[] serkit) {
mSerkit = serkit;
}
/**
* Use this encryption when the values should be used only inside the scope of the application, since it depends on the device.
* For example - use when a value needs to be scrambled before it's saved to the preferences, and decrypted when read from there.
*/
public String encrypt(Context context, String value) {
if (value == null){
return null;
}
try {
final byte[] bytes = value.getBytes(UTF8);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(mSerkit));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(
Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID).getBytes(UTF8), 20));
return new String(Base64.encode(pbeCipher.doFinal(bytes), Base64.NO_WRAP), UTF8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String decrypt(Context context, String value) {
if (value == null){
return null;
}
try {
final byte[] bytes = Base64.decode(value, Base64.DEFAULT);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(mSerkit));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(
Settings.Secure.getString(context.getContentResolver(),Settings.Secure.ANDROID_ID).getBytes(UTF8), 20));
return new String(pbeCipher.doFinal(bytes),UTF8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.Log;
import java.util.Map;
/**
* This class helps in managing a SharedPreference with automatic use of resource id's,
* and a quick support for apply/commit
*/
@SuppressLint("CommitPrefEdits")
public class PreferenceUtil {
protected Resources mRes;
protected SharedPreferences mPref;
public PreferenceUtil(Resources res, SharedPreferences preferences) {
mRes = res;
mPref = preferences;
}
public boolean isPrefContains(int resId) {
return (mPref.contains(mRes.getString(resId)));
}
public void removePref(int resId) {
mPref.edit().remove(mRes.getString(resId)).commit();
}
public String getString(int resId, String defValue) {
return (mPref.getString(mRes.getString(resId), defValue));
}
public String getString(int resId) {
return getString(resId, null);
}
public void applyString(int resId, String value) {
mPref.edit().putString(mRes.getString(resId), value).apply();
}
public void commitString(int resId, String value) {
mPref.edit().putString(mRes.getString(resId), value).commit();
}
public boolean getBoolean(int resId, boolean defValue) {
return (mPref.getBoolean(mRes.getString(resId), defValue));
}
public boolean getBoolean(int resId) {
return getBoolean(resId, false);
}
public void applyBoolean(int resId, boolean value) {
mPref.edit().putBoolean(mRes.getString(resId), value).apply();
}
public void commitBoolean(int resId, boolean value) {
mPref.edit().putBoolean(mRes.getString(resId), value).commit();
}
public void applyBooleanReverseValue(int resId) {
applyBoolean(resId, !getBoolean(resId));
}
public void commitBooleanReverseValue(int resId) {
applyBoolean(resId, !getBoolean(resId));
}
public int getInt(int resId, int defValue) {
return (mPref.getInt(mRes.getString(resId), defValue));
}
public int getInt(int resId) {
return getInt(resId, Integer.MIN_VALUE);
}
public void applyInt(int resId, int value) {
mPref.edit().putInt(mRes.getString(resId), value).apply();
}
public void commitInt(int resId, int value) {
mPref.edit().putInt(mRes.getString(resId), value).commit();
}
public long getLong(int resId, long defValue) {
return (mPref.getLong(mRes.getString(resId), defValue));
}
public long getLong(int resId) {
return getLong(resId, Long.MIN_VALUE);
}
public void applyLong(int resId, long value) {
mPref.edit().putLong(mRes.getString(resId), value).apply();
}
public void commitLong(int resId, long value) {
mPref.edit().putLong(mRes.getString(resId), value).commit();
}
public float getFloat(int resId, float defValue) {
return (mPref.getFloat(mRes.getString(resId), defValue));
}
public float getFloat(int resId) {
return getFloat(resId, Float.MIN_VALUE);
}
public void applyLong(int resId, float value) {
mPref.edit().putFloat(mRes.getString(resId), value).apply();
}
public void commitLong(int resId, float value) {
mPref.edit().putFloat(mRes.getString(resId), value).commit();
}
/***
* Runs on a map of values (key-value) and inserts into the shared preferences
* This can be used also on values which are maps themselves
* Limitation:
* <ul>
* <li> Can't parse a value which is a list
* <li> Float will be case to Double
* </ul>
* @param map The Map containing values to commit
*/
public void commitMap(Map<String, Object> map) {
SharedPreferences.Editor edit = mPref.edit();
runOverMap(map, edit);
edit.commit();
}
/***
* Runs on a map of values (key-value) and inserts into the shared preferences
* This can be used also on values which are maps themselves
* Limitation:
* <ul>
* <li> Can't parse a value which is a list
* <li> Float will be case to Double
* </ul>
* @param map The Map containing values to apply
*/
public void applyMap(Map<String, Object> map) {
SharedPreferences.Editor edit = mPref.edit();
runOverMap(map, edit);
edit.apply();
}
private void runOverMap(Map<String, Object> map, SharedPreferences.Editor edit) {
for (String key : map.keySet()) {
Object value = map.get(key);
if (value instanceof String) {
edit.putString(key, (String) value);
} else if (value instanceof Boolean) {
edit.putBoolean(key, (Boolean) value);
} else if (value instanceof Integer) {
edit.putInt(key, (Integer) value);
} else if (value instanceof Float) {
edit.putFloat(key, (Float) value);
} else if (value instanceof Double) {
Log.w("PreferenceUtil", "Warning: Converting a Double into a Float");
edit.putFloat(key, (float) ((double) ((Double) value)));
} else if (value instanceof Long) {
edit.putLong(key, (Long) value);
} else if (value instanceof Map) {
// Recursively call next map
runOverMap((Map) value, edit);
} else {
Log.e("PreferenceUtil",
"Trying to enter unknown type inside a shared pref map. type=" +
value.getClass().getSimpleName());
}
}
}
}
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
/**
* This class helps in managing a SharedPreference with automatic use of resource id's,
* a quick support for apply/commit, and using some encryption/decryption of strings
*/
public class SecuredPreferenceUtil extends PreferenceUtil {
private final SecureStringHandler mSecureString;
interface SecureStringHandler{
public String encrypt(Context ctx, String stringToEncrypt);
public String decrypt(Context ctx, String stringToDecrypt);
}
public SecuredPreferenceUtil(Resources res, SharedPreferences preferences, SecureStringHandler secureString) {
super(res, preferences);
mSecureString = secureString;
}
public String getSecuredString(Context ctx, int resId, String defValue) {
return mSecureString.decrypt(ctx, getString(resId, defValue));
}
public String getSecuredString(Context ctx, int resId) {
return getSecuredString(ctx, resId, null);
}
public void applySecuredString(Context ctx, int resId, String value) {
String encryptedValue = mSecureString.encrypt(ctx, value);
mPref.edit().putString(mRes.getString(resId), encryptedValue).apply();
}
public void commitSecuredString(Context ctx, int resId, String value) {
String encryptedValue = mSecureString.encrypt(ctx, value);
mPref.edit().putString(mRes.getString(resId), encryptedValue).commit();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment