获取所有SharedPreferences名称及其所有键?

11
我正在制作备份程序,用于将手机中的SharedPreferences数据保存到我自己定义的文件中。但我不知道如何列出所有这些数据,这是我需要做的:
例如,有两个程序使用名称"Program A"和"Program B"保存了他们的SharedPreferences。我需要获取包含这两个名称的字符串数组。然后,我使用"Program A"的getSharedPreferences方法,我需要获取该程序保存的所有键名。
真的可能吗?
编辑1:我不知道手机上有哪些程序/活动。我想要获取每个程序保存的所有键名。就像你备份手机所有数据一样,但只备份SharedPreferences值。
例如:你的手机有10个程序,每个程序创建一个名为Program 1到Program 10的SharedPreferences(当然,它们可以随意命名)。我想获取所有这些Program 1到Program 10的字符串。然后,如果Program 1有5个叫做Key 1到Key 5的键名,我想获取这些键名。
编辑2:根据NikolaMKD的指导,我已经完成了以下操作,但列表返回所有程序,每行都显示"No Preferences",即使在第一次保存SharedPreferences时,我的活动也是如此。
public class Test extends ListActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedPreferences preferences = getSharedPreferences("Test", 1);
        // No matter what name is: Test or the package name
        Editor editor = preferences.edit();
        editor.putInt("TestKey", 0);
        editor.commit();

        List<ResolveInfo> Temp = 
            getPackageManager().queryIntentActivities(
                    new Intent(Intent.ACTION_MAIN, null)
                    .addCategory(Intent.CATEGORY_LAUNCHER), 0);
        String[] App = new String[Temp.size()];
        for (int i = 0; i < Temp.size(); i++) {
            App[i] = Temp.get(i).activityInfo.name;
            FileReader reader = null;
            try {
                reader = new FileReader("/data/data/"
                        + App[i] + "/shared_prefs/" + App[i] + "_preferences.xml");
            } catch (FileNotFoundException e) {
                reader = null;
            }
            if (reader != null)
                App[i] += " (Have Prefereces)";
            else
                App[i] += " (No Prefereces)";
        }
        setListAdapter(new ArrayAdapter<String>(this, R.layout.main, App));
    }



}

你的应用程序听起来需要root权限才能运行。 - Thomas Dignan
@Tom Dignan:我已经获取了root权限! - Luke Vo
@Tom Dignan:嗯,你是指root手机还是软件的root权限?我能通过其他方式解决这个问题吗? - Luke Vo
偏好设置通常对应用程序是私有的,因此除非设备已取得 root 权限,否则您将无法读取任意应用程序的偏好存储。 - Thomas Dignan
1
那不是糟糕的事情,那被称为安全。 - Waza_Be
6个回答

13

获取来自以下路径的所有_preferences.xml:

/data/data/(package)/shared_prefs/(package)_preferences.xml

解析XML,在XML中每个键都有一个名称。我可能误解了您的问题。


数据文件夹在哪里?我该如何读取它?我需要任何权限吗?我甚至无法从“IO文件管理器”或我的电脑中看到这个文件夹。 - Luke Vo
软件包怎么样?我不知道设备上有哪些程序,我想列出它们所有的清单。顺便说一句,从DDMS读取的数据文件夹是一个空文件夹。 - Luke Vo
从以下代码中,你会得到什么输出: List<ResolveInfo> Temp = getPackageManager().queryIntentActivities( new Intent(Intent.ACTION_MAIN, null) .addCategory(Intent.CATEGORY_LAUNCHER), 0); 记录该列表中的项目并查看结果,在DDMS文件浏览器中进行比较。同时尝试迭代所有类型的Intent类别,例如DEFAULT,因为有许多活动会使用它,并可能保存偏好设置。 - Nikola Despotoski
嘿,我需要什么权限吗?我的手机已经取得了root权限,但是当我使用DDMS时,整个data文件夹仍然是空的! - Luke Vo
在模拟器上尝试,模拟器具有对系统数据的根访问权限。如果您在模拟器上成功了,您也将在已获取 root 权限的手机上成功。我从未在实际设备上尝试过... :) - Nikola Despotoski
显示剩余4条评论

6

试试这个:

    Map<String, ?> allPrefs = prefs.getAll(); //your sharedPreference
    Set<String> set = allPrefs.keySet();
    for(String s : set){
        LOG.d(TAG, s + "<" + allPrefs.get(s).getClass().getSimpleName() +"> =  "
                + allPrefs.get(s).toString());
    }

5
使用sharedPreference.getAll();方法,该方法会返回一个Map

4

不要以为这是可能的,你无法读取其他应用程序的 /data/data/ 文件夹。在模拟器上,你可以读取它们,因为你具有 root 访问权限。


如果我的应用程序具有root权限,我可以这样做吗? - Luke Vo
是的,应该。root具有访问/data/data文件夹和子文件夹的权限。共享首选项文件的完整路径为/data/data/[包名]/shared_prefs/[文件名].xml。 - Vector
1
<code>reader = new FileReader("/data/data/" + App[i] + "/shared_prefs/" + App[i] + "_preferences.xml");</code>无法工作,因为XML文件的名称可能与包名称不同。您需要解析/shared_prefs文件夹下的所有文件。 - Vector
感谢您提供的有用信息!我已经完成了程序。 - Luke Vo

0

这是个好问题,我认为没有直接的方法可以做到。最好的方法是将这些名称存储在DefaultSharedPreferences或某种全局数组中,或者如果您知道首选项资源ID,则可以从活动本身检索sharedPreferences:

String packageName = String packageName = context.getPackageName(); 
Resources resources = context.getResources(); 
String sharedPrefName = resources.getResourceEntryName(R.id.PREFERENCES_RESOURCE_ID); 
sharedPrefName = packageName+"_"+sharedPrefName;

不,我的意思是手机上的所有程序,也就是说,我不知道哪些程序/活动保存了它们。我已经编辑了我的帖子以提供更多信息。 - Luke Vo

0
你可以循环遍历你的共享偏好目录中的所有xml文件,并获取所有文件的名称,这些名称是你应用程序中的共享偏好名称。
File src = new File("/data/data/" + BuildConfig.APPLICATION_ID + "/shared_prefs");
if (src.isDirectory()) {
    String files[] = src.list();
    for (int i = 0; i < files.length; i++) {
        if (files[i].contains(".xml")) {
            reloadSharedPreference(context, files[i].replace(".xml", ""));
        }
    }
}

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