Copy the shared preferences XML file from /data on Samsung device failed

前端 未结 6 758
粉色の甜心
粉色の甜心 2020-12-09 20:46

There\'s an exporting feature in my application. It\'s just a copy operation since all my settings are store in shared preference.

I just copy the xml file from /da

相关标签:
6条回答
  • 2020-12-09 21:03

    CommonsWare's suggestion would a be clever hack, but unfortunately it won't work.

    Samsung does not always put the shared_prefs directory in the same parent directory as the getFilesDir().

    I'd recommend testing for the existence of (hardcode it, except for package name): /dbdata/databases/<package_name>/shared_prefs/package.name_preferences.xml and if it exists use it, otherwise fall back to either CommonsWare's suggestion of new File(getFilesDir(), "../shared_prefs") or just /data/data/<package_name>/shared_prefs/package.name_preferences.xml.

    A warning though that this method could potentially have problems if a user switched from a Samsung rom to a custom rom without wiping, as the /dbdata/databases file might be unused but still exist.

    More details

    On some Samsung devices, such as the Galaxy S series running froyo, the setup is this:

    /data/data/<package_name>/(lib|files|databases)

    Sometimes there's a shared_prefs there too, but it's just Samsung's attempt to confuse you! Don't trust it! (I think it can happen as a left over from a 2.1 upgrade to 2.2, but it might be a left over from users switching roms. I don't really know, I just have both included in my app's bug report interface and sometimes see both files).

    And:

    /dbdata/databases/<package_name>/shared_prefs

    That's the real shared_prefs directory.

    However on the Galaxy Tab on Froyo, it's weird. Generally you have: /data/data/<package_name>/(lib|shared_prefs|files|databases)

    With no /dbdata/databases/<package_name> directory, but it seems the system apps do have: /dbdata/databases/<package_name>/yourdatabase.db

    And added bonus is that /dbdata/databases/<package_name> is not removed when your app is uninstalled. Good luck using SharedPreferences if the user ever reinstalls your app!

    0 讨论(0)
  • 2020-12-09 21:04

    You have to create the shared_prefs directory:

    try{
        String dir="/data/data/package.name/shared_prefs";
    
        // Create one directory
        boolean success = (new File(dir)).mkdirs();
        if (success) {
          // now copy the file
        }
    
    }catch (Exception e){//Catch exception if any
        System.err.println("Error: " + e.getMessage());
    }
    

    Also... the package of your app is package.name? Make sure you are referring to the right package.

    0 讨论(0)
  • 2020-12-09 21:05

    Best way to get valid path on all devices - run method Context.getSharedPrefsFile defined as:

    /**
     * {@hide}
     * Return the full path to the shared prefs file for the given prefs group name.
     *
     * <p>Note: this is not generally useful for applications, since they should
     * not be directly accessing the file system.
     */
    public abstract File getSharedPrefsFile(String name);
    

    Because of it hidden need use reflection and use fallback on fail:

    private File getSharedPrefsFile(String name) {
        Context context = ...;
        File file = null;
        try {
            if (Build.VERSION.SDK_INT >= 24) {
                try {
                    Method m = context.getClass().getMethod("getSharedPreferencesPath", new Class[] {String.class});
                    file = (File)m.invoke(context, new Object[]{name});
                } catch (Throwable e) {
                    Log.w("App TAG", "Failed call getSharedPreferencesPath", e);
                }
            }
    
            if (file == null) {
                Method m = context.getClass().getMethod("getSharedPrefsFile", new Class[] {String.class});
                file = (File)m.invoke(context, new Object[]{name});
            }
        } catch (Throwable e) {
            Log.w("App TAG", "Failed call getSharedPrefsFile", e);
    
            file = new File(context.getFilesDir(), "../shared_prefs/" + name + ".xml");
        }
        return file;
    }
    

    On some Samsungs implements like this:

    public File getSharedPrefsFile(String paramString) {
        return makeFilename(getPreferencesDir(), paramString + ".xml");
    }
    
    private File getPreferencesDir() {
        synchronized (this.mSync) {
            if (this.mPreferencesDir == null) {
                this.mPreferencesDir = new File("/dbdata/databases/" + getPackageName() + "/", "shared_prefs");
            }
            File localFile = this.mPreferencesDir;
            return localFile;
        }
    }
    

    On other Android like this:

    public File getSharedPrefsFile(String name) {
        return makeFilename(getPreferencesDir(), name + ".xml");
    }
    
    private File getPreferencesDir() {
        synchronized (mSync) {
            if (mPreferencesDir == null) {
                mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
            }
            return mPreferencesDir;
        }
    }
    
    private File getDataDirFile() {
        if (mPackageInfo != null) {
            return mPackageInfo.getDataDirFile();
        }
        throw new RuntimeException("Not supported in system context");
    }
    

    After while Google change API for level 24 and later: https://android.googlesource.com/platform/frameworks/base/+/6a6cdafaec56fcd793214678c7fcc52f0b860cfc%5E%21/core/java/android/app/ContextImpl.java

    0 讨论(0)
  • 2020-12-09 21:14

    Never never never never never never never never never hardwire paths.

    Unfortunately, there's no getSharedPreferenceDir() anywhere that I can think of. The best solution I can think of will be:

    new File(getFilesDir(), "../shared_prefs")
    

    This way if a device manufacturer elects to change partition names, you are covered.

    Try this and see if it helps.

    0 讨论(0)
  • 2020-12-09 21:22

    Try using

    context.getFilesDir().getParentFile().getAbsolutePath()
    
    0 讨论(0)
  • 2020-12-09 21:26

    I've tested in Samsung P1010 with:

    //I'm in a IntentService class

    File file = this.getDir("shared_prefs", MODE_PRIVATE);

    I got: "/data/data/package.name/app_shared_prefs"

    It works fine to me. I can run ffmpeg in this folder.

    Look:

    Context.getDir

    0 讨论(0)
提交回复
热议问题