Commit 698ce9fe75b69b0d12296d6f693ad9f6112c727c

Authored by biao
2 parents b1869cf8 ba96a4bc

Merge branch 'master' into dev_song_master

lib/common/permission/permissionRequestPage.dart
  1 +import 'dart:async';
1 import 'dart:io'; 2 import 'dart:io';
2 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
  4 +import 'package:flutter_screenutil/flutter_screenutil.dart';
3 import 'package:permission_handler/permission_handler.dart'; 5 import 'package:permission_handler/permission_handler.dart';
4 import 'package:wow_english/common/core/app_config_helper.dart'; 6 import 'package:wow_english/common/core/app_config_helper.dart';
  7 +import 'package:wow_english/common/permission/permissionRequester.dart';
5 8
6 import '../../utils/log_util.dart'; 9 import '../../utils/log_util.dart';
7 10
8 -/// 权限检查及请求  
9 -/// 外部可通过此方法来进行权限的检查和请求,将自动跳转到`PermissionRequestPage`页面。  
10 -/// 传入 `Permission` 以及对应的权限名称 `permissionTypeStr`,如果有权限则返回 `Future true`  
11 -/// `isRequiredPermission` 如果为 `true`,则 "取消" 按钮将执行 "退出app" 的操作  
12 -Future<bool> permissionCheckAndRequest(  
13 - BuildContext context,  
14 - Permission permission,  
15 - String permissionTypeStr,  
16 - {bool isRequiredPermission = false}) async {  
17 - if (!await permission.status.isGranted) {  
18 - await Navigator.of(context).push(PageRouteBuilder(  
19 - opaque: false,  
20 - pageBuilder: ((context, animation, secondaryAnimation) {  
21 - return PermissionRequestPage(permission, permissionTypeStr,  
22 - isRequiredPermission: isRequiredPermission);  
23 - })));  
24 - } else {  
25 - return true;  
26 - }  
27 - return false;  
28 -}  
29 - 11 +///带有隐私合规弹窗的透明权限申请页面,主要应对android各大应用市场对隐私权限申请需同步告知索取权限目的
30 class PermissionRequestPage extends StatefulWidget { 12 class PermissionRequestPage extends StatefulWidget {
31 - const PermissionRequestPage(this.permission, this.permissionTypeStr, 13 + const PermissionRequestPage(this.permissions,
  14 + this.permissionNames, this.permissionDesc,
32 {super.key, this.isRequiredPermission = false}); 15 {super.key, this.isRequiredPermission = false});
33 16
34 - final Permission permission;  
35 - final String permissionTypeStr; 17 + final List<Permission> permissions;
  18 + final List<String> permissionNames;
  19 + final String permissionDesc;
  20 +
  21 + ///是否需要强制授予
36 final bool isRequiredPermission; 22 final bool isRequiredPermission;
37 23
38 @override 24 @override
@@ -49,13 +35,64 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt; @@ -49,13 +35,64 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt;
49 void initState() { 35 void initState() {
50 super.initState(); 36 super.initState();
51 WidgetsBinding.instance.addObserver(this); 37 WidgetsBinding.instance.addObserver(this);
  38 + String permissionDesc = widget.permissionDesc;
  39 + String permissionStr = widget.permissionNames.join('、');
52 msgList = [ 40 msgList = [
53 - "${widget.permissionTypeStr}功能需要获取您设备的${widget.permissionTypeStr}权限,否则可能无法正常工作。\n是否申请${widget.permissionTypeStr}权限?",  
54 - "${widget.permissionTypeStr}权限不全,是否重新申请权限?",  
55 - "没有${widget.permissionTypeStr}权限,您可以手动开启权限",  
56 - widget.isRequiredPermission ? "退出应用" : "取消" 41 + "$permissionDesc,需要获取您设备的$permissionStr权限",
  42 + "你还没有开启$permissionStr权限,开启后即可$permissionDesc",
  43 + "未开启$permissionStr权限导致功能受限,您可以手动开启权限",
  44 + widget.isRequiredPermission ? "退出应用" : "以后再说"
57 ]; 45 ];
58 - _checkPermission(widget.permission); 46 + _handlePermission(widget.permissions);
  47 + }
  48 +
  49 + @override
  50 + Widget build(BuildContext context) {
  51 + double screenWidth = MediaQuery.of(context).size.width;
  52 + // PackageInfo packageInfo = await PackageInfo.fromPlatform();
  53 + // String packageName = packageInfo.packageName;
  54 + return Scaffold(
  55 + backgroundColor: Colors.transparent,
  56 + body: Align(
  57 + alignment: Alignment.topCenter,
  58 + child: Container(
  59 + width: screenWidth / 2,
  60 + padding: const EdgeInsets.all(16.0),
  61 + decoration: BoxDecoration(
  62 + color: Colors.white,
  63 + borderRadius: BorderRadius.circular(10.0), // 圆角半径
  64 + boxShadow: const [
  65 + BoxShadow(
  66 + color: Colors.black26,
  67 + blurRadius: 4.0,
  68 + offset: Offset(2, 2),
  69 + ),
  70 + ],
  71 + ),
  72 + child: Column(
  73 + mainAxisSize: MainAxisSize.min,
  74 + crossAxisAlignment: CrossAxisAlignment.start,
  75 + children: [
  76 + Center(
  77 + child: Text(
  78 + '${widget.permissionNames.join('、')}权限使用说明',
  79 + style: TextStyle(
  80 + color: Colors.black,
  81 + fontSize: 15.sp,
  82 + fontWeight: FontWeight.w500,
  83 + fontFamily: 'PingFangSC-Regular'),
  84 + textAlign: TextAlign.left,
  85 + ),
  86 + ),
  87 + 16.verticalSpace,
  88 + Text(
  89 + widget.permissionDesc,
  90 + style: const TextStyle(color: Colors.black54,
  91 + fontFamily: 'PingFangSC-Regular'),
  92 + textAlign: TextAlign.left,
  93 + ),
  94 + ],
  95 + ))));
59 } 96 }
60 97
61 @override 98 @override
@@ -63,46 +100,66 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt; @@ -63,46 +100,66 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt;
63 super.didChangeAppLifecycleState(state); 100 super.didChangeAppLifecycleState(state);
64 Log.d("didChangeAppLifecycleState state=$state _isGoSetting=$_isGoSetting"); 101 Log.d("didChangeAppLifecycleState state=$state _isGoSetting=$_isGoSetting");
65 // 监听 app 从后台切回前台 102 // 监听 app 从后台切回前台
66 - if (state == AppLifecycleState.resumed && _isGoSetting) {  
67 - _checkPermission(widget.permission); 103 + if (state == AppLifecycleState.resumed && _isGoSetting && !_isDialogShowing) {
  104 + _handlePermission(widget.permissions);
68 } 105 }
69 } 106 }
70 107
71 /// 校验权限 108 /// 校验权限
72 - void _checkPermission(Permission permission) async {  
73 - final PermissionStatus status = await permission.status;  
74 - _handlePermissionStatus(permission, status); 109 + void _handlePermission(List<Permission> permissions) async {
  110 + ///一个新待申请权限列表
  111 + List<Permission> intentPermissionList = [];
  112 +
  113 + ///遍历当前权限申请列表
  114 + for (Permission permission in permissions) {
  115 + PermissionStatus status = await permission.status;
  116 +
  117 + ///如果不是允许状态就添加到新的申请列表中
  118 + if (!status.isGranted) {
  119 + intentPermissionList.add(permission);
  120 + }
  121 + }
  122 +
  123 + if (intentPermissionList.isEmpty) {
  124 + _popPage(true);
  125 + } else {
  126 + _requestPermission(intentPermissionList);
  127 + }
75 } 128 }
76 129
77 - void _handlePermissionStatus(Permission permission, PermissionStatus status) {  
78 - Log.d('_handlePermissionStatus=$status permission=$permission');  
79 - if (status.isGranted) {  
80 - _popPage(); 130 + ///实际触发请求权限
  131 + Future<void> _requestPermission(List<Permission> permissions) async {
  132 + Log.d('_requestPermission permissions=$permissions');
  133 + MapEntry<Permission, PermissionStatus>? statusEntry =
  134 + await requestPermissionsInner(permissions);
  135 + if (statusEntry == null) {
  136 + ///都手动同意授予了
  137 + _popPage(true);
81 return; 138 return;
82 } 139 }
83 140
  141 + Permission permission = statusEntry.key;
  142 + PermissionStatus status = statusEntry.value;
  143 +
84 // 还未申请权限或之前拒绝了权限(在 iOS 上为首次申请权限,拒绝后将变为 `永久拒绝权限`) 144 // 还未申请权限或之前拒绝了权限(在 iOS 上为首次申请权限,拒绝后将变为 `永久拒绝权限`)
85 if (status.isDenied) { 145 if (status.isDenied) {
86 showAlert( 146 showAlert(
87 - permission, msgList[0], msgList[3], _isGoSetting ? "前往系统设置" : "确定"); 147 + permission, msgList[0], msgList[3], _isGoSetting ? "前往系统设置" : "继续");
88 } 148 }
89 // 权限已被永久拒绝 149 // 权限已被永久拒绝
  150 + /// 在 Android 上:Android 11+ (API 30+):用户是否第二次拒绝权限。低于 Android 11 (API 30):用户是否拒绝访问请求的功能,并选择不再显示请求。
  151 + /// 在 iOS 上:如果用户拒绝访问所请求的功能。
90 if (status.isPermanentlyDenied) { 152 if (status.isPermanentlyDenied) {
91 _isGoSetting = true; 153 _isGoSetting = true;
92 showAlert( 154 showAlert(
93 - permission, msgList[2], msgList[3], _isGoSetting ? "前往系统设置" : "确定"); 155 + permission, msgList[2], msgList[3], _isGoSetting ? "前往系统设置" : "继续");
94 } 156 }
95 - // 拥有部分权限  
96 - if (status.isLimited) { 157 + // isLimited:拥有部分权限(受限,仅在 iOS (iOS14+) 上受支持)
  158 + // isRestricted:拥有部分权限,活动限制(例如,设置了家长///控件,仅在iOS以上受支持。(仅限 iOS)
  159 + if (status.isLimited || status.isRestricted) {
97 if (Platform.isIOS || Platform.isMacOS) _isGoSetting = true; 160 if (Platform.isIOS || Platform.isMacOS) _isGoSetting = true;
98 showAlert( 161 showAlert(
99 - permission, msgList[1], msgList[3], _isGoSetting ? "前往系统设置" : "确定");  
100 - }  
101 - // 拥有部分权限,活动限制(例如,设置了家长///控件,仅在iOS以上受支持。(仅限 iOS)  
102 - if (status.isRestricted) {  
103 - if (Platform.isIOS || Platform.isMacOS) _isGoSetting = true;  
104 - showAlert(  
105 - permission, msgList[1], msgList[3], _isGoSetting ? "前往系统设置" : "确定"); 162 + permission, msgList[1], msgList[3], _isGoSetting ? "前往系统设置" : "继续");
106 } 163 }
107 } 164 }
108 165
@@ -126,7 +183,7 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt; @@ -126,7 +183,7 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt;
126 onPressed: () { 183 onPressed: () {
127 widget.isRequiredPermission 184 widget.isRequiredPermission
128 ? _quitApp() 185 ? _quitApp()
129 - : _popDialogAndPage(context); 186 + : _popDialog(context, false);
130 }), 187 }),
131 TextButton( 188 TextButton(
132 child: Text(confirmMsg), 189 child: Text(confirmMsg),
@@ -134,24 +191,16 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt; @@ -134,24 +191,16 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt;
134 if (_isGoSetting) { 191 if (_isGoSetting) {
135 openAppSettings(); 192 openAppSettings();
136 } else { 193 } else {
137 - _requestPermisson(permission); 194 + _handlePermission(widget.permissions);
138 } 195 }
139 - _popDialog(context); 196 + _popDialog(context, null);
140 }) 197 })
141 ], 198 ],
142 ); 199 );
143 }).then((value) => { 200 }).then((value) => {
144 _isDialogShowing = false, 201 _isDialogShowing = false,
145 - });  
146 - }  
147 -  
148 - /// 申请权限  
149 - void _requestPermisson(Permission permission) async {  
150 - // 申请权限  
151 - PermissionStatus status = await permission.request();  
152 - Log.d('requestPermisson权限检测=$status _isGoSetting=$_isGoSetting');  
153 - // 再次校验  
154 - _handlePermissionStatus(permission, status); 202 + _popPage(value)
  203 + });
155 } 204 }
156 205
157 @override 206 @override
@@ -160,29 +209,23 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt; @@ -160,29 +209,23 @@ class _PermissionRequestPageState extends State&lt;PermissionRequestPage&gt;
160 super.dispose(); 209 super.dispose();
161 } 210 }
162 211
163 - @override  
164 - Widget build(BuildContext context) {  
165 - return Container();  
166 - }  
167 -  
168 /// 退出应用程序 212 /// 退出应用程序
169 void _quitApp() { 213 void _quitApp() {
170 AppConfigHelper.exitApp(); 214 AppConfigHelper.exitApp();
171 } 215 }
172 216
173 - /// 关闭整个权限申请页面  
174 - void _popDialogAndPage(BuildContext dialogContext) {  
175 - _popDialog(dialogContext);  
176 - _popPage();  
177 - }  
178 -  
179 /// 关闭弹窗 217 /// 关闭弹窗
180 - void _popDialog(BuildContext dialogContext) { 218 + /// isAllGranted为null的话跳到系统设置页
  219 + void _popDialog(BuildContext dialogContext, bool? isAllGranted) {
181 Navigator.of(dialogContext).pop(); 220 Navigator.of(dialogContext).pop();
  221 + _popPage(isAllGranted);
182 } 222 }
183 223
184 - /// 关闭透明页面  
185 - void _popPage() {  
186 - Navigator.of(context).pop(); 224 + /// 关闭权限申请透明页面
  225 + /// isAllGranted 所有权限都授予,为空不关闭
  226 + void _popPage(bool? isAllGranted) {
  227 + if (isAllGranted != null) {
  228 + Navigator.of(context).pop(isAllGranted);
  229 + }
187 } 230 }
188 } 231 }
lib/common/permission/permissionRequester.dart 0 → 100644
  1 +import 'package:flutter/cupertino.dart';
  2 +import 'package:permission_handler/permission_handler.dart';
  3 +import 'package:wow_english/common/permission/permissionRequestPage.dart';
  4 +
  5 +/// 带隐私合规功能的权限检查及请求入口
  6 +/// 外部可通过此方法来进行权限的检查和请求,将自动跳转到`PermissionRequestPage`页面。
  7 +/// 传入 `Permission` 以及对应的(中文)权限名称 `permissionName`
  8 +/// permissionDesc:设备权限使用说明(描述)
  9 +/// isRequiredPermission:是否强制要求 如果为 `true`,则 "取消" 按钮将执行 "退出app" 的操作
  10 +/// return 如果有权限则返回 `Future<true>`
  11 +Future<bool> requestPermission(
  12 + BuildContext context,
  13 + Permission permission,
  14 + String permissionName,
  15 + String permissionDesc,
  16 + {bool isRequiredPermission = false}) async {
  17 + return requestPermissions(context, [permission], [permissionName], permissionDesc,
  18 + isRequiredPermission: isRequiredPermission);
  19 +}
  20 +
  21 +
  22 +Future<bool> requestPermissions(
  23 + BuildContext context,
  24 + List<Permission> permissions,
  25 + List<String> permissionNames,
  26 + String permissionDesc,
  27 + {bool isRequiredPermission = false}) async {
  28 +
  29 + // List<PermissionStatus> statuses = await Future.wait(
  30 + // permissions.map((permission) => permission.status),
  31 + // );
  32 + // bool allGranted = statuses.every((status) => status.isGranted);
  33 +
  34 + bool allGranted = await isPermissionsGranted(permissions);
  35 + if (allGranted) {
  36 + return true;
  37 + } else {
  38 + return await Navigator.of(context).push(PageRouteBuilder(
  39 + opaque: false,
  40 + pageBuilder: ((context, animation, secondaryAnimation) {
  41 + return PermissionRequestPage(permissions, permissionNames, permissionDesc,
  42 + isRequiredPermission: isRequiredPermission);
  43 + })));
  44 + }
  45 +}
  46 +
  47 +///(实际请求前)判断权限数组是否都授予
  48 +Future<bool> isPermissionsGranted(List<Permission> permissions) async {
  49 + // 使用 every 直接检查权限状态
  50 + return await Future.wait(permissions.map((permission) async {
  51 + return await permission.status.isGranted;
  52 + })).then((statuses) => statuses.every((status) => status));
  53 +}
  54 +
  55 +///请求权限
  56 +Future<MapEntry<Permission, PermissionStatus>?> requestPermissionsInner(List<Permission> permissionList) async {
  57 + Map<Permission, PermissionStatus> statusesMap = await permissionList.request();
  58 + for (var entry in statusesMap.entries) {
  59 + if (!entry.value.isGranted) {
  60 + return entry;
  61 + }
  62 + }
  63 + return null;
  64 +}
