轻作



重拾写作的乐趣

Xposed XSharedPreferences在安卓N以后及解决方案

2020.03.03

由于在Android 7 (SDK 24) 及以后 Context.MODE_WORLD_READABLE 被废弃
导致Xposed XSharedPreference不可用

  1. 使用RemotePreferences, 但是需要Context

  2. 使用Context.createDeviceProtectedStorageContext()
    把文件储存到/data/user_de/0/包名/shared_prefs/名称.xml, 然后再修复权限

    @SuppressWarnings("ConstantConditions")
    public static String getSharedPrefsPath() {
        if (prefsPathCurrent == null) try {
            Field fFile = prefs.getClass().getDeclaredField("mFile");
            fFile.setAccessible(true);
            prefsPathCurrent = ((File) fFile.get(prefs)).getParentFile().getAbsolutePath();
            return prefsPathCurrent;
        } catch (Throwable t) {
            return prefsPath;
        }
        else return prefsPathCurrent;
    }

    @SuppressWarnings("ConstantConditions")
    public static String getSharedPrefsFile() {
        if (prefsFileCurrent == null) try {
            Field fFile = prefs.getClass().getDeclaredField("mFile");
            fFile.setAccessible(true);
            prefsFileCurrent = ((File) fFile.get(prefs)).getAbsolutePath();
            return prefsFileCurrent;
        } catch (Throwable t) {
            return prefsFile;
        }
        else return prefsFileCurrent;
    }
    
    @SuppressLint({"SetWorldReadable", "SetWorldWritable"})
    public static void fixPermissionsAsync(Context context) {
        AsyncTask.execute(() -> {
            try {
                Thread.sleep(500);
            } catch (Throwable ignore) {
            }
            File pkgFolder = context.getDataDir();
            if (pkgFolder.exists()) {
                pkgFolder.setExecutable(true, false);
                pkgFolder.setReadable(true, false);
                pkgFolder.setWritable(true, false);
            }
            File sharedPrefsFolder = new File(Helpers.getSharedPrefsPath());
            if (sharedPrefsFolder.exists()) {
                sharedPrefsFolder.setExecutable(true, false);
                sharedPrefsFolder.setReadable(true, false);
                sharedPrefsFolder.setWritable(true, false);
            }
            File sharedPrefsFile = new File(Helpers.getSharedPrefsFile());
            if (sharedPrefsFile.exists()) {
                sharedPrefsFile.setReadable(true, false);
                sharedPrefsFile.setExecutable(true, false);
                sharedPrefsFile.setWritable(true, false);
            }
        });
    }
  • 摘自 CustoMIUIzerMod
    但是此方法在 Android 9 (SDK 28) 及以上的部分机型, 会因为Selinux的限制导致出现部分情况异常.
  1. 如果运行在LSPosed或者EdXposed下, 可直接使用XSharedPreferences
<meta-data android:name="xposedminversion" android:value="93" />
<meta-data android:name="xposedsharedprefs" android:value="true" />
  • 参考

LSPosed: New XSharedPreferences EdXposed: New XSharedPreferences

其他参考资料

XSharedPreference & SharedPreference - XPosed模块中的preference使用 Xposed–Android N 以上 XSharedPreferences

发表评论