鸿蒙 Flutter 开源项目实战:从零搭建跨设备文件管理工具并开源
#harmonyos #flutter #开源项目 #文件管理工具 #跨设备协同开源项目是提升技术能力、参与生态共建的重要途径。本文以「鸿蒙跨设备文件管理工具」为例,完整讲解从需求分析、架构设计、功能开发到项目开源的全流程,所有代码遵循开源规范,可直接用于二次开发或学习参考,契合 CSDN「我的第一个开源项目」故事征集活动主题。
作者链接:哇是林啊 1标签:#harmonyos #flutter #开源项目 #文件管理工具 #跨设备协同
开源项目是提升技术能力、参与生态共建的重要途径。本文以「鸿蒙跨设备文件管理工具」为例,完整讲解从需求分析、架构设计、功能开发到项目开源的全流程,所有代码遵循开源规范,可直接用于二次开发或学习参考,契合 CSDN「我的第一个开源项目」故事征集活动主题。
一、开源项目需求与架构设计
1.1 核心需求
开发一款适配鸿蒙多设备的文件管理工具,支持本地文件浏览、跨设备文件传输、文件分类管理、文件搜索四大核心功能,同时具备轻量化、高性能、易扩展的特点。
1.2 项目架构设计
采用三层架构设计,分离 UI 层、业务逻辑层、数据层,便于维护和扩展:
- UI 层:Flutter 实现跨设备统一界面,适配手机、平板、智慧屏;
- 业务逻辑层:封装文件操作、跨设备传输、搜索等核心逻辑;
- 数据层:整合鸿蒙本地文件 API、分布式软总线 API、文件数据库。
1.3 技术栈选型
- 跨端框架:Flutter 3.16+;
- 鸿蒙原生:Java(文件操作、软总线通信);
- 状态管理:Provider 6.0+;
- 本地存储:Hive(轻量级 NoSQL 数据库,存储文件索引);
- 开源工具:git(版本控制)、markdown(文档编写)。
二、项目基础搭建与核心模块开发
2.1 项目结构初始化
创建 Flutter 项目并搭建标准目录结构,同时初始化 git 仓库:
bash
运行
# 创建项目
flutter create harmony_file_manager
cd harmony_file_manager
# 初始化git
git init
echo "# 鸿蒙跨设备文件管理工具" > README.md
git add .
git commit -m "初始化项目"
项目核心目录结构如下:
plaintext
harmony_file_manager/
├── flutter_module/
│ ├── lib/
│ │ ├── core/ # 核心业务逻辑
│ │ ├── model/ # 数据模型
│ │ ├── pages/ # UI页面
│ │ ├── provider/ # 状态管理
│ │ ├── utils/ # 工具类
│ │ └── main.dart # 入口文件
├── entry/ # 鸿蒙原生项目
├── README.md # 开源项目文档
└── LICENSE # 开源许可证
2.2 核心数据模型设计
创建文件数据模型,用于统一管理文件信息,代码如下:
dart
// flutter_module/lib/model/file_model.dart
import 'dart:io';
import 'package:hive/hive.dart';
part 'file_model.g.dart'; // 自动生成序列化代码
@HiveType(typeId: 0)
class FileModel extends HiveObject {
@HiveField(0)
final String filePath; // 文件路径
@HiveField(1)
final String fileName; // 文件名
@HiveField(2)
final String fileType; // 文件类型(图片/文档/视频等)
@HiveField(3)
final int fileSize; // 文件大小(字节)
@HiveField(4)
final DateTime modifyTime; // 修改时间
@HiveField(5)
final String deviceId; // 所属设备ID
FileModel({
required this.filePath,
required this.fileName,
required this.fileType,
required this.fileSize,
required this.modifyTime,
required this.deviceId,
});
// 转换文件大小为友好格式
String get formattedSize {
if (fileSize < 1024) return '$fileSize B';
if (fileSize < 1024 * 1024) return '${(fileSize / 1024).toStringAsFixed(2)} KB';
return '${(fileSize / (1024 * 1024)).toStringAsFixed(2)} MB';
}
}
执行flutter pub run build_runner build生成序列化代码。
2.3 本地文件管理核心功能
封装本地文件浏览、分类、搜索功能,工具类代码如下:
dart
// flutter_module/lib/core/file/local_file_manager.dart
import 'dart:io';
import 'package:hive/hive.dart';
import '../model/file_model.dart';
import '../../utils/channel_manager.dart';
class LocalFileManager {
final Box<FileModel> _fileBox = Hive.box<FileModel>('file_box');
final HarmonyChannelManager _channelManager = HarmonyChannelManager();
// 初始化文件索引
Future<void> initFileIndex() async {
final deviceId = await _channelManager.invokeMethod<String>('getDeviceId');
if (deviceId == null) return;
// 扫描本地文件并建立索引
await _scanLocalFiles('/sdcard', deviceId);
}
// 扫描本地文件
Future<void> _scanLocalFiles(String directoryPath, String deviceId) async {
final directory = Directory(directoryPath);
if (!directory.existsSync()) return;
final files = directory.listSync(recursive: false);
for (var file in files) {
if (file is File) {
final fileType = _getFileType(file.path);
final fileModel = FileModel(
filePath: file.path,
fileName: file.path.split('/').last,
fileType: fileType,
fileSize: file.lengthSync(),
modifyTime: file.lastModifiedSync(),
deviceId: deviceId,
);
_fileBox.add(fileModel);
} else if (file is Directory) {
// 递归扫描子目录
await _scanLocalFiles(file.path, deviceId);
}
}
}
// 根据文件后缀判断文件类型
String _getFileType(String filePath) {
final suffix = filePath.split('.').last.toLowerCase();
if (['jpg', 'png', 'jpeg', 'gif'].contains(suffix)) return 'image';
if (['mp4', 'avi', 'mov'].contains(suffix)) return 'video';
if (['doc', 'docx', 'pdf', 'txt'].contains(suffix)) return 'document';
return 'other';
}
// 按类型筛选文件
List<FileModel> getFilesByType(String type) {
return _fileBox.values.where((file) => file.fileType == type).toList();
}
// 搜索文件(按文件名模糊匹配)
List<FileModel> searchFiles(String keyword) {
return _fileBox.values
.where((file) => file.fileName.toLowerCase().contains(keyword.toLowerCase()))
.toList();
}
}
2.4 跨设备文件传输功能
整合前文实现的分布式软总线能力,实现跨设备文件发送与接收,代码如下:
dart
// flutter_module/lib/core/file/cross_device_file_manager.dart
import '../softbus/softbus_manager.dart';
import '../model/file_model.dart';
import '../../utils/channel_manager.dart';
class CrossDeviceFileManager {
final SoftBusManager _softBusManager = SoftBusManager();
final HarmonyChannelManager _channelManager = HarmonyChannelManager();
// 发送文件到目标设备
Future<bool> sendFileToDevice(String deviceId, FileModel file) async {
return await _softBusManager.sendFile(
deviceId: deviceId,
localFilePath: file.filePath,
);
}
// 接收来自其他设备的文件
Future<void> receiveFile() async {
// 注册文件接收回调
_channelManager.invokeMethod('registerFileReceiver', (Map<String, dynamic> data) {
final filePath = data['filePath'];
final deviceId = data['deviceId'];
// 将接收的文件添加到本地索引
_addReceivedFileToIndex(filePath, deviceId);
});
}
// 将接收的文件添加到本地索引
Future<void> _addReceivedFileToIndex(String filePath, String deviceId) async {
final file = File(filePath);
final fileType = _getFileType(filePath);
final fileModel = FileModel(
filePath: filePath,
fileName: file.path.split('/').last,
fileType: fileType,
fileSize: file.lengthSync(),
modifyTime: file.lastModifiedSync(),
deviceId: deviceId,
);
final box = Hive.box<FileModel>('file_box');
box.add(fileModel);
}
String _getFileType(String filePath) {
final suffix = filePath.split('.').last.toLowerCase();
if (['jpg', 'png', 'jpeg', 'gif'].contains(suffix)) return 'image';
if (['mp4', 'avi', 'mov'].contains(suffix)) return 'video';
if (['doc', 'docx', 'pdf', 'txt'].contains(suffix)) return 'document';
return 'other';
}
}
2.5 状态管理与 UI 页面实现
使用 Provider 管理全局文件数据,状态管理代码如下:
dart
// flutter_module/lib/provider/file_provider.dart
import 'package:flutter/foundation.dart';
import '../model/file_model.dart';
import '../core/file/local_file_manager.dart';
import '../core/file/cross_device_file_manager.dart';
class FileProvider extends ChangeNotifier {
final LocalFileManager _localFileManager = LocalFileManager();
final CrossDeviceFileManager _crossDeviceManager = CrossDeviceFileManager();
List<FileModel> _allFiles = [];
List<FileModel> _filteredFiles = [];
String _currentType = 'all';
List<FileModel> get filteredFiles => _filteredFiles;
String get currentType => _currentType;
// 初始化
Future<void> init() async {
await _localFileManager.initFileIndex();
await _crossDeviceManager.receiveFile();
_allFiles = Hive.box<FileModel>('file_box').values.toList();
_filteredFiles = _allFiles;
notifyListeners();
}
// 切换文件类型
void switchFileType(String type) {
setState(() {
_currentType = type;
if (type == 'all') {
_filteredFiles = _allFiles;
} else {
_filteredFiles = _localFileManager.getFilesByType(type);
}
});
}
// 搜索文件
void searchFiles(String keyword) {
setState(() {
_filteredFiles = _localFileManager.searchFiles(keyword);
});
}
// 发送文件
Future<bool> sendFile(String deviceId, FileModel file) async {
return await _crossDeviceManager.sendFileToDevice(deviceId, file);
}
void setState(VoidCallback fn) {
fn();
notifyListeners();
}
}
创建文件管理主页面,UI 代码如下:
dart
// flutter_module/lib/pages/file_manager_home.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../provider/file_provider.dart';
import '../model/file_model.dart';
class FileManagerHomePage extends StatefulWidget {
const FileManagerHomePage({super.key});
@override
State<FileManagerHomePage> createState() => _FileManagerHomePageState();
}
class _FileManagerHomePageState extends State<FileManagerHomePage> {
final TextEditingController _searchController = TextEditingController();
@override
void initState() {
super.initState();
Provider.of<FileProvider>(context, listen: false).init();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('鸿蒙跨设备文件管理器')),
body: Consumer<FileProvider>(
builder: (context, provider, child) {
return Column(
children: [
// 搜索框
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _searchController,
decoration: const InputDecoration(
hintText: '搜索文件...',
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(),
),
onChanged: provider.searchFiles,
),
),
// 文件类型筛选
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: ['all', 'image', 'video', 'document', 'other']
.map((type) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: ElevatedButton(
onPressed: () => provider.switchFileType(type),
style: ElevatedButton.styleFrom(
backgroundColor: provider.currentType == type ? Colors.blue : Colors.grey,
),
child: Text(_getTypeName(type)),
),
))
.toList(),
),
),
// 文件列表
Expanded(
child: provider.filteredFiles.isEmpty
? const Center(child: Text('暂无文件'))
: ListView.builder(
itemCount: provider.filteredFiles.length,
itemBuilder: (context, index) {
final file = provider.filteredFiles[index];
return ListTile(
title: Text(file.fileName),
subtitle: Text('${file.formattedSize} · ${file.modifyTime.toString().substring(0, 16)}'),
trailing: IconButton(
icon: const Icon(Icons.send),
onPressed: () => _sendFile(context, provider, file),
),
);
},
),
),
],
);
},
),
);
}
String _getTypeName(String type) {
switch (type) {
case 'all': return '全部文件';
case 'image': return '图片';
case 'video': return '视频';
case 'document': return '文档';
case 'other': return '其他';
default: return type;
}
}
Future<void> _sendFile(BuildContext context, FileProvider provider, FileModel file) async {
// 此处可弹窗选择目标设备,简化处理直接传入测试设备ID
const testDeviceId = 'test_device_001';
final result = await provider.sendFile(testDeviceId, file);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(result ? '文件发送成功' : '文件发送失败')),
);
}
}
三、项目开源与文档编写
3.1 开源许可证选择
选择Apache License 2.0,允许商用和二次开发,同时要求保留原作者版权声明。在项目根目录创建LICENSE文件,写入许可证内容。
3.2 编写 README.md 文档
详细介绍项目功能、安装教程、使用方法、贡献指南等,吸引开发者使用和贡献代码:
markdown
# 鸿蒙跨设备文件管理工具
一款基于Flutter和鸿蒙系统开发的跨设备文件管理工具,支持本地文件浏览、分类管理、跨设备传输等功能。
## 功能特点
1. 本地文件管理:支持文件浏览、分类、搜索;
2. 跨设备传输:基于鸿蒙分布式软总线,实现高速文件传输;
3. 多设备适配:适配鸿蒙手机、平板、智慧屏等设备;
4. 轻量化设计:体积小、启动快,占用资源少。
## 环境要求
- 鸿蒙系统:HarmonyOS 6.0+
- Flutter:3.16.0+
- DevEco Studio:4.1.0+
## 安装教程
1. 克隆仓库:git clone https://github.com/yourname/harmony_file_manager.git
2. 安装依赖:cd harmony_file_manager/flutter_module && flutter pub get
3. 打开项目:用DevEco Studio打开项目,编译运行。
## 贡献指南
1. Fork本仓库;
2. 创建特性分支:git checkout -b feature/xxx;
3. 提交代码:git commit -m 'feat: 添加xxx功能';
4. 推送分支:git push origin feature/xxx;
5. 提交Pull Request。
## 许可证
本项目基于Apache License 2.0开源,详见LICENSE文件。
3.3 提交代码并推送到开源平台
将项目推送到 GitCode、GitHub 等开源平台,完成开源发布:
bash
运行
# 添加远程仓库
git remote add origin https://github.com/yourname/harmony_file_manager.git
# 推送代码
git push -u origin main
四、开源项目维护与社区运营
- 问题响应:及时处理用户提交的 Issue,解决使用过程中的 bug;
- 版本迭代:规划后续版本功能,如文件预览、批量传输、云存储集成等;
- 社区交流:创建项目交流群,收集用户反馈,邀请开发者参与贡献。
更多推荐
所有评论(0)