Android获取外接U盘USB设备外接sd卡路径及文件的正确姿势

您所在的位置:网站首页 如何读取手机u盘文件 Android获取外接U盘USB设备外接sd卡路径及文件的正确姿势

Android获取外接U盘USB设备外接sd卡路径及文件的正确姿势

2024-06-27 16:02| 来源: 网络整理| 查看: 265

android应用开发中和U盘打交道的场景其实比较少,这次项目因为是做的汽车的中控系统里的一个视频播放应用,需求是可以播放插入的U盘里的视频。因为之前没有接触过这方面的东西,算是记录一下吧。主要分两步,第一:监听U盘的插拔;第二:获取U盘路径以及扫描该路径下所有文件。

1.监听U盘的插拔: 这里是通过系统广播来实现监听的,网上也有很多这方面的资料,但是很多说的方法是无效的,以下方式在5.0以上系统都验证过了是可以的。手里没有5.0以下的机子所以没验证5.0以下的系统,有需要的同学可以自己验证下。

public class ExternalStorageMonitor { public static final String TAG = "ExternalStorageMonitor"; public static final String EXTERNAL_STORAGE_DEFAULT_PATH = "/mnt/media_rw"; private static ExternalStorageMonitor mInstance; private List deviceListeners; private Context mContext; public static ExternalStorageMonitor getInstance(Context context){ if (mInstance == null){ synchronized (ExternalStorageMonitor.class){ if (mInstance == null){ mInstance = new ExternalStorageMonitor(context); } } } return mInstance; } private ExternalStorageMonitor(Context context) { mContext = context.getApplicationContext(); deviceListeners = new ArrayList(); } public boolean init(ExternalStorageDeviceListener listener) { addDeviceListener(listener); startMonitor(); // 在系统启动前是否已经有设备插入 detectDevice(); return true; } public void addDeviceListener(ExternalStorageDeviceListener listener) { for (ExternalStorageDeviceListener deviceListener : deviceListeners) { if (listener == deviceListener) { return; } } deviceListeners.add(listener); } public void removeDeviceListener(ExternalStorageDeviceListener listener) { deviceListeners.remove(listener); } /** * 开始监听USB设备的插拔 * */ private void startMonitor() { IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); USBBroadCastReceiver usbBroadCastReceiver = new USBBroadCastReceiver(); mContext.registerReceiver(usbBroadCastReceiver, filter); } /** * 检测是否有USB设备的插入 */ private void detectDevice() { UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); if (usbManager != null) { HashMap deviceHashMap = usbManager.getDeviceList(); if (deviceHashMap.isEmpty()) { return; } for (UsbDevice device : deviceHashMap.values()) { Log.d(TAG, "device name: " + device.getDeviceName() + "\nvendor id:" + device.getVendorId()); dispatchAttachedListener(); } } } private void dispatchAttachedListener() { for (ExternalStorageDeviceListener deviceListener : deviceListeners) { deviceListener.onAttached(); } } private void dispatchDetachedListener() { for (ExternalStorageDeviceListener deviceListener : deviceListeners) { deviceListener.onDetached(); } } public interface ExternalStorageDeviceListener { void onAttached(); void onDetached(); } private class USBBroadCastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "onReceive: "); switch (intent.getAction()) { case UsbManager.ACTION_USB_DEVICE_ATTACHED: Log.d(TAG, "U盘插入"); dispatchAttachedListener(); break; case UsbManager.ACTION_USB_DEVICE_DETACHED: Log.d(TAG, "U盘拔出"); dispatchDetachedListener(); break; default: break; } } } }

2.获取U盘路径并扫描文件: 关于获取U盘路径花费了比较多的时间,中间遇到了不少问题,好在最后还是成功了。

首先是权限问题,U盘的挂载点和外接sd卡的路径是不同的,所以就算是申请了"android.permission.WRITE_EXTERNAL_STORAGE"和 "android.permission.READ_EXTERNAL_STORAGE"的权限,那也仅仅是能获取到外接sd卡路径的权限有了,还是没有权限获取U盘的路径。这就是为什么用adb shell命令查看到了U盘路径,但是代码里写死路径去扫描,却扫描不到任何文件的原因,这里需要在manifest里添加如下权限:

这个权限是系统应用权限,U盘的挂载路径是在/mnt/路径下的,而不是像外接sd卡一样大多是在/storage/目录下。

然后就是获取U盘路径了,因为我们这个车中控系统本身就是项目组其他组的同事定制做的,所以可以保证U盘的挂载路径唯一,我们应用层可以写死这个路径直接去扫描文件就可以了。但是也有方法动态获取的,我这边自己研究了下总结了两个方法:

/** * 根据label获取外部存储路径(此方法适用于android7.0以上系统) * @param context * @param label 内部存储:Internal shared storage SD卡:SD card USB:USB drive(USB storage) */ @RequiresApi(api = Build.VERSION_CODES.N) public static String getExternalPath(Context context, String label) { String path = ""; StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); //获取所有挂载的设备(内部sd卡、外部sd卡、挂载的U盘) List volumes = mStorageManager.getStorageVolumes();//此方法是android 7.0以上的 try { Class storageVolumeClazz = Class.forName("android.os.storage.StorageVolume"); //通过反射调用系统hide的方法 Method getPath = storageVolumeClazz.getMethod("getPath"); Method isRemovable = storageVolumeClazz.getMethod("isRemovable"); // Method getUserLabel = storageVolumeClazz.getMethod("getUserLabel");//userLabel和description是一样的 for (int i = 0; i < volumes.size(); i++) { StorageVolume storageVolume = volumes.get(i);//获取每个挂载的StorageVolume // 通过反射调用getPath、isRemovable、userLabel String storagePath = (String) getPath.invoke(storageVolume); //获取路径 boolean isRemovableResult = (boolean) isRemovable.invoke(storageVolume);//是否可移除 String description = storageVolume.getDescription(context);//此方法是android 7.0以上的 if (label.equals(description)){ path = storagePath; break; } LogUtils.d(TAG+"getExternalPath--", " i=" + i + " ,storagePath=" + storagePath + " ,description=" + description); } } catch (Exception e) { LogUtils.d(TAG+"getExternalPath--", " e:" + e); } return path; } public static void getAllExternalPath(Context context) { StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); try { Class volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo"); //这里需要说明一下,还有一个getVolumeList方法获取到的是StorageVolume数组(但是此数组不包含USB外接设备) Method getVolumeList = mStorageManager.getClass().getMethod("getVolumes"); //获取所有挂载的设备(内部sd卡、外部sd卡、挂载的U盘) List result = (List) getVolumeList.invoke(mStorageManager); // final int size = Array.getLength(result); //通过反射调用系统hide的方法 Method getPath = volumeInfoClazz.getMethod("getPath"); Method getDescription = volumeInfoClazz.getMethod("getDescription"); for (int i = 0; i < result.size(); i++) { // Object storageVolume = Array.get(result, i); Object storageVolume = result.get(i); // 通过反射调用getPath File filePath = (File) getPath.invoke(storageVolume); //获取路径 String storagePath = filePath.getAbsolutePath(); String description = (String) getDescription.invoke(storageVolume); LogUtils.d(TAG, " i=" + i + " ,storagePath=" + storagePath + " ,description=" + description); } } catch (Exception e) { LogUtils.d(TAG, " e:" + e); } }

说明一下,第一个方法适用于Android7.0以上系统,可以很好的得到内置sd,外置sd卡,和usb外接设备的路径。 第二个方法这边只是提供了一个思路,可以根据具体不同情况分析得到的description来区分是sd卡的路径还是usb设备的路径,或者根据得到的storagePath路径来排除掉sd卡的,剩下的就是usb设备的路径了,因为不同厂商都会对android系统做不同程度的各种定制,导致外接sd卡的路径实在太多了,据不完全统计,外接sd卡常见的路径有如下: /storage/emulated/0/

/storage/extSdCard

/mnt/external_sd/

/mnt/sdcard2/

/mnt/sdcard/external_sd/

/mnt/sdcard-ext/

/mnt/sdcard/

/storage/sdcard0/

/mnt/extSdCard/

/mnt/extsd/

/mnt/emmc/

/mnt/extern_sd/

/mnt/ext_sd/

/mnt/ext_card/

/mnt/_ExternalSD/

/sdcard2/

/sdcard/

/sdcard/sd/

/sdcard/external_sd/

/mnt/sd/

/mnt/

/storage/

/mnt/sdcard/sd/

/mnt/exsdcard/

/mnt/sdcard/extStorages/SdCard/

/ext_card/

/storage/extSdCard

真的是贼多,想要用第二种方法获取usb设备(即U盘)路径 的,基本可以从获取到的storagePath里排除掉包含"sd" “card” "storage"的路径,剩下的基本就是U盘路径了,但还不绝对是。。

我也很无奈,目前位置没找到好的能获取7.0以下系统的U盘路径的方法。如有哪位大神知道,还望告知。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3