fix:增加图片选择和拍照功能

This commit is contained in:
jingyun
2026-06-23 10:07:35 +08:00
parent 75ba309e8c
commit 8cf919283b
16 changed files with 1288 additions and 45 deletions
@@ -43,6 +43,8 @@ class DeviceHeaderService {
String _androidOaid = '';
String _androidImei = '';
String _androidMac = '';
IosDeviceInfo? iosDeviceInfo;
AndroidDeviceInfo? androidDeviceInfo;
Future<void>? _baseInitialization;
Future<void>? _identityInitialization;
@@ -120,9 +122,23 @@ class DeviceHeaderService {
_iosIdfv = await _resolveIdfv();
await _collectIosPaidIfMissing();
}
await getDeviceInfo();
} catch (_) {}
}
Future<void> getDeviceInfo() async {
try {
final deviceInfoPlugin = DeviceInfoPlugin();
if (Platform.isIOS) {
iosDeviceInfo = await deviceInfoPlugin.iosInfo;
} else if (Platform.isAndroid) {
androidDeviceInfo = await deviceInfoPlugin.androidInfo;
}
} catch (e) {
print('$e');
}
}
Future<void> _collectAndroidIdIfAgreed() async {
if (_androidId.isNotEmpty) return;
if (!StorageService.to.getBool(storagePrivacyAgreed)) return; // 隐私同意后才采集
+20
View File
@@ -0,0 +1,20 @@
import '../../features/assets/data/asset_models.dart';
class UploadRepository {
const UploadRepository();
Future<UploadResult> uploadAssetImage(AssetImage image) async {
// TODO: Connect to upload backend.
return UploadResult(
remoteUrl: image.remoteUrl,
thumbnailUrl: image.thumbnailUrl,
);
}
}
class UploadResult {
const UploadResult({this.remoteUrl, this.thumbnailUrl});
final String? remoteUrl;
final String? thumbnailUrl;
}
+13
View File
@@ -0,0 +1,13 @@
import '../../features/assets/data/asset_models.dart';
import 'upload_repository.dart';
class UploadService {
const UploadService({required this.repository});
final UploadRepository repository;
Future<UploadResult> uploadAssetImage(AssetImage image) async {
// Placeholder: future implementation will upload the file and return URLs.
return repository.uploadAssetImage(image);
}
}
+119
View File
@@ -0,0 +1,119 @@
import 'dart:io';
import 'dart:ui' as ui;
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:gal/gal.dart';
import 'package:http/http.dart' as http;
import 'package:jinzhi_flutter_app/common/services/device_header_service.dart';
import 'package:permission_handler/permission_handler.dart';
class ImageUtil {
static const String _albumName = 'jinzhi';
static Stream<FileResponse> downloadImage(String url, String key) {
return DefaultCacheManager().getFileStream(
url,
key: key,
withProgress: true,
);
}
static Future<String> downloadImageInFile(String url, String key) async {
final file = await DefaultCacheManager().getSingleFile(url, key: key);
return file.path;
}
static Future<bool> requestForImagePermission() async {
if (Platform.isIOS) {
PermissionStatus photoStatus = await Permission.photosAddOnly.status;
if (photoStatus != PermissionStatus.granted) {
photoStatus = await Permission.photosAddOnly.request();
if (photoStatus != PermissionStatus.granted) {
return false;
}
}
} else if (Platform.isAndroid) {
int? sdkInt = DeviceHeaderService.to.androidDeviceInfo?.version.sdkInt;
if (sdkInt != null && sdkInt >= 33) {
// ✅ Android 13+ 不需要读权限,直接返回 true
// gal 插件内部通过 MediaStore 写入
return true;
} else {
// ✅ Android 10-12 仍可能需要 storage 权限
final status = await Permission.storage.request();
return status.isGranted;
}
} else {
return false;
}
return true;
}
static Future<void> saveImage(FileInfo fileInfo) async {
await Gal.putImage(fileInfo.file.path, album: _albumName);
}
static Future<void> saveImageData(ByteData byteData) async {
Uint8List imageBytes = byteData.buffer.asUint8List();
await Gal.putImageBytes(
imageBytes,
name: 'XWallpaper_share',
album: _albumName,
);
}
static Future<void> saveImageUint8List(Uint8List imageBytes) async {
await Gal.putImageBytes(
imageBytes,
name: 'XWallpaper_share',
album: _albumName,
);
}
static Future<void> saveUIImageData(ui.Image image) async {
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List imageBytes = byteData!.buffer.asUint8List();
await Gal.putImageBytes(
imageBytes,
name: 'XWallpaper_share',
album: _albumName,
);
}
static Future<Uint8List> createTransparentImage(double aspectRatio) async {
double minSize = 100;
double width = minSize * aspectRatio;
double height = minSize;
final recorder = PictureRecorder();
final canvas = Canvas(
recorder,
Rect.fromLTWH(0, 0, width.toDouble(), height.toDouble()),
);
final paint = Paint()..color = Colors.transparent;
canvas.drawRect(
Rect.fromLTWH(0.0, 0.0, width.toDouble(), height.toDouble()),
paint,
);
final picture = recorder.endRecording();
final img = await picture.toImage(width.toInt(), height.toInt());
final pngBytes = await img.toByteData(format: ImageByteFormat.png);
return pngBytes!.buffer.asUint8List();
}
// 下载图片并返回 Uint8List(简单实现)
static Future<Uint8List?> fetchThumbBytes(String? url) async {
if (url == null || url.isEmpty) return null;
try {
final resp = await http.get(Uri.parse(url));
if (resp.statusCode == 200) return resp.bodyBytes;
} catch (_) {}
return null;
}
}