Commit 698ce9fe75b69b0d12296d6f693ad9f6112c727c
Merge branch 'master' into dev_song_master
Showing
6 changed files
with
216 additions
and
90 deletions
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<PermissionRequestPage> | @@ -49,13 +35,64 @@ class _PermissionRequestPageState extends State<PermissionRequestPage> | ||
| 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<PermissionRequestPage> | @@ -63,46 +100,66 @@ class _PermissionRequestPageState extends State<PermissionRequestPage> | ||
| 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<PermissionRequestPage> | @@ -126,7 +183,7 @@ class _PermissionRequestPageState extends State<PermissionRequestPage> | ||
| 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<PermissionRequestPage> | @@ -134,24 +191,16 @@ class _PermissionRequestPageState extends State<PermissionRequestPage> | ||
| 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<PermissionRequestPage> | @@ -160,29 +209,23 @@ class _PermissionRequestPageState extends State<PermissionRequestPage> | ||
| 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 'package:wow_english/pages/section/subsection/base_section/state.dart'; | @@ -15,7 +15,7 @@ import 'package:wow_english/pages/section/subsection/base_section/state.dart'; | ||
| 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 'package:wow_english/pages/section/subsection/base_section/event.dart'; | @@ -11,6 +11,7 @@ import 'package:wow_english/pages/section/subsection/base_section/event.dart'; | ||
| 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 'package:wow_english/utils/aliyun_oss_util.dart'; | @@ -14,6 +14,8 @@ import 'package:wow_english/utils/aliyun_oss_util.dart'; | ||
| 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<UserAvatarEvent, UserAvatarState> { | @@ -32,7 +34,9 @@ class UserAvatarBloc extends Bloc<UserAvatarEvent, UserAvatarState> { | ||
| 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<UserAvatarEvent, UserAvatarState> { | @@ -56,7 +60,8 @@ class UserAvatarBloc extends Bloc<UserAvatarEvent, UserAvatarState> { | ||
| 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<UserAvatarEvent, UserAvatarState> { | @@ -75,11 +80,8 @@ class UserAvatarBloc extends Bloc<UserAvatarEvent, UserAvatarState> { | ||
| 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<UserAvatarEvent, UserAvatarState> { | @@ -90,7 +92,23 @@ class UserAvatarBloc extends Bloc<UserAvatarEvent, UserAvatarState> { | ||
| 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 { |