MoodCanvas/lib/services/image_save_service.dart
fengshengxiong 91b7eebbf2 接入TopON
2026-01-22 16:34:55 +08:00

152 lines
4.3 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
class ImageSaveService {
/// 保存图片到相册 - 改进版本,避免 debugNeedsPaint 错误
static Future<bool> saveImageToGallery(
GlobalKey repaintBoundaryKey, {
String? fileName,
}) async {
try {
// 1. 检查权限
final hasPermission = await _requestPermission();
if (!hasPermission) {
debugPrint('没有相册访问权限');
return false;
}
// 2. 使用调度器确保在正确的时机捕获
final completer = Completer<bool>();
SchedulerBinding.instance.addPostFrameCallback((_) async {
try {
// 额外等待确保所有绘制完成
await Future.delayed(const Duration(milliseconds: 100));
final result = await _captureAndSave(repaintBoundaryKey, fileName);
completer.complete(result);
} catch (e) {
debugPrint('捕获图片失败: $e');
completer.complete(false);
}
});
return await completer.future;
} catch (e) {
debugPrint('保存图片失败: $e');
return false;
}
}
/// 内部方法:捕获并保存图片
static Future<bool> _captureAndSave(
GlobalKey repaintBoundaryKey,
String? fileName,
) async {
try {
// 获取 RepaintBoundary
final boundary =
repaintBoundaryKey.currentContext?.findRenderObject()
as RenderRepaintBoundary?;
if (boundary == null) {
debugPrint('无法获取RepaintBoundary');
return false;
}
// 多次尝试捕获,避免绘制冲突
ui.Image? image;
int attempts = 0;
const maxAttempts = 5;
while (attempts < maxAttempts) {
try {
// 检查是否正在绘制
if (boundary.debugNeedsPaint) {
debugPrint(
'RepaintBoundary 正在绘制中,等待... (尝试 ${attempts + 1}/$maxAttempts)',
);
await Future.delayed(Duration(milliseconds: 200 * (attempts + 1)));
attempts++;
continue;
}
// 尝试捕获图片
image = await boundary.toImage(pixelRatio: 3.0);
break;
} catch (e) {
debugPrint('捕获尝试 ${attempts + 1} 失败: $e');
attempts++;
if (attempts < maxAttempts) {
await Future.delayed(Duration(milliseconds: 300 * attempts));
}
}
}
if (image == null) {
debugPrint('所有捕获尝试都失败了');
return false;
}
// 转换为字节数据
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) {
debugPrint('无法转换图片数据');
return false;
}
final pngBytes = byteData.buffer.asUint8List();
// 保存到相册
final result = await ImageGallerySaver.saveImage(
pngBytes,
name: fileName ?? 'MoodCanvas_${DateTime.now().millisecondsSinceEpoch}',
quality: 100,
);
debugPrint('保存结果: $result');
return result['isSuccess'] == true;
} catch (e) {
debugPrint('_captureAndSave 失败: $e');
return false;
}
}
/// 请求相册访问权限
static Future<bool> _requestPermission() async {
if (Platform.isIOS) {
// iOS 14+ 需要 photos 权限
final status = await Permission.photos.request();
return status.isGranted;
} else if (Platform.isAndroid) {
// Android 需要存储权限
final status = await Permission.storage.request();
return status.isGranted;
}
return false;
}
/// 检查权限状态
static Future<bool> checkPermission() async {
if (Platform.isIOS) {
final status = await Permission.photos.status;
return status.isGranted;
} else if (Platform.isAndroid) {
final status = await Permission.storage.status;
return status.isGranted;
}
return false;
}
/// 打开应用设置页面
static Future<void> openSettings() async {
await openAppSettings();
}
}