android 数据存储

发表于:,更新于:,By Sally
大纲
  1. 1. 当用户卸载app时,android系统会删除:
  2. 2. SharedPreference
  3. 3. File
    1. 3.1. 内部存储
    2. 3.2. 外部存储
    3. 3.3. 权限permission
    4. 3.4. 将文件保存到内部存储
    5. 3.5. 保存文件到外部存储
    6. 3.6. 查询可用空间
    7. 3.7. 删除文件
  4. 4. Database

当用户卸载app时,android系统会删除:

  • 保存在内部存储(internal storage)的所有文件

  • 通过getExternalFilesDir()方法保存在外部存储(external storage)的所有文件

  • 还有,应该手动删除缓存文件getCacheDir()以及定期删除不需要的文件

SharedPreference

  • getSharedPreferences() - 可以有操作多个文件,通过文件名区分。可以在app的任何上下文中调用。

  • getPreferences() - 在activity中操作一个文件,因为取回的文件属于某个activity,所以不需要提供名称参数。

  • 在fragment中使用

1
2
Context context = getActivity;
SharedPreferences sharedPref = context.getPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVITE);
  • 如果你的activity只需要一个shared preference 文件
1
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);

如果创建一个文件指定模式为MODE_WORLD_READABLEorMODE_WORLD_WRITEABLE,则其他的app如若知道文件的标志符就可以访问该数据

  • 写数据
1
2
3
4
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_file_key), saved_value);
editor.commit();
  • 读数据
1
2
SharedPreference sharedPref = getActivity().getPreferences(Context.MODE_PRIVITE);
int value = sharedPref.getInt(getString(R.string.saved_file_key), defaultValue);

File

内部存储

  • 总是可用

  • 默认情况下,只有你自己的app可以访问

  • 当用户卸载app,这里的文件将被移除

当你决定用户或者其他app都不可能访问你的文件时,最好存在内部存储

外部存储

  • 并不总是可用,用户可能会添加或移除外部存储设备

  • 全局可读(its world-readable),所以存在这里的文件,可以在你的控制范围之外被读取

  • 如果外部存储文件的文件位置是通过getExternalFilesDir()方法获取的,当用户卸载app时,系统会移除app保存的文件

    • 当然外部存储也分两种类型,public files用户和其他app可用,但当用户卸载app时,文件依然保留,例如:app拍的照片和下载的文件;private files用户卸载app时移除文件,如:app下载的额外资源,历史媒体文件。

如果对文件的访问不做限制(restriction),允许用户(通过电脑访问)或者其他应用访问,文件存储在外部存储为好

尽管app默认会安装到内部存储,你也可以通过设置manifest文件的android:installLocation属性,指定app的存储位置

权限permission

  • 存储到外部存储时,需要WRITE_EXTERNAL_STORAGE权限
1
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORATE" />

目前,app默认有读取外部存储的权限,但是将来的版本会修改。如果app需要读取外部存储,需要READ_EXTERNAL_STORAGE

1
<uses-premission android:name="android.permission.READ_EXTERNAL_STORAGE" />

如果,你的app指定了WRITE_EXTERNAL_STORAGE权限,那它隐含的就有了读外部存储的权限

将文件保存到内部存储

  • getFilesDir() - 为你的app返回一个内部的文件夹

  • getCacheDir() - 为app返回一个临时存储的内部存储的文件夹。当文件不再需要时记得将他删除,使用时,给它一个合适的内存大小限制,如1mb。如果系统内存过低,会直接删除缓存文件不会给出警告

1
2
3
4
5
6
7
8
9
10
11
12
13
// 通过构造方法创建新的file
File file = new File(context.getFilesDir(), filename);
// 通过`openFileOutput()`粗昂件一个文件输出流
String filename = 'myfile';
String string = 'hello world!!!';
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} cache(Exception e) {
e.printStackTrace();
}

保存文件到外部存储

  • 因为外部存储可能不可用,所以getexternalStorageState()判断一下外部存储状态,如果返回MEDIA_MOUNTED,那就可用啦
1
2
3
4
5
6
7
8
9
10
// checks if external storage is aailable for read and write
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorateState();
return Environment.MEDIA_MOUNTED.wquals(state);
}
// checks if external storage is available to at least read
public boolean isExternalStoragereadable() {
String state = Environment.getExternalStorateState();
return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
}

尽管在外部存储的文件可以被用户或者其他应用修改,这里有两类文件(public/private files)供选择:

  • public files

    用户和其他app都可以访问,当用户卸载该app时,文件仍旧存在,且用户可用。eg: 该app拍的照片或者下载的文件

  • private files

    文件属于该app,且当用户卸载app时文件也被删除。尽管用户或者其他app可以通过技巧访问该文件,因为文件位于外部存储,但是文件事实上是不提供给该app以后的其他用户值的。当用户删除该app,系统将删除该app存储在外部存储的所有private directory。
    eg: 该app下载的额外资源以及临时的媒体文件。

如果要在外部存储存入公共的文件,使用getExternalStoragePublicDirectory()方法获得File,这个方法携带一个参数指定存储文件的类型,如DIRECTORY_MUSICDIRECTORY_PICRURE

1
2
3
4
5
6
7
8
public File getAlbumStorageDir(String albumName) {
// get the directory for the user's public picture directory
File file = new File(Environment.getExternalStoragePublicdirectory(Environment.DIRECTORY_PICTURE), albumName);
if(!file.mkdirs()) {
Log.e(LOG_TAG, "directory not created");
}
return file;
}

在外部存储存入app的私有文件,使用getExternalFilesDir()然后指定任何一个标示文件夹的名字。为一个使用该方式创建的文件夹被添加到你app外部存储的跟文件夹中。当用户卸载你的app时,系统删除该文件夹。

1
2
3
4
5
6
7
8
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_PICTURE), albumName);
if(!file.mkdirs()) {
Log.e(LOG_TAG, "directory not created");
}
return file;
}

如果没有与定义的字文件夹适合你要存储的文件,你可以使用getExternalFilesDir()方法不传入任何参数,该方法将返回你app外部存储私有文件夹的根文件夹。

查询可用空间

可以通过getFreeSpace()hegetTotalSpace()两个方法获取可用空间和总空间。

但是,系统不保证你可以写通过getFreeSpace()获得可用容量大小的东西。如果该方法返回的空间比你要存储文件的size大个几m,或者文件系统容量小于总容量的90%,或许是可以安全执行的。除此之外,你也许不应该存储。

当你存储文件的时候,你不确定具体需要的存储空间,此时:你不需要请求可用的存储空间,可以通过try catch来处理和捕获io异常。eg:将png文件存储为jpeg,改变文件的编码,在存储之前不知道文件的具体大小。

删除文件

直接的删除文件的方法 to have the opened file reference, 调用delete()删除自己

1
myFile.delete();

如果文件保存在内部存储,你需要当前的Context对象调用deleteFile()方法删除

1
myContext.deleteFile(fileName);

Database

1
# TODO