android 6.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盘挂载路径

首先获取StorageManager的实例

StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
1
我们通过StorageManager的getVolumes方法获取全部的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的列表

在获取到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盘路径
        }
    }
}

要获取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盘总空间

在获取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;
        }

    }

}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值