这今天项目中有一个将设备的数据文件复制到U盘的功能,复制完成之后,在设备看U盘的文件都是好的,数据也正常,当拔出U盘后放到电脑上,有时就会出现文件为0B的情况,后来才发现,是U盘没有安全卸载的原因。
初期的设想是控制程序跳转到android的设置的存储界面,让用户进行点击U盘的安全卸载选项,代码如下:
Intent intent = new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS);
startActivity(intent);
很简单粗暴,直接跳转界面。
But,问题来了,系统的界面和当前设备的UI风格不统一。这就是个很让人挠头的问题了,只能自己实现U盘卸载的功能了。
网上查了好多的资料,感觉没有自己想要的功能,无奈之下,给硬件组要了一份当前系统的Setting的源码,请教了一圈,最后确定了存储功能的源码位置:
在这个文件夹下的Memory.java这个文件中,下面来看看U盘卸载功能是如何实现的,直接上源码:
private void doUnmount() {
// Present a toast here
Toast.makeText(getActivity(), unmoutUSBorSD.equals("usb")?R.string.custom_usb_unmount_inform_text:R.string.custom_sd_unmount_inform_text, Toast.LENGTH_SHORT).show();
IMountService mountService = getMountService();
try {
sLastClickedMountToggle.setEnabled(false);
sLastClickedMountToggle.setTitle(getString(R.string.sd_ejecting_title));
sLastClickedMountToggle.setSummary(getString(R.string.sd_ejecting_summary));
mountService.unmountVolume(sClickedMountPoint, true, false);
} catch (RemoteException e) {
// Informative dialog to user that unmount failed.
showDialogInner(DLG_ERROR_UNMOUNT);
}
}
关键点就两句 IMountService mountService = getMountService();和mountService.unmountVolume(sClickedMountPoint, true, false); ,其余的和U盘卸载基本没有关系,下面来看 getMountService()方法:
private synchronized IMountService getMountService() {
if (mMountService == null) {
IBinder service = ServiceManager.getService("mount");
if (service != null) {
mMountService = IMountService.Stub.asInterface(service);
} else {
Log.e(TAG, "Can't get mount service");
}
}
return mMountService;
}
只是获取了系统的一个服务,那么unmountVolume(sClickedMountPoint, true, false);中的sClickedMountPoint又是啥呢?
接着找,如下:
final StorageVolume volume = category.getStorageVolume();
if (volume != null && category.mountToggleClicked(preference)) {
sLastClickedMountToggle = preference;
sClickedMountPoint = volume.getPath();
String state = mStorageManager.getVolumeState(volume.getPath());
if (volume.getPath().contains("usb")){
unmoutUSBorSD = "usb";
}else{
unmoutUSBorSD = "sd";
}
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
unmount();
} else {
mount();
}
return true;
}
可以确定是U盘的挂载路径,OK到这里,基本U盘的卸载方法已经明了,如果使用系统的服务或方法的话,采用反射机制是一个不错的方式,过程不在进行说明,增加如下文件
文件下载地址: https://download.csdn.net/download/u011685953/10992318
使用方法如下:
//安全卸载U盘
public void doUnMountU() {
IMountService service = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
try {
service.unmountVolume(App_DataPara.getApp().GetExternalStorageDirectory(), true, false);
} catch (RemoteException e) {
e.printStackTrace();
}
}
App_DataPara.getApp().GetExternalStorageDirectory()为需要卸载的U盘的挂载的文件目录。String类型
因为踩过坑,所以记录一下,同时分享出来,哪怕对一个人有帮助也行!