android - Delete shared preferences using an adb command

android - Delete shared preferences using an adb command

Shayne Misti Author: Shayne Misti Date: 2022-10-05
android - Delete shared preferences using an adb command

All you need to know about android - Delete shared preferences using an adb command , in addintion to Android: How to properly suppress Lint warning - "Consider using apply()" - when calling commit() on SharedPreferences.Editor? , android - SharedPreferences are sometimes deleted , unity3d - Using shared preferences between unity and native android sdk , android - Using a custom subclass of SharedPreferences with PreferenceActivity or PreferenceFragment

  1. android - Delete shared preferences using an adb command
  2. Question:

    I need to delete a shared preferences file using an adb command. Is there a way to do that without uninstalling the app?

    I could not find anything that did it?


    Solution 1:

    If you want to clear all the preferences, a single command will do it:

    adb shell pm clear <package name>

    Solution 2:

    Definitely not on an unrooted phone. On normal consumer builds (user builds), only the application itself can access the app's data.

    If you have root, you can access the shell via

    adb shell
    

    Then navigate to the app's data directory (/data/data/<package name>), find the file and rm it.

    Alternatively, you can do it all at once with

    adb shell rm /data/data/<package name>/<file name> 
    

    Solution 3:

    You can try this on a DEBUG application only:

    $ adb shell
    $ adb run-as mypackagename
    
    $ cd /data/data/mypackagename/shared_prefs
    

    //then remove whatever you want

  3. Android: How to properly suppress Lint warning - "Consider using apply()" - when calling commit() on SharedPreferences.Editor?
  4. Question:

    I need to commit() rather than apply() my changes to my SharedPreferences.Editor:

    SharedPreferences sharedPrefs = getSharedPreferences("MY_SHARED_PREFS_FILE_NAME", Context.MODE_PRIVATE);
    SharedPreferences.Editor sharedPrefsEditor = sharedPrefs.edit();
    sharedPrefsEditor.putBoolean("MY_BOOLEAN", true);
    sharedPrefsEditor.commit(); // <-- I get the Lint warning on this line.
    

    But Lint gives me this warning:

    Consider using apply instead; commit writes its data to persistent storage immediately, whereas apply will handle it in the background...

    How do I suppress that Lint warning?

    Adding @SuppressWarnings("all") before my method signature suppresses the warning, but is there a more specific String I can use instead of "all"? (Could not find anything here.)


    Solution 1:

    @SuppressLint("ApplySharedPref") works for me.

    Any time you need to suppress a lint, what you have to do is to find the Lint issue id and pass it to this annotation.

    You can find it by going to File > Settings > Editor > Code Style > Inspections > Android > Lint. There you can search for the lint you want to suppress and, after selection it, you will be able to see its issue id on the Description area.

  5. android - SharedPreferences are sometimes deleted
  6. Question:

    My app uses SharedPreferences (with the help of a PreferenceActivity) to store all settings. But sometimes all settings are deleted and all values are set back to default. Mostly on Android 3.x tabs. On normal smartphones there are no problems.

    I have observed that all settings are deleted when the application process is killed by Android. I noticed this because the notification icon is no longer displayed. I also wonder why the process is killed on tablets and not on smartphones. On my smartphone the notification icon never disappears.

    My app also has a service, the main process and the service both read and write settings to the SharedPreferences. I've sometimes noticed that all settings are cleared once the service writes to the SharedPreferences. But it does not happen every time.

    Any ideas? I realize that the SharedPreferences should not be used by different processes, but it works on all smartphones without problems!


    Solution 1:

    I found out the reason why the settings disappear: If two processes write data to SharedPreferences, it can happen that all SharedPreferences are reset to default values. In my case all settings are cleared when the service write the first data to SharedPreferences.

    Now, the service provides only read access to the SharedPreferences. The settings that are accessed by both processes writing are stored in a database.

    Solution 2:

    Solution 3:

    I have had the same issue. All values from shared preferences become default if one value occasionally written with key = null. This is possible when you creating new constants using Eclipse, which inits them with null by default, and then you forgot to go to the beginning of the class and change constant to some meaningful value. If you continue using the app, read operation of shared preferences will return valid values. But when context is changed(for example, when activity killed by android and recreated) all values from shared preferences will return default values(zeroes).

    So check your shared preferences's keys! I hope this answer will help someone.

  7. unity3d - Using shared preferences between unity and native android sdk
  8. Question:

    I am working on an app using native android sdk development. However I have a co-worker who is working on Unity.

    I would like to create an activity A that would does some work and then call another activity B.

    My coworker is creating Activity B screen using Unity.

    Both activities will be using shared preferences (reading and writing to it)

    Is there way that this can be accomplished?

    Thank you so much


    Solution 1:

    You'd need to write a plugin for Android to get this to work. While the official doc is great to get started, here's some sample code you can use after you've gone through it.

    I won't go into details about how to create the plugin, because that's pretty well documented on the Unity website (link given by nexx)

    In the below example, I've just written a couple of methods. You can modify them to accept and return other data types, or better make them generic.

    Native Android Code

    public static final String PREFS_NAME = "MyPrefsFile";
    
    public void setPreferenceString (String prefKey, String prefValue) {
        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(prefKey, prefValue);
        editor.commit();
    
    }
    
    public String getPreferenceString (String prefKey) {
        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        String playerName = settings.getString(prefKey, "");
        return playerName;
    }
    



    Now, on Unity C# side, your plugin will have code like this

        AndroidJavaObject AJO = null;
    
    public void SetPreferenceString (string prefKey, string prefValue) {
        if(AJO == null)
            AJO = new AndroidJavaObject("com.yourcompany.productname.activity", new object[0]);
    
        AJO.Call("setPreferenceString", new object[] { prefKey, prefValue } );
    }
    
    public string GetPreferenceString (string prefKey) {
        if(AJO == null)
            AJO = new AndroidJavaObject("com.yourcompany.productname.activity", new object[0]);
    
        if(AJO == null)
            return string.Empty;
        return AJO.Call<string>("getPreferenceString", new object[] { prefKey } );
    }
    



    Usage in Unity

    //Setting a player's name to be "John Doe"
    void Start () {
        SetPreferenceString("playerName", "John Doe");
    }
    
    //Get the stored player's name
    string GetPlayerName () {
        return GetPreferenceString("playerName");
    }
    




    This is by no means the best way of writing the plugin. It should, however give you a fair idea how to handle SharedPrefs.

    Obviously, ensure that both of you are using the same preferences!

  9. android - Using a custom subclass of SharedPreferences with PreferenceActivity or PreferenceFragment
  10. Question:

    I'm using a custom subclass of SharedPreferences to encrypt my saved settings in the app, similar to what's being done in the second response here: What is the most appropriate way to store user settings in Android application

    The number of preferences I have to save is growing. Before I was just using a custom view to update these preferences but that is going to become cumbersome and I want to use PreferenceActivity or PreferenceFragment instead. Problem is, it does not seem that there is a way to have either of those classes access my data using my subclass, meaning that the data it pulls from the default preferences file is going to be gibberish as it wasn't decrypted.

    I've found that some people have created custom implementations of Preference that encrypt the data there, but I'd prefer not to do that as the data is already being encrypted/decrypted in my SharedPreferences subclass and I'd like to keep it that way. I've also been looking over the source code of PreferenceActivity and PreferenceManager and I'm not sure the best way to approach this.

    Has anyone else had any luck accomplishing something like this and have any suggestions as to where I might start?


    Solution 1:

    I think by keeping your encryption in the SharedPrefs subclass that you already have, you limit the modularity and the separation of concerns.

    So I would suggest reconsidering sub-classing the preference classes themselves (such as CheckBoxPreference) and perform your calculation there.

    Ideally you could also use some type of composition or a static utility so that while you might have to subclass each type of preference you use, you can use a single place to perform the encryption/decryption calculations. This would also allow you more flexibility in the future if you need to encrypt or decrypt some other data or if the API changes.

    For sub-classing maybe you could do this:

    So for example:

    class ListPreferenceCrypt extends ListPreference
    {
        ListPreferenceCrypt (Context context, AttributeSet attrs)   {
            super ( context, attrs );
        }
        ListPreferenceCrypt (Context context)   {
            super ( context );
        }
    
        @Override
        public void setValue( String value )
        {
            //encrypt value
            String encryptedVal = MyCryptUtil.encrypt(value);
            super.setValue ( encryptedVal );
        }
    
        @Override
        public String getValue( String key )
        {
            //decrypt value
            String decryptedValue = MyCryptUtil.decrypt(super.getValue ( key ));
            return decryptedValue;
        }
    
    }
    

    NOTE the above is psuedo-code, there would be different methods to override


    And your XML might look like this:

    <PreferenceScreen
            xmlns:android="http://schemas.android.com/apk/res/android">
    
        <PreferenceCategory
                android:title="@string/inline_preferences">
    
            <com.example.myprefs.ListPreferenceCrypt
                    android:key="listcrypt_preference"
                    android:title="@string/title_listcrypt_preference"
                    android:summary="@string/summary_listcrypt_preference" />
    
        </PreferenceCategory>
    
    </PreferenceScreen>
    

    EDIT

    Caveats/Decompiling

    As I thought about this more, I realized one of the caveats is that this method is not particularly difficult to bypass when decompiling an APK. This does give the full class names of overriden classes in the layouts (though that can be avoided by not using XML)

    However, I don't think this is significantly less secure than sub-classing SharedPreferences. That too, is susceptible to decompiling. Ultimately, if you want stronger security, you should consider alternative storage methods. Perhaps OAuth or the AccountManager as suggested in your linked post.

    Solution 2:

    How about this:

    • Store a byte[16] in a .SO. If you do not use a .SO then make one just for that purpose.
    • Use that byte array to crypt a new byte[16] then Base64 encode the result. Hardcode that in your class file.

    Now that you've setup the keys let me explain:

    Yes, potentially one could peek into the .SO and find the byte array ergo your key. But with the cyphered key2 being base64 encoded, he would need to decode it and reverse the encryption with the said key to extract key2 bytes. So far this only involves dissassembling the app.

    • When you want to store encrypted data, first do a AES pass with key1, then a AES/CBC/Padding5 pass with Key2 and an IV*
    • You can safely Base64 encode the IV and save it like that in your /data/data folder if you'd like to change the IV every time a new password is stored.

    With these two steps disassembling the app is no longer the only thing required, as it's now required to also take control of your runtime to get to the crypted data. Which you have to say is pretty sufficient for a stored password.

    Then you could simply store that into SharedPreferences :) That way if your SharedPreferences get compromised, the data is still locked away. I don't think subclassing it is really the right approach but since you already wrote your class - oh well.

    Here's some code to further illustrate what I mean

    //use to encrypt key
    public static byte[] encryptA(byte[] value) throws GeneralSecurityException, IOException
    {
        SecretKeySpec sks = getSecretKeySpec(true);
        System.err.println("encrypt():\t" + sks.toString());
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, sks, cipher.getParameters());
        byte[] encrypted = cipher.doFinal(value);
        return encrypted;
    }
    
    //use to encrypt data
    public static byte[] encrypt2(byte[] value) throws GeneralSecurityException, IOException
    {
        SecretKeySpec key1 = getSecretKeySpec(true);
        System.err.println("encrypt():\t" + key1.toString());
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, key1, cipher.getParameters());
        byte[] encrypted = cipher.doFinal(value);
    
        SecretKeySpec key2 = getSecretKeySpec(false);
        System.err.println("encrypt():\t" + key2.toString());
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key2, new IvParameterSpec(getIV()));
        byte[] encrypted2 = cipher.doFinal(encrypted);
    
        return encrypted2;//Base64Coder.encode(encrypted2);
    }
    //use to decrypt data
    public static byte[] decrypt2(byte[] message, boolean A) throws GeneralSecurityException, IOException
    {
        SecretKeySpec key1 = getSecretKeySpec(false);
        System.err.println("decrypt():\t" + key1.toString());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key1, new IvParameterSpec(getIV()));
        byte[] decrypted = cipher.doFinal(message);
    
        SecretKeySpec key2 = getSecretKeySpec(true);
        System.err.println("decrypt():\t" + key2.toString());
        cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, key2);
        byte[] decrypted2 = cipher.doFinal(decrypted);
    
        return decrypted2;
    }
    
        //use to decrypt key
    public static byte[] decryptKey(String message, byte[] key) throws GeneralSecurityException
    {
        SecretKeySpec sks = new SecretKeySpec(key, ALGORITHM);
        System.err.println("decryptKey()");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, sks);
        byte[] decrypted = cipher.doFinal(Base64Coder.decode(message));
        return decrypted;
    }
    
    //method for fetching keys
    private static SecretKeySpec getSecretKeySpec(boolean fromSO) throws NoSuchAlgorithmException, IOException, GeneralSecurityException
    {
        return new SecretKeySpec(fromSO ? getKeyBytesFromSO() : getKeyBytesFromAssets(), "AES");
    }
    

    What do you think?

    I realize it might be off topic since you're asking about using your own SharedPreferences but I'm giving you a working solution to the problem of storing sensitive data :)