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 init() async { final prefs = await SharedPreferences.getInstance(); _cachedUriString = prefs.getString(_prefKeySafUri); if (kDebugMode) { print('[SAF] 初始化,缓存 URI: $_cachedUriString'); } } /// 获取当前授权状态 Future 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 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 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> 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> 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 validatePermission() async { final state = await getPermissionState(); return state == SafPermissionState.authorized; } /// 清除授权缓存 void _clearCache() { _cachedUriString = null; _saveUri(null); } /// 保存 URI 到 SharedPreferences Future _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; }