android读写u盘支持安卓10以上的最新方法

本人是在写一个app需要读取u盘文件列表,网上找了好多方法,要不就是没有media权限,要不就是收不到广播,全部用不了,就这样搁置了一段时间终于又找到了一个大佬的方法,在这做个笔记

谷歌从Android5.0以上已经不支持开发者随便读写手机的外部存储(包含tf卡、otg外接u盘等),换句话说5.0以下我们还是可以直接读写usb设备的。

当你直接拿到u盘挂载路径,去操作的时候,File类已经读取不到任何东西,因为缺少了以下这个权限

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

当然如果你是root用户,也可以直接修改系统配置文件,/system/etc/permissions/platform.xml文件中有两组配置,其中

    <permission name="android.permission.WRITE_MEDIA_STORAGE" ><group gid="media_rw" /></permission>

是u盘等外接媒体的权限,而

<permission name="android.permission.READ_EXTERNAL_STORAGE" />
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" />

这两组就是手机内置的外部存储,除了系统使用的内部存储,其他一切都是外部存储,所以读写u盘也需要用到他们,那要怎么改呢,从我了解下来,实际上大概样子就是如下

<permission name="android.permission.WRITE_EXTERNAL_STORAGE"><group gid="media_rw" /><group gid="sdcard_rw" />
</permission><permission name="android.permission.WRITE_MEDIA_STORAGE" ><group gid="media_rw" /><group gid="sdcard_rw" />
</permission>

当然没有root的用户看看就好了,接下来说说非root用户。

针对非root用户,有些比如ES文件浏览器,他们可以直接操作u盘,实际上是通过google的特定方法,SAF框架操作外置sd卡,也就是DocumentFile类,假如不用这个类,直接想操作,那只能向rom厂商申请系统签名,加入白名单,成为系统应用。

SAF框架,你只需要在AndroidManifest.xml加上,想了解可以去官网看看https://developer.android.com/guide/topics/providers/document-provider.html

<providerandroid:name="com.github.mjdev.libaums.storageprovider.UsbDocumentProvider"android:authorities="com.github.mjdev.libaums.storageprovider.documents"android:exported="true"android:grantUriPermissions="true"android:permission="android.permission.MANAGE_DOCUMENTS"android:enabled="@bool/isAtLeastKitKat"><intent-filter><action android:name="android.content.action.DOCUMENTS_PROVIDER" /></intent-filter>
</provider>

重点来了,废话不多说,以上的方法仅供了解,下面才是真正的开始,采用第三方框架 libaums

//https://github.com/magnusja/libaums
implementation 'me.jahnen.libaums:core:0.9.1'

具体实现如下:

