用JavaFX做一个手机文件下载器
界面设想
刚开始想借鉴windows的文件管理器,于是用工具提取了windows的部分图标。最后改成左侧显示文件夹树,右侧显示选中的文件夹的文件,下方显示下载和上传的进度。
功能设想
我的文件经常下载到"sdcard/download",所以就以它为根本路径。
- 显示路径下文件夹和文件
- 下载文件到当前路径
- 上传文件
- 当前路径
- 指定路径
- 显示上传下载进度
借助Spring
很久以前,我想借助Spring的容器,查看了一些资料,发现大部分都是和SpringBoot搭配。于是这一次我也打算和SpringBoot搭配。通过寻找,找到了"springboot-javafx-support",但是它支持SpringBoot2,对Java和JavaFx的高版本支持也不太好。但我想尝试一下,看看能不能尽可能解决,因为我想用Java17、SpringBoot3、JavaFX17。最后,策略改变了,借鉴这个JavaFX17 整合 SpringBoot 3.1.0 (IDEA2023.1.2 ,jdk17.0.7 ) - 初步整合 - 知乎 (zhihu.com)。
后话:我怀疑创建了两个容器,因为我尝试了许多方法,只有一个类里的注入可以成功,其它地方都不能注入成功,容器里没有bean。所以最后主要放入了几个布局类。
准备环境
JavaFX17、Java17、SpringBoot3.0.5、adb(改支持中文的1.0.31、原版1.0.41)
1 | <parent> |
具体实现
-
使用Font Awesome图标
本来想像网页那样使用图标,但找到的一些方式都不太兼容。最后选择使用字体方式。
- Font Awesome下载字体等资源
- 借助文本编辑器和正则表达式,从文件里将图标名和Unicode 编码提取出来放到Map里
- 在Label里放入从Map里提取的Unicode
- 将字体文件读入,应该也可安装后通过名字读入
- 为Label设置字体
-
执行adb命令
借助
ProcessBuilder
执行命令,封装到工具类- 参数为数组,每一个元素为命令的一部分,即将一条命令放入数组
- 通过
BufferedReader
读取结果的每一行,默认utf-8编码 - 将结果封装为
List
返回
-
读取文件夹和文件信息(应该新建一个线程处理,我当时没有,不过还好不是传输大文件)
- 封装
TreeItem
,赋予文件夹属性 - 封装文件夹类,具有名称、路径、文件夹集合、文件集合、修改时间和大小的属性,添加增加大小的方法、文件夹集合和文件集合清除方法
TreeItem
作为根结点参数传入- 借助工具类,执行
adb shell ls -lt 手机path
- 使用正则分隔每一行信息提取需要的信息:
drwxrws--- 2 u0_a185 media_rw 8192 2023-09-18 23:28 Browser
,可以从权限处区分文件和文件夹,可以获得文件大小(文件夹大小不对,可以用内部文件累加),可以获得修改时间,可以获得名称 - 封装文件类,继承
Label
,具有名称、路径、大小、修改时间和后缀,定义一个初始化方法对Label进行一部分设置 - 根据每一行信息,创建
TreeItem
添加到根节点里,创建Label
,添加点击下载事件,放到文件集合里 - 返回根节点
TreeItem
- 封装
-
下载手机文件
- 封装下载功能到工具类
- 命令为
adb pull "手机文件路径" .
,路径的双引号还是保留好 - 从点击事件里获取手机文件路径
- 新开一个线程执行下载
-
上传到手机
由于拖拽的文件不一定只有一个,所以①命令拼接(不行)②一个文件一个命令
- 封装上传功能到工具类
- 传入存放路径和文件路径
- 命令为
adb push "手机存放路径" 文件路径
- 遍历文件路径,新开线程执行命令
- 当前文件夹
FlowPane
添加DragOver
事件,修改接收模式FlowPane
添加DragDropped
事件,获取文件等信息,上传文件
- 指定文件夹
TreeView
设置CellFactory
- 重写
updateItem
方法 - 给
TreeCell
添加DragOver
事件,修改接收模式和给TreeView
获得选择模型focus
当前的TreeCell
- 给
TreeCell
添加DragDropped
事件,获取文件和路径等信息,上传文件
-
进度条
- 在
HBox
放入Label
作为文件名和上传下载图标,放入ProgressBar
作为进度条,放入Label
作为进度条数值 - 在工具类封装进度条方法
- 创建内部类继承
Task
,实现call
方法,在里面不停读取文件当前大小(封装)与文件总大小进行比较,更新进度 - 创建
Service<Integer>
,实现createTask
,返回前面创建的Task
- 进度条绑定
Task
- 给
Task
添加监听,修改进度Label
的Text
- 启动
Service
- 在
-
获取文件大小信息
- 电脑文件
(new File(path)).length();
- 手机文件
- 命令为
adb shell ls -lt "手机文件所在文件夹路径" | grep "文件名"
- 提取信息里的大小返回
- 命令为
- 电脑文件
-
其它
- 一些组件到处使用,所以放到容器,我通过配置类进行注入(笨办法是继承然后添加
@Component
)
- 一些组件到处使用,所以放到容器,我通过配置类进行注入(笨办法是继承然后添加
结构
1 | D:. |
代码
git clone https://gitee.com/pengxiandyou/java-fx---mobile-file-download.git
注意
- 有adb环境,建议支持中文的版本
- 中文版本adb不一定完全支持中文,文件名后缀前的最后一个中文后要有除数字的其它字符
- 运行使用
java -jar 包
,有打包exe,也可双击 - 乱码是正常的,Android ADB 完美支持中文 详细讲解(一) - 鸿网互联 (68idc.cn)