External Storage
所有Android设备都支持可以保存文件的共享外部存储器,这个外部存储器可以是可移动存储器(如SD卡),也可以是内置在设备中的外部存储器(不可移动)。外部存储器上的文件时全部可读的,当设备通过USB连接电脑和电脑互传文件时,外部存储器上的文件不可修改。
当外部存储器被挂载到电脑上或被移除,文件对android设备就不可见了,且此时外部存储器上的文件是没有安全保障的。所有程序都可以读写外部存储器上的文件,用户也可以删除这些文件。
检查存储器的可用性
对存储器进行任何操作之前,为了防止存储设备因挂载到电脑、丢失、只可读或其他原因造成无法使用,必须调用getExternalStorageState() 方法来检查存储设备是否可用。下面的代码演示了如何检查其可用性(可读可写):
booleanmExternalStorageAvailable = false;如果你是用API Level 8或更高的版本,调用getExternalFilesDir()来打开外部存储器中你想用来保存文件的目录。这个方法需要一个指定子目录类型的参数,如DIRECTORY_MUSIC和DIRECTORY_RINGTONES.如果相应的目录不存在,该方法将在必要时创建所需的目录。通过指定目录的类型,可以保证android媒体扫描器可以方便的给系统中的文件归类(如,铃声文件归为铃声而不是音乐)。程序被卸载后,相应目录及里面的内容都会被删除。
如果是用API Level 7或者更老的版本,就需要调用getExternalStorageDirectory()来获取外部存储器的根目录。向外部存储器写入数据时的目录如下:
/Android/data/ <package_name>/files/如果希望外部存储器上的文件不是只对指定的程序有用,并且不会因为卸载程序而被删除,就应该把这些文件保存在外部存储器的公共目录下,这些目录在外部存储器的根目录下,如Music/, Pictures/, Ringtones/等。
API Level 8及更高版本中,调用getExternalStoragePublicDirectory(),如前面所述,传递一个目录的类型参数,该方法就会创建相应的目录。类型参数可以为:
DIRECTORY_MUSIC, DIRECTORY_PODCASTS,DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS,DIRECTORY_PICTURES,DIRECTORY_MOVIES,IRECTORY_DOWNLOADS, or DIRECTORY_DCIM.
API Level 7及较低版本中,调用getExternalStorageDirectory()来获取外部存储器的跟目录,然后就可以把文件保存在以下相应的文件夹中:
· Music/ - Media scanner classifies all media found here as user music.
· Podcasts/ - Media scanner classifies all media found here asa podcast.
· Ringtones/ - Media scanner classifies all media found here as aringtone.
· Alarms/ - Media scanner classifies all media found here asan alarm sound.
· Notifications/ - Media scanner classifies all media found here asa notification sound.
· Pictures/ - All photos (excluding those taken with the camera).
· Movies/ - All movies (excluding those taken with thecamcorder).
· Download/ - Miscellaneous downloads.
有关getExternalStoragePublicDirectory(String type)和getExternalStorageDirectory()的使用,下面给出官方文档上的例子。
publicstatic File getExternalStoragePublicDirectory (String type)void createExternalStoragePublicPicture() {
// Create a path where we will place our picture in the user's
// public pictures directory. Note that you should be careful about
// what you place here, since the user often manages these files. For
// pictures and other media owned by the application, consider
// Context.getExternalMediaDir().
File path =Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
try {
// Make sure the Pictures directory exists.
path.mkdirs();
// Very simple code to copy a picture from the application's
// resource into the external file. Note that this code does
// no error checking, and assumes the picture is small (does not
// try to copy it in chunks). Note that if external storage is
// not currently mounted this will silently fail.
InputStream is = getResources().openRawResource(R.drawable.balloons);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
newMediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path +":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.w("ExternalStorage", "Error writing " + file,e);
}
}
void deleteExternalStoragePublicPicture() {
// Create a path where we will place our picture in the user's
// public pictures directory and delete the file. If external
// storage is not currently mounted this will fail.
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
file.delete();
}
boolean hasExternalStoragePublicPicture() {
// Create a path where we will place our picture in the user's
// public pictures directory and check if the file exists. If
// external storage is not currently mounted this will think the
// picture doesn't exist.
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
return file.exists();
}
publicstatic File getExternalStorageDirectory ()
BroadcastReceiver mExternalStorageReceiver;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
void updateExternalStorageState() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
}else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
}else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
handleExternalStorageState(mExternalStorageAvailable,
mExternalStorageWriteable);
}
void startWatchingExternalStorage() {
mExternalStorageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("test", "Storage: " + intent.getData());
updateExternalStorageState();
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
registerReceiver(mExternalStorageReceiver, filter);
updateExternalStorageState();
}
void stopWatchingExternalStorage() {
unregisterReceiver(mExternalStorageReceiver);
}