/*** 动态注册监听USB设备的广播。* 由于耗电等原因,8.0不能对大部分的广播进行静态注册*/private void registerUsbReceiver() {USBBroadCastReceiver usbBroadCastReceiver = new USBBroadCastReceiver(getActivity());usbBroadCastReceiver.setOnPermListener(new USBBroadCastReceiver.OnPermListener() {@Overridepublic void onRemove() {updateUdiskView();}@Overridepublic void onConnect() {updateUdiskView();}});IntentFilter filter = new IntentFilter(USBBroadCastReceiver.ACTION_USB_PERMISSION);filter.addAction("android.hardware.usb.action.USB_STATE");filter.addAction("android.hardware.usb.action.USB_DEVICE_ATTACHED");filter.addAction("android.hardware.usb.action.USB_DEVICE_DETACHED");getActivity().registerReceiver(usbBroadCastReceiver, filter);/*** 启动软件尝试读取u盘*/usbBroadCastReceiver.redUDiskDeviceList();}
package com.zj.ruokeplayer.receive;import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_ATTACHED;
import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED;import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.util.Log;import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.zj.jplayercore.controller.JPlayer;
import com.zj.ruokeplayer.model.GlobalConstant;import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;import me.jahnen.libaums.core.UsbMassStorageDevice;
import me.jahnen.libaums.core.fs.FileSystem;
import me.jahnen.libaums.core.fs.UsbFile;
import me.jahnen.libaums.core.fs.UsbFileStreamFactory;
import me.jahnen.libaums.core.partition.Partition;/*** usb设备处理*/
public class USBBroadCastReceiver extends BroadcastReceiver {public static final String ACTION_USB_PERMISSION = "com.android.rkplayer.USB_PERMISSION";private UsbMassStorageDevice[] storageDevices;private final String TAG = "rkplayer_usb";private Context context;private OnPermListener onPermListener;public USBBroadCastReceiver(Context context) {this.context = context;}public void setOnPermListener(OnPermListener onPermListener) {this.onPermListener = onPermListener;}@Overridepublic void onReceive(Context context, Intent intent) {String intentAction = intent.getAction();UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);switch (intentAction) {case ACTION_USB_PERMISSION://自定义Actionif (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {//                    LogUtils.i(TAG, "用户同意USB设备访问权限");ToastUtils.showShort("您已同意USB设备访问");readDevice(getUsbMass(device));} else {//                    LogUtils.i(TAG, "用户拒绝USB设备访问权限");ToastUtils.showShort("您已拒绝USB设备访问权限");GlobalConstant.usbInited = false;onPermListener.onRemove();}break;case ACTION_USB_DEVICE_ATTACHED:
//                LogUtils.i(TAG, "U盘设备插入");ToastUtils.showShort("U盘设备插入");if (device != null) {redUDiskDeviceList();}break;case ACTION_USB_DEVICE_DETACHED:ToastUtils.showShort("U盘设备移除");GlobalConstant.usbInited = false;onPermListener.onRemove();
//                LogUtils.i(TAG, "U盘设备移除");break;default://。。。}}/*** 获取存储设备* @param usbDevice 与android设备连接在一起的USB设备* @return Usb设备的一个包装类*/private UsbMassStorageDevice getUsbMass(UsbDevice usbDevice) {for (UsbMassStorageDevice device : storageDevices) {if (usbDevice.equals(device.getUsbDevice())) {return device;}}return null;}/*** USB设备读取*/public void redUDiskDeviceList() {//设备管理器UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);//获取U盘存储设备storageDevices = UsbMassStorageDevice.getMassStorageDevices(context);PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);//一般手机只有1个OTG插口if (storageDevices.length <= 0) {return;}UsbMassStorageDevice device = storageDevices[0];//读取设备是否有权限if (usbManager.hasPermission(device.getUsbDevice())) {readDevice(device);} else {//没有权限,进行申请usbManager.requestPermission(device.getUsbDevice(), pendingIntent);}}/*** 初始化USB设备* @param device USB设备*/private void readDevice(UsbMassStorageDevice device) {try {device.init();//初始化//设备分区Partition partition = device.getPartitions().get(0);//文件系统FileSystem currentFs = partition.getFileSystem();//可以获取到设备的标识currentFs.getVolumeLabel();//通过FileSystem可以获取当前U盘的一些存储信息,包括剩余空间大小,容量等等LogUtils.e("Volume Label: ", currentFs.getVolumeLabel());LogUtils.e("Capacity: ", fSize(currentFs.getCapacity()));LogUtils.e("Occupied Space: ", fSize(currentFs.getOccupiedSpace()));LogUtils.e("Free Space: ", fSize(currentFs.getFreeSpace()));LogUtils.e("Chunk size: ", fSize(currentFs.getChunkSize()));GlobalConstant.usbInited = true;readAndWrite(currentFs);} catch (Exception e) {e.printStackTrace();}}/*** 格式化* @param sizeInByte* @return*/public static String fSize(long sizeInByte) {if (sizeInByte < 1024) {return String.format("%s", sizeInByte);} else if (sizeInByte < 1024 * 1024) {return String.format(Locale.CANADA, "%.2fKB", sizeInByte / 1024.);} else if (sizeInByte < 1024 * 1024 * 1024) {return String.format(Locale.CANADA, "%.2fMB", sizeInByte / 1024. / 1024);} else {return String.format(Locale.CANADA, "%.2fGB", sizeInByte / 1024. / 1024 / 1024);}}/*** 读写文件** @param currentFs*/public void readAndWrite(FileSystem currentFs) {onPermListener.onConnect();try {//设置当前文件对象为根目录UsbFile usbFile = currentFs.getRootDirectory();UsbFile[] files = usbFile.listFiles();for (UsbFile file : files) {LogUtils.i(TAG,  file.getName());}} catch (Exception e) {e.printStackTrace();}}/*** 回调* @param currentFs*/public interface OnPermListener {public void onRemove();public void onConnect();}
}

应用中会唤起读取u盘的权限,基本就到这里结束了

android免root读写u盘最新方法,支持安卓Q+相关推荐

  1. Android 免root 备份数据,福利来了!安卓手机免root数据恢复方法

