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

这篇具有很好参考价值的文章主要介绍了android免root读写u盘最新方法,支持安卓Q+。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

<provider
    android: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() {
            @Override
            public void onRemove() {
                updateUdiskView();
            }

            @Override
            public 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;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
        switch (intentAction) {
            case ACTION_USB_PERMISSION:
                //自定义Action
                if (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盘的权限,基本就到这里结束了文章来源地址https://www.toymoban.com/news/detail-414697.html

到了这里,关于android免root读写u盘最新方法,支持安卓Q+的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 安卓Android Studio读写MifareOne M1 IC卡源码

    本示例使用的发卡器: https://item.taobao.com/item.htm?id=615391857885spm=a1z10.5-c-s.w4002-21818769070.11.3d2f789eOUPJBK 源码下载:AndroidstudioRFIDNFC读写源码资源-CSDN文库

    2024年02月01日
    浏览(35)
  • RK3588平台开发系列讲解(安卓篇)Android12 获取 root 权限

    沉淀、分享、成长,让自己和他人都能有所收获!😄 📢获取 Android 设备的 root 权限是指取得超级用户( root 用户)的权限,使得用户可以对系统进行更广泛的修改和操作。但需要注意,获取 root 权限可能会导致安全风险,包括系统不稳定、数据丢失或设备损坏,因此应该谨

    2024年02月03日
    浏览(67)
  • 通刷-晶晨S905L/S905LB主控芯片_安卓6.0-带ROOT-线刷通刷固件包(支持多种遥控)

    通刷-晶晨S905L/S905LB主控芯片_安卓6.0-带ROOT-线刷通刷固件包(支持多种遥控) 固件说明: 本固件教程针对晶晨S905L/S905L-B芯片机型通刷,此为安卓6.0线刷固件!支持移动遥控器等多种遥控! 1,安卓6.0,适合2.1,1.1t,3300l等老机型,大部分型号有线无线正常。 2,纯净固件,

    2024年02月07日
    浏览(43)
  • 【Windows 11】系统安装修改版 Subsystem for Android 安卓子系统,并用 Magisk Root

    目录 步骤 1. 卸载已安装的Window Subsystem for Android 官方版本 2. 启用\\\"Hyper-V\\\" 和 \\\"虚拟机平台\\\"  3. 查看 CPU 处理器是架构 4. 下载修改版Windows Subsystem Android安卓子系统 5. 解压 WSA .zip 包解压缩,并看到有 “AppxManifest.xml” 的文件路径并复制 6. 安装 WSA 安卓子系统 7. 打 开WSA安卓子系

    2024年02月06日
    浏览(48)
  • Android Studio 支持安卓手机投屏

    有时当我们在线上做技术分享或者功能演示时,希望共享连接中的手机屏幕,此时我们会求助 ApowerMirror,LetsView,Vysor,Scrcpy 等工具。如果你是一个 Android Developer,那么现在你有了更好的选择。 自 Android Studio Electric Eel (电鳗)起支持了手机投屏,且功能非常强大: 手机屏幕

    2024年01月17日
    浏览(44)
  • Android文件选择器 路径选择 支持安卓4.4 ~ 13 支持Android/data目录访问 支持SD卡 适配Android11

    Android上进行文件选择或操作的第三方库,自动申请存储权限,支持 Android4.4 ~ 13,再也不用为了适配各种版本而苦恼了,快速集成,一句代码搞定,完善的文档,支持无root权限访问和操作Android/data和Android/obb目录(适配Android 13),支持SD卡,高度自定义UI满足你的所有需求,使用非常

    2024年02月04日
    浏览(35)
  • C++版Android实时投屏软件系统源码,安卓手机投屏软件源码,无需root权限

    QtScrcpy 可以通过 USB / 网络连接Android设备,并进行显示和控制。无需root权限。 同时支持 GNU/Linux ,Windows 和 MacOS 三大主流桌面平台。 完整代码下载地址:C++版Android实时投屏软件系统源码 它专注于: 精致 (仅显示设备屏幕) 性能 (30~60fps) 质量 (1920×1080以上) 低延迟 (35~70ms) 快速启

    2024年02月05日
    浏览(43)
  • Linux下 VScode以sudo/root权限运行的最新方法

    如果你用以下代码无法以sudo权限运行Vscode,那么可能是因为你的Vscode版本是近期的,而这段代码貌似从2020年就有了,被各种转载。 最新的代码如下,参考issue:无法使用 --no-sandbox 作为 sudo 用户运行 vscode #151187 在2023年6月23日,Ubuntu20.4 VScode 1.79.2中执行这段代码测试成功。

    2024年02月10日
    浏览(29)
  • 让Ubuntu 18.04系统支持root用户登录的方法

    默认的Ubuntu 18.04系统在登陆界面上是不支持root用户直接登录的,但是你可以使用下面的方法让Ubuntu 18.04也支持root登录。通常情况下,在Ubuntu 18.04中的普通用户只能通过运行sudo [命令] [参数]来获得系统临时使用root权限,或者是运行su root切换到root用户权限下,下面是使用roo

    2024年02月14日
    浏览(38)
  • 如何通过Android平台的API实现5G网络的支持 安卓系统版本和5g网络相关【一】

    前面分享了两篇5G基带相关的移植修改博文。 安卓高通机型的基带移植 修改 编译的相关 增加信号 支持5G等【一】 安卓高通机型的基带移植 修改 编译的相关 增加信号 支持5G等【二】 今天的帖子聊聊安卓版本与5G网络与机型和修改之间相关的话题。众所周知,目前的机型基本

    2024年02月09日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包