Android获得所有存储设备位置的最佳方法
作者:徒步青云 发布时间:2022-06-27 21:08:51
标签:Android,存储,设备
本方式可以获得内部存储设备地址、SD卡地址、USB设备地址,兼容性能达到99%(别问我为什么这么保证,因为是借鉴了Android设置->存储页面的源码)。
由于调用了几个被@hide的方法,所以采用了反射。
具体代码如下:
public static List<HomeDirBean> getAllExternalStorage(Context context) {
List<HomeDirBean> storagePath = new ArrayList<>();
StorageManager storageManager = (StorageManager) context.getSystemService(STORAGE_SERVICE);
StorageVolume[] storageVolumes;
try {
Method getVolumeList = StorageManager.class.getDeclaredMethod("getVolumeList");
storageVolumes = (StorageVolume[]) getVolumeList.invoke(storageManager);
Method getVolumeState = StorageManager.class.getDeclaredMethod("getVolumeState", String.class);
for (StorageVolume storageVolume : storageVolumes) {
String desc = storageVolume.getDescription(context);
Log.i(TAG, "storageVolume name--->" + desc);
Method getPath = StorageVolume.class.getMethod("getPath");
String path = (String) getPath.invoke(storageVolume);
Log.i(TAG, "StoragePath--->" + path);
//这里需要用StorageManager反射调用getVolumeState函数,而不应该用StorageVolume的getState方法,因为可能会报错
String state = (String) getVolumeState.invoke(storageManager, path);
Log.i(TAG, "storageVolume State--->" + state);
if (Environment.MEDIA_MOUNTED.equals(state)) {
HomeDirBean bean = new HomeDirBean(path, desc);
storagePath.add(bean);
}
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return storagePath;
}
这里需要注意,可能有小伙伴会问,既然StorageVolume类有getState方法,为啥还要用StorageManager反射调用getVolumeState方法,并传入path地址,而在源码里,StorageManager的getVolumeState的方法的实现,也是将path重新创建为StorageVolume类,然后再调用其getState方法,我们这样做成这不是多此一举吗?
源码截图如下:
答案当然不是了,不然我也不会放弃性能去反射那个方法去装这个逼了。主要原因是@hide的这个方法里,mountPoint被重新打包成StorageVolume时,这相当于系统去创建的一个StorageVolume实例,自然可以执行它的所有方法。而如果是应用直接调用,在被打包时,很多方法被隐藏了,比如这个getState方法,这时候应用就会报错,找不到该方法。
先简单写到这,以后有补充再添加。
来源:https://blog.csdn.net/baidu_28136669/article/details/60877403


猜你喜欢
- 1.在C#中使用FolderBrowserDialog类,就可以实现选择文件夹的功能,并将所选择的的文件夹路径记录下来。(1).首先先引入命
- 前言这个也是Java实验课程的一个作业,和Java实现简单的图形界面计算器一起做的,因为以前没有做过GUI编程,所以做的非常简陋,还有很多B
- Java中Static关键字的一些用法详解1. Static 修饰类属性,因为静态成员变量可以通过类名+属性名调用,非静态成员变量不能通过类
- 在app中经常会用到底部菜单的控件,每次都需要写好多代码,今天我们用到了前几篇博客里的控件来进一步封装底部菜单。先看效果图:主要包括以下功能
- 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java
- 1,通过Handler机制主线程中定义Handler,子线程发消息,通知Handler完成UI更新,Handler对象必须定义在主线程中,如
- 1、题目描述找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知
- 1.获取Return返回值//存储过程//Create PROCEDURE MYSQL//
- 本文实例讲述了C#实现对二维数组排序的方法。分享给大家供大家参考。具体实现方法如下:/// <summary>/// A gen
- synchronized都问啥?如果Java面试有什么是必问的,synchronized必定占据一席之地。初出茅庐时synchronized
- 整理文档,搜刮出一个Spring 实现excel及pdf导出表格的代码,稍微整理精简一下做下分享。excel 导出:package ligh
- 经过测试 将resultMap="java.lang.Integer"改成resultType="java.l
- 本文实例讲述了Android判断网络类型的方法。分享给大家供大家参考,具体如下:判断网络类型是wifi,还是3G,还是2G网络,对不同的网络
- 自从SEOTcs系统11月份24日更新了一下SEO得分算法以来,一直困扰我的一个问题出现了,java的数据job任务,在执行过程中会经常报以
- 现有一些图片在服务器上的链接,在浏览器中打开这些链接是直接显示在浏览器页面的形式。现在需要生成这些图片的单独下载以及打包下载链接,即在浏览器
- 最近看到在Linux上折腾jmeter的人越来越多,不过即使在windows上,jmeter的脚本我还是建议用命令行来执行(降低GUI模式带
- 意图:想将项目用到的两个dll库文件(CryptEnDe.dll和ICSharpCode.SharpZipLib.dll)一同编译进exe中
- 1.传递引用在一个方法中将一个对象的引用传递给另外一个方法,引用指向的对象是同一个public class Person {int age;
- 1.图集导航1.1 为什么对包名的命名要有所规范呢!使用规范的命名有益于程序的开发和后期阅读通俗的说:就是自己写的代码别人也能看的懂,代码结
- 1.前言任何系统,我们不会傻傻的在每一个地方进行异常捕获和处理,整个系统一般我们会在一个的地方统一进行异常处理,spring boot全局异