HarmonyOS鸿蒙Next中做鸿蒙化flutter,功能需要保存图片到相册中
HarmonyOS鸿蒙Next中做鸿蒙化flutter,功能需要保存图片到相册中
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:experimental_stu/components/toast/finish_toast.dart';
import 'package:experimental_stu/event/app_events.dart';
import 'package:experimental_stu/event/event_manager.dart';
import 'package:experimental_stu/services/app_permission_status.dart';
import 'package:experimental_stu/utils/assets_util.dart';
import 'package:experimental_stu/utils/toast_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart'
if (dart.library.html) 'package:experimental_stu/web/image_gallery_saver_web.dart';
import 'package:file_system/file_system.dart' as fs;
class Ceshi extends StatefulWidget {
double scale = 1;
String qrUrl = '';
/// 默认及加载失败图
String defImgPath;
final String title;
double? titleSize;
double? btnFontSize;
Size? btnSize;
Ceshi({
Key? key,
this.scale = 1,
required this.title,
this.titleSize,
this.btnFontSize,
this.btnSize,
required this.qrUrl,
required this.defImgPath,
}) : super(key: key);
@override
_CeshiState createState() => _CeshiState();
}
class _CeshiState extends State<Ceshi> {
Uint8List? qrData;
@override
initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
await AppPermissionStatus.instance.saveAlbum.getStatus();
getImageAsUint8List(widget.qrUrl, AssetsUtil.successQr);
});
}
createDefQr(double scale) {
return Image.asset(AssetsUtil.successQr,
width: 200 * scale, height: 200 * scale, fit: BoxFit.fitWidth);
}
showSuccessToast(double scale) {
SmartDialog.showToast('',
alignment: Alignment.center,
displayTime: const Duration(seconds: 3), builder: (context) {
return FinishToast(message: '已保存到相册', scale: scale);
});
}
void showErrorToast(String message, double scale) {
SmartDialog.showToast('',
alignment: Alignment.center,
displayTime: const Duration(seconds: 3), builder: (context) {
return FinishToast(message: message, scale: scale);
});
}
getImageAsUint8List(String imageUrl, String localAssetName) async {
Dio dio = Dio();
Uint8List? imageBytes;
try {
// 尝试从网络获取图片
Response response = await dio.get(imageUrl,
options: Options(responseType: ResponseType.bytes));
imageBytes = response.data;
} catch (e) {
// 网络请求失败,从本地资产加载图片
final ByteData data = await rootBundle.load(localAssetName);
imageBytes = data.buffer.asUint8List();
}
if (mounted) {
setState(() {
qrData = imageBytes;
});
}
}
@override
Widget build(BuildContext context) {
double scale = widget.scale;
return Container(
width: 302.w * scale,
height: 384.w * scale,
padding: EdgeInsets.symmetric(
horizontal: 35.w * scale, vertical: 20.w * scale),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(26.9.w),
),
child: Column(
children: [
Text(
widget.title,
style: TextStyle(
color: Colors.black,
fontSize: widget.titleSize ?? 23.55.w,
fontWeight: FontWeight.w600,
),
),
Expanded(
child: Container(
width: 232.w * scale,
height: 232.w * scale,
alignment: Alignment.center,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
AssetsUtil.successQrBorder), // AssetImage用于加载项目中的图片
fit: BoxFit.fitWidth, // 图片填充方式
),
),
child: qrData == null
? createDefQr(scale)
: Image.memory(qrData!,
width: 200.w * scale,
height: 200.w * scale,
fit: BoxFit.fitWidth),
),
),
GestureDetector(
onTap: () async {
if (qrData == null) {
showErrorToast('图片不存在,无法保存', scale);
return;
}
// if (Platform.isOhos) {
// Map result = await ImageGallerySaver.saveImage(qrData!);
// if (result['isSuccess']) {
// showSuccessToast(scale);
// } else {
// print('保存失败了Error: ${result['error']}'); // Handle erro
// ToastUtil.shortTime('保存失败');
// }
// return;
// }
bool isGranted = AppPermissionStatus.instance.saveAlbum.isGranted;
if (!isGranted) {
ShowPermissionRequestEvent event = ShowPermissionRequestEvent(
name: '媒体权限使用说明:',
deniedDescribe: '请开启存储权限',
tag: 'savePhone',
permissionAlbum: AppPermissionStatus.instance.saveAlbum,
describe: '用于保存图片到相册');
EventManager.instance.eventBus.fire(event);
isGranted = await event.completer.future;
}
if (isGranted) {
await ImageGallerySaver.saveImage(qrData!);
showSuccessToast(scale);
}
},
child: Container(
width: widget.btnSize?.width ?? 161.5.w * scale,
height: widget.btnSize?.height ?? 53.8.w * scale,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color(0xFFFF7613),
borderRadius: BorderRadius.circular(30.w * scale),
),
child: Text(
'保存图片',
style: TextStyle(
color: Colors.white,
fontSize: widget.btnFontSize ?? 20.w,
fontWeight: FontWeight.w400,
),
),
),
),
],
),
);
}
}
和
import 'package:permission_handler/permission_handler.dart';
class AppPermissionStatus {
// 单例实例
static final AppPermissionStatus _instance = AppPermissionStatus._internal();
// 私有构造函数,防止外部实例化
AppPermissionStatus._internal() {
// 在这里添加初始化逻辑
// 例如:初始化权限状态、注册监听器等
_initPermissionStatus();
}
// 公共静态方法,用于获取单例实例
static AppPermissionStatus get instance => _instance;
// 保存到相册能力
PermissionAbility saveAlbum = PermissionAbility(list: [
Permission.storage,
Permission.photos,
]);
/// 相机权限
PermissionAbility camera = PermissionAbility(list: [Permission.camera]);
/// 相册权限
PermissionAbility mediaPhoto = PermissionAbility(list: [Permission.storage]);
///图片权限
PermissionAbility photos = PermissionAbility(list: [Permission.photos]);
/// 麦克风
PermissionAbility microphone =
PermissionAbility(list: [Permission.microphone]);
// 添加私有初始化方法
void _initPermissionStatus() async {
// 初始化逻辑的具体实现
}
}
/// 权限能力单元
class PermissionAbility {
List<Permission> list;
bool isGranted;
PermissionAbility({required this.list, this.isGranted = false});
Future<bool> getStatus() async {
bool granted = true;
int i = 0;
for (i = 0; i < list.length; i++) {
PermissionStatus status = await list[i].status;
if (status != PermissionStatus.granted) {
granted = false;
}
}
isGranted = granted;
return granted;
}
Future<bool> request() async {
bool granted = isGranted;
Map<Permission, PermissionStatus> status = await list.request();
for (int i = 0; i < list.length; i++) {
if (status[list[i]] == PermissionStatus.granted) {
granted = true;
break;
}
}
isGranted = granted;
return granted;
}
}
是我主要的代码,其实代码已经写好了,现在唯一的问题是当我点击保存图片的时候他会提示"请开启存储权限",我在使用麦克风的时候开启麦克风权限可以正常开启,但是保存到相册的时候却没有存储权限
更多关于HarmonyOS鸿蒙Next中做鸿蒙化flutter,功能需要保存图片到相册中的实战教程也可以访问 https://www.itying.com/category-92-b0.html
插眼学习,
更多关于HarmonyOS鸿蒙Next中做鸿蒙化flutter,功能需要保存图片到相册中的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
没有数据
- 是否弹允许保存的弹窗了?需要用户点击允许授权才能保存到相册。
- 确认的的qrData是有图片数据的 如仍然有问题,可以给个你的详细demo,提供给git下载地址。
我没有遇到过允许保存的弹窗,我无法提供代码,其实这些就是差不多的主要代码了,你可以简单写一个demo吗就是简单保存相册就行,我也是非常诧异为什么我的代码有问题
楼主,你这边保存图片是用的flutter_image_gallery_saver三方库吧,这个库不需要申请存储权限,直接使用
ImageGallerySaver.saveImage(qrData!);保存图片即可,具体可以参考example中使用方式.
这是因为该三方库底层是用的API:phAccessHelper.showAssetsCreationDialog,不需要申请权限。
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
我有想加过但是他是要用户授权的,也就是说他要申请白名单ACL才行,但是AGC平台不受理必须是要克隆,传输数据的才行。然后就提醒 Install Failed: error: failed to install bundle. code:9568289 error: install failed due to grant request permissions failed. View detailed instructions.
使用三方库image_gallery_saver这个不需要申请acl权限,直接调用即可。然后会弹个窗用户允许即可保存到相册。
哥有案例吗,因为你也能看到我的代码里用到了image_gallery_saver,但是压根走不到那里去,直接在
bool isGranted = AppPermissionStatus.instance.saveAlbum.isGranted;
if (!isGranted) {
ShowPermissionRequestEvent event = ShowPermissionRequestEvent(
name: '媒体权限使用说明:',
deniedDescribe: '请开启存储权限',
tag: 'savePhone',
permissionAlbum: AppPermissionStatus.instance.saveAlbum,
describe: '用于保存二维码到相册');
EventManager.instance.eventBus.fire(event);
isGranted = await event.completer.future;
}
就卡住了,
在HarmonyOS鸿蒙Next中,使用鸿蒙化Flutter保存图片到相册需通过@ohos.file.photoAccessHelper
模块实现。首先获取photoAccessHelper
实例,创建相册资源写入选项,使用createAsset
方法写入图片数据到指定媒体库位置。需申请ohos.permission.WRITE_IMAGEVIDEO
权限。Flutter侧通过MethodChannel调用鸿蒙原生接口传递图片字节数据。
在HarmonyOS Next中,Flutter应用保存图片到相册需要适配鸿蒙的权限机制。你当前使用的是permission_handler
插件,该插件在鸿蒙环境下可能无法正确映射存储权限。
解决方案:
- 使用鸿蒙原生权限API替代
permission_handler
- 在
AndroidManifest.xml
中确认已声明ohos.permission.WRITE_USER_STORAGE
权限 - 实现鸿蒙特定的权限请求逻辑:
// 鸿蒙权限检查示例
import 'package:harmonyos_flutter/harmonyos_flutter.dart';
Future<bool> checkStoragePermission() async {
final result = await PermissionUtil.checkSelfPermission(
'ohos.permission.WRITE_USER_STORAGE'
);
return result == PermissionGrantedResult.GRANTED;
}
注意:image_gallery_saver
插件在鸿蒙平台可能需要鸿蒙特定的实现,确保使用支持HarmonyOS的版本或自行实现原生桥接。