Files
MEIZU-Battery-Healthy/lib/services/saf_storage_service.dart
T

172 lines
5.0 KiB
Dart

import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_saf/flutter_saf.dart';
import '../models/saf_permission_state.dart';
/// SAF 存储服务
/// 负责管理通过 SAF 授权的文件夹访问
class SafStorageService {
static final SafStorageService _instance = SafStorageService._internal();
factory SafStorageService() => _instance;
SafStorageService._internal();
static const String _prefKeySafUri = 'saf_storage_uri';
static const String _prefKeySafPermission = 'saf_permission_uri';
/// 存储的授权 URI
String? _cachedUriString;
/// 初始化,从 SharedPreferences 恢复授权状态
Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
_cachedUriString = prefs.getString(_prefKeySafUri);
if (kDebugMode) {
print('[SAF] 初始化,缓存 URI: $_cachedUriString');
}
}
/// 获取当前授权状态
Future<SafPermissionState> getPermissionState() async {
if (_cachedUriString == null || _cachedUriString!.isEmpty) {
return SafPermissionState.unauthorized;
}
try {
final uri = Uri.parse(_cachedUriString!);
// 检查 Uri 是否仍然有效
final isValid = await FlutterSaf.isDirectory(uri);
if (!isValid) {
_clearCache();
return SafPermissionState.expired;
}
return SafPermissionState.authorized;
} catch (e) {
_clearCache();
return SafPermissionState.expired;
}
}
/// 请求 SAF 授权(引导用户选择文件夹)
/// 返回授权结果
Future<SafAuthorizationResult> requestPermission() async {
try {
// 调用系统文件夹选择器
// 引导用户选择 /storage/emulated/0/mbattery_charger/
// 或者用户可以选择任何目录,但我们建议选择具体路径
final uri = await FlutterSaf.openDocumentTree();
if (uri == null) {
return SafAuthorizationResult.denied();
}
// 获取持久化 URI 权限
await FlutterSaf.takePersistableUriPermission(uri);
// 验证是否为目录
final isValid = await FlutterSaf.isDirectory(uri);
if (!isValid) {
return SafAuthorizationResult.error('选择的路径不是有效目录');
}
// 保存 URI
final uriString = uri.toString();
_cachedUriString = uriString;
await _saveUri(uriString);
if (kDebugMode) {
print('[SAF] 授权成功,URI: $uriString');
}
return SafAuthorizationResult.success(uriString);
} catch (e) {
if (kDebugMode) {
print('[SAF] 授权失败: $e');
}
return SafAuthorizationResult.error('授权失败: $e');
}
}
/// 检查指定日期的日志文件是否存在
Future<bool> logFileExists(String fileName) async {
final state = await getPermissionState();
if (state != SafPermissionState.authorized) {
return false;
}
try {
final uri = Uri.parse(_cachedUriString!);
final fileUri = await FlutterSaf.getFile(uri, fileName);
return fileUri != null && await FlutterSaf.isFile(fileUri);
} catch (e) {
return false;
}
}
/// 读取日志文件内容
/// 返回文件行列表,如果文件不存在或读取失败返回空列表
Future<List<String>> readLogFile(String fileName) async {
final state = await getPermissionState();
if (state != SafPermissionState.authorized) {
return [];
}
try {
final uri = Uri.parse(_cachedUriString!);
final fileUri = await FlutterSaf.getFile(uri, fileName);
if (fileUri == null || !await FlutterSaf.isFile(fileUri)) {
return [];
}
final content = await FlutterSaf.readTextFile(fileUri);
return content.split('\n');
} catch (e) {
if (kDebugMode) {
print('[SAF] 读取文件失败: $e');
}
return [];
}
}
/// 获取文件夹中的文件列表
Future<List<String>> listFiles() async {
final state = await getPermissionState();
if (state != SafPermissionState.authorized) {
return [];
}
try {
final uri = Uri.parse(_cachedUriString!);
final files = await FlutterSaf.listFiles(uri);
return files.where((f) => f.isFile).map((f) => f.name).toList();
} catch (e) {
return [];
}
}
/// 检查授权是否有效,如果失效则清除缓存
Future<bool> validatePermission() async {
final state = await getPermissionState();
return state == SafPermissionState.authorized;
}
/// 清除授权缓存
void _clearCache() {
_cachedUriString = null;
_saveUri(null);
}
/// 保存 URI 到 SharedPreferences
Future<void> _saveUri(String? uriString) async {
final prefs = await SharedPreferences.getInstance();
if (uriString != null && uriString.isNotEmpty) {
await prefs.setString(_prefKeySafUri, uriString);
} else {
await prefs.remove(_prefKeySafUri);
}
}
/// 获取缓存的 URI(用于调试)
String? get cachedUri => _cachedUriString;
}