当前位置: 首页 > article >正文

手把手教你实现一个文件浏览器

文件选择功能在很多的应用中都有被用到,用来选择用户手机中的文件或目录。首先我建议你使用官方的API选择手机文件,然后使用dview的方式选择目录。

使用官方API选择手机文件
public static void selectFile(@NonNull Activity activity, int requestCode) {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("*/*");
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    activity.startActivityForResult(intent, requestCode);
}

使用这个API可以打开手机系统内置的文件选择器,虽然一般来说会比较丑,但功能全,稳定性好。然后这个方法已经被集成到dora framework( https://github.com/dora4/dora )中了。

IntentUtils.selectFile(context, AppConfig.REQUEST_CODE_CHOOSE_FILE)

使用以上方式即可调用。

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == AppConfig.REQUEST_CODE_CHOOSE_FILE) {
        val uri = data?.data ?: return
        val path = IoUtils.getPathFromUri(context, uri)
        if (path == null) {
            Log.e("dora", "You can't read file.")
            return
        }
        val file = File(path)
        // 在此处理文件...
    }
}

把所有的request code定义到全局是有好处的,第一个好处呢就是方便查找功能,第二个好处呢则是可以方便保证全局的请求码都不一致,这样避免错误。说到这里,我提一嘴通常初中级程序员喜欢使用的魔法数问题。总是一大堆的数字计算,而不把数字转换成全局的常量。这样做在算法复用并修改时很有可能漏掉,也很容易被忽略,特别是缺少代码评审流程的开发团队。所以,我建议除了你完全可以确认不会被其他地方用到以外,常量一律提到全局。

自定义一个文件浏览器

文件浏览器组件已经被定义到dview框架集合下,https://github.com/dora4/dview-file-browser 。

效果演示

在这里插入图片描述

巧克力风格的文件浏览器,目前适配的语言有英语、中文(简体)和中文(繁体)。

Get Started
// 选择目录
FileBrowser.chooseFolder(activity)
// 选择文件
FileBrowser.chooseFile(activity)
// 选择文件和目录
FileBrowser.chooseFileAndFolder(activity)

选择目录通过点击标题栏右上角的选择按钮,而选择文件则点击具体的某一个文件条目。

public static final int REQUEST_CODE_CHOOSE_FILE = 1;
public static final int REQUEST_CODE_CHOOSE_FOLDER = 2;
public static final int REQUEST_CODE_CHOOSE_BOTH_FILE_AND_FOLDER = 3;

通过以上枚举的请求码获取选择的路径。

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == FileBrowser.REQUEST_CODE_CHOOSE_FILE) {
        val path = data?.getStringExtra(FileBrowser.EXTRA_PATH) ?: return
        if (path == null) {
            Log.e("dora", "You can't read file.")
            return
        }
        val file = File(path)
        // 在此处理文件...
    }
}
思路分析

要开发这样一个文件浏览器,首先要注意的一点就是Android 13开始细分了文件管理权限。我们来看看Android 13以后的6种文件权限分别是什么?

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<!-- Android 13版本适配,细化存储权限开始 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- Android 13版本适配,细化存储权限结束 -->

READ_EXTERNAL_STORAGE:Android 6以前定义在xml中,Android 6到Android12,使用代码运行时申请权限。
WRITE_EXTERNAL_STORAGE:同READ_EXTERNAL_STORAGE。
MANAGE_EXTERNAL_STORAGE:调用系统的文件浏览器API使用。
READ_MEDIA_IMAGESREAD_MEDIA_IMAGESREAD_MEDIA_VIDEO:Android13开始要逐个申请,当然是代码运行时进行权限的申请。需要注意的是,即使你在运行时申请权限,也要在清单文件中定义,这样才能在设置中被用户看到。

阅读源码,我们发现在清单文件中,有这么一段。

<application>
    <activity
        android:name="dora.widget.filebrowser.FileBrowserActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="dora.widget.filebrowser.action.CHOOSE_FILE"/>
            <action android:name="dora.widget.filebrowser.action.CHOOSE_FOLDER"/>
            <action android:name="dora.widget.filebrowser.action.CHOOSE_BOTH_FILE_AND_FOLDER"/>
        </intent-filter>
    </activity>
</application>

android:exported属性设置为true,表示此activity可以被外部应用调启。<intent-filter/>中定义了三种action,用于区分你要调启这个activity的用途。当然调启的逻辑都被封装到了FileBrowser类中,使用者可以无需知道这些原理即可使用。


http://www.kler.cn/a/300982.html

相关文章:

  • Kylin Linux V10 替换安装源,并在服务器上启用 EPEL 仓库
  • C#与Vue2上传下载Excel文件
  • 题解 CodeForces 430B Balls Game 栈 C/C++
  • SpeingMVC框架(三)
  • 音视频入门基础:RTP专题(1)——RTP官方文档下载
  • 2025年中科院分区大类划分公布!新增8155本
  • 文件压缩zip工具
  • vue3的学习
  • 【LeetCode 算法笔记】49. 字母异位词分组
  • EmguCV学习笔记 VB.Net 11.3 DNN其它
  • 特种设备考试真题题库及答案
  • adb有线连接正常,adb connect失败
  • 利用 GitHub Actions 自动提交 URL 到 IndexNow
  • Docker 镜像配置
  • delphi 12 给App授予权限
  • 聚铭网络受邀成为ISC终端安全生态联盟首批成员单位
  • 【jvm】记一次hive堆heap内存溢出的排查
  • opencv之图像轮廓(三)--凸包
  • 机器学习 第11章 特征选择与稀疏学习
  • 【网络】UDP协议的简单使用
  • 前端性能优化——对节流与防抖的理解
  • pico2 开发环境搭建-基于ubuntu
  • 李宏毅结构化学习 01
  • 力扣238 移动零 Java版本 时间复杂度为O(0)
  • 机器学习 第12章 计算学习理论
  • 在Excel里制作简单游戏界面