0 \ No newline at end of file 65 \ No newline at end of file
lib/pages/practice/bloc/topic_picture_bloc.dart
@@ -15,7 +15,7 @@ import &#39;package:wow_english/pages/section/subsection/base_section/state.dart&#39;; @@ -15,7 +15,7 @@ import &#39;package:wow_english/pages/section/subsection/base_section/state.dart&#39;;
15 import 'package:wow_english/utils/loading.dart'; 15 import 'package:wow_english/utils/loading.dart';
16 import 'package:wow_english/utils/toast_util.dart'; 16 import 'package:wow_english/utils/toast_util.dart';
17 17
18 -import '../../../common/permission/permissionRequestPage.dart'; 18 +import '../../../common/permission/permissionRequester.dart';
19 import '../../../route/route.dart'; 19 import '../../../route/route.dart';
20 20
21 part 'topic_picture_event.dart'; 21 part 'topic_picture_event.dart';
@@ -258,7 +258,7 @@ class TopicPictureBloc @@ -258,7 +258,7 @@ class TopicPictureBloc
258 await audioPlayer.stop(); 258 await audioPlayer.stop();
259 // 调用封装好的权限检查和请求方法 259 // 调用封装好的权限检查和请求方法
260 bool result = 260 bool result =
261 - await permissionCheckAndRequest(context, Permission.microphone, "录音"); 261 + await requestPermission(context, Permission.microphone, "录音", "用于开启录音,识别您的开口作答并给出反馈");
262 if (result) { 262 if (result) {
263 methodChannel.invokeMethod('startVoice', { 263 methodChannel.invokeMethod('startVoice', {
264 'word': event.testWord, 264 'word': event.testWord,
lib/pages/reading/bloc/reading_bloc.dart
@@ -11,6 +11,7 @@ import &#39;package:wow_english/pages/section/subsection/base_section/event.dart&#39;; @@ -11,6 +11,7 @@ import &#39;package:wow_english/pages/section/subsection/base_section/event.dart&#39;;
11 import 'package:wow_english/pages/section/subsection/base_section/state.dart'; 11 import 'package:wow_english/pages/section/subsection/base_section/state.dart';
12 12
13 import '../../../common/core/user_util.dart'; 13 import '../../../common/core/user_util.dart';
  14 +import '../../../common/permission/permissionRequester.dart';
14 import '../../../common/request/dao/listen_dao.dart'; 15 import '../../../common/request/dao/listen_dao.dart';
15 import '../../../common/request/exception.dart'; 16 import '../../../common/request/exception.dart';
16 import '../../../models/course_process_entity.dart'; 17 import '../../../models/course_process_entity.dart';
@@ -336,7 +337,7 @@ class ReadingPageBloc @@ -336,7 +337,7 @@ class ReadingPageBloc
336 void startRecord(String content) async { 337 void startRecord(String content) async {
337 // 调用封装好的权限检查和请求方法 338 // 调用封装好的权限检查和请求方法
338 bool result = 339 bool result =
339 - await permissionCheckAndRequest(context, Permission.microphone, "录音"); 340 + await requestPermission(context, Permission.microphone, "录音", "用于开启录音,识别您的开口作答并给出反馈");
340 if (result) { 341 if (result) {
341 methodChannel.invokeMethod('startVoice', { 342 methodChannel.invokeMethod('startVoice', {
342 'word': content, 343 'word': content,
lib/pages/user/modify/modify_user_avatar_page.dart
@@ -22,7 +22,7 @@ class ModifyUserAvatarPage extends StatelessWidget { @@ -22,7 +22,7 @@ class ModifyUserAvatarPage extends StatelessWidget {
22 @override 22 @override
23 Widget build(BuildContext context) { 23 Widget build(BuildContext context) {
24 return BlocProvider( 24 return BlocProvider(
25 - create: (context) => UserAvatarBloc(), 25 + create: (context) => UserAvatarBloc(context),
26 child: _ModifyUserAvatarPage(pageType: pageType), 26 child: _ModifyUserAvatarPage(pageType: pageType),
27 ); 27 );
28 } 28 }
lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart
@@ -14,6 +14,8 @@ import &#39;package:wow_english/utils/aliyun_oss_util.dart&#39;; @@ -14,6 +14,8 @@ import &#39;package:wow_english/utils/aliyun_oss_util.dart&#39;;
14 import 'package:wow_english/utils/log_util.dart'; 14 import 'package:wow_english/utils/log_util.dart';
15 import 'package:wow_english/utils/toast_util.dart'; 15 import 'package:wow_english/utils/toast_util.dart';
16 16
  17 +import '../../../../common/permission/permissionRequester.dart';
  18 +
17 part 'user_avatar_event.dart'; 19 part 'user_avatar_event.dart';
18 part 'user_avatar_state.dart'; 20 part 'user_avatar_state.dart';
19 21
@@ -32,7 +34,9 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; { @@ -32,7 +34,9 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
32 34
33 final ImagePicker picker = ImagePicker(); 35 final ImagePicker picker = ImagePicker();
34 36
35 - UserAvatarBloc() : super(UserAvatarInitial()) { 37 + final BuildContext context;
  38 +
  39 + UserAvatarBloc(this.context) : super(UserAvatarInitial()) {
36 on<GetImageFromPhotoEvent>(_getImageFromPhoto); 40 on<GetImageFromPhotoEvent>(_getImageFromPhoto);
37 on<GetImageFromCameraEvent>(_getImageFromCamera); 41 on<GetImageFromCameraEvent>(_getImageFromCamera);
38 on<ChangeUserEnterAppStateEvent>(_changeUserEnterAppState); 42 on<ChangeUserEnterAppStateEvent>(_changeUserEnterAppState);
@@ -56,7 +60,8 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; { @@ -56,7 +60,8 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
56 } else { 60 } else {
57 permission = Permission.photos; 61 permission = Permission.photos;
58 } 62 }
59 - await getPermissionStatus(permission).then((value) async { 63 + await requestPermission(context, permission, "文件读取", "用于在更换头像场景下从相册中选取图片等文件").then((value) async {
  64 + // await getPermissionStatus(permission).then((value) async {
60 if (!value) { 65 if (!value) {
61 debugPrint('失败$value'); 66 debugPrint('失败$value');
62 return; 67 return;
@@ -75,11 +80,8 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; { @@ -75,11 +80,8 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
75 } 80 }
76 81
77 void _getImageFromCamera(GetImageFromCameraEvent event, Emitter<UserAvatarState> emitter) async { 82 void _getImageFromCamera(GetImageFromCameraEvent event, Emitter<UserAvatarState> emitter) async {
78 - await getPermissionStatus(Permission.camera).then((value) async {  
79 - if (!value) {  
80 - debugPrint('失败$value');  
81 - return;  
82 - } 83 + bool result = await requestPermission(context, Permission.camera, "拍照", "用于在更换头像场景下调用相机拍照");
  84 + if (result) {
83 _file = await picker.pickImage(source: ImageSource.camera); 85 _file = await picker.pickImage(source: ImageSource.camera);
84 EasyLoading.show(); 86 EasyLoading.show();
85 try { 87 try {
@@ -90,7 +92,23 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; { @@ -90,7 +92,23 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
90 showToast('上传头像失败: $e'); 92 showToast('上传头像失败: $e');
91 } 93 }
92 EasyLoading.dismiss(); 94 EasyLoading.dismiss();
93 - }); 95 + }
  96 + // await getPermissionStatus(Permission.camera).then((value) async {
  97 + // if (!value) {
  98 + // debugPrint('失败$value');
  99 + // return;
  100 + // }
  101 + // _file = await picker.pickImage(source: ImageSource.camera);
  102 + // EasyLoading.show();
  103 + // try {
  104 + // final urlStr = await _uploadAvatar(_file!.path);
  105 + // emitter(ChangeImageState(urlStr));
  106 + // } catch (e) {
  107 + // Log.e('上传头像失败:$e');
  108 + // showToast('上传头像失败: $e');
  109 + // }
  110 + // EasyLoading.dismiss();
  111 + // });
94 } 112 }
95 113
96 void _changeUserEnterAppState(ChangeUserEnterAppStateEvent event, Emitter<UserAvatarState> emitter) async { 114 void _changeUserEnterAppState(ChangeUserEnterAppStateEvent event, Emitter<UserAvatarState> emitter) async {