diff --git a/wgshare/android/app/src/main/AndroidManifest.xml b/wgshare/android/app/src/main/AndroidManifest.xml index dd7af8c..a942699 100644 --- a/wgshare/android/app/src/main/AndroidManifest.xml +++ b/wgshare/android/app/src/main/AndroidManifest.xml @@ -21,7 +21,8 @@ android:label="智汇享" android:name="${applicationName}" android:icon="@mipmap/ic_launcher" - android:enableOnBackInvokedCallback="true"> + android:enableOnBackInvokedCallback="true" + android:usesCleartextTraffic="true"> - + - + diff --git a/wgshare/android/app/src/main/res/drawable/launch_background.xml b/wgshare/android/app/src/main/res/drawable/launch_background.xml index 304732f..ab3bdee 100644 --- a/wgshare/android/app/src/main/res/drawable/launch_background.xml +++ b/wgshare/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,12 @@ - + - + diff --git a/wgshare/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/wgshare/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..9afea95 100644 Binary files a/wgshare/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/wgshare/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/wgshare/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/wgshare/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..99337be 100644 Binary files a/wgshare/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/wgshare/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/wgshare/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/wgshare/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..88a5287 100644 Binary files a/wgshare/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/wgshare/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/wgshare/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/wgshare/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..7d39ad3 100644 Binary files a/wgshare/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/wgshare/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/wgshare/android/app/src/main/res/mipmap-xxhdpi/launch_image.png b/wgshare/android/app/src/main/res/mipmap-xxhdpi/launch_image.png new file mode 100644 index 0000000..18c5754 Binary files /dev/null and b/wgshare/android/app/src/main/res/mipmap-xxhdpi/launch_image.png differ diff --git a/wgshare/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/wgshare/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..61dbd90 100644 Binary files a/wgshare/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/wgshare/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/wgshare/android/gradle.properties b/wgshare/android/gradle.properties index 2597170..429ce1b 100644 --- a/wgshare/android/gradle.properties +++ b/wgshare/android/gradle.properties @@ -1,3 +1,4 @@ org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true +android.suppressUnsupportedCompileSdk=34 diff --git a/wgshare/assets/images/2.0x/upappbg.png b/wgshare/assets/images/2.0x/upappbg.png new file mode 100644 index 0000000..cdff910 Binary files /dev/null and b/wgshare/assets/images/2.0x/upappbg.png differ diff --git a/wgshare/assets/images/3.0x/upappbg.png b/wgshare/assets/images/3.0x/upappbg.png new file mode 100644 index 0000000..28274f5 Binary files /dev/null and b/wgshare/assets/images/3.0x/upappbg.png differ diff --git a/wgshare/assets/images/upappbg.png b/wgshare/assets/images/upappbg.png new file mode 100644 index 0000000..d5b8e3d Binary files /dev/null and b/wgshare/assets/images/upappbg.png differ diff --git a/wgshare/lib/common/models/app_updata_info_entity.dart b/wgshare/lib/common/models/app_updata_info_entity.dart new file mode 100644 index 0000000..38363bf --- /dev/null +++ b/wgshare/lib/common/models/app_updata_info_entity.dart @@ -0,0 +1,34 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'app_updata_info_entity.g.dart'; + +@JsonSerializable(checked: true) +class AppUpdataInfoEntity extends Object{ + + @JsonKey(name: 'versionCode') + int versionCode; + + @JsonKey(name: 'versionName') + String versionName; + + @JsonKey(name: 'updateType') + int updateType; + + @JsonKey(name: 'versionDescribe') + String versionDescribe; + + @JsonKey(name: 'androidurl') + String androidurl; + + @JsonKey(name: 'appStoreUrl') + String appStoreUrl; + + @JsonKey(name: 'apkSavePath') + String apkSavePath; + + AppUpdataInfoEntity(this.versionCode,this.versionName,this.updateType,this.versionDescribe,this.androidurl,this.appStoreUrl,this.apkSavePath); + + factory AppUpdataInfoEntity.fromJson(Map srcJson) => _$AppUpdataInfoEntityFromJson(srcJson); + + Map toJson() => _$AppUpdataInfoEntityToJson(this); +} diff --git a/wgshare/lib/common/store/app_storage_key.dart b/wgshare/lib/common/store/app_storage_key.dart index c0c433f..91efc89 100644 --- a/wgshare/lib/common/store/app_storage_key.dart +++ b/wgshare/lib/common/store/app_storage_key.dart @@ -5,7 +5,10 @@ enum AppStorageKey { userInfo(value: 'USERINFO', label: "登录用户的基本信息"), account(value: 'ACCOUNT', label: "用户名"), pwd(value: 'PWD', label: "密码"), - loginType(value: 'LOGINTYPE', label: "登录类型"); + loginType(value: 'LOGINTYPE', label: "登录类型"), + appUpDataInfo(value: 'APPUPDATAINFO', label: "app更新信息"), + isRefuseHomeCheckPermission(value: 'ISREFUSEHOMECHECKPERMISSION', label: "是否拒绝会议列表页请求文件访问权限"), + skipUpVersion(value: 'SKIPUPVERSION', label: "跳过此版本更新的版本号"),; final String label; final String value; diff --git a/wgshare/lib/common/store/business_store.dart b/wgshare/lib/common/store/business_store.dart new file mode 100644 index 0000000..0c03b2f --- /dev/null +++ b/wgshare/lib/common/store/business_store.dart @@ -0,0 +1,58 @@ +import 'package:get/get.dart'; +import 'package:wgshare/common/mixins/request_tool_mixin.dart'; +import 'package:wgshare/common/store/app_storage_key.dart'; +import 'package:wgshare/utils/storage.dart'; + +import '../models/app_updata_info_entity.dart'; + +class BusinessStore extends GetxController with RequestToolMixin { + static BusinessStore get to => Get.find(); + + /// app版本更新信息 + Rx appUpdataInfoEntity = Rx(null); + + /// 是否拒绝会议列表页请求文件访问权限 + bool? isRefuseHomeCheckPermission = false; + + /// 跳过此版本更新的版本号 + int? skipUpVersion = 0; + + BusinessStore init() { + isRefuseHomeCheckPermission = StorageService.to.read(AppStorageKey.isRefuseHomeCheckPermission.value); + skipUpVersion = StorageService.to.read(AppStorageKey.skipUpVersion.value); + try { + var appUpdataInfo = StorageService.to.read(AppStorageKey.appUpDataInfo.value); + if (appUpdataInfo != null) { + appUpdataInfoEntity.value = AppUpdataInfoEntity.fromJson(appUpdataInfo); + } + } catch (err) { + StorageService.to.remove(AppStorageKey.userInfo.value); + appUpdataInfoEntity.value = null; + } + return this; + } + + /// 缓存app版本更新信息 + void setAppUpdataInfo(AppUpdataInfoEntity info) { + appUpdataInfoEntity.value = info; + StorageService.to.write(AppStorageKey.appUpDataInfo.value, info); + } + + /// 缓存是否拒绝会议列表页请求文件访问权限状态 + void setIsRefuseHomeCheckPermission(bool type) { + isRefuseHomeCheckPermission = type; + StorageService.to.write(AppStorageKey.isRefuseHomeCheckPermission.value, type); + } + + /// 跳过此版本更新的版本号 + void setSkipUpVersion(int code) { + skipUpVersion = code; + StorageService.to.write(AppStorageKey.skipUpVersion.value, code); + } + + /// 清空缓存app版本更新信息 + void erase() { + appUpdataInfoEntity.value = null; + StorageService.to.write(AppStorageKey.appUpDataInfo.value, null); + } +} diff --git a/wgshare/lib/common/store/user_store.dart b/wgshare/lib/common/store/user_store.dart index 294b7a6..908762d 100644 --- a/wgshare/lib/common/store/user_store.dart +++ b/wgshare/lib/common/store/user_store.dart @@ -63,7 +63,10 @@ class UserStore extends GetxController with RequestToolMixin { token = null; loginType = null; - StorageService.to.erase(); + StorageService.to.write(AppStorageKey.userInfo.value, null); + StorageService.to.write(AppStorageKey.token.value, null); + StorageService.to.write(AppStorageKey.loginType.value, null); + // StorageService.to.erase(); } // 用户信息更新 diff --git a/wgshare/lib/main.dart b/wgshare/lib/main.dart index fb12d3b..3f287c2 100644 --- a/wgshare/lib/main.dart +++ b/wgshare/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:al_downloader/al_downloader.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -12,6 +13,7 @@ import 'package:wgshare/utils/utils.dart'; import 'common/config/app_config.dart'; import 'common/config/colorUtils.dart'; +import 'common/store/business_store.dart'; import 'routes/app_pages.dart'; import 'routes/app_routes.dart'; @@ -26,6 +28,10 @@ void main() async { /// 初始化UserStore Get.put(UserStore().init()); + Get.put(BusinessStore().init()); + + /// 初始化后台下载 + ALDownloader.initialize(); runApp(const MyApp()); } diff --git a/wgshare/lib/pages/homePage/home_logic.dart b/wgshare/lib/pages/homePage/home_logic.dart index c42f1ed..55cbad0 100644 --- a/wgshare/lib/pages/homePage/home_logic.dart +++ b/wgshare/lib/pages/homePage/home_logic.dart @@ -1,16 +1,20 @@ +import 'package:al_downloader/al_downloader.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:wgshare/common/models/common/base_structure_result.dart'; import 'package:wgshare/common/mixins/request_tool_mixin.dart'; +import 'package:wgshare/common/store/business_store.dart'; import 'package:wgshare/common/store/user_store.dart'; +import 'package:wgshare/utils/storage.dart'; import '../../common/models/meeting_room_item.dart'; import '../../routes/app_routes.dart'; import '../../utils/permission/PermissionService.dart'; import '../../utils/toast_utils.dart'; import '../../view/public_dialog.dart'; -import '../../view/upgrade/loadJson/load_network_json.dart'; +import '../../view/upgrade/loadJson/hide_load_network_json.dart'; import 'home_state.dart'; class HomeLogic extends GetxController with RequestToolMixin { @@ -20,8 +24,38 @@ class HomeLogic extends GetxController with RequestToolMixin { @override void onInit() { super.onInit(); - doHttpCheckVersion(Get.context!); - doHttpGetMeetingRoomList(state.pageIndex.value,state.pageSize.value); + /// 检查更新(后台) + HideCheckVersion hideCheckVersion = HideCheckVersion(); + hideCheckVersion.doHttpHideCheckVersion(); + /// 权限 + /*PermissionService.checkPermission(permissionList: [Permission.manageExternalStorage]).then((value){ + if(value == true){ + hideCheckVersion.doHttpHideCheckVersion(); + }else{ + if(null == BusinessStore.to.isRefuseHomeCheckPermission || BusinessStore.to.isRefuseHomeCheckPermission == false){ + publicDialog(Get.context!, + hideCancelBtn: true, + title: '请求权限说明', + describe: + 'APP需要获取您的文件访问权限,用以确保新版本下载后可以正常安装。', + leftBtnStr: '拒绝', + rightBtnStr: '同意', + leftBtnCallback: () { + BusinessStore.to.setIsRefuseHomeCheckPermission(true); + }, rightBtnCallback: () { + PermissionService.requestStoragePermissions().then((value){ + if(value == true){ + hideCheckVersion.doHttpHideCheckVersion(); + } + }); + }); + }else{ + hideCheckVersion.doHttpHideCheckVersion(); + } + } + });*/ + + doHttpGetMeetingRoomList(state.pageIndex.value, state.pageSize.value); } @override @@ -33,18 +67,19 @@ class HomeLogic extends GetxController with RequestToolMixin { /// 获取会议列表 Future doHttpGetMeetingRoomList(int pageIndex, int pageSize) async { debugPrint("wgs输出===:token:${UserStore.to.token}"); - BaseStructureResult res = await getClient().getMeetingRoomList(pageIndex,pageSize); - if(null != res.data){ - if(state.pageIndex == 1){ + BaseStructureResult res = await getClient() + .getMeetingRoomList(pageIndex, pageSize); + if (null != res.data) { + if (state.pageIndex == 1) { state.meetingRooms.value = res.data!.items; state.totalPage.value = res.data!.totalPage; state.total.value = res.data!.total; state.refreshController.refreshCompleted(resetFooterState: true); - }else{ - if(state.pageIndex.value < state.totalPage.value){ + } else { + if (state.pageIndex.value < state.totalPage.value) { state.meetingRooms.value.addAll(res.data!.items); state.refreshController.loadComplete(); - }else{ + } else { state.refreshController.loadNoData(); } } @@ -52,15 +87,15 @@ class HomeLogic extends GetxController with RequestToolMixin { } /// 下拉刷新 - void onRefresh(){ + void onRefresh() { state.pageIndex.value = 1; - doHttpGetMeetingRoomList(state.pageIndex.value,state.pageSize.value); + doHttpGetMeetingRoomList(state.pageIndex.value, state.pageSize.value); } /// 上滑加载更多 - void onLoading(){ + void onLoading() { state.pageIndex.value += 1; - doHttpGetMeetingRoomList(state.pageIndex.value,state.pageSize.value); + doHttpGetMeetingRoomList(state.pageIndex.value, state.pageSize.value); } /// 返回键退出 @@ -68,7 +103,8 @@ class HomeLogic extends GetxController with RequestToolMixin { DateTime now = DateTime.now(); // 物理键,两次间隔大于4秒, 退出请求无效 if (state.currentBackPressTime == null || - now.difference(state.currentBackPressTime!) > const Duration(seconds: 4)) { + now.difference(state.currentBackPressTime!) > + const Duration(seconds: 4)) { state.currentBackPressTime = now; ToastUtils.showInfo("再按一次退出"); return false; @@ -79,15 +115,17 @@ class HomeLogic extends GetxController with RequestToolMixin { } /// 进入会议室 - void gotoMeetingRoom(BuildContext context, int index){ - PermissionService.checkPermission(permissionList: [Permission.microphone,Permission.camera]).then((value){ - if(value == true){ + void gotoMeetingRoom(BuildContext context, int index) { + PermissionService.checkPermission( + permissionList: [Permission.microphone, Permission.camera]).then(( + value) { + if (value == true) { Get.back(); Get.toNamed(Routes.meetingMainPage, arguments: { "roomNumber": state.meetingRooms.value[index].roomNum }); - }else{ + } else { publicDialog( context, hideCancelBtn: true, @@ -95,15 +133,15 @@ class HomeLogic extends GetxController with RequestToolMixin { describe: '进入会议室需要获取您的麦克风以及摄像头权限,用以确保能够正常参会发言。', leftBtnStr: '拒绝', rightBtnStr: '同意', - leftBtnCallback: (){ + leftBtnCallback: () { Get.toNamed(Routes.meetingMainPage, arguments: { "roomNumber": state.meetingRooms.value[index].roomNum }); }, - rightBtnCallback: (){ - PermissionService.requestPermissions().then((value){ - if(value == true){ + rightBtnCallback: () { + PermissionService.requestPermissions().then((value) { + if (value == true) { Get.toNamed(Routes.meetingMainPage, arguments: { "roomNumber": state.meetingRooms.value[index].roomNum @@ -115,4 +153,4 @@ class HomeLogic extends GetxController with RequestToolMixin { } }); } -} +} \ No newline at end of file diff --git a/wgshare/lib/pages/homePage/home_view.dart b/wgshare/lib/pages/homePage/home_view.dart index db206c1..903b1a3 100644 --- a/wgshare/lib/pages/homePage/home_view.dart +++ b/wgshare/lib/pages/homePage/home_view.dart @@ -10,6 +10,7 @@ import 'package:wgshare/routes/app_routes.dart'; import 'package:wgshare/utils/cus_behavior.dart'; import 'package:wgshare/utils/toast_utils.dart'; import '../../utils/color_util.dart'; +import '../../view/upgrade/loadJson/load_network_json.dart'; import 'home_logic.dart'; class HomePage extends StatefulWidget { diff --git a/wgshare/lib/pages/loginPage/login_logic.dart b/wgshare/lib/pages/loginPage/login_logic.dart index e2d1821..3b5c9c5 100644 --- a/wgshare/lib/pages/loginPage/login_logic.dart +++ b/wgshare/lib/pages/loginPage/login_logic.dart @@ -15,6 +15,7 @@ import '../../common/store/user_store.dart'; import '../../routes/app_routes.dart'; import '../../utils/permission/PermissionService.dart'; import '../../view/public_dialog.dart'; +import '../../view/upgrade/loadJson/hide_load_network_json.dart'; import '../../view/upgrade/loadJson/load_network_json.dart'; import 'login_state.dart'; @@ -24,6 +25,8 @@ class LoginLogic extends GetxController with RequestToolMixin { @override void onInit() { super.onInit(); + HideCheckVersion hideCheckVersion = HideCheckVersion(); + hideCheckVersion.doHttpHideCheckVersion(); } @override diff --git a/wgshare/lib/pages/loginPage/login_view.dart b/wgshare/lib/pages/loginPage/login_view.dart index 70a715c..10c0c07 100644 --- a/wgshare/lib/pages/loginPage/login_view.dart +++ b/wgshare/lib/pages/loginPage/login_view.dart @@ -1,3 +1,4 @@ +import 'package:al_downloader/al_downloader.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -375,6 +376,7 @@ class _LoginPageState extends State { ), ), onTap: () { + ALDownloader.cancelAll(); if (state.pageState.value == 0) { logic.doHttpLogin(); } else { diff --git a/wgshare/lib/pages/metting/meeting_main_logic.dart b/wgshare/lib/pages/metting/meeting_main_logic.dart index 0ce4835..c45b704 100644 --- a/wgshare/lib/pages/metting/meeting_main_logic.dart +++ b/wgshare/lib/pages/metting/meeting_main_logic.dart @@ -17,6 +17,7 @@ import '../../common/models/common/base_structure_result.dart'; import '../../common/models/meeting_room_info.dart'; import '../../common/models/meeting_room_msg.dart'; import '../../common/models/meeting_room_user.dart'; +import '../../common/store/business_store.dart'; import '../../utils/agora/AgoraUtil.dart'; import '../../utils/permission/PermissionService.dart'; import '../../utils/toast_utils.dart'; diff --git a/wgshare/lib/utils/color_util.dart b/wgshare/lib/utils/color_util.dart index 68d30c9..166cd3b 100644 --- a/wgshare/lib/utils/color_util.dart +++ b/wgshare/lib/utils/color_util.dart @@ -73,6 +73,8 @@ class ColorUtil { static const Color_255_69_69 = Color.fromRGBO(255, 69, 69, 1); + static const Color_84_84_84 = Color.fromRGBO(84, 84, 84, 1); + /// 十六进制颜色, /// hex, 十六进制值,例如:0xffffff, /// alpha, 透明度 [0.0,1.0] diff --git a/wgshare/lib/utils/permission/AndroidPermissionHandler.dart b/wgshare/lib/utils/permission/AndroidPermissionHandler.dart index b810515..2c72f28 100644 --- a/wgshare/lib/utils/permission/AndroidPermissionHandler.dart +++ b/wgshare/lib/utils/permission/AndroidPermissionHandler.dart @@ -82,15 +82,18 @@ class AndroidPermissionHandler { return isCameraPermission; } - Future requestStoragePermission() async { + Future requestStoragePermission() async { + var isStoragePermission = false; PermissionStatus status = await Permission.manageExternalStorage.request(); if (status.isGranted) { print("Android: 存储权限已授予"); + isStoragePermission = true; } else if (status.isPermanentlyDenied) { print("Android: 存储权限被永久拒绝,请前往设置开启"); } else { print("Android: 存储权限被拒绝"); } + return isStoragePermission; } Future requestNotificationPermission() async { diff --git a/wgshare/lib/utils/permission/IosPermissionHandler.dart b/wgshare/lib/utils/permission/IosPermissionHandler.dart index a292cf7..875fc43 100644 --- a/wgshare/lib/utils/permission/IosPermissionHandler.dart +++ b/wgshare/lib/utils/permission/IosPermissionHandler.dart @@ -62,15 +62,18 @@ class IosPermissionHandler { return isCameraPermission; } - Future requestStoragePermission() async { + Future requestStoragePermission() async { + var isStoragePermission = false; PermissionStatus status = await Permission.photos.request(); if (status.isGranted) { print("iOS: 存储权限已授予"); + isStoragePermission = true; } else if (status.isPermanentlyDenied) { print("iOS: 存储权限被永久拒绝,请前往设置开启"); } else { print("iOS: 存储权限被拒绝"); } + return isStoragePermission; } Future requestNotificationPermission() async { diff --git a/wgshare/lib/utils/permission/PermissionService.dart b/wgshare/lib/utils/permission/PermissionService.dart index 013d290..ffd368a 100644 --- a/wgshare/lib/utils/permission/PermissionService.dart +++ b/wgshare/lib/utils/permission/PermissionService.dart @@ -19,14 +19,16 @@ class PermissionService { return isRequestPermissions; } - static Future requestStoragePermissions() async { + static Future requestStoragePermissions() async { + var isRequestPermissions = false; if (Platform.isIOS) { // 调用iOS权限处理逻辑 - IosPermissionHandler().requestStoragePermission(); + isRequestPermissions = await IosPermissionHandler().requestStoragePermission(); } else if (Platform.isAndroid) { // 调用Android权限处理逻辑 - AndroidPermissionHandler().requestStoragePermission(); + isRequestPermissions = await AndroidPermissionHandler().requestStoragePermission(); } + return isRequestPermissions; } /// 检测是否有权限 diff --git a/wgshare/lib/utils/routeUtil.dart b/wgshare/lib/utils/routeUtil.dart new file mode 100644 index 0000000..20c1c2f --- /dev/null +++ b/wgshare/lib/utils/routeUtil.dart @@ -0,0 +1,23 @@ +import 'package:flutter/cupertino.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; + +class RouteUtil { + + /** + * 获取当前路由 + */ + static String getRoute(){ + var routePath = Get.currentRoute; + return routePath; + } + + /** + * 获取context + */ + static BuildContext getContext(){ + var context = Get.context!; + return context; + } + +} \ No newline at end of file diff --git a/wgshare/lib/view/upgrade/hide_upgrade_dialog.dart b/wgshare/lib/view/upgrade/hide_upgrade_dialog.dart new file mode 100644 index 0000000..c0afc59 --- /dev/null +++ b/wgshare/lib/view/upgrade/hide_upgrade_dialog.dart @@ -0,0 +1,218 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/src/size_extension.dart'; +import 'package:get/get.dart'; +import 'package:install_plugin/install_plugin.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:wgshare/utils/color_util.dart'; +import 'package:wgshare/utils/toast_utils.dart'; +import 'package:wgshare/view/upgrade/util/load_file_cancel_request.dart'; + +import '../../common/store/business_store.dart'; +import '../../utils/permission/PermissionService.dart'; +import '../public_dialog.dart'; + +hideUpgradeDialog( + BuildContext context, + String describe, + String apkSavePath, + String appStoreUrl, + int versionCode,{ + btnWidth = 116.0, + btnHeight = 42.0, + bool hideCancelBtn = false, +}) { + showDialog( + context: context, + barrierDismissible: hideCancelBtn, + builder: (_) => PopScope( + canPop: hideCancelBtn, + child: HintDialog(describe, apkSavePath, appStoreUrl, versionCode, btnWidth, + btnHeight, hideCancelBtn), + )); +} + +class HintDialog extends StatefulWidget { + final String describe; //版本更新内容 + final String apkSavePath; + final String appStoreUrl; + final int versionCode; + final double btnWidth; //按钮宽度 + final double btnHeight; //按钮高度 + final bool hideCancelBtn; //是否隐藏取消btn(实际用途还是否可以点击空白和返回键关闭) + + HintDialog(this.describe, this.apkSavePath, this.appStoreUrl, this.versionCode, this.btnWidth, + this.btnHeight, this.hideCancelBtn); + + @override + State createState() { + return HintDialogState(); + } +} + +class HintDialogState extends State { + // 安装按钮状态,0:未点击、1:安装成功、2:安装失败 + int confirmBtnType = 0; + + // 按钮文字 + String btnStr = "立即安装"; + + // apk路径 + late String apkPath; + + late loadFileCancelRequest loadRequest; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + height: 400.h, + margin: const EdgeInsets.only(left: 40, right: 40), + padding: + const EdgeInsets.only(top: 20, bottom: 20, left: 12, right: 12), + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/upappbg.png'), + fit: BoxFit.fill, + ), + ), + child: _contentStyle(), + ), + ); + } + + ///内容区域样式 + _contentStyle() { + return Column( + children: [ + // _title(), + Expanded( + child: Container(), + ), + _hintMsg(), + GestureDetector( + child: Container( + width: double.infinity, + height: 50.h, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(6)), + color: ColorUtil.Color_85_117_242, + ), + margin: const EdgeInsets.only(top: 12), + alignment: Alignment.center, + child: Text( + btnStr, + style: TextStyle( + fontSize: 14.sp, color: ColorUtil.Color_255_255_255), + ), + ), + onTap: () { + if (Platform.isIOS) { + _gotoAppStore(); + } else { + if (confirmBtnType == 0) { + PermissionService.checkPermission(permissionList: [Permission.manageExternalStorage]).then((value){ + if(value == true){ + _installApk(); + }else{ + publicDialog(Get.context!, + hideCancelBtn: true, + title: '请求权限说明', + describe: + 'APP需要获取您的文件访问权限,用以确保新版本下载后可以正常安装。', + leftBtnStr: '拒绝', + rightBtnStr: '同意', + leftBtnCallback: () { + BusinessStore.to.setIsRefuseHomeCheckPermission(true); + }, rightBtnCallback: () { + PermissionService.requestStoragePermissions().then((value){ + if(value == true){ + _installApk(); + } + }); + }); + } + }); + } + /*if (confirmBtnType == 1) { + SystemNavigator.pop(); + } + if (confirmBtnType == 2) { + Navigator.of(context).pop(); + }*/ + } + }, + ), + Visibility( + visible: widget.hideCancelBtn, + child: GestureDetector( + child: Container( + margin: const EdgeInsets.only(top: 20), + child: Text( + "跳过此版本", + style: + TextStyle(fontSize: 14.sp, color: ColorUtil.Color_84_84_84), + ), + ), + onTap: () { + BusinessStore.to.setSkipUpVersion(widget.versionCode); + Get.back(); + }, + ), + ) + ], + ); + } + + ///提示信息布局 + _hintMsg() { + return SingleChildScrollView( + child: Container( + alignment: Alignment.topLeft, + margin: const EdgeInsets.only(), + child: Text(widget.describe, + style: const TextStyle( + fontSize: 14, + color: ColorUtil.Color_244_244_244, + decoration: TextDecoration.none, + height: 1.4)), + ), + ); + } + + /// 安装APK + _installApk() async { + await InstallPlugin.installApk(widget.apkSavePath, appId: "com.yuanxuan.wgshare").then((result) { + debugPrint("检查更新-安卓安装成功:$result"); + /*setState(() { + confirmBtnType = 2; + btnStr = "关闭APP,重新打开"; + });*/ + BusinessStore.to.erase(); + }).catchError((error) { + debugPrint("检查更新-安卓安装失败:$error"); + /*setState(() { + confirmBtnType = 2; + btnStr = "跳过"; + });*/ + }); + } + + /// 跳转苹果应用商店 + _gotoAppStore() async { + await InstallPlugin.install(widget.appStoreUrl).then((result) { + debugPrint("检查更新-苹果安装成功:$result"); + }).catchError((error) { + debugPrint("检查更新-苹果安装失败:$error"); + }); + } +} diff --git a/wgshare/lib/view/upgrade/loadJson/entity/upgrade_entity.dart b/wgshare/lib/view/upgrade/loadJson/entity/upgrade_entity.dart index 1119a93..bf23da7 100644 --- a/wgshare/lib/view/upgrade/loadJson/entity/upgrade_entity.dart +++ b/wgshare/lib/view/upgrade/loadJson/entity/upgrade_entity.dart @@ -2,7 +2,6 @@ import 'package:json_annotation/json_annotation.dart'; part 'upgrade_entity.g.dart'; - @JsonSerializable() class UpgradeEntity extends Object { @@ -16,7 +15,7 @@ class UpgradeEntity extends Object { bool success; @JsonKey(name: 'data') - Data data; + UpgradeData data; UpgradeEntity(this.code,this.message,this.success,this.data,); @@ -28,7 +27,7 @@ class UpgradeEntity extends Object { @JsonSerializable() -class Data extends Object { +class UpgradeData extends Object { @JsonKey(name: 'versionCode') int versionCode; @@ -48,10 +47,10 @@ class Data extends Object { @JsonKey(name: 'appStoreUrl') String appStoreUrl; - Data(this.versionCode,this.versionName,this.updateType,this.versionDescribe,this.androidurl,this.appStoreUrl); + UpgradeData(this.versionCode,this.versionName,this.updateType,this.versionDescribe,this.androidurl,this.appStoreUrl); - factory Data.fromJson(Map srcJson) => _$DataFromJson(srcJson); + factory UpgradeData.fromJson(Map srcJson) => _$UpgradeDataFromJson(srcJson); - Map toJson() => _$DataToJson(this); + Map toJson() => _$UpgradeDataToJson(this); } diff --git a/wgshare/lib/view/upgrade/loadJson/hide_load_network_json.dart b/wgshare/lib/view/upgrade/loadJson/hide_load_network_json.dart new file mode 100644 index 0000000..190ed22 --- /dev/null +++ b/wgshare/lib/view/upgrade/loadJson/hide_load_network_json.dart @@ -0,0 +1,149 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:al_downloader/al_downloader.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:wgshare/utils/toast_utils.dart'; +import 'package:wgshare/view/upgrade/hide_upgrade_dialog.dart'; +import '../../../common/models/app_updata_info_entity.dart'; +import '../../../common/store/business_store.dart'; +import '../../../utils/routeUtil.dart'; +import 'entity/upgrade_entity.dart'; + +class HideCheckVersion{ + Future request(String url) async{ + Response response = await Dio().get(url); + return response.data; + } + + Future doHttpHideCheckVersion() async { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + String versionCode = packageInfo.buildNumber; + + if(null != BusinessStore.to.appUpdataInfoEntity.value){ + ToastUtils.showSuccess('00000'); + if(int.tryParse(versionCode)! < BusinessStore.to.appUpdataInfoEntity.value!.versionCode){ + ToastUtils.showSuccess('11111--缓存跳过版本${BusinessStore.to.skipUpVersion}-缓存安装版本${BusinessStore.to.appUpdataInfoEntity.value!.versionCode}'); + if(null != BusinessStore.to.skipUpVersion){ + if(BusinessStore.to.skipUpVersion! < BusinessStore.to.appUpdataInfoEntity.value!.versionCode){ + hideUpgradeDialog( + RouteUtil.getContext(), + BusinessStore.to.appUpdataInfoEntity.value!.versionDescribe, + hideCancelBtn: BusinessStore.to.appUpdataInfoEntity.value!.updateType == 1 ? false : true, + BusinessStore.to.appUpdataInfoEntity.value!.apkSavePath, + BusinessStore.to.appUpdataInfoEntity.value!.appStoreUrl, + BusinessStore.to.appUpdataInfoEntity.value!.versionCode, + ); + }else{ + ToastUtils.showSuccess('22222'); + doHttpUp(); + } + }else{ + doHttpUp(); + } + }else{ + ToastUtils.showSuccess('33333'); + BusinessStore.to.erase(); + } + }else{ + ToastUtils.showSuccess('44444'); + doHttpUp(); + } + } + + Future doHttpUp() async { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + String versionCode = packageInfo.buildNumber; + + Future map = request("http://192.168.2.9:8827/latest.json"); + map.then((result) async { + var jsonStr = json.encode(result); + var listDynamic = jsonDecode(jsonStr); + UpgradeEntity upgradeEntity = UpgradeEntity.fromJson(listDynamic); + + debugPrint('55555${upgradeEntity.code}-${upgradeEntity.data.versionCode}-${upgradeEntity.data.androidurl}'); + ToastUtils.showSuccess('55555${upgradeEntity.code}-${upgradeEntity.data.versionCode}-${upgradeEntity.data.androidurl}'); + + if(upgradeEntity.code == 200){ + + debugPrint("检查更新-服务器版本信息:$jsonStr"); + debugPrint("检查更新-当前版本号:$versionCode"); + + if(int.tryParse(versionCode)! < upgradeEntity.data.versionCode){ + if((BusinessStore.to.skipUpVersion ?? 0) < upgradeEntity.data.versionCode){ + if (Platform.isAndroid) { + /// 下载APK + try { + var appDocDir = await getTemporaryDirectory(); + var apkSavePath = "${appDocDir.path}/wgshare_up.apk"; + // String url = "https://www.onlinedown.net/iopdfbhjl/632869?module=download&t=website&v=20241229163449"; + // String url = "https://s3.cn-north-1.amazonaws.com.cn/mtab.kezaihui.com/apk/takeaway_phone_release_1.apk"; + String url = upgradeEntity.data.androidurl; + ALDownloader.download(url, + directoryPath: "${appDocDir.path}/", + fileName: "wgshare_up.apk", + handlerInterface: + ALDownloaderHandlerInterface(progressHandler: (progress) { + debugPrint('检查更新 | 下载进度 = $progress, url = $url'); + ToastUtils.showSuccess('下载进度$progress'); + }, succeededHandler: () { + debugPrint('检查更新 | 下载成功, url = $url'); + debugPrint('检查更新,当前路由是:${RouteUtil.getRoute()}'); + debugPrint('检查更新,APK保存路径:$apkSavePath'); + + BusinessStore.to.setAppUpdataInfo(AppUpdataInfoEntity( + upgradeEntity.data.versionCode, + upgradeEntity.data.versionName, + upgradeEntity.data.updateType, + upgradeEntity.data.versionDescribe, + upgradeEntity.data.androidurl, + upgradeEntity.data.appStoreUrl, + apkSavePath + )); + + if (RouteUtil.getRoute() == '/meetingMainPage') { + ToastUtils.showInfo( + "新版本静默下载完毕\n将择机通知安装", + duration: const Duration(milliseconds: 3000)); + } else { + hideUpgradeDialog( + RouteUtil.getContext(), + upgradeEntity.data.versionDescribe, + hideCancelBtn: upgradeEntity.data.updateType == 1 ? false : true, + apkSavePath, + '', + upgradeEntity.data.versionCode, + ); + } + }, failedHandler: () { + debugPrint('检查更新 | 下载失败, url = $url'); + }, pausedHandler: () { + debugPrint('检查更新 | 下载暂停, url = $url'); + })); + } catch (e) { + debugPrint("检查更新-安卓下载失败:$e"); + } + }else{ + hideUpgradeDialog( + RouteUtil.getContext(), + upgradeEntity.data.versionDescribe, + hideCancelBtn: upgradeEntity.data.updateType == 1 ? false : true, + '', + upgradeEntity.data.appStoreUrl, + upgradeEntity.data.versionCode, + ); + } + } + }else{ + return; + } + }else{ + return; + } + }); + } +} + diff --git a/wgshare/lib/view/upgrade/upgrade_dialog.dart b/wgshare/lib/view/upgrade/upgrade_dialog.dart index acb660b..594f3e9 100644 --- a/wgshare/lib/view/upgrade/upgrade_dialog.dart +++ b/wgshare/lib/view/upgrade/upgrade_dialog.dart @@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/src/size_extension.dart'; +import 'package:get/get.dart'; import 'package:install_plugin/install_plugin.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -43,7 +44,7 @@ class HintDialog extends StatefulWidget { final String versionName; final double btnWidth; //按钮宽度 final double btnHeight; //按钮高度 - final bool hideCancelBtn; //是否隐藏取消btn(实际用途为是否可以点击空白和返回键关闭) + final bool hideCancelBtn; //是否隐藏取消btn(实际用途还是否可以点击空白和返回键关闭) HintDialog(this.title, this.describe, this.url, this.appStoreUrl, this.versionName, this.btnWidth, this.btnHeight, this.hideCancelBtn); @@ -55,11 +56,11 @@ class HintDialog extends StatefulWidget { } class HintDialogState extends State { - // 安装按钮状态,0:未点击、1:点击下载、2:安装成功、3:安装失败 + // 安装按钮状态,0:未点击、1:点击下载、2:下载成功、3:安装成功、4:安装失败 int confirmBtnType = 0; // 按钮文字 - String btnStr = "更新"; + String btnStr = "立即更新"; // 下载进度 double progressValue = 0.0; @@ -83,8 +84,10 @@ class HintDialogState extends State { padding: const EdgeInsets.only(top: 20, bottom: 20, left: 12, right: 12), decoration: BoxDecoration( - color: const Color.fromRGBO(255, 255, 255, 1), - borderRadius: BorderRadius.circular(8), + image: DecorationImage( + image: AssetImage('assets/images/upappbg.png'), + fit: BoxFit.fill, + ), ), child: _contentStyle(), ), @@ -95,10 +98,11 @@ class HintDialogState extends State { _contentStyle() { return Column( children: [ - _title(), + // _title(), Expanded( - child: _hintMsg(), + child: Container(), ), + _hintMsg(), Visibility( visible: confirmBtnType == 1 ? true : false, child: Container( @@ -117,9 +121,9 @@ class HintDialogState extends State { GestureDetector( child: Container( width: double.infinity, - height: 42.h, + height: 50.h, decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(99)), + borderRadius: BorderRadius.all(Radius.circular(6)), color: ColorUtil.Color_85_117_242, ), margin: const EdgeInsets.only(top: 12), @@ -168,6 +172,24 @@ class HintDialogState extends State { } } }, + ), + Visibility( + visible: widget.hideCancelBtn, + child: GestureDetector( + child: Container( + margin: const EdgeInsets.only(top: 20), + child: Text( + "跳过此版本", + style: TextStyle( + fontSize: 14.sp, + color: ColorUtil.Color_84_84_84 + ), + ), + ), + onTap: (){ + Get.back(); + }, + ), ) ], ); @@ -192,11 +214,11 @@ class HintDialogState extends State { return SingleChildScrollView( child: Container( alignment: Alignment.topLeft, - margin: const EdgeInsets.only(left: 8, right: 8), + margin: const EdgeInsets.only(), child: Text(widget.describe, style: const TextStyle( fontSize: 14, - color: ColorUtil.Color_89_88_88, + color: ColorUtil.Color_244_244_244, decoration: TextDecoration.none, height: 1.4)), ), @@ -238,45 +260,11 @@ class HintDialogState extends State { }); ToastUtils.showError("下载失败"); } - - /*Dio dio = Dio(); - try { - // 设置apk下载路径 - var appDocDir = await getTemporaryDirectory(); - apkPath = "${appDocDir.path}/wgshare_${widget.versionName}.apk"; - - setState(() { - confirmBtnType = 1; - btnStr = "取消"; - }); - - // 下载文件 - await dio.download(widget.url, apkPath, onReceiveProgress: (received, total) { - if (total != -1) { - // 下载进度 - setState(() { - progressValue = (received / total * 100); - }); - } - }).then((onValue){ - setState(() { - confirmBtnType = 2; - btnStr = "安装"; - }); - }); - } catch (e) { - debugPrint("检查更新-下载失败:$e"); - setState(() { - confirmBtnType = 0; - btnStr = "更新"; - }); - ToastUtils.showError("下载失败"); - }*/ } /// 安装APK _installApk(String path) async { - await InstallPlugin.installApk(path).then((result) { + await InstallPlugin.installApk(path, appId: "com.yuanxuan.wgshare").then((result) { debugPrint("检查更新-安卓安装成功:$result"); setState(() { confirmBtnType = 3; diff --git a/wgshare/pubspec.lock b/wgshare/pubspec.lock index 80d172a..6a0ee48 100644 --- a/wgshare/pubspec.lock +++ b/wgshare/pubspec.lock @@ -30,6 +30,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.5.0" + al_downloader: + dependency: "direct main" + description: + name: al_downloader + sha256: "00b96b113da7e013f532527238e2f8e5219834f6b4e52df6ff8b12f26eda7101" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.8.4" analyzer: dependency: transitive description: @@ -347,6 +355,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.3.1" + flutter_downloader: + dependency: transitive + description: + name: flutter_downloader + sha256: "2b126083d2e6b7c09755bca12012c4c734bcf7666cf07ba00c508fcb83e8d0d7" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.11.1" flutter_easyloading: dependency: "direct main" description: @@ -1018,6 +1034,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" + queue: + dependency: transitive + description: + name: queue + sha256: "9a41ecadc15db79010108c06eae229a45c56b18db699760f34e8c9ac9b831ff9" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.0+2" retrofit: dependency: "direct main" description: diff --git a/wgshare/pubspec.yaml b/wgshare/pubspec.yaml index 168d401..f65eaa4 100644 --- a/wgshare/pubspec.yaml +++ b/wgshare/pubspec.yaml @@ -98,6 +98,9 @@ dependencies: # 文件目录 path_provider: ^2.0.2 + # 后台下载 + al_downloader: ^1.8.2 + dev_dependencies: flutter_test: sdk: flutter