public final class CryptoSharedPreferences extends Object implements android.content.SharedPreferences
SharedPreferences implementation that supports encryption for both keys
and values that are persisted in shared preferences. New instances of CryptoSharedPreferences
may be created via CryptoSharedPreferences.Builder and its CryptoSharedPreferences.Builder.build() method.
CryptoSharedPreferences is the fact that all values
persisted via these preferences implementation are encrypted. Encryption of values stored
in shared preferences should improve security standards of an Android application as the encrypted
values that are stored within a corresponding preferences Xml file are obscured so any
possible attacker that gains access to preferences files containing encrypted values will have
hard time reading them. Each instance of CryptoSharedPreferences is required to be created
with at least Crypto implementation that will be used for values encryption and decryption.
A desired Crypto should be supplied via CryptoSharedPreferences.Builder.valueCrypto(Crypto) otherwise
the builder will throw an exception if a new instance of crypto preferences is tried to be created
via CryptoSharedPreferences.Builder.build(). See other sections of this description to get more info.
Below snippet shows contents of a shared preferences Xml without and with encryption applied to both keys and values:
<!-- Preference data without encryption applied. -->
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<map>
<string name="universum.studios.android.preference.crypto.PREFERENCE.UserName">
Android User
</string>
<long name="universum.studios.android.preference.crypto.PREFERENCE.UserBirthDate">
1490986235741
</long>
</map>
<!-- Preference data with encryption applied. -->
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<map>
<string name="dW5pdmVyc3VtLnN0dWRpb3MuYW5kcm9pZC5wcmVmZXJlbmNlLmNyeXB0by5QUkVGRVJFTkNFLlVzZXJOYW1l">
QW5kcm9pZCBVc2Vy
</string>
<string name="dW5pdmVyc3VtLnN0dWRpb3MuYW5kcm9pZC5wcmVmZXJlbmNlLmNyeXB0by5QUkVGRVJFTkNFLlVzZXJCaXJ0aERhdGU=">
MTQ5MDk4NjIzNTc0MQ==
</string>
</map>
Crypto
implementation should be supplied via CryptoSharedPreferences.Builder.keyCrypto(Crypto) for CryptoSharedPreferences.
The specified crypto will be then used by the crypto preferences for encryption of preference keys
whenever a preference value is requested to be persisted or obtained and for decryption whenever
a change callback for registered OnSharedPreferenceChangeListener is about to be dispatched
(see paragraph below).
In order to receive callback of OnSharedPreferenceChangeListener with instance of
crypto preferences along with decrypted key so the listener does
not need to deal with either key nor value decryption such listener should be registered via
SharedPreferences.registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener) and later
unregistered via SharedPreferences.unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener).
Then each listener's callback
will cary instance of the crypto preferences and already decrypted key of which associated value
has changed. The changed value may be obtained in a standard fashion via one of get...(...)
methods directly via the dispatched preferences instance like shown below:
CryptoSharedPreferences.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(@NonNull SharedPreferences preferences, @NonNull String key) {
// ... preferences are actually CryptoSharedPreferences and the key is already decrypted
switch (key) {
SamplePreferenceKey.USER_NAME:
final String userName = preferences.getString(key, "Unknown");
// ... userName will contain decrypted value
break;
// ... handle changes for other preference keys
}
}
});
get...(...)
methods need to be always decrypted, obtaining of such values may be potentially a time consuming
task. In order to speed up this operation an implementation of SharedPreferencesCache may
be supplied via CryptoSharedPreferences.Builder.valueCache(SharedPreferencesCache) for CryptoSharedPreferences.
Such cache will be then used by the crypto preferences for storing of already decrypted values
which may be retrieved whenever they are requested in a much faster fashion. When cache is used
it is simply asked if it contains value for the requested key, if YES, that value is returned, if
NO, an encrypted value is obtained from the wrapped preferences, decrypted, stored in the cache
and returned. A specific value stored in the cache is invalidated (evicted from the cache) whenever
a new edit session is started for key associated with that value, that is whenever edit()
is called and followed by put...(...) call with that key.
In order to speed up obtaining of preference values that need to be decrypted whenever they are
to be returned to the caller where this task may potentially a time consuming operation| Modifier and Type | Class and Description |
|---|---|
static class |
CryptoSharedPreferences.Builder
Builder that may be used to create instances of
CryptoSharedPreferences with a desired
configuration. |
| Modifier and Type | Method and Description |
|---|---|
boolean |
contains(String key) |
android.content.SharedPreferences.Editor |
edit() |
Map<String,?> |
getAll() |
boolean |
getBoolean(String key,
boolean defValue) |
float |
getFloat(String key,
float defValue) |
int |
getInt(String key,
int defValue) |
long |
getLong(String key,
long defValue) |
String |
getString(String key,
String defValue) |
Set<String> |
getStringSet(String key,
Set<String> defValues) |
void |
registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener listener) |
void |
unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener listener) |
public void registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener listener)
registerOnSharedPreferenceChangeListener in interface android.content.SharedPreferencespublic void unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener listener)
unregisterOnSharedPreferenceChangeListener in interface android.content.SharedPreferencespublic Map<String,?> getAll()
getAll in interface android.content.SharedPreferencespublic boolean contains(String key)
contains in interface android.content.SharedPreferencespublic String getString(String key, String defValue)
getString in interface android.content.SharedPreferencespublic Set<String> getStringSet(String key, Set<String> defValues)
getStringSet in interface android.content.SharedPreferencespublic int getInt(String key, int defValue)
getInt in interface android.content.SharedPreferencespublic long getLong(String key, long defValue)
getLong in interface android.content.SharedPreferencespublic float getFloat(String key, float defValue)
getFloat in interface android.content.SharedPreferencespublic boolean getBoolean(String key, boolean defValue)
getBoolean in interface android.content.SharedPreferencespublic android.content.SharedPreferences.Editor edit()
edit in interface android.content.SharedPreferences