比如在代码中使用pm.getPackageArchiveInfo(absPath, PackageManager.GET_ACTIVITIES);来获取u盘里面某个apk的版本号,absPath具体为/storage/A804-B928/dangs-factory.apk,这样会导致拔出u盘后/mnt/media_rw/A804-B928路径没有被卸载。请问有什么更好的方式能获取u盘里apk的版本号同时还不出现不能卸载的问题
时间: 2024-01-03 19:03:15 浏览: 89
可以使用`PackageParser`解析应用程序的信息,获取应用程序的版本号,这种方式不会占用文件系统的句柄,也不会导致文件系统被占用而无法卸载。
示例代码如下:
```java
String apkPath = "/storage/A804-B928/dangs-factory.apk";
File file = new File(apkPath);
PackageParser packageParser = new PackageParser();
PackageParser.Package pkg = packageParser.parsePackage(file, 0);
packageParser.collectCertificates(pkg, 0);
String versionName = pkg.versionName; // 获取应用程序的版本号
int versionCode = pkg.versionCode; // 获取应用程序的版本码
```
这样就可以获取指定apk的版本号,而不会占用文件系统的句柄,也不会导致文件系统无法卸载。
相关问题
PackageInfo pkgInfo = pm.getPackageArchiveInfo(absPath, PackageManager.GET_ACTIVITIES); 比如用这个来获取u盘里面的apk信息会导致u盘拔出的时候没有卸载成功,有什么可以替换掉这个的
你可以使用以下代码来获取包信息,它不会导致u盘拔出的时候没有卸载成功:
```java
PackageInfo pkgInfo = getPackageManager().getPackageArchiveInfo(absPath, 0);
if (pkgInfo != null) {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
String appName = getPackageManager().getApplicationLabel(appInfo).toString();
String packageName = appInfo.packageName;
String versionName = pkgInfo.versionName;
int versionCode = pkgInfo.versionCode;
Drawable icon = getPackageManager().getApplicationIcon(appInfo);
}
```
这里使用了`getPackageManager().getPackageArchiveInfo()`来获取包信息,第二个参数为0表示不获取任何附加信息。然后可以从`PackageInfo`中获取应用信息和版本信息,使用`getPackageManager().getApplicationLabel()`获取应用名称,使用`getPackageManager().getApplicationIcon()`获取应用图标。
现在有个需求: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盘。
阅读全文