删除 SharedPreferences 文件

27

我允许用户创建多个SharedPreferences文件,但同时也希望他们可以选择删除这些文件。我知道我可以使用内部存储,但这不是我的问题。

我的问题是:“我如何在代码或手动方式下删除一个SharedPreferences文件?(不只是清除其内容)”


2
你尝试过clear()方法吗?我认为它实际上是用于删除存储在共享偏好中的所有值。因此,一旦你提供了这个方法,你的用户将会获得共享偏好的默认值。 - Andro Selva
1
clear()会清空文件,但不会从文件系统中删除文件。一个设计不良的应用程序(像我的)可能会导致许多空文件占用空间。@kirill和@inazaruk的方法似乎适合我。 - Richard Le Mesurier
6个回答

36

如果您通过Context.getSharedPreferences("X")获取SharedPreferences实例,则您的文件将命名为X.xml

它将位于/data/data/com.your.package.name/shared_prefs/X.xml。 您可以从该位置删除该文件。 还要检查/data/data/com.your.package.name/shared_prefs/X.bak文件,如果存在,请也将其删除。

但请注意,SharedPreferences实例将所有数据保存在内存中。 因此,您需要先清除首选项,提交更改,然后再删除首选项备份文件。

这应该足以实现您的设计决策。


5
是的,它可能会将数据保留在内存中一段时间。它可能会检测到文件已被删除并清除自身,但我不建议依赖这一点。至于删除文件,请参阅文档:http://developer.android.com/reference/java/io/File.html#File%28java.lang.String%29。这很容易: File file= new File("/data/data/.../shared_prefs/X.xml"); 然后 file.delete(); - inazaruk
6
对于我上述问题的答案是:不。 - Paul
@Paul 以编程方式删除似乎对我有效(Nexus 7,未root,已签名应用程序)。但是我还没有检查过提交到商店的应用程序... - Richard Le Mesurier
你应该能够删除首选项文件。所有的首选项文件都是以你的应用程序 UID 作为所有者创建的。因此,你的应用程序拥有所有必需的权限。 - inazaruk
2
不要硬编码路径,可以使用 context.getFilesDir().getParent() + File.separator + "shared_prefs"(文件目录是 shared_prefs 目录的同级目录)。 - arlomedia
显示剩余4条评论

32

这里有一个简单的方法可以清除给定上下文的所有SharedPreferences,适用于单元测试。

public static void clearSharedPreferences(Context ctx){
    File dir = new File(ctx.getFilesDir().getParent() + "/shared_prefs/");
    String[] children = dir.list();
    for (int i = 0; i < children.length; i++) {
        // clear each preference file
        ctx.getSharedPreferences(children[i].replace(".xml", ""), Context.MODE_PRIVATE).edit().clear().commit();
        //delete the file
        new File(dir, children[i]).delete();
    }
}

请注意,当您在使用此功能进行 Android 单元测试并在您的 Application 类中使用 sharedpreferences 时,可能会导致竞争条件并且可能无法正常工作。


3
到目前为止我找到的最佳答案。 - Marco
不能依赖硬编码的路径。谁知道Google在下一个Android版本中会做出什么改变。:( - Mohit Atray
非常感谢。我在使用EncryptedSharedPreferences并删除应用程序后重新安装时遇到了AEADBadTagException问题。这是一个简单的解决方案,完全解决了我的问题! - jhwblender

9

Java:

public static boolean deleteSharedPreferences(Context context, String name) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return context.deleteSharedPreferences(name);
    } else {
        context.getSharedPreferences(name, MODE_PRIVATE).edit().clear().apply();
        File dir = new File(context.getApplicationInfo().dataDir, "shared_prefs");
        return new File(dir, name + ".xml").delete();
    }
}

Kotlin:

companion object {
    fun deleteSharedPreferences(context: Context, name: String): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return context.deleteSharedPreferences(name)
        } else {
            context.getSharedPreferences(name, MODE_PRIVATE).edit().clear().apply()
            val dir = File(context.applicationInfo.dataDir, "shared_prefs")
            return File(dir, "$name.xml").delete()
        }
    }
}

1
不要使用apply(),它可能会导致竞态条件。请改用commit() - Mohit Atray

9
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    context.deleteSharedPreferences(preferencesKey);
} else {
    try {
        org.apache.commons.io.FileUtils.cleanDirectory(new File(context.getCacheDir().getParent() + "/shared_prefs/"));
    } catch (IOException e) {
        Log.e(TAG, "Cannot delete files in shared pref directory", e);
    }
}

FileUtils 是什么? - azizbekian
@azizbekian FileUtils 是 Apache Commons IO 库中的实用工具类。可以通过 implementation 'commons-io:commons-io:2.6' 引入该库。 - hasnain_ahmad

4

这很简单!

您的默认SD卡偏好设置XML文件路径可能是:/data/data/您的包名/shared_prefs/您的共享偏好设置XML文件

例如:/data/data/com.hirecraft.hirecraftmanager/shared_prefs/swipe_preferences.xml

删除偏好设置XML文件:

File deletePrefFile = new File("/data/data/com.hirecraft.hirecraftmanager/shared_prefs/swipe_preferences.xml");
deletePrefFile.delete();

或者像这样获取文件路径字符串,

String filePath = getApplicationContext().getFilesDir().getParent()+"/shared_prefs/swipe_preferences.xml";
File deletePrefFile = new File(filePath );
 deletePrefFile.delete();

第二个选项是错误的。getApplicationContext()。getFilesDir()。getPath()+“ /”+“ shared_prefs /”导致/ data / data / com.hirecraft.hirecraftmanager / files / shared_prefs / swipe_preferences.xml!shared_prefs文件夹不在files文件夹下。对于第二个选项进行反对票。 - goseib
1
第二个选项是错误的。 getApplicationContext().getFilesDir()。getPath()+“ /”+“ shared_prefs /”导致/data/data/com.hirecraft.hirecraftmanager/files/shared_prefs/swipe_preferences.xml !!! shared_prefs文件夹不在files文件夹下。 用getParent()替换getPath()。 因为您的不友好态度而踩反对票! - goseib

0
我发现(在Android 12中,原始问题的几年后),如果我在某些代码编辑首选项值后不久删除共享首选项文件,应用新的首选项可能直到我删除文件后才完成,此时Android将重新创建具有所有先前值的文件。
当我按照@inazaruk的建议在删除文件之前清除首选项时,也发生了这种情况,因为我在那里使用了apply()。也许如果我使用commit()而不是apply(),这不会引起问题,但我发现在我的情况下不需要清除首选项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接