可以通过调用以下两种方法之一创建新的共享首选项文件或访问现有的文件:
Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
或者
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
要写入共享首选项文件, 请通过SharedPreferences 调用 edit() 来创建一个 SharedPreferences.Editor。
通过putInt() 和 putString() 方法写入的键和值。然后调用 commit() 以保存更改。例如:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_high_score), newHighScore);
editor.commit();
要从SharedPreferences文件中读取数据,可以调用诸如 getInt() 和 getString() 等方法读取数 据,并根据需要提供要在键不存在的情况下返回的默认值。 例如:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt(getString(R.string.saved_high_score), defaultValue);
Android系统通过File API读取和写入文件,File对象适合读取或写入大量数据,比如位图或通过网络交互的任何数据
所有的Andorid设备都有两个文件存储区域:内部存储和外部存储,这些存储空间的明明在Android最初诞生的时候就已经有了。
为什么要区分内部存储和外部存储?
一些设备将永久性存储空间划分为内部和外部存储两个分区,即便没有可移动的存储介质,也始终有两个存储空间,并且无论外部存储设备是否可移动,API均一致。
一下列表汇集了关于各种存储空间的实际信息:
内部存储 | 外部存储 |
---|---|
它始终可用 | 它并非始终可用,因为用户可采用 USB 存储的形式装载外部存储,并在某些情况下会从设备中将其删除。 |
默认情况下只有本应用可以访问此处保存的文件 | 它是全局可读的,因此此处保存的文件可能不受我们控制地被读取。 |
当用户卸载我们的应用时,系统会从内部存储中删除您的应用的所有文件。 | 当用户卸载我们的应用时,只有属于我们通过 getExternalFilesDir() 将应用的文件保存在目录中时,系统才会从此处删除我们应用中的文件。 |
建议:
提示:App默认安装在内部存储中,但也可以通过 android:installLocation属性,使得应用安装在外部存储中,当APK非常大,用户更喜欢这个选择
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
在内部存储中保存文件时,您可以通过调用以下两种方法之一获取作为 File 的相应目录:
getFilesDir()
返回表示当前应用内部目录的 File 。
getCacheDir()
返回表示当前应用临时缓存文件的内部目录的 File 。 务必删除所有不再需要的文件,并对在指定时间使用的内存量实现合理大小限制,比如,1MB。 如果在系统即将耗尽存储,它会在不进行警告的情况下删除当前应用缓存文件。
下面的示例是在这些目录之中新建文件
File file = new File(context.getFilesDir(), filename);
或者,可以调用 openFileOutput() 获取写入到内部目录中的文件的 FileOutputStream 。例如,此处显示如何向文件写入一些文本:
String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
F或者,如果需要缓存某些文件,应改用 createTempFile()。例如,以下方法从 URL 提取文件名并在应用的内部缓存目录中以该名称创建文件
public File getTempFile(Context context, String url) {
File file;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
catch (IOException e) {
// Error while creating file
}
return file;
}
要知道,外部存储不一定可用,比如用户移除了提供外部存储的SD卡,因此,在使用外部存储时,需要 调用getExternalStorageState()查询外部存储状态,如果返回值是MEDIA_MOUNTED,那么我们可以在外部存储中进行读写操作
下面是Google官方的示例:
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
尽管外部存储可以被用户和其他应用修改,但最好在此处保存两类文件:
公共文件
应供其他应用和用户自由使用的文件。 当用户卸载应用时,用户应仍可以使用这些文件。
例如,应用拍摄的照片或其他已下载的文件
私有文件
本属于当前应用且应在用户卸载应用时删除的文件。尽管这些文件在技术上可被用户和其他应用访问(因为它们在外部存储上),它们是实际上不向当前应用之外的用户提供值的文件。当用户卸载应用时,系统会删除应用外部专用目录中的所有文件。
例如,当前应用下载的其他资源或临时介质文件。
如果要使用外部存储中的公共文件,可以使用 getExternalStoragePublicDirectory()方法获取表示外部存储上对应目录的File,该方法可以获得指定文件类型参数的目录。比如 DIRECTORY_MUSIC 或 DIRECTORY_PICTURES。 例如:
getExternalStoragePublicDirectory()c
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
getExternalFilesDir()
如果要保存当前应用的专用文件,可以通过调用 getExternalFilesDir() 获取相应的目录并向指定目录传递想要的目录类型的名称。
通过该方法创建的各个目录以及目录下的文件,当用户卸载应用时,系统会删除这些文件
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
getExternalFilesDir() 传递null参数时,将返回外部存储中当前应用目录的根目录
切记,用户卸载的时候,会删除 getExternalFilesDir() 中创建的目录,如果你希望保存的文件在App卸载后仍然可用,那么请使用 getExternalStoragePublicDirectory()。
无论对于共享的文件使用 getExternalStoragePublicDirectory() 还是对当前应用专用文件使用 getExternalFilesDir() ,使用诸如 DIRECTORY_PICTURES 的 API 常数提供的目录名称非常重要。 这些目录名称可确保系统正确处理文件。 例如,保存在 DIRECTORY_RINGTONES 中的文件由系统介质扫描程序归类为铃声,而不是音乐。
可以调用getFreeSpace()或getTotalSpace()来分别获取目前可用空间和存储区中总空间。
但是系统并不保证可以写入与getFreeSpace()显示的一样多的字节,只有当返回的数字大于要保存的数据几MB时,才是相对安全的写入操作。
建议:保存文件之前,无需检查可用空间量。 可以尝试立刻写入文件,然后在 IOException 出现时将其捕获。 如果不知道所需的确切空间量,是可以这样做的。 例如,如果在保存文件之前通过将 PNG 图像转换成JPEG 更改了文件的编码,我们事先将不知道文件的大小。
作为程序员,应始终删除不再需要的文件。删除文件最直接的方法是让打开的文件参考自行调用 delete()。
myFile.delete();
如果文件保存在内部存储中,还可以请求 Context 通过调用 deleteFile() 来定位和删除文件:
myContext.deleteFile(fileName);
切记:
当用户卸载您的应用时,Android 系统会删除以下各项:
- 保存在内部存储中的所有文件
- 使用 getExternalFilesDir() 保存在外部存储中的所有文件。
但是,我们应手动删除使用 getCacheDir() 定期创建的所有缓存文件并且定期删除不再需要的其他文件。