• AndroidManifest.xml
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><receiver android:name=".receiver.UsbReceiver">    <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>
  • UsbReceiver.java
public class UsbReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        UsbManager.getInstance().usbObserveReceive(context, intent, Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction())                ? Constants.USB_TYPE_ATTACH : Constants.USB_TYPE_DETACH);    }}
  • UsbInfo.java
public class UsbInfo {    // uuid    public String uuid;    // uri    public Uri uri;    // u盘类型    public String fsType;    // u盘名称    public String fsLabel;    // u盘路径    public String path;    // u盘路径    public String internalPath;    // 已格式化显示的可用空间大小    public String availableSize;    // 已格式化显示的总空间大小    public String totalSize;    @Override    public String toString() {        return "UsbInfo{" +                "uuid='" + uuid + '\'' +                ", uri=" + uri +                ", fsType='" + fsType + '\'' +                ", fsLabel='" + fsLabel + '\'' +                ", path='" + path + '\'' +                ", internalPath='" + internalPath + '\'' +                ", availableSize='" + availableSize + '\'' +                ", totalSize='" + totalSize + '\'' +                '}';    }}
  • UsbObserveType .java
public class Constants {public static final int USB_TYPE_ATTACH = 0x3001;public static final int USB_TYPE_DETACH = 0x3002;}@IntDef(flag = true, value = {        Constants.USB_TYPE_ATTACH, Constants.USB_TYPE_DETACH})public @interface UsbObserveType {}
  • UsbManager.java
public class UsbManager {    private static final String TAG = "UsbManager";    private Set<UsbInfo> mUsbInfos = new LinkedHashSet<>();    private List<OnUsbReceiveListener> mOnUsbReceiveListeners = new LinkedList<>();    private static class UsbManagerHolder {        private static final UsbManager INSTANCE = new UsbManager();    }    public static UsbManager getInstance() {        return UsbManagerHolder.INSTANCE;    }    public Set<UsbInfo> getUsbInfos(Context context) {        if (mUsbInfos.size() == 0)            return queryUsbInfos(context);        return mUsbInfos;    }    public void registerUsbReceiveListener(OnUsbReceiveListener listener) {        mOnUsbReceiveListeners.add(listener);    }    public void unregisterUsbReceiveListener(OnUsbReceiveListener listener) {        mOnUsbReceiveListeners.remove(listener);    }    public void usbObserveReceive(Context context, Intent intent, @UsbObserveType int usbObserveType) {        Set<UsbInfo> tUsbInfos = queryUsbInfos(context);        UsbInfo attachUsbInfo = new UsbInfo();        if (usbObserveType == Constants.USB_TYPE_ATTACH) {            for (UsbInfo usbInfo : tUsbInfos) {                if (intent.getData().getPath().equals(usbInfo.path)) {                    usbInfo.uri = intent.getData();                    attachUsbInfo = usbInfo;                    mUsbInfos.add(attachUsbInfo);                    break;                }            }        } else {            for (UsbInfo usbInfo : mUsbInfos) {                if (usbInfo.uri.equals(intent.getData())) {                    attachUsbInfo = usbInfo;                    mUsbInfos.remove(attachUsbInfo);                    break;                }            }        }        Log.i(TAG, "intent = " + intent + ", usbInfos = " + mUsbInfos);        for (OnUsbReceiveListener listener : mOnUsbReceiveListeners) {            if (listener != null) {                listener.onUsbReceive(usbObserveType, mUsbInfos, attachUsbInfo);            }        }    }    public Set<UsbInfo> queryUsbInfos(Context context) {        Set<UsbInfo> usbInfos = new LinkedHashSet<>();        try {            StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);            Class clazz = Class.forName("android.os.storage.StorageManager");            Method methodGetVolumes = clazz.getMethod("getVolumes");            List<?> volumeInfos = (List<?>) methodGetVolumes.invoke(sm);            @SuppressLint("PrivateApi") Class volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo");            Method methodGetFsUUID = volumeInfoClazz.getMethod("getFsUuid");            Field fieldFsType = volumeInfoClazz.getDeclaredField("fsType");            Field fieldFsLabelField = volumeInfoClazz.getDeclaredField("fsLabel");            Field fieldPath = volumeInfoClazz.getDeclaredField("path");            Field fieldInternalPath = volumeInfoClazz.getDeclaredField("internalPath");            if (volumeInfos != null) {                for (Object volumeInfo : volumeInfos) {                    String uuid = (String) methodGetFsUUID.invoke(volumeInfo);                    if (uuid != null) {                        UsbInfo usbInfo = new UsbInfo();                        usbInfo.uuid = uuid;                        usbInfo.fsType = (String) fieldFsType.get(volumeInfo);                        usbInfo.fsLabel = (String) fieldFsLabelField.get(volumeInfo);                        usbInfo.path = (String) fieldPath.get(volumeInfo);                        usbInfo.internalPath = (String) fieldInternalPath.get(volumeInfo);                        try {                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {                                StatFs statFs = new StatFs(usbInfo.path);                                usbInfo.availableSize = Formatter.formatFileSize(context, statFs.getAvailableBytes());                                usbInfo.totalSize = Formatter.formatFileSize(context, statFs.getTotalBytes());                            }                        } catch (IllegalArgumentException e) {                            e.printStackTrace();                        }                        usbInfos.add(usbInfo);                    }                }            }        } catch (Exception e) {            e.printStackTrace();        }        return usbInfos;    }    public interface OnUsbReceiveListener {        void onUsbReceive(@UsbObserveType int usbObserveType, Set<UsbInfo> usbInfos, UsbInfo currUsbInfo);    }}
  • 使用
public class TestActivity extends AppCompatActivity implements UsbManager.OnUsbReceiveListener {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        UsbManager.getInstance().registerUsbReceiveListener(this);    } @Override    protected void onDestroy() {        UsbManager.getInstance().unregisterUsbReceiveListener(this);        super.onDestroy();    }@Override    public void onUsbReceive(int usbObserveType, Set<UsbInfo> usbInfos, UsbInfo currUsbInfo) {    // 接收处理    }}

注意事项:

在实际项目开发过程中,比如在TV机顶盒开发,使用以上方法是可以较为准确的监听到USB的插拔,但是如果尝试将数据写入USB,将会出现无法写入提示 permission denied,这个时候需要去修改源码。

从源码中定位到 frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java,搜索到 systemReady() 这个方法,加入以下几句代码:

StorageManagerInternal StorageManagerInternal = LocalServices.getService(StorageManagerInternal.class);StorageManagerInternal.addExternalStoragePolicy(        new StorageManagerInternal.ExternalStorageMountPolicy() {    @Override    public int getMountMode(int uid, String packageName) {        if (Process.isIsolated(uid)) {            return Zygote.MOUNT_EXTERNAL_NONE;        }        // 添加允许写权限---开始if (checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) {            return Zygote.MOUNT_EXTERNAL_DEFAULT;        }        // 添加允许写权限---结束        if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {            return Zygote.MOUNT_EXTERNAL_DEFAULT;        }        if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {            return Zygote.MOUNT_EXTERNAL_READ;        }        return Zygote.MOUNT_EXTERNAL_WRITE;    }    @Override    public boolean hasExternalStorage(int uid, String packageName) {        return true;    }});

然后在app的 AndroidManifest.xml 加入权限即可:

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

更多相关文章

  1. Android 权限管理框架
  2. Android之SharedPreferences权限
  3. I2C-Tools 4.0使用说明及android平台移植,提供源码下载路径
  4. android 获取屏幕尺寸大小
  5. Android PopupWindow显示位置和显示大小
  6. 基于Android系统软件管理器源码
  7. android仿苹果Iphone桌面源码
  8. PointerLocationView 源码分析
  9. Android 开发艺术探索 源码地址

随机推荐

  1. Android Command 开发常用命令行合集
  2. 奉上20个Android很有用的代码片段
  3. Android 判断wifi是2.4G还是5G
  4. android 遍历所有控件
  5. Android分享一款漂亮的折叠书架菜单
  6. find ./ -name "hardware.*" 查找文件
  7. 分享Android微信红包插件
  8. Android 判断当前程序是否在前台运行
  9. Error:Could not determine the dependen
  10. Android 多线程1