diff --git a/marking_app/android/app/src/main/AndroidManifest.xml b/marking_app/android/app/src/main/AndroidManifest.xml index 5dc79c3..91aad8c 100644 --- a/marking_app/android/app/src/main/AndroidManifest.xml +++ b/marking_app/android/app/src/main/AndroidManifest.xml @@ -35,7 +35,14 @@ android:name="flutterEmbedding" android:value="2" /> - + + + + @@ -47,8 +54,10 @@ - - + + + + @@ -58,4 +67,6 @@ + + diff --git a/marking_app/android/app/src/main/res/xml/file_paths.xml b/marking_app/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..c4e8da4 --- /dev/null +++ b/marking_app/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/marking_app/android/app/src/profile/AndroidManifest.xml b/marking_app/android/app/src/profile/AndroidManifest.xml index 6281e88..186b8b4 100644 --- a/marking_app/android/app/src/profile/AndroidManifest.xml +++ b/marking_app/android/app/src/profile/AndroidManifest.xml @@ -13,9 +13,13 @@ - + - + + + + + diff --git a/marking_app/lib/components/PictureOverview.dart b/marking_app/lib/components/PictureOverview.dart index 8c89dbb..c93a840 100644 --- a/marking_app/lib/components/PictureOverview.dart +++ b/marking_app/lib/components/PictureOverview.dart @@ -124,7 +124,8 @@ class PictureOverviewState extends ConsumerState with CommonMix } if (value.scale < 1) { initScale = value.scale; - Future.delayed(Duration(seconds: 5), () => ref.read(zoomHistoryProvider.notifier).setState(initScale!)); + // 5 + Future.delayed(Duration(seconds: 1), () => ref.read(zoomHistoryProvider.notifier).setState(initScale!)); } } }); @@ -270,15 +271,15 @@ class PictureOverviewState extends ConsumerState with CommonMix void onPanUpPosition(Offset val) async { // 手指在移动 非物体移动的位置 - print('**************** 正在移动位置 YYY:${val.dy}'); - print('**************** 正在移动位置 XXX:${val.dx}'); + // print('**************** 正在移动位置 YYY:${val.dy}'); + // print('**************** 正在移动位置 XXX:${val.dx}'); zoomOffset = val; } // 缩放组件 ==> 缩放监听 void onScaleUpdate(double scale, double zoom) async { - print('zoom:$zoom'); - print('scale:${scale}'); + // print('zoom:$zoom'); + // print('scale:${scale}'); // MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo(); MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo(); double positionX = historyZoomInfo?.positionX ?? 0; diff --git a/marking_app/lib/pages/login/index.dart b/marking_app/lib/pages/login/index.dart index 2317dec..3c72178 100644 --- a/marking_app/lib/pages/login/index.dart +++ b/marking_app/lib/pages/login/index.dart @@ -44,10 +44,8 @@ class _TheLoginState extends ConsumerState with CommonMixin { //添加证书 setHttpsPEM() async { - (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = - (client) { - client.badCertificateCallback = - (X509Certificate cert, String host, int port) { + (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { + client.badCertificateCallback = (X509Certificate cert, String host, int port) { return true; }; }; @@ -75,7 +73,7 @@ class _TheLoginState extends ConsumerState with CommonMixin { @override void initState() { - Future.delayed(Duration(seconds: 2), () => sysProtocol(context)); + Future.delayed(Duration(seconds: 1), () => sysProtocol(context)); Future(() { // 延迟更新 Provider ref.read(userTokenProvider.notifier).clean(); // 进入登录页先清空信息 @@ -89,14 +87,12 @@ class _TheLoginState extends ConsumerState with CommonMixin { receiveTimeout: 8000, ), ); - dio.interceptors - .add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 + dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 setHttpsPEM(); client = RestClient(dio, baseUrl: RequestConfig().loginBaseUrl); - _userNameController = TextEditingController() - ..addListener(userNameListener); + _userNameController = TextEditingController()..addListener(userNameListener); _passwordController = TextEditingController(); _pwdFocus = FocusNode(); _theFocus = FocusNode(); @@ -114,11 +110,10 @@ class _TheLoginState extends ConsumerState with CommonMixin { void getShowRegister() async { RestClient client = await getClientLogin(); BaseStructureResult resultData = await client.showRegister(); - if(resultData.success){ + if (resultData.success) { setState(() { showRegister = resultData.data; }); - } } @@ -126,8 +121,7 @@ class _TheLoginState extends ConsumerState with CommonMixin { String userName = _userNameController.text; int useNameLength = userName.length; bool hasNameValNew = useNameLength > 0; - if (hasNameValNew != hasNameVal) - toUpState(setState, () => hasNameVal = hasNameValNew, mounted); + if (hasNameValNew != hasNameVal) toUpState(setState, () => hasNameVal = hasNameValNew, mounted); const isProd = bool.fromEnvironment('dart.vm.product'); if (!isProd && useNameLength == 11) { _passwordController.text = userName.substring(useNameLength - 6); @@ -182,15 +176,12 @@ class _TheLoginState extends ConsumerState with CommonMixin { child: SizedBox( height: 86.w, width: 86.w, - child: Image.asset('assets/images/logo.png', - fit: BoxFit.cover), + child: Image.asset('assets/images/logo.png', fit: BoxFit.cover), ), ), Container( - margin: EdgeInsets.symmetric( - horizontal: 32.w, vertical: 24.h), - padding: EdgeInsets.only( - top: 34.h, bottom: 16.h, left: 22.w, right: 22.w), + margin: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.h), + padding: EdgeInsets.only(top: 34.h, bottom: 16.h, left: 22.w, right: 22.w), decoration: BoxDecoration( color: Colors.white, border: Border.all(width: 1.w, color: Colors.white), @@ -219,18 +210,13 @@ class _TheLoginState extends ConsumerState with CommonMixin { ), decoration: InputDecoration( hintText: "请输入账号", - hintStyle: TextStyle( - fontSize: 16.sp, - color: const Color.fromRGBO(153, 153, 153, 1)), + hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)), labelText: "账号", - labelStyle: TextStyle( - fontSize: 16.sp, - color: const Color.fromRGBO(148, 163, 182, 1)), + labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)), suffixIcon: !hasNameVal ? null : Transform.translate( - offset: - Offset(10, 10), // 根据原始组件的padding值来设置偏移量 + offset: Offset(10, 10), // 根据原始组件的padding值来设置偏移量 child: IconButton( alignment: Alignment.center, padding: EdgeInsets.zero, @@ -266,19 +252,13 @@ class _TheLoginState extends ConsumerState with CommonMixin { onTap: _showPassword, child: Icon( Icons.remove_red_eye, - color: !_isShowPwd - ? Theme.of(context).primaryColor - : Colors.grey, + color: !_isShowPwd ? Theme.of(context).primaryColor : Colors.grey, ), ), - hintStyle: TextStyle( - fontSize: 16.sp, - color: const Color.fromRGBO(153, 153, 153, 1)), + hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)), labelText: "密码", isDense: true, - labelStyle: TextStyle( - fontSize: 16.sp, - color: const Color.fromRGBO(148, 163, 182, 1)), + labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)), ), ), SizedBox( @@ -294,10 +274,8 @@ class _TheLoginState extends ConsumerState with CommonMixin { checkColor: Colors.white, value: keepPwd, onChanged: (value) { - FocusScope.of(context) - .requestFocus(_pwdFocus); - FocusScope.of(context) - .requestFocus(_theFocus); + FocusScope.of(context).requestFocus(_pwdFocus); + FocusScope.of(context).requestFocus(_theFocus); setState(() { keepPwd = value ?? false; }); @@ -322,15 +300,11 @@ class _TheLoginState extends ConsumerState with CommonMixin { if (showRegister == true) InkWell( onTap: () { - RouterManager.router.navigateTo( - context, RouterManager.registerPath); + RouterManager.router.navigateTo(context, RouterManager.registerPath); }, child: Text( '注册', - style: TextStyle( - fontSize: 14.sp, - color: const Color.fromRGBO( - 148, 163, 182, 1)), + style: TextStyle(fontSize: 14.sp, color: const Color.fromRGBO(148, 163, 182, 1)), )), ], ), @@ -339,9 +313,7 @@ class _TheLoginState extends ConsumerState with CommonMixin { child: Container( margin: EdgeInsets.symmetric(vertical: 10.h), decoration: BoxDecoration( - color: canLogin - ? const Color.fromRGBO(9, 105, 246, 1) - : Colors.grey, + color: canLogin ? const Color.fromRGBO(9, 105, 246, 1) : Colors.grey, boxShadow: [ BoxShadow( color: const Color.fromRGBO(46, 91, 255, 0.5), @@ -359,8 +331,7 @@ class _TheLoginState extends ConsumerState with CommonMixin { height: 50.h, child: Text( '登 录', - style: TextStyle( - fontSize: 16.sp, color: Colors.white), + style: TextStyle(fontSize: 16.sp, color: Colors.white), ), ), ), @@ -374,10 +345,8 @@ class _TheLoginState extends ConsumerState with CommonMixin { checkColor: Colors.white, value: readAgreement, onChanged: (value) { - FocusScope.of(context) - .requestFocus(_pwdFocus); - FocusScope.of(context) - .requestFocus(_theFocus); + FocusScope.of(context).requestFocus(_pwdFocus); + FocusScope.of(context).requestFocus(_theFocus); setState(() { readAgreement = value ?? false; }); @@ -458,22 +427,16 @@ class _TheLoginState extends ConsumerState with CommonMixin { print('userPwdMd5=$userPwdMd5'); EasyLoading.show(status: 'loading...'); try { - BaseStructureResult resultData = - await client.toLogin(UserLoginParams(userName, userPwdMd5)); - UserLogin? userData = resultData.code == 200 && resultData.data != null - ? UserLogin.fromJson(resultData.data) - : null; - if (resultData.code != 200 || - userData?.accessToken == null || - userData?.accessToken == '') { + BaseStructureResult resultData = await client.toLogin(UserLoginParams(userName, userPwdMd5)); + UserLogin? userData = resultData.code == 200 && resultData.data != null ? UserLogin.fromJson(resultData.data) : null; + if (resultData.code != 200 || userData?.accessToken == null || userData?.accessToken == '') { return toMsg(resultData.message ?? '登录失败,请重试'); } FastData fastData = FastData.getInstance(); fastData.setToken(userData!.accessToken); - BaseStructureResult userRes = - await client.getUserInfo('Bearer ${userData.accessToken}'); + BaseStructureResult userRes = await client.getUserInfo('Bearer ${userData.accessToken}'); if (userRes.code != 200 || userRes.data == null) { throw Exception('登录失败,请重试'); @@ -489,8 +452,7 @@ class _TheLoginState extends ConsumerState with CommonMixin { ref.read(userTokenProvider.notifier).initToken(); // 跳转登录页 - RouterManager.router.navigateTo(context, RouterManager.root, - clearStack: true, transition: getTransition()); + RouterManager.router.navigateTo(context, RouterManager.root, clearStack: true, transition: getTransition()); }); } catch (e) { toPrint(val: e.toString()); diff --git a/marking_app/lib/pages/mainPage.dart b/marking_app/lib/pages/mainPage.dart index 8c76648..ffb6307 100644 --- a/marking_app/lib/pages/mainPage.dart +++ b/marking_app/lib/pages/mainPage.dart @@ -28,6 +28,7 @@ import 'package:marking_app/provider/user_provider.dart'; import 'package:marking_app/utils/index.dart'; import 'package:marking_app/utils/request/rest_client.dart'; import 'package:package_info/package_info.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'homework_correction/job_home.dart'; @@ -104,7 +105,7 @@ class TheMainPageState extends ConsumerState with CommonMixin { } void getAppUpgrade(UserInfo user) async { - if (!bool.fromEnvironment('dart.vm.product')) return; + // if (!bool.fromEnvironment('dart.vm.product')) return; try { showUpgrade = true; if (['18888888888'].contains(user.loginName)) return; diff --git a/marking_app/lib/utils/app_upgrade/DownloadApk.dart b/marking_app/lib/utils/app_upgrade/DownloadApk.dart index 2aeda91..331684f 100644 --- a/marking_app/lib/utils/app_upgrade/DownloadApk.dart +++ b/marking_app/lib/utils/app_upgrade/DownloadApk.dart @@ -6,6 +6,7 @@ * @LastEditors: wangyang 1147192855@qq.com * @LastEditTime: 2022-08-02 15:12:21 */ +import 'dart:convert'; import 'dart:io'; import 'package:dio/dio.dart'; @@ -13,11 +14,10 @@ import 'package:flutter/cupertino.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:install_plugin/install_plugin.dart'; import 'package:marking_app/provider/upgrade_provider.dart'; -// import 'package:install_plugin_v2/install_plugin_v2.dart'; import 'package:marking_app/utils/app_upgrade/model/UpdateAppEvent.dart'; -import 'package:marking_app/utils/index.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:app_installer/app_installer.dart'; class DownloadApk { /// 下载安卓更新包 @@ -58,9 +58,7 @@ class DownloadApk { debugPrint('make sure the apk file is set'); return false; } - Map statuses = await [Permission.storage].request(); - if (statuses[Permission.storage]!.isGranted) { // String? result = await InstallPlugin.installApk(_apkFilePath, appId: event.packageName).catchError((error) { // debugPrint('install apk error: $error'); @@ -68,16 +66,17 @@ class DownloadApk { // debugPrint('install apk $result'); // ToastUtils.getFluttertoast(context: context, msg: 'install apk $result'); try { - final result = await InstallPlugin.installApk(_apkFilePath, appId: event.packageName); - print('这是是执行安装的程序:' + result.runtimeType.toString()); - if (result['isSuccess'] ?? false) { - ToastUtils.showSuccess('install apk $result'); - RestartWidget.restartApp(context); // 安装成功 重启APP - return true; - } - } catch (e) {} - } else { - debugPrint('Permission request fail!'); + // InstallPlugin.install(filePathOrUrlString)com.example.marking_app + await AppInstaller.installApk(_apkFilePath); + // var result = await InstallPlugin.installApk(_apkFilePath, appId: event.packageName); + // print('这是是执行安装的程序:' + jsonEncode(result)); + // if (!(result?['isSuccess'] ?? false)) {} + // Restadget.restartApp(context); // 安装成功 重启APP + print('安装执行完成了..............0.0'); + } catch (e) { + print('安装进入报错....'); + print(e); + } } return false; @@ -87,7 +86,7 @@ class DownloadApk { static void showDownloadProgress(context, num received, num total, WidgetRef ref) { if (total != -1) { double progress = double.parse((received / total).toStringAsFixed(2)); - debugPrint('下载进度$progress'); + // debugPrint('下载进度$progress'); ref.read(upgradeProvider.notifier).setVal(progress); } } diff --git a/marking_app/lib/utils/app_upgrade/UpdateDialog.dart b/marking_app/lib/utils/app_upgrade/UpdateDialog.dart index f16a0f9..ef60cac 100644 --- a/marking_app/lib/utils/app_upgrade/UpdateDialog.dart +++ b/marking_app/lib/utils/app_upgrade/UpdateDialog.dart @@ -14,7 +14,6 @@ * @LastEditors: Please set LastEditors * @LastEditTime: 2021-01-12 15:08:43 */ -import 'dart:async'; import 'package:clipboard/clipboard.dart'; import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -27,6 +26,7 @@ import 'package:marking_app/utils/my_text.dart'; import 'package:percent_indicator/linear_percent_indicator.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher_string.dart'; class UpdateDialog extends Dialog { @@ -145,6 +145,19 @@ class DownloadButton extends ConsumerWidget { final String deviceInfo; const DownloadButton(this.updateAppEvent, {required this.deviceInfo, Key? key}) : super(key: key); + // 打开浏览器或者对应的对应市场进行下载 + Future toLaunch(UpdateAppEvent data) async { + var uri = Uri.parse('market://details?id=com.example.marking_app'); + if (await canLaunchUrl(uri)) { + // 跳进对应的应用市场进行更新操作 + return await launchUrl(uri); + } + // 无法进入应用市场就打开浏览器进行下载 + uri = Uri.parse(data.link); + if (await canLaunchUrl(uri)) return await launchUrl(uri); + return false; + } + @override Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(upgradeProvider); @@ -163,7 +176,8 @@ class DownloadButton extends ConsumerWidget { child: MaterialButton( onPressed: () => easyThrottle('DownloadButton_App_Upgrade', () async { if (deviceInfo == "android" && updateAppEvent.equipment == Equipment.android) { - bool flag = await UpgradePermission(updateAppEvent.deviceInfo).checkPermission(); + // 权限检查 判断是否有读写内存的权限 + bool flag = await UpgradePermission(updateAppEvent.deviceInfo).checkPermission(context); if (flag) { flag = await DownloadApk.installApk(context, updateAppEvent, ref); @@ -176,8 +190,10 @@ class DownloadButton extends ConsumerWidget { } return; } - await FlutterClipboard.copy(updateAppEvent.link); - setTimeOut(1000, () => ToastUtils.showInfo('下载链接已经复制到设备,可前往浏览器下载安装')); + // 进入应用市场进行下载 + await toLaunch(updateAppEvent); + // await FlutterClipboard.copy(updateAppEvent.link); + // setTimeOut(1000, () => ToastUtils.showInfo('下载链接已经复制到设备,可前往浏览器下载安装')); } else if (deviceInfo == "ios" && updateAppEvent.equipment == Equipment.ios) { try { await launchUrlString(updateAppEvent.link); diff --git a/marking_app/lib/utils/app_upgrade/UpgradePermission.dart b/marking_app/lib/utils/app_upgrade/UpgradePermission.dart index 1337eca..6ca4b8c 100644 --- a/marking_app/lib/utils/app_upgrade/UpgradePermission.dart +++ b/marking_app/lib/utils/app_upgrade/UpgradePermission.dart @@ -6,6 +6,8 @@ * @LastEditors: wangyang 1147192855@qq.com * @LastEditTime: 2022-08-01 14:08:57 */ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:marking_app/utils/index.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -14,34 +16,65 @@ class UpgradePermission { const UpgradePermission(this._flatform); /// 检查是否有权限,用于安卓 - Future checkPermission() async { - // if (_flatform == 'android') { + Future checkPermission(BuildContext context) async { + if (_flatform != 'android') return true; // 非安卓 + var status = await Permission.storage.request(); + if (status.isGranted) return true; - // return await Permission.storage.request().isGranted; - // } else { - // return true; - // } + if (status.isDenied) { + // 普通拒绝 可以再进行提示 + await showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("权限提示"), + content: const Text("无法获取存储权限,请同意获取设备存储权限"), + actions: [ + MaterialButton( + color: Theme.of(context).primaryColor, + child: const Text("同意", style: TextStyle(color: Colors.white)), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ); + }, + ); - if (_flatform == 'android') { - final status = await Permission.storage.status; - if (status != PermissionStatus.granted) { - final result = await Permission.storage.request(); - if (result == PermissionStatus.granted) { - return true; - } - if (status == PermissionStatus.denied) { - ToastUtils.showError('拒绝了保存安装权限'); - } - - if (status == PermissionStatus.permanentlyDenied) { - ToastUtils.showError('用户永久拒绝保存安装权限,请前往设置权限'); - } - } else { - return true; + if (isPad()) { + // 平板无法发起权限询问 直接进入APP权限设置页面 + await openAppSettings(); + return false; } - } else { - return true; + + return checkPermission(context); } + + // 拒绝并不再提示 + await showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("权限提示"), + content: const Text("储存权限被永久拒绝,并且不再提示。请前往设置页面同意储存权限"), + actions: [ + MaterialButton( + color: Colors.green.shade900, + child: const Text("退出APP", style: TextStyle(color: Colors.white)), + onPressed: () => Navigator.of(context).pop(false), + ), + MaterialButton( + color: Colors.green.shade900, + child: const Text("确定", style: TextStyle(color: Colors.white)), + onPressed: () => Navigator.of(context).pop(true), + ), + ], + ); + }, + ); + + await openAppSettings(); return false; } } diff --git a/marking_app/pubspec.yaml b/marking_app/pubspec.yaml index 0c52cc6..324ff6a 100644 --- a/marking_app/pubspec.yaml +++ b/marking_app/pubspec.yaml @@ -114,6 +114,8 @@ dependencies: flutter_staggered_grid_view: ^0.6.2 # 饼图 flutter_echart: ^2.0.0 + app_installer: ^1.1.0 + dev_dependencies: