1. 先从一个例子说起:使用隐式 Intent 启动相机拍照保存为头像:
final Intent captureImage = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 检查相机是否可用
boolean canTakePhoto = mPhotoFile != null &&
captureImage.resolveActivity(packageManager) != null;
if (canTakePhoto) {
Uri uri = Uri.fromFile(mPhotoFile);
// 把拍到的照片保存地址的 url 传入 Intent
captureImage.putExtra(MediaStore.EXTRA_OUTPUT, uri);
}
mPhotoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivityForResult(captureImage, REQUEST_PHOTO);
}
});
public File getPhotoFile(Crime crime) {
// 保存到 External Storage 中
File externalFileDir = mContext
.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (externalFileDir == null) {
return null;
}
return new File(externalFileDir, crime.getPhotoFileName());
}
public String getPhotoFileName() {
return "IMG_" + getId().toString() + ".jpg";
}
// 回调时设置已经储存的图片
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
return;
}
if (REQUEST_DATE == requestCode) {
updateDate();
} else if (REQUEST_CONTACT == requestCode && data != null) {
mCrime.setSuspect(suspect);
mSuspectButton.setText(suspect);
} else if (requestCode == REQUEST_PHOTO) {
updatePhotoView();
}
}
2. 由此引申的 Android 储存系统的知识点:
表格 1:Context类提供的基本文件和目录处理方法
Method | Purpose |
File getFilesDir() | 获取/data/data//files目录 |
FileInputStream openFileInput(String name) | 打开现有文件进行读取 |
FileOutputStream openFileOutput(String name, int mode) | 打开文件进行写入,如不存在就创建它 |
File getDir(String name, int mode) | 获取/data/data//目录的子目录(如不存在就先创 建它) |
String[] fileList() | 获取/data/data//files目录下的文件列表。可与其他方 法配合使用,例如openFileInput(String) |
File getCacheDir() | 获取/data/data//cache目录。应注意及时清理该目 录,并节约使用空间 |
表格 2:Context类提供的外部文件和目录处理方法
方 法 | 使 用 目 的 |
File getExternalCacheDir() | 获取主外部存储上的缓存文件目录。用法类似getCacheDir()方法,但要 注意, Android一般不会自动清理该目录 |
File[] getExternalCacheDirs() | 获取多个外部存储上的缓存文件目录 |
File getExternalFilesDir(String) | 获取主外部存储上存放常规文件的文件目录。通过String参数,可访问特 定内容类型的子目录。内容类型常量以DIRECTORY_为前缀,定义在 Environment 中 。 例 如 , 用 于 图 像 文 件 的 Environment.DIRECTORY_ PICTURES |
File[] getExternalFilesDirs(String) | 类似getExternalFilesDir(String)方法,但该方法可获取指定类型的 所有文件目录 |
File[] getExternalMediaDirs() | 获 取 Android存储 图片 、视 频和 音乐 文件 的所 有外 部文 件目 录。和 getExternalFilesDir(Environment.DIRECTORY_PICTURES)方法区别 在于,调用该方法,多媒体扫描器会自动扫描目标目录,并将存放的多媒 体文件暴露给能够播放音乐、浏览视频和图片的应用。也就是说, getExternalMediaDirs()方法返回目录中存放的任何文件都会自动出现 在多媒体应用中 |
手机的储存分为 Internal Storage 和 External Storage(主存储路径/storage/emulated/0)两种,如果再加上一张 sd 卡,也就多出来了一个 External Storage(副储存路径/storage/emulated/1)
- Internal Storage
- 使用表格 1中的方法保存在 Interal Storage 上的文件以 app 的包名作为标识存放在 Android 文件系统的特定目录下[/data/data/com.example.xx];
- 从技术上讲,如果文件被设置为可读的,那么其他 app 就可以读取该 internal 文件。然而,其他 app 需要知道包名与文件名。若没有设置为可读或者可写,其他app是没有办法读写的。因此我们只要使用了MODE_PRIVATE ,那么这些文件就不可能被其他app所访问。
- 在应用被卸载时,这些文件会被系统删除
- External Storage
- 使用表格 2中的方法保存在 External Storage 上的文件保存在[/storage/emulated/0/Android/data/com.example.app/files/xxx]下
- 同样在应用被卸载时,这些文件会被系统删除
- 文件储存为 public 文件
- 同样是保存在 External Storage 上的文件
- 使用
Environment.getExternalStoragePublicDirectory()
得到的目录是[/storage/emulated/0],此处保存的文件永远不会被系统删除
补充:使用 External Storage 前要先检查其状态
/* 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;
}
参考–>《Android 编程权威指南》,AllenWang的个人博客–>关于储存的详解,保存到文件–Trainiing
拓展–>Android存储挖坑记–>清晰详细的储存详解