ACTION_MEDIA_EJECT和ACTION_MEDIA_EJECT的作用和区别
时间: 2023-05-20 10:01:38 浏览: 365
ACTION_MEDIA_EJECT和ACTION_MEDIA_UNMOUNTED都是Android系统中的广播事件,它们的作用是卸载外部存储设备。区别在于,ACTION_MEDIA_EJECT是在设备被完全卸载之前发送的广播事件,而ACTION_MEDIA_UNMOUNTED是在设备已经被卸载之后发送的广播事件。
相关问题
现在有个需求:u盘里面有一个工厂apk,u盘插入android设备后客制化的sdmc apk会接收到ACTION_MEDIA_MOUNTED广播后使用pm.getPackageArchiveInfo(absPath, PackageManager.GET_ACTIVITIES)去获取u盘里面的工厂apk信息,在这个时候突然把u盘拔掉,在系接收到ACTION_MEDIA_EJECT或者ACTION_MEDIA_UNMOUNTED广播后,可以做哪些处理使得U盘可以成功卸载,不会再下次插入的时候系统提示“vold : ForceUnmount failed: Device or resource busy” 请通过代码来实现
好的,以下是一个示例代码,用于在接收到ACTION_MEDIA_EJECT或ACTION_MEDIA_UNMOUNTED广播后,停止使用U盘的进程和服务,并卸载U盘:
```java
private static final String USB_STORAGE_PATH = "/mnt/usb_storage"; // U盘挂载路径
private BroadcastReceiver mUsbStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == null) {
return;
}
if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
// U盘插入,获取工厂apk信息
String path = intent.getData().getPath();
if (USB_STORAGE_PATH.equals(path)) {
PackageInfo packageInfo = getPackageInfoFromUsb();
// TODO: 处理工厂apk信息
}
} else if (Intent.ACTION_MEDIA_EJECT.equals(action)
|| Intent.ACTION_MEDIA_UNMOUNTED.equals(action)) {
// U盘卸载,停止使用U盘的进程和服务,并卸载U盘
String path = intent.getData().getPath();
if (USB_STORAGE_PATH.equals(path)) {
stopUsingUsb();
unmountUsb();
}
}
}
};
// 获取U盘中的工厂apk信息
private PackageInfo getPackageInfoFromUsb() {
String apkPath = USB_STORAGE_PATH + "/factory.apk";
PackageManager pm = getPackageManager();
PackageInfo packageInfo = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
return packageInfo;
}
// 停止使用U盘的进程和服务
private void stopUsingUsb() {
// TODO: 停止使用U盘的进程和服务
}
// 卸载U盘
private void unmountUsb() {
try {
Process process = Runtime.getRuntime().exec("su");
OutputStream os = process.getOutputStream();
os.write(("umount " + USB_STORAGE_PATH + "\n").getBytes("UTF-8"));
os.write(("am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///mnt/sdcard\n").getBytes("UTF-8"));
os.flush();
os.close();
process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
```
需要注意的是,上述代码需要在具有root权限的设备上运行。如果设备没有root权限,则需要在接收到广播后,提示用户手动卸载U盘。
如果U盘在访问时被意外拔出,可能会导致U盘无法正常卸载,下次插入时系统会提示"vold: ForceUnmount failed: Device or resource busy"。为了避免这种情况发生,可以在应用程序中监听ACTION_MEDIA_EJECT广播,并在接收到广播时释放对U盘的访问,具体做法如下: 在应用程序中注册ACTION_MEDIA_EJECT广播接收器。 在广播接收器中释放对U盘的访问,即关闭U盘中打开的文件、释放相关资源,确保U盘上的文件已经关闭,不再被应用程序占用。 在广播接收器中调用unmount方法,将U盘卸载,确保U盘可以成功卸载。 最后,要在应用程序中及时释放对U盘的访问,避免占用U盘资源,从而导致U盘无法正常卸载。 这里说到的4点问题,请通过代码呈现出来
以下是完整的代码示例:
```java
public class MainActivity extends AppCompatActivity {
private UsbBroadcastReceiver mUsbBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册ACTION_MEDIA_EJECT广播接收器
mUsbBroadcastReceiver = new UsbBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_EJECT);
registerReceiver(mUsbBroadcastReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 及时释放对U盘的访问
releaseUsbAccess();
// 注销广播接收器
unregisterReceiver(mUsbBroadcastReceiver);
}
/**
* 释放U盘访问
*/
private void releaseUsbAccess() {
// 关闭U盘中打开的文件,释放相关资源
// ...
}
/**
* U盘广播接收器
*/
public class UsbBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
// U盘被卸载,释放对U盘的访问
releaseUsbAccess();
// 卸载U盘
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (usbDevice != null) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(context.getPackageName() + ".UsbBroadcastReceiver"), 0);
usbManager.requestPermission(usbDevice, pendingIntent);
usbManager.unmount(usbDevice);
}
}
}
}
}
```
在代码中,我们首先在onCreate()方法中注册了ACTION_MEDIA_EJECT广播接收器。在广播接收器中,我们实现了对U盘访问的释放(releaseUsbAccess()方法)和卸载(UsbManager.unmount()方法)操作。在onDestroy()方法中,我们及时释放对U盘的访问,同时注销广播接收器。