Last active
August 29, 2015 13:56
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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