获取方式
SharedPreferences一个轻量级的存储类适合用于保存软件配置参数,实际上是用xml文件存放数据,文件存保存在/data/data/<package name>/shared_prefs/
获取SharedPreferences有以下三种方式
- ContextWrapper.getSharedPreferences(String name, int mode)
- PreferenceManager.getDefaultSharedPreferences(Context context)
- Activity.getPreferences(int mode)
第一种方式是最常用的,指定偏好文件的名称,名称中不需要包含后缀xml,同时指定偏好文件的作用范围mode。
第二种获取默认的偏好文件, 是使用默认的名称(应用包名+_preferences)和默认的Mode返回(Context.MODE_PRIVATE),源码参考:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public static SharedPreferences getDefaultSharedPreferences(Context context) { return context.getSharedPreferences(getDefaultSharedPreferencesName(context), getDefaultSharedPreferencesMode()); } public static String getDefaultSharedPreferencesName(Context context) { return context.getPackageName() + "_preferences"; } private static int getDefaultSharedPreferencesMode() { return Context.MODE_PRIVATE; }
第三种是Activity特有的,实际上是使用Activity的类名作为偏好文件的名称,意味着同样的类获取到的是同一个偏好文件,不同的类获取到不同的偏好文件,源码参考:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public SharedPreferences getPreferences(int mode) { return getSharedPreferences(getLocalClassName(), mode); } /** * Returns class name for this activity with the package prefix removed. * This is the default name used to read and write settings. * * @return The local class name. */ @NonNull public String getLocalClassName() { final String pkg = getPackageName(); final String cls = mComponent.getClassName(); int packageLen = pkg.length(); if (!cls.startsWith(pkg) || cls.length() <= packageLen || cls.charAt(packageLen) != '.') { return cls; } return cls.substring(packageLen+1); }
MODE类型
mode主要以下值:
MODE_PRIVATE 文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
MODE_APPEND 模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。,注意这个在SharePreference中其实是没有效果的,以下会论证。
MODE_ENABLE_WRITE_AHEAD_LOGGING
以下三个由于不安全,
已被遗弃,官方不推荐使用
MODE_WORLD_READABLE 表示当前文件可以被其他应用读取
MODE_WORLD_WRITEABLE 表示当前文件可以被其他应用写入。
MODE_MULTI_PROCESS 多进程的访问
注:可以组合使用Context.MODE_APPEND+Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE
导出文件
下面补充下查看、导出偏好文件或者数据库文件的方法
1、打开Android Sudio ---> Tools ---> Android ----> Android Device Monitor ----> File Explore
此时应该能看到data目录,但是点开没有任何东西,这是因为android每个文件或文件夹都是有权限控制的,在File Explore窗口中有一栏为Permissions就是说明对该文件或文件夹的权限,如果权限满足应该如下图:
![](https://images2015.cnblogs.com/blog/588729/201705/588729-20170512160219707-775073372.png)
2、在Android Studio ---> Terminal终端窗口输入
View Code
(1) adb shell,注意如果没有配置环境变量,需要进入到sdk下的platform-tools下执行
(2) su,这是获取管理员权限
(3)chmod 777 /data,这是对data文件夹drwxrwxrwx权限,同理如果/data/data/应用包名,这个路径中有权限不是drwxrwxrwx权限的,使用该命令授权。这样之后就能看到应用的缓存文件了。
3、导出文件时,如果使用File Explore中的Pull a file from device会提示Failed to pull selection: open failed: Permission denied。不能通过这种方式导出到本地电脑上,有另外的方式可以导出文件,在adb shell中使用
cp /data/data/my.test/shared_prefs/pre1.xml /mnt/sdcard
将指定文件导出到/mnt/sdcard/,这个路径就是手机的根目录,然后就可以导出到电脑查看了。
其他
MODE_PRIVATE 和 MODE_APPEND 比较:
可能会理解MODE_PRIVATE 是 覆盖添加,MODE_APPEND 是追加添加,但是事实上在SharePreference中MODE_APPEND 是无效的,
SharedPreferences preferences1 = getSharedPreferences("pre1", MODE_PRIVATE); SharedPreferences preferences2 = getSharedPreferences("pre2", MODE_PRIVATE | MODE_APPEND); for (int i = 0; i < 10; i++) { preferences1.edit().putString("aaa", "aaa" + i).commit(); preferences2.edit().putString("aaa", "aaa" + i).commit(); } preferences1.edit().putString("bbb", "bbb").commit(); preferences2.edit().putString("bbb", "bbb").commit(); preferences1.edit().putString("aaa", "aaa" + "?").commit(); preferences2.edit().putString("aaa", "aaa" + "?").commit();
结果导出pre1.xml和pre2.xml比较, 两个文件完全一致:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="aaa">aaa?</string> <string name="bbb">bbb</string> </map>
但是在FileOutputStream操作中,却不一样:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
write("a.txt", Context.MODE_PRIVATE, "aaaaaaaaaaaaaaaaaaaaa"); write("a.txt", Context.MODE_PRIVATE, "bbbbbbbbbbbbbbbbbbbbb"); write("b.txt", Context.MODE_APPEND, "aaaaaaaaaaaaaaaaaaaaa"); write("b.txt", Context.MODE_APPEND, "bbbbbbbbbbbbbbbbbbbbb"); private void write(String name, int mode, String text) { try { FileOutputStream outStream = openFileOutput(name, mode); outStream.write(text.getBytes()); outStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
文件a.xml中的内容是: bbbbbbbbbbbbbbbbbbbbb
文件b.xml中的内容是:aaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbb
说明在FileOutputStream 文件操作中,MODE_PRIVATE是覆盖添加,MODE_APPEND是追加添加。