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

文件选择功能在很多的应用中都有被用到,用来选择用户手机中的文件或目录。首先我建议你使用官方的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类中,使用者可以无需知道这些原理即可使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dora丶Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值