这个demo演示了如何读写外部存储卡。演示了三种情况:
* 1.向存储卡的共享目录中的图片目录中写入一张图片:
* 位置为:/storage/sdcard/Pictures
* 2.向本地应用的图片目录中写入一张图片
* 位置为:/storage/sdcard/Android/data/包名/files/Pictures
* 3.向本地应用的目录中写入一个文件
* 位置为:/storage/sdcard/Android/data/包名/files/
activity_main.xml
ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/layout">
</LinearLayout>
</ScrollView>
activity_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#88a0a0a0"
android:padding="4dp"
android:gravity="center_vertical"
android:id="@+id/label" />
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:padding="4dp"
android:gravity="center_vertical"
android:id="@+id/path" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<Button
android:id="@+id/create"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Create"
android:layout_weight="0"/>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<Button
android:id="@+id/delete"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Delete"
android:layout_weight="0"/>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
MainActivity
public class MainActivity extends Activity {
private LinearLayout layout;
// 定义一个类,用于管理每种情况的布局,因为是一样的布局,所以可以达到利用的目的
static class Item {
View mRoot;
Button mCreate;
Button mDelete;
}
// 定义三种情况下的布局
Item mPublicPicture;
Item mPrivatePicture;
Item mPrivatefile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = (LinearLayout) findViewById(R.id.layout);
mPublicPicture = createStorageControls(
"Picture: getExternalStoragePublicDirectory",
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
new OnClickListener() {
@Override
public void onClick(View v) {
createPublicPicture();
updateExternalStorageState();
}
}, new OnClickListener() {
@Override
public void onClick(View v) {
deletePublicPicture();
updateExternalStorageState();
}
});
layout.addView(mPublicPicture.mRoot);
mPrivatePicture = createStorageControls("Picture: getExternalFilesDir",
// 注意这个方法不在Environment里面而是在Activity当中
getExternalFilesDir(Environment.DIRECTORY_PICTURES),
new OnClickListener() {
@Override
public void onClick(View v) {
createPrivatePicture();
updateExternalStorageState();
}
}, new OnClickListener() {
@Override
public void onClick(View v) {
deletePrivatePicture();
updateExternalStorageState();
}
});
layout.addView(mPrivatePicture.mRoot);
mPrivatefile = createStorageControls("Picture: getExternalFilesDir",
// 注意这个方法不在Environment里面而是在Activity当中
getExternalFilesDir(null), new OnClickListener() {
@Override
public void onClick(View v) {
createPrivateFile();
updateExternalStorageState();
}
}, new OnClickListener() {
@Override
public void onClick(View v) {
deletePrivateFile();
updateExternalStorageState();
}
});
layout.addView(mPrivatefile.mRoot);
watchingStorageState();
}
//定义一个广播接收者,用于监视外部存储卡的挂载状态
private BroadcastReceiver mReceiver;
private void watchingStorageState() {
mReceiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateExternalStorageState();
}
};
//注册广播接收者
IntentFilter filter=new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
registerReceiver(mReceiver, filter);
updateExternalStorageState();
}
@Override
protected void onDestroy() {
super.onDestroy();
//unregisterReceiver(mReceiver);
}
private boolean mStorageAvaiable = false;
private boolean mStorageWriteable = false;
// 更新外部存储卡的状态:判断存储卡是否可写可用,并根据存储卡的状态和目录中是否已经存在该文件
// 来设置按钮的可用状态
protected void updateExternalStorageState() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mStorageAvaiable = true;
mStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mStorageAvaiable = true;
mStorageWriteable = false;
} else {
mStorageAvaiable = false;
mStorageWriteable = false;
}
handleStorageState(mStorageAvaiable, mStorageWriteable);
}
private void handleStorageState(boolean avaiable, boolean writeable) {
boolean has = hasPublicPicture();
mPublicPicture.mCreate.setEnabled(!has && writeable);
mPublicPicture.mDelete.setEnabled(has && writeable);
has = hasPrivatePicture();
mPrivatePicture.mCreate.setEnabled(!has && writeable);
mPrivatePicture.mDelete.setEnabled(has && writeable);
has=hasPrivateFile();
mPrivatefile.mCreate.setEnabled(!has && writeable);
mPrivatefile.mDelete.setEnabled(has && writeable);
}
private boolean hasPublicPicture() {
File path = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(path, "demopicture.jpg");
return file.exists();
}
private boolean hasPrivatePicture() {
File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file = new File(path, "demopicture.jpg");
return file.exists();
}
private boolean hasPrivateFile() {
File path = getExternalFilesDir(null);
File file = new File(path, "demopicture.jpg");
return file.exists();
}
// 该方法将一张图片复制到外部存储卡的共享目录的图片目录下
protected void createPublicPicture() {
File path = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(path, "demopicture.jpg");
try {
// 确保目录被创建
path.mkdirs();
System.out.println(path);
InputStream is = getResources().openRawResource(
R.drawable.ic_launcher);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
// 对文件进行扫描,以确保用户能够马上使用刚刚被复制到的图片,比如在图库中更新显示
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
new OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
} catch (Exception e) {
Log.w("ExternalStorage", "Error Writing:" + file, e);
}
}
protected void deletePublicPicture() {
File path = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(path, "demopicture.jpg");
file.delete();
}
// 该方法将一张图片复制到外部存储卡本地应用目录下的图片目录下
protected void createPrivatePicture() {
File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file = new File(path, "demopicture.jpg");
try {
// 确保目录被创建
path.mkdirs();
System.out.println(path);
InputStream is = getResources().openRawResource(
R.drawable.ic_launcher);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
// 对文件进行扫描,以确保用户能够马上使用刚刚被复制到的图片,比如在图库中更新显示
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
new OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
} catch (Exception e) {
Log.w("ExternalStorage", "Error Writing:" + file, e);
}
}
protected void deletePrivatePicture() {
File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file = new File(path, "demopicture.jpg");
file.delete();
}
// 该方法将一张图片复制到外部存储卡本地应用目录下
protected void createPrivateFile() {
File path = getExternalFilesDir(null);
File file = new File(path, "demopicture.jpg");
try {
// 确保目录被创建
path.mkdirs();
System.out.println(path);
InputStream is = getResources().openRawResource(
R.drawable.ic_launcher);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
// 对文件进行扫描,以确保用户能够马上使用刚刚被复制到的图片,比如在图库中更新显示
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
new OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
} catch (Exception e) {
Log.w("ExternalStorage", "Error Writing:" + file, e);
}
}
protected void deletePrivateFile() {
File path = getExternalFilesDir(null);
File file = new File(path, "demopicture.jpg");
file.delete();
}
/*
* 创建每种情况下的布局
*/
private Item createStorageControls(String label, File path,
View.OnClickListener createClick, View.OnClickListener deleteClick) {
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
Item item = new Item();
item.mRoot = inflater.inflate(R.layout.activity_item, null);
TextView tv = (TextView) item.mRoot.findViewById(R.id.label);
tv.setText(label);
if (path != null) {
tv = (TextView) item.mRoot.findViewById(R.id.path);
tv.setText(path.toString());
}
item.mCreate = (Button) item.mRoot.findViewById(R.id.create);
item.mDelete = (Button) item.mRoot.findViewById(R.id.delete);
item.mCreate.setOnClickListener(createClick);
item.mDelete.setOnClickListener(deleteClick);
return item;
}
}
别忘了添加读写外部存储卡的权限