Wolf6969
Wolf6969

Reputation: 157

Android: Modify SharedPreferences of another app

I'm trying to write application that must read, modify and save some settings in Shared preferences of another application (data/data/package_name/shared_prefs/file.xml).

This application isn't mine, and I have rooted device for testing.

What android permissions i should add to manifest and how can I access this file and modify it? I know that SharedPreferences are unique to each App/APK, but I need to modify it in root mode.

I have working code to modify xml file on sdcard, but when I change path to "data/data/package_name/shared_prefs/file.xml" it gives me an exception and message

android open failed eacces (permission denied)

Is there a way I can achieve that?

Upvotes: 8

Views: 12161

Answers (5)

Barakuda
Barakuda

Reputation: 788

I had the same problem, I tried everything, every suggestion I found on StackOverflow and other places on the web and nothing helped. I always ended up with the "No permission" error even though my device is rooted.

Finally, I came up with an elegant solution using Xposed.

In my solution below, I'm hooking the onCreate method of the Application class, then I'm getting a hold on the Context of the app I want to edit it's SharedPreferences and then I'm using the Context to edit the SharedPreferences. Here it is:

public class MainXposed implements IXposedHookLoadPackage{
    private static final String TAG = "MainXposed";

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        Log.d( TAG, "handleLoadPackage: loadPackageParam.packageName --> " + loadPackageParam.packageName );
        if ( loadPackageParam.packageName.contains( "com.someapp" ) ) {
    
            findAndHookMethod("android.app.Application", loadPackageParam.classLoader, "onCreate", new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                
                }
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    Log.d( TAG, "afterHookedMethod()" );

                    String pkg = "com.someapp";
                    Application application = ( Application ) param.thisObject;
                    Context someappContext = application.getApplicationContext();
    
                    someappContext.createPackageContext( pkg ,Context.CONTEXT_IGNORE_SECURITY );
                    SharedPreferences someapp_prefs = someappContext.getSharedPreferences(pkg + "_preferences", Context.MODE_PRIVATE );
                    SharedPreferences.Editor editor = someapp_prefs.edit();
                    editor.putString( "some_prefs_key", "someNewValue" );
                    editor.apply();
                }
            });
        }
    }
}

Upvotes: 1

azyoot
azyoot

Reputation: 1172

To actually answer your question, if you have root, you can do it with reflection. I have done it on android 4.1, on other platforms it may work differently. The good thing is that shared preferences is not accessible only by system services, so you can access "hidden" methods via reflection. Put this in a try-catch:

Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", "chmod 777 /data/data/package_name/shared_prefs/package_name_preferences.xml" });
proc.waitFor();
proc = Runtime.getRuntime().exec(new String[] { "su", "-c", "chmod 777 /data/data/package_name/shared_prefs" });
proc.waitFor();
proc = Runtime.getRuntime().exec(new String[] { "su", "-c", "chmod 777 /data/data/package_name" });
proc.waitFor();

File preffile = new File("/data/data/package_name/shared_prefs/package_name_preferences.xml");

Class prefimplclass = Class.forName("android.app.SharedPreferencesImpl");

Constructor prefimplconstructor = prefimplclass.getDeclaredConstructor(File.class,int.class);
prefimplconstructor.setAccessible(true);

Object prefimpl = prefimplconstructor.newInstance(preffile,Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);


Editor editor = (Editor) prefimplclass.getMethod("edit").invoke(prefimpl);
//put your settings here
editor.commit();

Upvotes: 9

Mgamerz
Mgamerz

Reputation: 2900

Unless you're the owner of the other application, you shouldn't be doing this. The only way without root would to have it be world readable, which is depreciated and almost never used.

I doubt anyone is going to give you an answer you want unless you state why you need access.

Upvotes: -3

Shade
Shade

Reputation: 10011

Take a look at this answer:

https://stackoverflow.com/a/13139280/361230

When you use su, you will have the permission to modify whatever you want on the filesystem.

However, I agree with Chris on the fact it's not really nice to do what you want to.

Upvotes: 2

Chris Banes
Chris Banes

Reputation: 31871

You should not be changing the preferences of another app, rooted or not.

Upvotes: -3

Related Questions