Android8.0中获取U盘的各种信息

权限

首先获取U盘信息,我们需要在androidmanifest.xml中添加以下权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.changhong.usbbroadcast">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".UsbBroadcast">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_MOUNTED"/>
                <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
                <data android:scheme="file"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

详细步骤

要获取U盘的详细信息主要用到3个类:
android.os.storage.StorageManager
android.os.storage.StorageVolume
android.os.storage.VolumeInfo

其中第3个类VolumeInfo默认不可见 ,因此只能通过反射调用,VolumeInfo中主要的成员变量如下:

    /** vold state */
    public final String id;
    public final int type;
    public final DiskInfo disk;
    public final String partGuid;
    public int mountFlags = 0;
    public int mountUserId = -1;
    public int state = STATE_UNMOUNTED;
    public String fsType;       //U盘类型,vfat ntfs
    public String fsUuid;       //UUID
    public String fsLabel;      //U盘名称,必须更改U盘名字后才能够正确显示,否则显示""
    public String path;         //U盘挂载路径
    public String internalPath; //U盘挂载路径
  1. 首先获取StorageManager的实例

    StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
  2. 我们通过StorageManagergetVolumes方法获取全部的Volumes,由于此方法在SDK中是hide,所以也需要通过反射来调用.

        /** {@hide} */
        public @NonNull List<VolumeInfo> getVolumes() {
            try {
                return Arrays.asList(mStorageManager.getVolumes(0));
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    Class storeManagerClazz = Class.forName("android.os.storage.StorageManager");
    
    Method getVolumesMethod = storeManagerClazz.getMethod("getVolumes");
    
    List<?> volumeInfos  = (List<?>)getVolumesMethod.invoke(storageManager);//获取到了VolumeInfo的列表
  3. 在获取到VolumeInfo的list后,我们通过反射依次获得每一个Volumes的各种信息,
    如果某些Volumes的uuid如果为null,那么我们需要忽略,也就是说UUID不为0的VolumeInfo则代表了我们 已经插入的U盘

    Class volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo");
    Field fsTypeField = volumeInfoClazz.getDeclaredField("fsType");
    Field fsLabelField = volumeInfoClazz.getDeclaredField("fsLabel");
    Field pathField = volumeInfoClazz.getDeclaredField("path");
    Field internalPath = volumeInfoClazz.getDeclaredField("internalPath");
    if(volumeInfos != null){
        for(Object volumeInfo:volumeInfos){
            String uuid = (String)getFsUuidMethod.invoke(volumeInfo);
            if(uuid != null){
                String fsTypeString = (String)fsTypeField.get(volumeInfo);//U盘类型
                String fsLabelString = (String)fsLabelField.get(volumeInfo);//U盘名称
                String pathString = (String)pathField.get(volumeInfo);//U盘路径
                String internalPathString = (String)internalPath.get(volumeInfo);//U盘路径
            }
        }
    }
  4. 要获取U盘的总空间以及剩余空间等,我们需要知道U盘挂载路径,同时使用android.os.StatFs这个类

    //StatFs statFs = new StatFs(internalPathString);
    StatFs statFs = new StatFs(pathString);                           
    long avaibleSize = statFs.getAvailableBytes();//获取U盘可用空间
    long totalSize = statFs.getTotalBytes();//获取U盘总空间
  5. 在获取U盘空间时,如果Statfs直接使用VolumeInfo的path时,我发现多次插拔U盘时获取的空间大小不准确,获取的大小老是1008091136字节,于是我通过internalPath去获取U盘空间,发现结果是OK的,但是如果我们使用internalPath,我们的App必需要获取system权限,否则会报权限错误,要获取system权限,则在androidmanifest中加入
    android:sharedUserId="android.uid.system"
    完整manifest如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:sharedUserId="android.uid.system"
    package="com.changhong.usbbroadcast">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".UsbBroadcast">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_MOUNTED"/>
                <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
                <data android:scheme="file"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

完整代码如下:


public class UsbBroadcast extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        switch (intent.getAction()) {
            case Intent.ACTION_MEDIA_MOUNTED: {
                StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
                try {
                    Class storeManagerClazz = Class.forName("android.os.storage.StorageManager");

                    Method getVolumesMethod = storeManagerClazz.getMethod("getVolumes");

                    List<?> volumeInfos  = (List<?>)getVolumesMethod.invoke(storageManager);

                    Class volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo");

                    Method getTypeMethod = volumeInfoClazz.getMethod("getType");
                    Method getFsUuidMethod = volumeInfoClazz.getMethod("getFsUuid");

                    Field fsTypeField = volumeInfoClazz.getDeclaredField("fsType");
                    Field fsLabelField = volumeInfoClazz.getDeclaredField("fsLabel");
                    Field pathField = volumeInfoClazz.getDeclaredField("path");
                    Field internalPath = volumeInfoClazz.getDeclaredField("internalPath");

                    if(volumeInfos != null){
                        for(Object volumeInfo:volumeInfos){
                            String uuid = (String)getFsUuidMethod.invoke(volumeInfo);
                            if(uuid != null){
                                String fsTypeString = (String)fsTypeField.get(volumeInfo);
                                String fsLabelString = (String)fsLabelField.get(volumeInfo);
                                String pathString = (String)pathField.get(volumeInfo);
                                String internalPathString = (String)internalPath.get(volumeInfo);
                                StatFs statFs = new StatFs(internalPathString);
                                long avaibleSize = statFs.getAvailableBytes();
                                long totalSize = statFs.getTotalBytes();
                            }
                        }
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }

                break;
            }
            case Intent.ACTION_MEDIA_UNMOUNTED: {

                break;
            }
            default:
                break;
        }

    }

}
  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值