    在使用手机的过程中,我们难免会发生一些"小意外",这些"小意外"无非就是手机死机啦,然后系统损坏啦,要么就是自己手贱不小心把文件给删除啦......于是我们就要 ...

  2. Android免Root环境下Hook框架Legend原理分析

    0x1 应用场景 现如今,免Root环境下的逆向分析已经成为一种潮流! 在2015年之前的iOS软件逆向工程领域,要想对iOS平台上的软件进行逆向工程分析,越狱iOS设备与安装Cydia是必须的!几乎 ...

  3. Android免root查看数据库内容

    Android免root查看数据库内容 用Android Studio 的一个小工具 1.首先需要Android Studio 3.0 还没有升级AS 3.0的小伙伴赶快升级啦. AS升级方式:菜单栏 ...

  4. 干货|Android免Root最全Hook插件(免Root Hook任意App)

    支持276个API接口的Hook,覆盖Android系统级API和50个常见开源框架的Hook,包括对网络.算法.TextView.WebView.JSONObject等API接口的Hook支持,可以 ...

  5. 【android免root脚本制作】基于控件的操作——auto.js进阶

    在[android免root脚本制作]自动坐标操作手机--京东金融程序金果摇钱树自动收金果 之后,想要做进一步优化,因为基于坐标点击如何屏幕被移动之类就会点击错位,不同手机还需去适配坐标,甚是麻烦,所 ...

  6. Anti-recall 防撤回神器 -- Android 免root查看撤回消息和闪照 官网

    Anti-recall 防撤回神器官方下载 Android 免root查看撤回消息和闪照 官网 下载地址 anti-recall.com 哪里撤回点哪里 妈妈再也不用担心我错过劲爆消息了呢 爆照撤回没 ...

  7. android中NFC读写功能的实现方法

    这篇文章主要为大家详细介绍了android中NFC读写功能的实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了android中NFC读写功能的 ...

  8. Android 免root 备份数据,教你安卓手机免Root恢复手机数据的三种方法

    说到安卓手机,人们对它的第一印象就是开源.自由.可定制.市面上大多数系统,比如Flyme.MIUI其实都是由安卓内核再加上一层自己的包装罢了.所以你会看到手机上一堆预装软件卸载不掉,这本质上就是手机厂 ...

  9. android免root运行adb高级权限命令,例如修改手机设置等(转)

    免Root实现静默安装和点击任意位置 0 前言 最近有了个需求:免 root 实现任意位置点击和静默安装.这个做过的小伙伴应该都知道正常情况下是不可能实现的.无障碍只能实现对已知控件的点击,并不能指定 ...

最新文章

  1. export linux命令_linux 初级3 环境变量命令env、set、export、declare的区别
  2. 计算器界面分析及界面程序实现
  3. 单像素骨架提取算法c语言实现,【图像】骨架提取与分水岭算法
  4. cad转dxf格式文件太大_想知道DWG、DWT、DWS和DXF是什么吗?从了解4种CAD图形格式开始吧...
  5. python下载numpy库_安装numpy库
  6. Project 3 resources reassigned !!!
  7. 用JAVA编程的数字时钟代码
  8. C++和C#结构体转换的问题
  9. linux dns权重设置,权重及权重配置
  10. Microsoft Visual Studio 2013/2015/2017 官方原版 ISO 镜像中文版下载
  11. Sentinel-1 SAR数据与精密轨道数据下载
  12. 后缀001,002,003等的文件解压
  13. ubuntu和windows双系统默认启动顺序
  14. 大一作业HTML网页作业 HTML CSS制作二十四节气网页
  15. gedit变身为编程利器的简单配置
  16. 【Chrome必备插件,一键提升10倍效率】新用户永久免广告,好用!
  17. [Python面试][基础算法题]Python基础面试(基础算法题目较多)
  18. C语言fgetc的使用
  19. python爬虫五大实例,爬虫初始与PyCharm安装
  20. Surface Pro5 如何安装Win10系统

热门文章

  1. 关于Oculus无法下载应用:(OVR40779122) 的解决方案
  2. XaaC一切皆计算机 和 XaaS一切皆服务
  3. matlab中omega是什么意思_小鸡宝宝考考你南柯一梦中的南柯是什么意思?
  4. 期末操作系统之HXL所给知识点(速成)
  5. 为RMI实现类Jini的发现机制
  6. 什么是数据库“存算分离”架构?
  7. 快速获取iOS APP中的所有素材
  8. 传奇单机架设图文教程
  9. google gms安装
  10. 什么是RCT实时时钟?(STM32中RTC时钟源)