开发一个功能需要使用内置卡、内置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博客