在内部保存文件
在内部存储保存文件时,你可以调用两种方法之一来获取相应的目录文件:
getFilesDir() 返回表示应用程序内部目录的文件
getCacheDir() 返回表示应用程序临时缓存文件的内部目录的文件。一旦不再需要要确保删除每个文件。确保删除不再需要的文件并且设置合理大小的内存总量,比如1MB。如果系统存储开始运行缓慢,它可能会不经警告而删除缓存文件。
要在这些目录中创建一个新文件可以使用 File()函数,用来传递由上述指定内部存储目录的方法之一所提供的文件。例如: File file = new File(context.getFilesDir(), filename);
如果需要缓存文件,就应该使用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; }
保存外部存储的文件
当用户已经安装PC存储或者移除了提供外部存储的SD卡,外部存储则不能使用,因此需要在访问前验证是否可用。调用 getExternalStorageState()可以来查询外部存储状态。如果返回状态等同于MEDIA_MOUNTED,那就可以读取和写入文件
/* 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() 来获取外部存储相应目录的文件。这一方法指定了要保存的文件类型,这样就可以和其他公共文件逻辑相连接,比如DIRECTORY_MUSIC 或 DIRECTORY_PICTURES。例如:
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()或者getExternalCacheDir()(路径为:/mnt/sdcard/android/data/com.xxx.xxx/cache)或者来获取相应的目录。这种方式创建的每个目录都会添加到包含所有应用程序外部存储文件的父类目录,用户卸载应用程序时系统会删除这些文件。
例如可以用这一方法来创建单独相册目录:
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()会在卸载时候被删除。如果用户卸载应用程序时保存的文件仍然可以使用——比如应用程序是摄像头,而用户想要保留图片,那么就要使用getExternalStoragePublicDirectory()。
不管你是对共享文件使用 getExternalStoragePublicDirectory()还是对私有文件使用getExternalFilesDir(),使用API常量比如DIRECTORY_PICTURES提供的目录名称是很重要的。这些目录名称确保系统可以适当处理文件。例如保存在 DIRECTORY_RINGTONES的文件由系统媒体扫描来进行铃声分类而不是音乐分类.
下面提供一下我自己使用的一个缓存文件清除类:
package com.rising.util; /* * 文 件 名: DataCleanManager.java * 描 述: 主要功能有清除内/外缓存,清除数据库,清除sharedPreference,清除files和清除自定义目录 */ import java.io.File; import android.content.Context; import android.os.Environment; /** * 本应用数据清除管理器 */ public class DataCleanManager { /** * 清除本应用内部缓存(/data/data/com.xxx.xxx/cache) * * @param context */ public static void cleanInternalCache(Context context) { deleteFilesByDirectory(context.getCacheDir()); } /** * 清除本应用所有数据库(/data/data/com.xxx.xxx/databases) * * @param context */ public static void cleanDatabases(Context context) { deleteFilesByDirectory(new File("/data/data/" + context.getPackageName() + "/databases")); } /** * * 清除本应用SharedPreference(/data/data/com.xxx.xxx/shared_prefs) * * @param * context */ public static void cleanSharedPreference(Context context) { deleteFilesByDirectory(new File("/data/data/" + context.getPackageName() + "/shared_prefs")); //下面这个sharefile在清除时候有引用,所以用这种方式清除 new SharePreferenceFile(context).clearData(); } /** * 按名字清除本应用数据库 * * @param context * @param dbName */ public static void cleanDatabaseByName(Context context, String dbName) { context.deleteDatabase(dbName); } /** * 清除/data/data/com.xxx.xxx/files下的内容 * * @param context */ public static void cleanFiles(Context context) { deleteFilesByDirectory(context.getFilesDir()); } /** * * 清除外部cache下的内容(/mnt/sdcard/android/data/com.xxx.xxx/cache) * * @param * context */ public static void cleanExternalCache(Context context) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { deleteFilesByDirectory(context.getExternalCacheDir()); } } /** * 清除自定义路径下的文件,使用需小心,请不要误删。而且只支持目录下的文件删除 * * @param filePath */ public static void cleanCustomCache(String filePath) { deleteFilesByDirectory(new File(filePath)); } /** * 清除本应用所有的数据 * * @param context * @param filepath */ public static void cleanApplicationData(Context context, String... filepath) { cleanInternalCache(context); cleanExternalCache(context); cleanDatabases(context); cleanSharedPreference(context); cleanFiles(context); for (String filePath : filepath) { cleanCustomCache(filePath); } } /** * 递归删除这个目录下面的文件,由于目录层数一般比较少,递归比较简单 * @Description: * @param directory * @return void */ private static void deleteFilesByDirectory(File directory) { if (directory != null && directory.exists()) { for (File item : directory.listFiles()) { if(item.isDirectory()){ deleteFilesByDirectory(item); }else{ item.delete(); } } } } }