Android 的文件存储
- 一直可用
- 默认情况下,存储于此的文件只有该应用本身有权限操作。
- 当用户卸载该应用,系统会删除该应用存储在内存储的所有文件。
- 并非一直可用,比如当用户用数据线连接电脑并打开数据存储或者移除存储卡。
- 对用户和其他应用可读。
- 当用户卸载该应用时必不会删除存储在外存储的文件,除非你保存的时候调用的是
getExternalFilesDir()
.
Tip: 默认情况下应用是安装在内存储,但是你可以在manifest中指定android:installLocation的属性值让应用安装在外存储上。特别是当应用应用特别大,而用户又有足够的问存储空间时。更多详情,请查阅
App
Install Location。
获得外存储权限
WRITE_EXTERNAL_STORAGE权限:
<manifest ...> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
Caution:目前,所有应用不必声明相关权限就可以在外存储上执行读的操作。然而,不久的将来就需要了。如果你的应用需要读取的操作(不需要写的操作),你可以在manifest中声明READ_EXTERNAL_STORAGE
权限,这样可以保证应用在后续版本中正常运行(即使当前系统并不要求该权限)。
<manifest ...> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ... </manifest>
如果你的应用已经声明了WRITE_EXTERNAL_STORAGE权限,就没必要再声明READ_EXTERNAL_STORAGE权限,因为WRITE_EXTERNAL_STORAGE默认包含了写的权限。
You don’t need any permissions to save files on the internal storage. Your application always has permission to read and write files in its internal storage directory.对于内存储并不需要任何读写的权限。
在内存储中保存文件
getFilesDir()
- 返回一个分配给该应用的内存储文件夹。
getCacheDir()
- 返回一个分配给该应用的内存储缓存文件夹File对象。当缓存文件不再需要时记得删除掉。当系统存储不够用时,系统可能会删除掉缓存的文件且没有提示。
File file = new File(context.getFilesDir(), filename);
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(); }
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; }
Note:一个应用的内存储空间是由应用包名标示的在安卓文件系统中的一个特定区域,技术上来讲,如果把文件的mode设为可读,那么其他应用就可访问。但是,前提是其他应用必须预先知道你的应用的包名和要访问的文件名。除非你明确声明某个文件为可读或可写,否则其他应用无法访问你的内存储文件也没有读写的权限。
在外存储中保存文件
/* 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; }
公开文件
完全属于你的应用的文件并且在用户卸载你的应用时应该被删除的文件可以存储在这里。虽然技术上来说,存储在外存储的文件对于用户和其他应用都可以访问,但是这些文件对于用户和其他应用一文不值。当用户删除你的应用时,系统会自动删除你的应用存储在这里的所有文件。比如说你的应用下载的资源文件或临时的文件。
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; }
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; }
DIRECTORY_RINGTONES
中的文件会被系统media
scanner归类为铃音而非音乐。查询剩余存储空间
如果你在保存某一文件时事先知道该文件的大小,你可以通过调用getFreeSpace()
或者 getTotalSpace()
来确定是否有足够的存储空间来保存该文件以免造成IOException异常。
但是,系统并不保证你通过getFreeSpace()查询出来有多少剩余存储就可以存储多少。如果剩余存储容量比你要存储的文件大小大个几MB,那么一般可以成功存储。
Note:其实你也可以不用在存储文件前预先查询剩余多少存储空间,你可以尝试着直接写入数据,然后如果有出现异常直接捕获就行了。这种写法一般可以用在当你事先不知道要写入数据的大小的时候。比如说当你要保存一张PNG格式的图片前要先把他转化为JPEG格式,那么你就不知道要保存的数据的大小。
删除文件
你应该经常删除不再需要的文件,最直接的方法就是直接调用File对象的delete()方法。
myFile.delete();
如果要删除的文件是存储在内存储中,你可以通过调用Conext的deleteFile()方法来删除。
myContext.deleteFile(fileName);
Note:当用户卸载你的应用时,安卓系统会自动删除以下位置的文件:
- 存储在内存储中的所有文件
- 通过
getExternalFilesDir()
方法存储在外存储中的所有文件。