Android获取内置卡、内置U盘和挂载U盘路径和内存大小
开发一个功能需要使用内置卡、内置U盘和挂载U盘以及分别展示它们内存的大小。
使用的是反射机制,然而在获取外接U盘时发现永远获取导的U盘大小信息是一个固定值,这显示是不正确的,开始是完全使用path路径,后来发现使用internalpath获取U盘大小时是真实的,然而内置卡又没有这个路径,故最后根据不同类型分别选择使用这两个路径。
使用internalPath的大前提获取系统级别的权限:
android:sharedUserId="android.uid.system"
具体代码如下:
public static final String TYPE_INTERNAL_SD_CARD = "SD_Card";//内置卡
public static final String TYPE_INTERNAL_T_CARD = "259";//内置T卡
public static final String TYPE_U_DISK = "8";//U盘
/**
* 获取内存大小 (其中path和internalPath为路径,实际看情况使用哪一个)
*
* @param context 上下文
* @param uDisks 内置T卡(U盘)或外置U盘
* @return String[] U盘信息,[0]U盘总内存大小 [1]U盘可用内存大小
*/
public static long[] getUsbMemoryMsg(Context context, String uDisks) {
String sdcardDir = null;
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Class<?> volumeInfoClazz = null;
Class<?> diskInfoClazz = null;
Class<?> storageVolumeClazz = null;
long[] memory = new long[2];
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
diskInfoClazz = Class.forName("android.os.storage.DiskInfo");
Method isUsb = diskInfoClazz.getMethod("isUsb");
volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo");
Method getType = volumeInfoClazz.getMethod("getType");
Method getDisk = volumeInfoClazz.getMethod("getDisk");
Method getDiskId = volumeInfoClazz.getMethod("getDiskId");
Field path = volumeInfoClazz.getDeclaredField("path");//这个路径获取U盘大小时会出现大小固定为某一值的情况;这个路径可以获取内置盘
Field internalPath = volumeInfoClazz.getDeclaredField("internalPath");//使用这个路径获取U盘大小就没有上述问题;内置盘没有这个路径
Method getVolumes = storageManager.getClass().getMethod("getVolumes");
Method getUserLabel = storageVolumeClazz.getMethod("getUserLabel");
Method getVolumeList = storageManager.getClass().getMethod("getVolumeList");
Object resultVolumeList = getVolumeList.invoke(storageManager);
List<Class<?>> result = (List) getVolumes.invoke(storageManager);
int resultVolumeListLength = Array.getLength(resultVolumeList);
for (int i = 0; i < result.size(); ++i) {
Object volumeInfo = result.get(i);
Log.w("StorageUtils", "volumeInfo::" + JSON.toJSONString(volumeInfo));
String labelInfo = null;
Object disk;
String diskId = null;
if (i < resultVolumeListLength) {
disk = Array.get(resultVolumeList, i);
labelInfo = (String) getUserLabel.invoke(disk);
}
disk = getDisk.invoke(volumeInfo);
diskId = (String) getDiskId.invoke(volumeInfo);
Log.w("StorageUtils", "disk::" + JSON.toJSONString(disk));
Log.w("StorageUtils", "diskId::" + diskId + ",,disk-path::" + path.get(volumeInfo) + ",," + (labelInfo == null ? "unknown" : labelInfo));
Log.w("StorageUtils", "uDisks::" + uDisks);
sdcardDir = (String) path.get(volumeInfo);
Log.w("StorageUtils ", "sdcardDir::" + sdcardDir);
//内置卡没有disk对象,有两个路径 /data和/storage/emulated只读一个即可
if (uDisks.equals(StorageUtils.TYPE_INTERNAL_SD_CARD) && diskId == null && sdcardDir.contains("/storage")) {
long total = getTotalExternalStorageSize(sdcardDir);
long available = getAvailableExternalStorageSize(sdcardDir);
memory[0] = total;
memory[1] = available;
Log.w("StorageUtils", "sdCard::total::" + total + ",,available::" + available + ",,internalPath::" + internalPath);
return memory;
}
//U盘类型(内置T卡)+U盘
if (diskId != null && diskId.contains(uDisks) && disk != null && (Boolean) isUsb.invoke(disk)) {
//使用internalPath代替path后没有上述问题
sdcardDir = (String) internalPath.get(volumeInfo);
long total = getTotalExternalStorageSize(sdcardDir);
long available = getAvailableExternalStorageSize(sdcardDir);
memory[0] = total;
memory[1] = available;
Log.w("StorageUtils", "total::" + total + ",,available::" + available + ",,internalPath::" + sdcardDir);
return memory;
}
}
return null;
} catch (Exception var22) {
Log.i("StorageUtils", "usb-path e " + var22.getMessage());
var22.printStackTrace();
Log.w("StorageUtils", "usb-path null");
return null;
}
}
/**
* 获取总内存
*/
public static long getTotalExternalStorageSize(String storagePath) {
StatFs statFs = new StatFs(storagePath);
long blockSize = statFs.getBlockSizeLong();
long totalBlocks = statFs.getBlockCountLong();
Log.d(TAG, "blockSize:" + blockSize);
Log.d(TAG, "totalBlocks:" + totalBlocks);
return totalBlocks * blockSize;
}
/**
* 获取剩余内存
*/
public static long getAvailableExternalStorageSize(String storagePath) {
StatFs statFs = new StatFs(storagePath);
long blockSize = statFs.getBlockSizeLong();
long availableBlocks = statFs.getAvailableBlocksLong();
Log.d(TAG, "blockSize:" + blockSize);
Log.d(TAG, "availableBlocks:" + availableBlocks);
return availableBlocks * blockSize;
}
上述代码中打印的volumeInfo参数信息如下:仅供参考
///内置卡
{
"description": "内部共享存储空间",
"id": "private",
"mountUserId": -10000,
"mountedReadable": true,
"mountedWritable": true,
"path": "/data",
"primary": false,
"primaryPhysical": false,
"state": 2,
"type": 1,
"visible": false
}
///内置T卡
{
"disk": {
"adoptable": false,
"defaultPrimary": false,
"description": "0x144d U 盘",
"flags": 8,
"id": "disk:259,0",
"label": "0x144d",
"sd": false,
"shortDescription": "U 盘",
"size": 1000204886016,
"stability": 0,
"stubVisible": false,
"sysPath": "/sys//devices/platform/fe150000.pc/nvme/nvme0/nvme0n1",
"usb": true,
"volumeCount": 1
},
"diskId": "disk:259,0",
"fsLabel": "",
"fsType": "vfat",
"fsUuid": "1EDB-1816",
"id": "public:259,1",
"internalPath": "/mnt/media_rw/1EDB-1816",
"mountFlags": 2,
"mountUserId": 0,
"mountedReadable": true,
"mountedWritable": true,
"normalizedFsUuid": "1edb-1816",
"partGuid": "",
"path": "/storage/1EDB-1816",
"primary": false,
"primaryPhysical": false,
"stability": 0,
"state": 2,
"stateDescription": 17040185,
"type": 0,
"visible": true
}
///U盘
{
"description": "新加卷 \b",
"disk": {
"adoptable": false,
"defaultPrimary": false,
"description": "Kingston U 盘",
"flags": 8,
"id": "disk:8,0",
"label": "Kingston",
"sd": false,
"shortDescription": "U 盘",
"size": 31029460992,
"stability": 0,
"stubVisible": false,
"sysPath": "/sys//devices/platform/usbdrd3_0/fc000000.usb/xhci-hcd.7.auto/usb9/9-1/9-1:1.0/host0/target0:0:0/0:0:0:0/block/sda",
"usb": true,
"volumeCount": 1
},
"diskId": "disk:8,0",
"fsLabel": "新加卷 \b",
"fsType": "vfat",
"fsUuid": "720F-AFA1",
"id": "public:8,1",
"internalPath": "/mnt/media_rw/720F-AFA1",
"mountFlags": 2,
"mountUserId": 0,
"mountedReadable": true,
"mountedWritable": true,
"normalizedFsUuid": "720f-afa1",
"partGuid": "",
"path": "/storage/720F-AFA1",
"primary": false,
"primaryPhysical": false,
"stability": 0,
"state": 2,
"stateDescription": 17040185,
"type": 0,
"visible": true
}
U盘插入拔出状态监听广播:
广播接收U盘插入拔出状态和路径_安卓接收到u盘插入的广播之后,怎么判断已经插入-CSDN博客