修复苹果登陆不能输入非数字,优化升级插件
This commit is contained in:
parent
d125a2b470
commit
122dfd6542
|
|
@ -5,9 +5,11 @@
|
||||||
*.swp
|
*.swp
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.atom/
|
.atom/
|
||||||
|
.build/
|
||||||
.buildlog/
|
.buildlog/
|
||||||
.history
|
.history
|
||||||
.svn/
|
.svn/
|
||||||
|
.swiftpm/
|
||||||
migrate_working_dir/
|
migrate_working_dir/
|
||||||
|
|
||||||
# IntelliJ related
|
# IntelliJ related
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,6 @@
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>12.0</string>
|
<string>13.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
# platform :ios, '12.0'
|
# platform :ios, '13.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
|
||||||
|
|
@ -477,9 +477,10 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
|
|
@ -495,7 +496,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 9;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = Z778GC45N8;
|
DEVELOPMENT_TEAM = Z778GC45N8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -503,7 +504,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 6;
|
MARKETING_VERSION = "$(FLUTTER_BUILD_NAME)";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.yuanxuan.makingS--buneng--choolAsignmentApp";
|
PRODUCT_BUNDLE_IDENTIFIER = "com.yuanxuan.makingS--buneng--choolAsignmentApp";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
|
@ -524,7 +525,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp.RunnerTests;
|
||||||
|
|
@ -542,7 +543,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = Z778GC45N8;
|
DEVELOPMENT_TEAM = Z778GC45N8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
|
|
@ -559,7 +560,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp.RunnerTests;
|
||||||
|
|
@ -619,10 +620,11 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
|
@ -671,9 +673,10 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
|
@ -689,7 +692,7 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 9;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = Z778GC45N8;
|
DEVELOPMENT_TEAM = Z778GC45N8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -697,7 +700,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 6;
|
MARKETING_VERSION = "$(FLUTTER_BUILD_NAME)";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp;
|
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
|
@ -719,7 +722,7 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 9;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = Z778GC45N8;
|
DEVELOPMENT_TEAM = Z778GC45N8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -727,7 +730,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 6;
|
MARKETING_VERSION = "$(FLUTTER_BUILD_NAME)";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp;
|
PRODUCT_BUNDLE_IDENTIFIER = com.yuanxuan.makingSchoolAsignmentApp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ class AppStateController extends GetxController with WidgetsBindingObserver {
|
||||||
final appLifecycleState = AppLifecycleState.resumed.obs;
|
final appLifecycleState = AppLifecycleState.resumed.obs;
|
||||||
|
|
||||||
// 便捷方法:判断应用是否在前台
|
// 便捷方法:判断应用是否在前台
|
||||||
bool get isAppInForeground => appLifecycleState.value == AppLifecycleState.resumed;
|
bool get isAppInForeground =>
|
||||||
|
appLifecycleState.value == AppLifecycleState.resumed;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/app_version.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
|
|
||||||
|
import 'package:yx_app_upgrade_flutter/yx_app_upgrade_flutter.dart';
|
||||||
|
|
||||||
|
class UpgradeLogic extends GetxService with RequestToolMixin {
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onReady() {
|
||||||
|
/// 首次检查更新
|
||||||
|
Future.delayed(const Duration(seconds: 10)).then(
|
||||||
|
(value) => checkUpdate(Get.context!),
|
||||||
|
);
|
||||||
|
|
||||||
|
/// 定时检查更新
|
||||||
|
_timer?.cancel();
|
||||||
|
_timer = Timer.periodic(
|
||||||
|
const Duration(seconds: 40),
|
||||||
|
(_) => checkUpdate(Get.context!),
|
||||||
|
);
|
||||||
|
super.onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
_timer?.cancel();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkUpdate(BuildContext context) {
|
||||||
|
UpgradeAuxiliaryUtils.instance.initiateVersionCheck(
|
||||||
|
context,
|
||||||
|
future: (int upType) async {
|
||||||
|
// upType: 1 为 Android, 2 为 iOS
|
||||||
|
try {
|
||||||
|
AppVersion? result = await getClient().getLastAppVersion(
|
||||||
|
'making_school_asignment_app',
|
||||||
|
upType,
|
||||||
|
);
|
||||||
|
if (result != null) return _convertToAppUpgradeVersion(result);
|
||||||
|
} catch (e, stack) {
|
||||||
|
debugPrint('fetchLatestUpgradeVersion error: $e\n$stack');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 将 UpdateappResult 转换为 AppUpgradeVersion
|
||||||
|
AppUpgradeVersion? _convertToAppUpgradeVersion(AppVersion? model) {
|
||||||
|
if (model == null) return null;
|
||||||
|
|
||||||
|
// 将文件大小从 KB 转换为字节
|
||||||
|
final filePath =
|
||||||
|
(model.appFileUrl?.isNotEmpty ?? false) ? model.appFileUrl : null;
|
||||||
|
|
||||||
|
return AppUpgradeVersion(
|
||||||
|
versionName: model.version,
|
||||||
|
// versionBuildNumber: model.version,
|
||||||
|
isForce: false,
|
||||||
|
updateContent: model.description ?? '修复BUG,优化体验',
|
||||||
|
downloadUrl: filePath,
|
||||||
|
appStoreUrl: filePath,
|
||||||
|
// apkSize: apkSizeBytes,
|
||||||
|
supportedMethods: [
|
||||||
|
AppUpgradeMethod.market,
|
||||||
|
AppUpgradeMethod.inApp,
|
||||||
|
AppUpgradeMethod.browser,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,159 +0,0 @@
|
||||||
/*
|
|
||||||
* @Descripttion: 下载APK
|
|
||||||
* @version: DownloadApk
|
|
||||||
* @Author: wy
|
|
||||||
* @Date: 2020-07-30 15:54:40
|
|
||||||
* @LastEditors: wangyang 1147192855@qq.com
|
|
||||||
* @LastEditTime: 2022-08-02 15:12:21
|
|
||||||
*/
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:app_installer/app_installer.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
import 'UpgradePermission.dart';
|
|
||||||
import 'model/UpdateAppEvent.dart';
|
|
||||||
import 'upgradeLogic.dart';
|
|
||||||
|
|
||||||
class DownloadApk {
|
|
||||||
/// 下载安卓更新包
|
|
||||||
static Future<File?> _downloadAndroid(
|
|
||||||
context, UpdateAppEvent event, UpgradeLogic logic) async {
|
|
||||||
/// 创建存储文件
|
|
||||||
Directory? storageDir = await getExternalStorageDirectory();
|
|
||||||
final storagePath = storageDir?.path ?? '/';
|
|
||||||
String version = event.version.replaceAll(".", "-");
|
|
||||||
File file = new File('$storagePath/${event.appName}v$version.apk');
|
|
||||||
if (await file.exists()) await file.delete();
|
|
||||||
if (!file.existsSync()) file.createSync();
|
|
||||||
try {
|
|
||||||
/// 发起下载请求
|
|
||||||
Response response = await Dio().get(
|
|
||||||
event.link,
|
|
||||||
onReceiveProgress: (num received, num total) {
|
|
||||||
showDownloadProgress(context, received, total, logic);
|
|
||||||
},
|
|
||||||
options: Options(
|
|
||||||
responseType: ResponseType.bytes,
|
|
||||||
followRedirects: false,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
file.writeAsBytesSync(response.data);
|
|
||||||
return file;
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
// toPrint(val: e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 安装apk
|
|
||||||
static Future<bool> installApk(
|
|
||||||
context, UpdateAppEvent event, UpgradeLogic logic) async {
|
|
||||||
try {
|
|
||||||
logic.loadingApk.value = true;
|
|
||||||
File? _apkFile = await _downloadAndroid(context, event, logic);
|
|
||||||
if (_apkFile == null) return false;
|
|
||||||
String _apkFilePath = _apkFile.path;
|
|
||||||
if (_apkFilePath.isEmpty) {
|
|
||||||
debugPrint('make sure the apk file is set');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await showDialog<bool>(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: const Text("未知应用安装权限提示",
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
)),
|
|
||||||
content: const Text("请注意:更新时若出现需要同意“安装未知应用权限”,请同意!!!"),
|
|
||||||
actions: [
|
|
||||||
MaterialButton(
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
child: const Text("我已知晓",
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white, fontWeight: FontWeight.bold)),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
await AppInstaller.installApk(_apkFilePath); // 安装APK
|
|
||||||
// 如果2秒还没有进入安装引导页面 一律视为更新失败,弹出其他方式更新
|
|
||||||
Utils.getInstance().setTimeOut(1, () async {
|
|
||||||
try {
|
|
||||||
// 其他方式下载
|
|
||||||
// await SystemNavigator.pop(); // 退出APP
|
|
||||||
var options = ['应用市场更新APP', '浏览器下载并安装APP'];
|
|
||||||
var uri =
|
|
||||||
Uri.parse('market://details?id=${event.packageName}'); // 应用市场URI
|
|
||||||
if (!await canLaunchUrl(uri))
|
|
||||||
options.removeAt(0); // 如果不能打开应用市场 就屏蔽掉 这个安装方式
|
|
||||||
String? option = await UpgradePermission.showCustomModalBottomSheet(
|
|
||||||
context, options);
|
|
||||||
if (option == '应用市场更新APP') await launchUrl(uri);
|
|
||||||
if (option == '浏览器下载并安装APP') await launchUrl(Uri.parse(event.link));
|
|
||||||
} catch (_) {}
|
|
||||||
});
|
|
||||||
|
|
||||||
print('安装执行完成了..............0.0');
|
|
||||||
} catch (e) {
|
|
||||||
print('安装进入报错....');
|
|
||||||
print(e);
|
|
||||||
} finally {
|
|
||||||
logic.loadingApk.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 展示下载进度
|
|
||||||
static void showDownloadProgress(
|
|
||||||
context, num received, num total, UpgradeLogic logic) {
|
|
||||||
if (total != -1) {
|
|
||||||
double progress = double.parse((received / total).toStringAsFixed(2));
|
|
||||||
// debugPrint('下载进度$progress');
|
|
||||||
logic.downloadRatio.value = progress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RestartWidget extends StatefulWidget {
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
const RestartWidget({super.key, required this.child});
|
|
||||||
|
|
||||||
static restartApp(BuildContext context) {
|
|
||||||
final _RestartWidgetState? state =
|
|
||||||
context.findAncestorStateOfType<_RestartWidgetState>();
|
|
||||||
state?.restartApp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<RestartWidget> createState() => _RestartWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _RestartWidgetState extends State<RestartWidget> {
|
|
||||||
Key key = UniqueKey();
|
|
||||||
|
|
||||||
void restartApp() {
|
|
||||||
setState(() {
|
|
||||||
key = UniqueKey();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return KeyedSubtree(
|
|
||||||
key: key,
|
|
||||||
child: widget.child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,223 +0,0 @@
|
||||||
/*
|
|
||||||
* @Author: wangyang 1147192855@qq.com
|
|
||||||
* @Date:
|
|
||||||
* @LastEditors: wangyang 1147192855@qq.com
|
|
||||||
* @LastEditTime: 2022-09-29 10:11:54
|
|
||||||
* @FilePath: \marking_app\lib\utils\app_upgrade\UpdateDialog.dart
|
|
||||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* @Descripttion: 版本更新提示弹窗
|
|
||||||
* @version:
|
|
||||||
* @Author: wy
|
|
||||||
* @Date: 2020-07-30 14:03:28
|
|
||||||
* @LastEditors: Please set LastEditors
|
|
||||||
* @LastEditTime: 2021-01-12 15:08:43
|
|
||||||
*/
|
|
||||||
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/DownloadApk.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/UpgradePermission.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/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';
|
|
||||||
|
|
||||||
import '../anti_shake_throttling.dart';
|
|
||||||
import 'model/UpdateAppEvent.dart';
|
|
||||||
|
|
||||||
class UpdateDialog extends Dialog {
|
|
||||||
final UpdateAppEvent updateAppEvent;
|
|
||||||
final String deviceInfo;
|
|
||||||
|
|
||||||
const UpdateDialog({super.key, required this.updateAppEvent, required this.deviceInfo});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Center(
|
|
||||||
child: Container(
|
|
||||||
width: isPad() ? ScreenUtil().screenWidth * 0.62 : 319.w,
|
|
||||||
height: 440.h,
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8.h),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(18.sp),
|
|
||||||
image: const DecorationImage(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
image: AssetImage("assets/images/upgrade_dialog_bgc.png"),
|
|
||||||
fit: BoxFit.fitWidth,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: ListView(
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
padding: EdgeInsets.fromLTRB(16.w, 0, 16.w, 0),
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
margin: EdgeInsets.only(top:isPad()? 136.h : 128.h, bottom: 10.h),
|
|
||||||
child: quickText(
|
|
||||||
updateAppEvent.title,
|
|
||||||
size: 18.sp,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: const Color.fromRGBO(58, 90, 159, 1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
HtmlWidget(
|
|
||||||
updateAppEvent.description,
|
|
||||||
customStylesBuilder: (element) {
|
|
||||||
return {'color': '#666666', 'font-weight': 'normal', 'text-decoration': 'none'};
|
|
||||||
},
|
|
||||||
onLoadingBuilder: (context, element, loadingProgress) => const CircularProgressIndicator(),
|
|
||||||
renderMode: RenderMode.column,
|
|
||||||
textStyle: TextStyle(fontSize: 14.sp, color: Colors.black87),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
DownloadProgress(),
|
|
||||||
DownloadButton(updateAppEvent, deviceInfo: deviceInfo),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调起
|
|
||||||
static showUpdateDialog(BuildContext context, UpdateAppEvent updateAppEvent) {
|
|
||||||
return showDialog(
|
|
||||||
barrierDismissible: false,
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return WillPopScope(
|
|
||||||
onWillPop: () async => false,
|
|
||||||
child: UpdateDialog(updateAppEvent: updateAppEvent, deviceInfo: updateAppEvent.deviceInfo),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 进度条
|
|
||||||
class DownloadProgress extends StatelessWidget {
|
|
||||||
DownloadProgress({super.key});
|
|
||||||
final logic = Get.find<UpgradeLogic>();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Obx(() {
|
|
||||||
var str = (logic.downloadRatio.value * 100).toString().split('.')[0];
|
|
||||||
if (logic.downloadRatio.value <= 0) return Container();
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
LinearPercentIndicator(
|
|
||||||
alignment: MainAxisAlignment.center,
|
|
||||||
width: isPad() ? ScreenUtil().screenWidth * 0.55 : 245.w,
|
|
||||||
animation: false,
|
|
||||||
lineHeight: 20.0.h,
|
|
||||||
percent: logic.downloadRatio.value,
|
|
||||||
center: quickText(
|
|
||||||
"$str%",
|
|
||||||
size: 14.sp,
|
|
||||||
align: TextAlign.center,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
linearStrokeCap: LinearStrokeCap.roundAll,
|
|
||||||
progressColor: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: 6.h,
|
|
||||||
),
|
|
||||||
quickText('更新中...', size: 12.sp, fontWeight: FontWeight.w500, color: const Color.fromRGBO(90, 90, 90, 1))
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 点击下载按钮
|
|
||||||
class DownloadButton extends StatelessWidget {
|
|
||||||
final UpdateAppEvent updateAppEvent;
|
|
||||||
final String deviceInfo;
|
|
||||||
DownloadButton(this.updateAppEvent, {required this.deviceInfo, super.key});
|
|
||||||
final logic = Get.find<UpgradeLogic>();
|
|
||||||
|
|
||||||
// 打开浏览器或者对应的对应市场进行下载
|
|
||||||
Future<bool> toLaunch(UpdateAppEvent data) async {
|
|
||||||
var uri = Uri.parse('market://details?id=${updateAppEvent.packageName}');
|
|
||||||
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) {
|
|
||||||
return Obx(() {
|
|
||||||
final count = logic.downloadRatio.value;
|
|
||||||
if (count > 0) return Container();
|
|
||||||
var primaryColor = Theme.of(context).primaryColor;
|
|
||||||
|
|
||||||
if (updateAppEvent.equipment == Equipment.windows) {
|
|
||||||
return SizedBox(
|
|
||||||
child: quickText('若没有弹出更新弹框,可关闭APP重新打开执行更新...', size: 16.sp),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
height: 38.h,
|
|
||||||
width: isPad() ? ScreenUtil().screenWidth * 0.45 : 245.w,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(42.h)),
|
|
||||||
gradient: LinearGradient(colors: [primaryColor, primaryColor.withOpacity(0.7)]),
|
|
||||||
),
|
|
||||||
child: MaterialButton(
|
|
||||||
onPressed: () => easyThrottle('DownloadButton_App_Upgrade', duration: const Duration(milliseconds: 1000), () async {
|
|
||||||
if (deviceInfo == "android" && updateAppEvent.equipment == Equipment.android) {
|
|
||||||
// 权限检查 判断是否有读写内存的权限
|
|
||||||
bool flag = await UpgradePermission(updateAppEvent.deviceInfo).checkPermission(context, updateAppEvent);
|
|
||||||
if (flag) {
|
|
||||||
flag = await DownloadApk.installApk(context, updateAppEvent, logic);
|
|
||||||
if (!flag) {
|
|
||||||
print('执行到了重置更新按钮的地方....');
|
|
||||||
logic.downloadRatio.value = 0.0; // 更新失败重置 更新按钮
|
|
||||||
} else {
|
|
||||||
print('更新成功重新打开APP..............');
|
|
||||||
RestartWidget.restartApp(context); // 安装成功 重启APP
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// await FlutterClipboard.copy(updateAppEvent.link);
|
|
||||||
// setTimeOut(1000, () => ToastUtils.showInfo('下载链接已经复制到设备,可前往浏览器下载安装'));
|
|
||||||
} else if (deviceInfo == "ios" && updateAppEvent.equipment == Equipment.ios) {
|
|
||||||
try {
|
|
||||||
print(updateAppEvent.link);
|
|
||||||
await launchUrlString(updateAppEvent.link);
|
|
||||||
} catch (e) {
|
|
||||||
print('进来更新报错$e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else if (deviceInfo == 'windows' && updateAppEvent.equipment == Equipment.windows) {
|
|
||||||
// await autoUpdater.setFeedURL(updateAppEvent.link);
|
|
||||||
// await autoUpdater.checkForUpdates();
|
|
||||||
// await autoUpdater.setScheduledCheckInterval(0);
|
|
||||||
// }
|
|
||||||
}),
|
|
||||||
child: quickText(!logic.loadingApk.value ? '立即体验' : '正在下载...', size: 16.sp, color: Colors.white, fontWeight: FontWeight.w500),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
/*
|
|
||||||
* @Descripttion: 获取本地权限
|
|
||||||
* @version: UpgradePermission
|
|
||||||
* @Author: wy
|
|
||||||
* @Date: 2020-07-30 15:41:39
|
|
||||||
* @LastEditors: wangyang 1147192855@qq.com
|
|
||||||
* @LastEditTime: 2022-08-01 14:08:57
|
|
||||||
*/
|
|
||||||
import 'package:app_installer/app_installer.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
import 'model/UpdateAppEvent.dart';
|
|
||||||
|
|
||||||
class UpgradePermission {
|
|
||||||
final String _flatform;
|
|
||||||
const UpgradePermission(this._flatform);
|
|
||||||
|
|
||||||
/// 检查是否有权限,用于安卓
|
|
||||||
/// noExecutions 执行次数
|
|
||||||
Future<bool> checkPermission(BuildContext context, UpdateAppEvent updateAppEvent, [int? noExecutions]) async {
|
|
||||||
noExecutions ??= 1;
|
|
||||||
if (_flatform != 'android') return true; // 非安卓
|
|
||||||
var status = await Permission.storage.request();
|
|
||||||
if (status.isGranted) return true;
|
|
||||||
|
|
||||||
if (status.isDenied) {
|
|
||||||
// 普通拒绝 可以再进行提示
|
|
||||||
|
|
||||||
await showDialog<bool>(
|
|
||||||
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 (noExecutions < 2) return checkPermission(context, updateAppEvent, ++noExecutions);
|
|
||||||
// 执行次数大于2次,就不再询问直接打开设置权限页面(防止某些机型不会弹起权限询问交互弹框)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拒绝并不再提示
|
|
||||||
bool? res = await showDialog<bool>(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: const Text("权限提示"),
|
|
||||||
content: const Text("储存权限被永久拒绝,并且不再提示。请前往设置页面同意储存权限"),
|
|
||||||
actions: [
|
|
||||||
MaterialButton(
|
|
||||||
color: Colors.green.shade900,
|
|
||||||
child: const Text("其它方式更新", style: TextStyle(color: Colors.white)),
|
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
|
||||||
),
|
|
||||||
MaterialButton(
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
child: const Text("前往设置", style: TextStyle(color: Colors.white)),
|
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (res == null || !res) {
|
|
||||||
// 其他方式下载
|
|
||||||
// await SystemNavigator.pop(); // 退出APP
|
|
||||||
var options = ['应用市场更新APP', '浏览器下载并安装APP'];
|
|
||||||
var uri = Uri.parse('market://details?id=${updateAppEvent.packageName}'); // 应用市场URI
|
|
||||||
// if (!await canLaunchUrl(uri)) options.removeAt(0); // 如果不能打开应用市场 就屏蔽掉 这个安装方式
|
|
||||||
String? option = await showCustomModalBottomSheet(context, options);
|
|
||||||
if (option == '应用市场更新APP') {
|
|
||||||
if (await canLaunchUrl(uri)) {
|
|
||||||
await launchUrl(uri);
|
|
||||||
} else {
|
|
||||||
await AppInstaller.goStore(updateAppEvent.packageName, 'iOSAppId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (option == '浏览器下载并安装APP') await launchUrl(Uri.parse(updateAppEvent.link));
|
|
||||||
} else
|
|
||||||
await openAppSettings();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 其他方式下载选择
|
|
||||||
static Future<String?> showCustomModalBottomSheet(context, List<String> options) async {
|
|
||||||
return showModalBottomSheet<String>(
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
isScrollControlled: true,
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
clipBehavior: Clip.antiAlias,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: const Radius.circular(20.0),
|
|
||||||
topRight: const Radius.circular(20.0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
height: MediaQuery.of(context).size.height / 4.0,
|
|
||||||
child: Column(children: [
|
|
||||||
SizedBox(
|
|
||||||
height: 50,
|
|
||||||
child: Stack(
|
|
||||||
textDirection: TextDirection.rtl,
|
|
||||||
children: [
|
|
||||||
Center(child: Text('选择其它方式更新APP', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0))),
|
|
||||||
IconButton(icon: Icon(Icons.close), onPressed: () => Navigator.of(context).pop()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Divider(height: 1.0),
|
|
||||||
Expanded(
|
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: options.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
var name = options[index];
|
|
||||||
return ListTile(
|
|
||||||
title: Text(name),
|
|
||||||
trailing: Icon(name.contains('浏览器') ? Icons.browser_updated_outlined : Icons.local_grocery_store_outlined),
|
|
||||||
onTap: () => Navigator.of(context).pop(name),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* @Descripttion:
|
|
||||||
* @version:
|
|
||||||
* @Author: wy
|
|
||||||
* @Date: 2020-07-30 14:10:44
|
|
||||||
* @LastEditors: wangyang 1147192855@qq.com
|
|
||||||
* @LastEditTime: 2022-09-28 18:20:11
|
|
||||||
*/
|
|
||||||
|
|
||||||
class UpdateAppEvent {
|
|
||||||
final String version;
|
|
||||||
final String title;
|
|
||||||
final String description;
|
|
||||||
final String link;
|
|
||||||
final bool upgrade;
|
|
||||||
final String deviceInfo;
|
|
||||||
final String appName;
|
|
||||||
final String packageName;
|
|
||||||
final Equipment equipment;
|
|
||||||
num? v;
|
|
||||||
num? lv;
|
|
||||||
|
|
||||||
UpdateAppEvent({
|
|
||||||
required this.version,
|
|
||||||
required this.title,
|
|
||||||
required this.description,
|
|
||||||
required this.link,
|
|
||||||
required this.upgrade,
|
|
||||||
required this.deviceInfo,
|
|
||||||
required this.appName,
|
|
||||||
required this.packageName,
|
|
||||||
this.v,
|
|
||||||
this.lv,
|
|
||||||
int type = 0,
|
|
||||||
}) : equipment = Equipment.values[type];
|
|
||||||
|
|
||||||
factory UpdateAppEvent.fromJson(Map json, String localVersion, String deviceInfo, String appName, String packageName,
|
|
||||||
{String keyStr = "version", String typeName = "packageNameType"}) {
|
|
||||||
String version = json[keyStr]; // 版本号
|
|
||||||
String? descriptionStr = json["description"];
|
|
||||||
|
|
||||||
String newDescription = '系统有更新,请立即下载';
|
|
||||||
bool upgrade = false;
|
|
||||||
num? v;
|
|
||||||
num? lv;
|
|
||||||
// 版本号
|
|
||||||
if (version != '') {
|
|
||||||
v = num.parse(version.replaceAll(".", ""));
|
|
||||||
lv = num.parse(localVersion.replaceAll(".", ""));
|
|
||||||
|
|
||||||
// if (lv < v) upgrade = true;
|
|
||||||
//当前版本不等于线上版本更新为线上版本
|
|
||||||
if (lv != v) upgrade = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 升级说明
|
|
||||||
if (descriptionStr != null && descriptionStr.isNotEmpty) {
|
|
||||||
newDescription = descriptionStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return UpdateAppEvent(
|
|
||||||
version: version, // 版本号
|
|
||||||
title: json["title"] ?? "发现新版本", // title
|
|
||||||
description: newDescription, //说明
|
|
||||||
link: json["downloadPath"]??'', // 链接地址
|
|
||||||
upgrade: upgrade,
|
|
||||||
deviceInfo: deviceInfo,
|
|
||||||
appName: appName,
|
|
||||||
packageName: packageName,
|
|
||||||
type: json[typeName] ?? 0,
|
|
||||||
v: v,
|
|
||||||
lv: lv,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return "UpdateAppEvent { version: $version, title: $title, description: $description, link: $link}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设备枚举
|
|
||||||
enum Equipment { other, android, ios, windows }
|
|
||||||
|
|
@ -1,156 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/job/app_version.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/permission_describe_util.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
|
|
||||||
import 'UpdateDialog.dart';
|
|
||||||
import 'model/UpdateAppEvent.dart';
|
|
||||||
|
|
||||||
class UpgradeLogic extends GetxController with RequestToolMixin {
|
|
||||||
Rx<bool> showUpgrade = false.obs; // 是否已经显示升级弹窗
|
|
||||||
Rx<bool> loadingApk = false.obs; // 是否已经显示升级弹窗
|
|
||||||
Rx<double> downloadRatio = 0.0.obs; // 下载比例
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// void onInit() {
|
|
||||||
|
|
||||||
// super.onInit();
|
|
||||||
// }
|
|
||||||
|
|
||||||
Future<UpdateAppEvent?> getUpdateAppEvent() async {
|
|
||||||
// 获取设备信息
|
|
||||||
String deviceInfo;
|
|
||||||
int deviceType;
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
deviceInfo = "android";
|
|
||||||
deviceType = 1;
|
|
||||||
} else if (Platform.isIOS) {
|
|
||||||
deviceInfo = "ios";
|
|
||||||
deviceType = 2;
|
|
||||||
} else if (Platform.isWindows) {
|
|
||||||
deviceInfo = "windows";
|
|
||||||
deviceType = 3;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
AppVersion? result = await getClient().getLastAppVersion('making_school_asignment_app', deviceType);
|
|
||||||
if (result == null) return null;
|
|
||||||
|
|
||||||
//获取当前版本
|
|
||||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
|
||||||
//获取当前版本
|
|
||||||
String localVersion = packageInfo.version;
|
|
||||||
String appName = packageInfo.appName; //应用名称
|
|
||||||
String packageName = packageInfo.packageName; //包名称
|
|
||||||
// String buildNumber = packageInfo.buildNumber; //小版本号
|
|
||||||
|
|
||||||
Map json = {
|
|
||||||
'downloadPath': Platform.isWindows ? '' : result.appFileUrl,
|
|
||||||
'version': result.version,
|
|
||||||
'systemType': deviceType,
|
|
||||||
'description': result.description ?? 'APP新版本更新',
|
|
||||||
};
|
|
||||||
return UpdateAppEvent.fromJson(json, localVersion, deviceInfo, appName, packageName, typeName: 'systemType');
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> getAppUpgrade(BuildContext context) async {
|
|
||||||
if (!const bool.fromEnvironment('dart.vm.product')) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
showUpgrade.value = true;
|
|
||||||
|
|
||||||
final names = [
|
|
||||||
UserStore.to.userDetailInfo.value?.name,
|
|
||||||
UserStore.to.userDetailInfo.value?.account,
|
|
||||||
].whereType<String>().where((name) => name.isNotEmpty).toList();
|
|
||||||
if (names.contains('AppleTester')) return;
|
|
||||||
|
|
||||||
UpdateAppEvent? updateAppEvent = await getUpdateAppEvent();
|
|
||||||
if (updateAppEvent != null && updateAppEvent.upgrade) {
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
|
||||||
AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo;
|
|
||||||
Permission storagePermission;
|
|
||||||
if (androidInfo.version.sdkInt >= 33) {
|
|
||||||
storagePermission = Permission.manageExternalStorage;
|
|
||||||
} else {
|
|
||||||
storagePermission = Permission.storage;
|
|
||||||
}
|
|
||||||
await PermissionDescribeUtil.instance.toLaunchPermissionRequest(
|
|
||||||
Get.context ?? context,
|
|
||||||
title: '储存权限请求',
|
|
||||||
describe: "为了提供更好的服务,需要获取到存储权限用于保存APP升级文件APK,进行升级",
|
|
||||||
permissions: [storagePermission],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await UpdateDialog.showUpdateDialog(
|
|
||||||
Get.context ?? context,
|
|
||||||
updateAppEvent,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
// 获取设备信息
|
|
||||||
String deviceInfo;
|
|
||||||
int deviceType;
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
deviceInfo = "android";
|
|
||||||
deviceType = 1;
|
|
||||||
} else if (Platform.isIOS) {
|
|
||||||
deviceInfo = "ios";
|
|
||||||
deviceType = 2;
|
|
||||||
} else if (Platform.isWindows) {
|
|
||||||
deviceInfo = "windows";
|
|
||||||
deviceType = 3;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != null) {
|
|
||||||
//获取当前版本
|
|
||||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
|
||||||
//获取当前版本
|
|
||||||
String localVersion = packageInfo.version;
|
|
||||||
String appName = packageInfo.appName; //应用名称
|
|
||||||
String packageName = packageInfo.packageName; //包名称
|
|
||||||
// String buildNumber = packageInfo.buildNumber; //小版本号
|
|
||||||
|
|
||||||
Map json = {'downloadPath': Platform.isWindows ? '' : result.appFileUrl, 'version': result.version, 'systemType': deviceType, 'description': result.description ?? 'APP新版本更新'};
|
|
||||||
UpdateAppEvent updateAppEvent = UpdateAppEvent.fromJson(json, localVersion, deviceInfo, appName, packageName, typeName: 'systemType');
|
|
||||||
if (updateAppEvent.upgrade) {
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
|
||||||
AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo;
|
|
||||||
Permission storagePermission;
|
|
||||||
if (androidInfo.version.sdkInt >= 33) {
|
|
||||||
storagePermission = Permission.manageExternalStorage;
|
|
||||||
} else {
|
|
||||||
storagePermission = Permission.storage;
|
|
||||||
}
|
|
||||||
await PermissionDescribeUtil.instance.toLaunchPermissionRequest(
|
|
||||||
Get.context ?? context,
|
|
||||||
title: '储存权限请求',
|
|
||||||
describe: "为了提供更好的服务,需要获取到存储权限用于保存APP升级文件APK,进行升级",
|
|
||||||
permissions: [storagePermission],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await UpdateDialog.showUpdateDialog(
|
|
||||||
Get.context ?? context,
|
|
||||||
updateAppEvent,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
} finally {
|
|
||||||
showUpgrade.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -16,12 +16,13 @@ import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
import 'common/config/request_config.dart';
|
import 'common/config/request_config.dart';
|
||||||
import 'common/utils/app_upgrade/upgradeLogic.dart';
|
import 'common/controllers/upgrade_logic.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
// 在测试模式下运行Get
|
// 在测试模式下运行Get
|
||||||
Get.testMode = true;
|
Get.testMode = true;
|
||||||
FlutterNativeSplash.preserve(widgetsBinding: WidgetsFlutterBinding.ensureInitialized());
|
FlutterNativeSplash.preserve(
|
||||||
|
widgetsBinding: WidgetsFlutterBinding.ensureInitialized());
|
||||||
|
|
||||||
/// 初始化本地存储
|
/// 初始化本地存储
|
||||||
await Get.putAsync<StorageService>(() => StorageService.init());
|
await Get.putAsync<StorageService>(() => StorageService.init());
|
||||||
|
|
@ -31,7 +32,8 @@ void main() async {
|
||||||
|
|
||||||
// Windows
|
// Windows
|
||||||
if (Platform.isWindows) {
|
if (Platform.isWindows) {
|
||||||
String feedURL = '${RequestConfig.imgUrl}infra-app/making_school_asignment_app/3/appcast.xml';
|
String feedURL =
|
||||||
|
'${RequestConfig.imgUrl}infra-app/making_school_asignment_app/3/appcast.xml';
|
||||||
await autoUpdater.setFeedURL(feedURL);
|
await autoUpdater.setFeedURL(feedURL);
|
||||||
await autoUpdater.checkForUpdates();
|
await autoUpdater.checkForUpdates();
|
||||||
await autoUpdater.setScheduledCheckInterval(3600);
|
await autoUpdater.setScheduledCheckInterval(3600);
|
||||||
|
|
@ -41,11 +43,14 @@ void main() async {
|
||||||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||||
statusBarIconBrightness: Brightness.light // dark:一般显示黑色 light:一般显示白色
|
statusBarIconBrightness: Brightness.light // dark:一般显示黑色 light:一般显示白色
|
||||||
));
|
));
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: [SystemUiOverlay.top]); // 屏幕刘海
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky,
|
||||||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); // 屏幕强制竖屏
|
overlays: [SystemUiOverlay.top]); // 屏幕刘海
|
||||||
|
await SystemChrome.setPreferredOrientations(
|
||||||
|
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); // 屏幕强制竖屏
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
|
|
||||||
Future.delayed(const Duration(seconds: 3), () => FlutterNativeSplash.remove());
|
Future.delayed(
|
||||||
|
const Duration(seconds: 3), () => FlutterNativeSplash.remove());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
|
|
@ -127,9 +132,11 @@ class MyApp extends StatelessWidget {
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return MediaQuery(
|
return MediaQuery(
|
||||||
//Setting font does not change with system font size
|
//Setting font does not change with system font size
|
||||||
data: MediaQuery.of(context).copyWith(textScaler: const TextScaler.linear(1.0)),
|
data: MediaQuery.of(context)
|
||||||
|
.copyWith(textScaler: const TextScaler.linear(1.0)),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: GestureDetector(onTap: () => Utils.hideKeyboard(), child: child),
|
body: GestureDetector(
|
||||||
|
onTap: () => Utils.hideKeyboard(), child: child),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import 'package:making_school_asignment_app/common/job/user_info.dart';
|
||||||
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
||||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
||||||
import 'package:making_school_asignment_app/page/home_page/children/my_info.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/my_info.dart';
|
||||||
|
|
@ -24,11 +23,8 @@ class StartPage extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _StartPageState extends State<StartPage> with RequestToolMixin {
|
class _StartPageState extends State<StartPage> with RequestToolMixin {
|
||||||
Timer? _timer;
|
|
||||||
Timer? _timerPermission;
|
|
||||||
DateTime? lastPopTime;
|
DateTime? lastPopTime;
|
||||||
final _pageController = Get.find<PageIndexController>();
|
final _pageController = Get.find<PageIndexController>();
|
||||||
final _upgradeLogic = Get.find<UpgradeLogic>();
|
|
||||||
|
|
||||||
late final List<Widget> _bodyList;
|
late final List<Widget> _bodyList;
|
||||||
|
|
||||||
|
|
@ -38,26 +34,12 @@ class _StartPageState extends State<StartPage> with RequestToolMixin {
|
||||||
|
|
||||||
// const WorkPage(),
|
// const WorkPage(),
|
||||||
_bodyList = [const HomePage(), const MyInfo()];
|
_bodyList = [const HomePage(), const MyInfo()];
|
||||||
// APP 启动后就直接更新
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((e) {
|
|
||||||
/// 首页用户未更新不进行更新判断,没有登陆的用户在登陆页面和40秒回调中检查弹出更新APP
|
|
||||||
if (!_upgradeLogic.showUpgrade.value && UserStore.to.userDetailInfo.value != null)
|
|
||||||
_upgradeLogic.getAppUpgrade(context);
|
|
||||||
});
|
|
||||||
_timer?.cancel();
|
|
||||||
_timer = Timer.periodic(const Duration(seconds: 40), (e) {
|
|
||||||
if (Get.currentRoute == Routes.login) return; // 在登录页面不更新APP
|
|
||||||
if (!_upgradeLogic.showUpgrade.value) _upgradeLogic.getAppUpgrade(context);
|
|
||||||
});
|
|
||||||
|
|
||||||
String? token = UserStore.to.token;
|
String? token = UserStore.to.token;
|
||||||
UserInfo? userInfo = UserStore.to.userInfo.value;
|
UserInfo? userInfo = UserStore.to.userInfo.value;
|
||||||
UserInfoDetail? userInfoDetail = UserStore.to.userDetailInfo.value;
|
UserInfoDetail? userInfoDetail = UserStore.to.userDetailInfo.value;
|
||||||
|
|
||||||
if ((token?.isNotEmpty ?? false) && userInfo != null) {
|
if ((token?.isNotEmpty ?? false) && userInfo != null) {
|
||||||
// Future.delayed(const Duration(milliseconds: 200)).then((e) {
|
|
||||||
// Get.toNamed(Routes.home);
|
|
||||||
// });
|
|
||||||
// 更新用户信息
|
// 更新用户信息
|
||||||
if (userInfoDetail == null) UserStore.to.updateUserInfo();
|
if (userInfoDetail == null) UserStore.to.updateUserInfo();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -72,8 +54,6 @@ class _StartPageState extends State<StartPage> with RequestToolMixin {
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
Get.delete<PageIndexController>();
|
Get.delete<PageIndexController>();
|
||||||
_timer?.cancel();
|
|
||||||
_timerPermission?.cancel();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,7 +121,9 @@ class _StartPageState extends State<StartPage> with RequestToolMixin {
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
onPopInvokedWithResult: (bool didPop, dynamic result) async {
|
onPopInvokedWithResult: (bool didPop, dynamic result) async {
|
||||||
if (lastPopTime == null || DateTime.now().difference(lastPopTime!) > const Duration(seconds: 1)) {
|
if (lastPopTime == null ||
|
||||||
|
DateTime.now().difference(lastPopTime!) >
|
||||||
|
const Duration(seconds: 1)) {
|
||||||
lastPopTime = DateTime.now();
|
lastPopTime = DateTime.now();
|
||||||
ToastUtils.getFluttertoast(
|
ToastUtils.getFluttertoast(
|
||||||
context: context,
|
context: context,
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/model/UpdateAppEvent.dart';
|
import 'package:making_school_asignment_app/common/controllers/upgrade_logic.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
|
|
@ -67,9 +66,11 @@ class LoginLogic extends GetxController with RequestToolMixin {
|
||||||
|
|
||||||
void toMsg(msg, [bool error = true]) {
|
void toMsg(msg, [bool error = true]) {
|
||||||
if (error) {
|
if (error) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => ToastUtils.showError(msg));
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((_) => ToastUtils.showError(msg));
|
||||||
} else {
|
} else {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => ToastUtils.showInfo(msg));
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((_) => ToastUtils.showInfo(msg));
|
||||||
}
|
}
|
||||||
state.canLogin.value = true;
|
state.canLogin.value = true;
|
||||||
}
|
}
|
||||||
|
|
@ -87,15 +88,6 @@ class LoginLogic extends GetxController with RequestToolMixin {
|
||||||
EasyLoading.show(status: 'loading...');
|
EasyLoading.show(status: 'loading...');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/// 检查升级APP
|
|
||||||
if (userName != 'AppleTester' && const bool.fromEnvironment('dart.vm.product')) {
|
|
||||||
UpdateAppEvent? updateAppEvent = await upgradeLogic.getUpdateAppEvent();
|
|
||||||
var upgrade = updateAppEvent?.upgrade ?? false;
|
|
||||||
if (upgrade) {
|
|
||||||
upgradeLogic.getAppUpgrade(Get.context ?? context);
|
|
||||||
return toMsg('请在升级APP后再次登陆', false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await getClient().toLogin(userName, userPwd);
|
await getClient().toLogin(userName, userPwd);
|
||||||
String? nameidentifier = UserStore.to.userInfo.value?.nameidentifier;
|
String? nameidentifier = UserStore.to.userInfo.value?.nameidentifier;
|
||||||
if (nameidentifier == null) {
|
if (nameidentifier == null) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:making_school_asignment_app/common/const_text.dart';
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
import 'package:making_school_asignment_app/common/controllers/upgrade_logic.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
@ -157,9 +157,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 20.r),
|
||||||
height: 20.r,
|
|
||||||
),
|
|
||||||
Obx(() {
|
Obx(() {
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
flutter/ephemeral
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
# Project-level configuration.
|
|
||||||
cmake_minimum_required(VERSION 3.10)
|
|
||||||
project(runner LANGUAGES CXX)
|
|
||||||
|
|
||||||
# The name of the executable created for the application. Change this to change
|
|
||||||
# the on-disk name of your application.
|
|
||||||
set(BINARY_NAME "making_school_asignment_app")
|
|
||||||
# The unique GTK application identifier for this application. See:
|
|
||||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
|
||||||
set(APPLICATION_ID "com.yuanxuan.making_school_asignment_app")
|
|
||||||
|
|
||||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
|
||||||
# versions of CMake.
|
|
||||||
cmake_policy(SET CMP0063 NEW)
|
|
||||||
|
|
||||||
# Load bundled libraries from the lib/ directory relative to the binary.
|
|
||||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
|
||||||
|
|
||||||
# Root filesystem for cross-building.
|
|
||||||
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
|
||||||
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
|
||||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Define build configuration options.
|
|
||||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
||||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
|
||||||
STRING "Flutter build mode" FORCE)
|
|
||||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
|
||||||
"Debug" "Profile" "Release")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Compilation settings that should be applied to most targets.
|
|
||||||
#
|
|
||||||
# Be cautious about adding new options here, as plugins use this function by
|
|
||||||
# default. In most cases, you should add new options to specific targets instead
|
|
||||||
# of modifying this function.
|
|
||||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
|
||||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
|
||||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
|
||||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
|
||||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Flutter library and tool build rules.
|
|
||||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
|
||||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
|
||||||
|
|
||||||
# System-level dependencies.
|
|
||||||
find_package(PkgConfig REQUIRED)
|
|
||||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
|
||||||
|
|
||||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
|
||||||
|
|
||||||
# Define the application target. To change its name, change BINARY_NAME above,
|
|
||||||
# not the value here, or `flutter run` will no longer work.
|
|
||||||
#
|
|
||||||
# Any new source files that you add to the application should be added here.
|
|
||||||
add_executable(${BINARY_NAME}
|
|
||||||
"main.cc"
|
|
||||||
"my_application.cc"
|
|
||||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Apply the standard set of build settings. This can be removed for applications
|
|
||||||
# that need different build settings.
|
|
||||||
apply_standard_settings(${BINARY_NAME})
|
|
||||||
|
|
||||||
# Add dependency libraries. Add any application-specific dependencies here.
|
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
|
||||||
|
|
||||||
# Run the Flutter tool portions of the build. This must not be removed.
|
|
||||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
|
||||||
|
|
||||||
# Only the install-generated bundle's copy of the executable will launch
|
|
||||||
# correctly, since the resources must in the right relative locations. To avoid
|
|
||||||
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
|
||||||
# the default top-level location.
|
|
||||||
set_target_properties(${BINARY_NAME}
|
|
||||||
PROPERTIES
|
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Generated plugin build rules, which manage building the plugins and adding
|
|
||||||
# them to the application.
|
|
||||||
include(flutter/generated_plugins.cmake)
|
|
||||||
|
|
||||||
|
|
||||||
# === Installation ===
|
|
||||||
# By default, "installing" just makes a relocatable bundle in the build
|
|
||||||
# directory.
|
|
||||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
|
||||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Start with a clean build bundle directory every time.
|
|
||||||
install(CODE "
|
|
||||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
|
||||||
" COMPONENT Runtime)
|
|
||||||
|
|
||||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
|
||||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
|
||||||
|
|
||||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
|
||||||
COMPONENT Runtime)
|
|
||||||
|
|
||||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
|
||||||
COMPONENT Runtime)
|
|
||||||
|
|
||||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
|
||||||
COMPONENT Runtime)
|
|
||||||
|
|
||||||
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
|
||||||
install(FILES "${bundled_library}"
|
|
||||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
|
||||||
COMPONENT Runtime)
|
|
||||||
endforeach(bundled_library)
|
|
||||||
|
|
||||||
# Copy the native assets provided by the build.dart from all packages.
|
|
||||||
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
|
|
||||||
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
|
||||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
|
||||||
COMPONENT Runtime)
|
|
||||||
|
|
||||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
|
||||||
# from a previous install.
|
|
||||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
|
||||||
install(CODE "
|
|
||||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
|
||||||
" COMPONENT Runtime)
|
|
||||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
|
||||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
|
||||||
|
|
||||||
# Install the AOT library on non-Debug builds only.
|
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
|
||||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
|
||||||
COMPONENT Runtime)
|
|
||||||
endif()
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
# This file controls Flutter-level build steps. It should not be edited.
|
|
||||||
cmake_minimum_required(VERSION 3.10)
|
|
||||||
|
|
||||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
|
||||||
|
|
||||||
# Configuration provided via flutter tool.
|
|
||||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
|
||||||
|
|
||||||
# TODO: Move the rest of this into files in ephemeral. See
|
|
||||||
# https://github.com/flutter/flutter/issues/57146.
|
|
||||||
|
|
||||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
|
||||||
# which isn't available in 3.10.
|
|
||||||
function(list_prepend LIST_NAME PREFIX)
|
|
||||||
set(NEW_LIST "")
|
|
||||||
foreach(element ${${LIST_NAME}})
|
|
||||||
list(APPEND NEW_LIST "${PREFIX}${element}")
|
|
||||||
endforeach(element)
|
|
||||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# === Flutter Library ===
|
|
||||||
# System-level dependencies.
|
|
||||||
find_package(PkgConfig REQUIRED)
|
|
||||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
|
||||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
|
||||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
|
||||||
|
|
||||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
|
||||||
|
|
||||||
# Published to parent scope for install step.
|
|
||||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
|
||||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
|
||||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
|
||||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
|
||||||
"fl_basic_message_channel.h"
|
|
||||||
"fl_binary_codec.h"
|
|
||||||
"fl_binary_messenger.h"
|
|
||||||
"fl_dart_project.h"
|
|
||||||
"fl_engine.h"
|
|
||||||
"fl_json_message_codec.h"
|
|
||||||
"fl_json_method_codec.h"
|
|
||||||
"fl_message_codec.h"
|
|
||||||
"fl_method_call.h"
|
|
||||||
"fl_method_channel.h"
|
|
||||||
"fl_method_codec.h"
|
|
||||||
"fl_method_response.h"
|
|
||||||
"fl_plugin_registrar.h"
|
|
||||||
"fl_plugin_registry.h"
|
|
||||||
"fl_standard_message_codec.h"
|
|
||||||
"fl_standard_method_codec.h"
|
|
||||||
"fl_string_codec.h"
|
|
||||||
"fl_value.h"
|
|
||||||
"fl_view.h"
|
|
||||||
"flutter_linux.h"
|
|
||||||
)
|
|
||||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
|
||||||
add_library(flutter INTERFACE)
|
|
||||||
target_include_directories(flutter INTERFACE
|
|
||||||
"${EPHEMERAL_DIR}"
|
|
||||||
)
|
|
||||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
|
||||||
target_link_libraries(flutter INTERFACE
|
|
||||||
PkgConfig::GTK
|
|
||||||
PkgConfig::GLIB
|
|
||||||
PkgConfig::GIO
|
|
||||||
)
|
|
||||||
add_dependencies(flutter flutter_assemble)
|
|
||||||
|
|
||||||
# === Flutter tool backend ===
|
|
||||||
# _phony_ is a non-existent file to force this command to run every time,
|
|
||||||
# since currently there's no way to get a full input/output list from the
|
|
||||||
# flutter tool.
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E env
|
|
||||||
${FLUTTER_TOOL_ENVIRONMENT}
|
|
||||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
|
||||||
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
|
||||||
VERBATIM
|
|
||||||
)
|
|
||||||
add_custom_target(flutter_assemble DEPENDS
|
|
||||||
"${FLUTTER_LIBRARY}"
|
|
||||||
${FLUTTER_LIBRARY_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
|
||||||
|
|
||||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
|
||||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
|
||||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
#define GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
|
|
||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
|
|
||||||
// Registers Flutter plugins.
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry);
|
|
||||||
|
|
||||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#
|
|
||||||
# Generated file, do not edit.
|
|
||||||
#
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
|
||||||
url_launcher_linux
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
|
||||||
)
|
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
|
||||||
endforeach(plugin)
|
|
||||||
|
|
||||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
|
||||||
endforeach(ffi_plugin)
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#include "my_application.h"
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
g_autoptr(MyApplication) app = my_application_new();
|
|
||||||
return g_application_run(G_APPLICATION(app), argc, argv);
|
|
||||||
}
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
#include "my_application.h"
|
|
||||||
|
|
||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
#ifdef GDK_WINDOWING_X11
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
|
||||||
|
|
||||||
struct _MyApplication {
|
|
||||||
GtkApplication parent_instance;
|
|
||||||
char** dart_entrypoint_arguments;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
|
||||||
|
|
||||||
// Implements GApplication::activate.
|
|
||||||
static void my_application_activate(GApplication* application) {
|
|
||||||
MyApplication* self = MY_APPLICATION(application);
|
|
||||||
GtkWindow* window =
|
|
||||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
|
||||||
|
|
||||||
// Use a header bar when running in GNOME as this is the common style used
|
|
||||||
// by applications and is the setup most users will be using (e.g. Ubuntu
|
|
||||||
// desktop).
|
|
||||||
// If running on X and not using GNOME then just use a traditional title bar
|
|
||||||
// in case the window manager does more exotic layout, e.g. tiling.
|
|
||||||
// If running on Wayland assume the header bar will work (may need changing
|
|
||||||
// if future cases occur).
|
|
||||||
gboolean use_header_bar = TRUE;
|
|
||||||
#ifdef GDK_WINDOWING_X11
|
|
||||||
GdkScreen* screen = gtk_window_get_screen(window);
|
|
||||||
if (GDK_IS_X11_SCREEN(screen)) {
|
|
||||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
|
||||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
|
||||||
use_header_bar = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (use_header_bar) {
|
|
||||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
|
||||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
|
||||||
gtk_header_bar_set_title(header_bar, "making_school_asignment_app");
|
|
||||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
|
||||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
|
||||||
} else {
|
|
||||||
gtk_window_set_title(window, "making_school_asignment_app");
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_window_set_default_size(window, 1280, 720);
|
|
||||||
gtk_widget_show(GTK_WIDGET(window));
|
|
||||||
|
|
||||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
|
||||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
|
||||||
|
|
||||||
FlView* view = fl_view_new(project);
|
|
||||||
gtk_widget_show(GTK_WIDGET(view));
|
|
||||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
|
||||||
|
|
||||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
|
||||||
|
|
||||||
gtk_widget_grab_focus(GTK_WIDGET(view));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements GApplication::local_command_line.
|
|
||||||
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
|
|
||||||
MyApplication* self = MY_APPLICATION(application);
|
|
||||||
// Strip out the first argument as it is the binary name.
|
|
||||||
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
|
||||||
|
|
||||||
g_autoptr(GError) error = nullptr;
|
|
||||||
if (!g_application_register(application, nullptr, &error)) {
|
|
||||||
g_warning("Failed to register: %s", error->message);
|
|
||||||
*exit_status = 1;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_application_activate(application);
|
|
||||||
*exit_status = 0;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements GApplication::startup.
|
|
||||||
static void my_application_startup(GApplication* application) {
|
|
||||||
//MyApplication* self = MY_APPLICATION(object);
|
|
||||||
|
|
||||||
// Perform any actions required at application startup.
|
|
||||||
|
|
||||||
G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements GApplication::shutdown.
|
|
||||||
static void my_application_shutdown(GApplication* application) {
|
|
||||||
//MyApplication* self = MY_APPLICATION(object);
|
|
||||||
|
|
||||||
// Perform any actions required at application shutdown.
|
|
||||||
|
|
||||||
G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements GObject::dispose.
|
|
||||||
static void my_application_dispose(GObject* object) {
|
|
||||||
MyApplication* self = MY_APPLICATION(object);
|
|
||||||
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
|
||||||
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void my_application_class_init(MyApplicationClass* klass) {
|
|
||||||
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
|
||||||
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
|
|
||||||
G_APPLICATION_CLASS(klass)->startup = my_application_startup;
|
|
||||||
G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
|
|
||||||
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void my_application_init(MyApplication* self) {}
|
|
||||||
|
|
||||||
MyApplication* my_application_new() {
|
|
||||||
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
|
||||||
"application-id", APPLICATION_ID,
|
|
||||||
"flags", G_APPLICATION_NON_UNIQUE,
|
|
||||||
nullptr));
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#ifndef FLUTTER_MY_APPLICATION_H_
|
|
||||||
#define FLUTTER_MY_APPLICATION_H_
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
|
|
||||||
GtkApplication)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* my_application_new:
|
|
||||||
*
|
|
||||||
* Creates a new Flutter-based application.
|
|
||||||
*
|
|
||||||
* Returns: a new #MyApplication.
|
|
||||||
*/
|
|
||||||
MyApplication* my_application_new();
|
|
||||||
|
|
||||||
#endif // FLUTTER_MY_APPLICATION_H_
|
|
||||||
|
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.7+8
|
version: 1.0.8+9
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.4.1 <4.0.0'
|
sdk: '>=3.4.1 <4.0.0'
|
||||||
|
|
@ -55,7 +55,7 @@ dependencies:
|
||||||
# 加密验签插件,支持SHA MD5 HMAC
|
# 加密验签插件,支持SHA MD5 HMAC
|
||||||
crypto: ^3.0.2
|
crypto: ^3.0.2
|
||||||
# 获取app版本号
|
# 获取app版本号
|
||||||
package_info_plus: ^8.0.0
|
package_info_plus: ^9.0.0
|
||||||
# 网络监控
|
# 网络监控
|
||||||
connectivity_plus: ^6.0.3
|
connectivity_plus: ^6.0.3
|
||||||
# toast组件用于系统尚未初始化完成时
|
# toast组件用于系统尚未初始化完成时
|
||||||
|
|
@ -71,15 +71,9 @@ dependencies:
|
||||||
url: https://gitea.23544.com/wangyang/zoom_widget.git
|
url: https://gitea.23544.com/wangyang/zoom_widget.git
|
||||||
# url: https://github.com/semakers/zoom-widget.git
|
# url: https://github.com/semakers/zoom-widget.git
|
||||||
# ref: a35c9da6afe405c23b5897b449683d424016e9f1
|
# ref: a35c9da6afe405c23b5897b449683d424016e9f1
|
||||||
# TODO 升级插件 暂时不使用
|
|
||||||
# app_upgrade_plugin:
|
retrofit: 4.6.0
|
||||||
# # path: C:\Users\wy\Desktop\my_project\app_upgrade_plugin
|
json_annotation: ^4.9.0
|
||||||
# git:
|
|
||||||
# url: https://gitea.23544.com/wangyang/app_upgrade_plugin.git
|
|
||||||
# start retrofit请求封装
|
|
||||||
retrofit: ^4.1.0
|
|
||||||
json_annotation: 4.9.0
|
|
||||||
# end retrofit请求封装
|
|
||||||
# 进度条
|
# 进度条
|
||||||
percent_indicator: ^4.2.3
|
percent_indicator: ^4.2.3
|
||||||
badges: ^3.1.2
|
badges: ^3.1.2
|
||||||
|
|
@ -102,7 +96,7 @@ dependencies:
|
||||||
app_installer: ^1.1.0
|
app_installer: ^1.1.0
|
||||||
# auto_updater: ^0.2.1
|
# auto_updater: ^0.2.1
|
||||||
auto_updater: ^1.0.0
|
auto_updater: ^1.0.0
|
||||||
permission_handler: ^11.3.1
|
permission_handler: ^12.0.1
|
||||||
flutter_distributor: 0.6.5
|
flutter_distributor: 0.6.5
|
||||||
# fastforge: ^0.6.5
|
# fastforge: ^0.6.5
|
||||||
flutter_native_splash: ^2.4.6
|
flutter_native_splash: ^2.4.6
|
||||||
|
|
@ -110,10 +104,15 @@ dependencies:
|
||||||
app_settings: ^5.1.1
|
app_settings: ^5.1.1
|
||||||
device_info_plus: ^11.1.0
|
device_info_plus: ^11.1.0
|
||||||
auto_size_text: ^3.0.0
|
auto_size_text: ^3.0.0
|
||||||
|
yx_app_upgrade_flutter:
|
||||||
|
git:
|
||||||
|
url: https://gitea.23544.com/wangyang/yx_app_upgrade_flutter.git
|
||||||
|
ref: 2.0.4
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
archive: ^4.0.2
|
archive: ^4.0.2
|
||||||
uuid: ^4.4.2
|
uuid: ^4.4.2
|
||||||
|
# analyzer: ^3..0
|
||||||
# meta: ^1.15.0
|
# meta: ^1.15.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue