Browse Source

feat : 程序自更新

dev
徐振升 3 weeks ago
parent
commit
40a3731f39
  1. 83
      README.md
  2. 14
      android/app/src/main/AndroidManifest.xml
  3. 6
      android/app/src/main/res/xml/file_paths.xml
  4. 2
      lib/app/bindings/initial_binding.dart
  5. 213
      lib/data/providers/upgrader_service.dart
  6. 8
      linux/flutter/generated_plugin_registrant.cc
  7. 2
      linux/flutter/generated_plugins.cmake
  8. 8
      macos/Flutter/GeneratedPluginRegistrant.swift
  9. 248
      pubspec.lock
  10. 5
      pubspec.yaml
  11. 3
      windows/flutter/generated_plugin_registrant.cc
  12. 1
      windows/flutter/generated_plugins.cmake

83
README.md

@ -1,39 +1,78 @@
# problem_check_system
# 项目名称:现场问题检查系统
系统架构为MVVM + 仓库模式
## 核心功能
这个应用需要实现以下功能:
本系统旨在为现场工作人员提供一个高效的问题记录与管理平台,支持离线操作和数据同步。
离线登录系统
1.1 在线/离线登录
需求: 用户能够使用用户名和密码进行登录。如果设备曾成功登录过,即使在离线状态下也能进入应用。
问题数据收集(描述、位置、图片等)
技术实现思路:
本地数据存储
在线: 登录成功后,从服务器获取用户身份信息和Token。
有网络时手动上传功能
离线: 将登录凭证(如Token)安全地存储在本地数据库中,启动时优先检查本地凭证。如果凭证有效,直接进入主界面。
技术栈
Flutter SDK
1.2 问题数据离线增删改查
需求: 用户在离线状态下能完整地创建、编辑、删除和查询问题数据。
GetX (状态管理、路由管理、依赖注入)
技术实现思路:
SQFlite (本地数据库)
本地数据库: 使用 SQFlite 作为本地数据库。
Image Picker (图片选择)
数据结构: 设计清晰的数据库表结构,包含问题描述、图片路径、创建时间、状态(如“待上传”)等字段。
Geolocator (位置信息)
操作: 所有的增删改查操作都直接在本地数据库上进行。
HTTP/Dio (网络请求)
1.3 问题数据上传/下载
需求: 在有网络连接时,系统能自动或手动将本地数据同步到服务器,并从服务器下载最新数据。
# !/bin/bash
技术实现思路:
echo "开始清理..."
flutter clean
上传队列: 在本地数据库中新增一个“待上传”队列。当用户离线进行增删改操作时,将这些操作记录在队列中。
echo "获取依赖..."
flutter pub get
智能同步: 当网络恢复时,按顺序处理上传队列中的任务。使用统一的 HTTP/Dio 拦截器处理身份验证和错误重试。
echo "构建APK..."
flutter build apk --release --target-platform android-arm64
差异化下载: 从服务器下载数据时,只拉取自上次同步以来有更新的数据,避免全量下载。
echo "构建完成!APK位置:build/app/outputs/flutter-apk/app-release.apk"
2. 系统架构:MVVM + 仓库模式
此架构能有效分离关注点,提高代码的可测试性和可维护性。
模型 (Model): 负责数据管理。定义问题数据的实体类,如 Problem。
视图模型 (ViewModel): 作为视图和模型之间的桥梁。
负责业务逻辑、状态管理和数据处理。
通过 GetX 管理 UI 状态,并与视图进行绑定。
使用 GetX 的依赖注入(DI)管理 Repository 实例。
视图 (View): 负责 UI 展示。
使用 Flutter Widgets 构建界面。
通过 GetX 提供的响应式组件(如 Obx),监听 ViewModel 中的状态变化并自动更新 UI。
仓库 (Repository): 负责统一数据源(本地数据库和网络)。
封装数据访问逻辑,向 ViewModel 提供统一的数据接口。
根据网络状态,决定是从 SQFlite 获取数据还是从网络请求。
3. 技术栈
Flutter SDK: 跨平台应用开发框架。
GetX:
状态管理: 轻量高效,用于管理 UI 状态。
路由管理: 简化页面跳转。
依赖注入: 方便管理和提供单例服务(如 Repository)。
SQFlite: 本地数据库,用于离线数据存储。
Image Picker: 用于从图库或相机选择图片。
HTTP/Dio: 网络请求库。推荐使用 Dio,因为它提供了更强大的拦截器、表单数据处理和错误处理功能。

14
android/app/src/main/AndroidManifest.xml

@ -2,9 +2,9 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<!-- 对于 Android 10 (API 29) 及以上版本,需要添加以下权限 -->
@ -16,6 +16,16 @@
android:label="现场问题检查"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- 添加文件提供者 -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<activity
android:name=".MainActivity"
android:exported="true"

6
android/app/src/main/res/xml/file_paths.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external" path="." />
<external-files-path name="external_files" path="." />
<cache-path name="cache" path="." />
</paths>

2
lib/app/bindings/initial_binding.dart

@ -8,6 +8,7 @@ import 'package:problem_check_system/data/repositories/file_repository.dart';
import 'package:problem_check_system/data/repositories/image_repository.dart';
import 'package:problem_check_system/data/repositories/image_repository_impl.dart';
import 'package:problem_check_system/data/repositories/problem_repository.dart';
import 'package:problem_check_system/data/providers/upgrader_service.dart';
import 'package:uuid/uuid.dart';
class InitialBinding implements Bindings {
@ -19,6 +20,7 @@ class InitialBinding implements Bindings {
void _registerCoreServices() {
///
Get.put(UpgraderService());
Get.put<GetStorage>(GetStorage(), permanent: true);
Get.put<Uuid>(Uuid(), permanent: true);
Get.put<HttpProvider>(HttpProvider());

213
lib/data/providers/upgrader_service.dart

@ -0,0 +1,213 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:open_file/open_file.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
class UpgraderService extends GetxService {
final Dio _dio = Dio();
final String _versionUrl =
'http://xhota.anxincloud.cn/problem/version.json'; // JSON
var isUpdateAvailable = false.obs;
var updateInfo = {}.obs;
var downloadProgress = '0'.obs;
var totalSize = '0'.obs;
var isDownloading = false.obs;
@override
void onInit() {
super.onInit();
checkForUpdate();
}
//
Future<void> checkForUpdate() async {
try {
//
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String currentVersion = packageInfo.version;
final response = await _dio.get(_versionUrl);
if (response.statusCode == 200) {
final latestVersion = response.data['version'];
if (latestVersion.compareTo(currentVersion) > 0) {
isUpdateAvailable.value = true;
updateInfo.value = response.data;
showUpdateDialog();
}
}
} catch (e) {
Get.log('检查更新失败: $e');
}
}
//
void showUpdateDialog() {
Get.dialog(
AlertDialog(
title: Text('发现新版本'),
content: Text(updateInfo['description'] ?? '有新的更新可用。'),
actions: [
TextButton(onPressed: () => Get.back(), child: Text('稍后')),
TextButton(
onPressed: () {
Get.back();
startDownload();
},
child: Text('立即更新'),
),
],
),
barrierDismissible: false,
);
}
//
Future<void> startDownload() async {
isDownloading.value = true;
showDownloadProgressDialog();
try {
Directory? dir = await getExternalStorageDirectory();
if (dir == null) {
Get.back(); //
Get.snackbar('错误', '无法获取外部存储目录。');
print('错误: getExternalStorageDirectory() 返回 null');
isDownloading.value = false;
return; // 退
}
String savePath = '${dir.path}/app-release.apk';
print('--- 调试信息 ---');
print('目标下载路径: $savePath');
print('--- 调试信息 ---');
//
final file = File(savePath);
if (!await file.parent.exists()) {
await file.parent.create(recursive: true);
print('--- 调试信息 ---');
print('已尝试创建父目录: ${file.parent.path}');
print('--- 调试信息 ---');
}
await _dio.download(
updateInfo['url'],
savePath,
onReceiveProgress: (received, total) {
if (total != -1) {
downloadProgress.value = (received / 1024 / 1024).toStringAsFixed(
2,
);
totalSize.value = (total / 1024 / 1024).toStringAsFixed(2);
//
// print('下载进度 - 目标路径: $savePath');
}
},
options: Options(
receiveTimeout: const Duration(seconds: 30), //
sendTimeout: const Duration(seconds: 30),
),
);
isDownloading.value = false;
Get.back(); //
//
if (await file.exists()) {
final fileSize = await file.length();
Get.log('文件验证成功!路径: $savePath');
Get.log('文件大小: ${(fileSize / 1024 / 1024).toStringAsFixed(2)} MB');
installApk(savePath);
} else {
Get.snackbar('下载失败', '文件下载完毕但未找到,请联系管理员。');
Get.log('错误:文件下载完毕但未找到!');
}
} on DioException catch (e) {
// 使 DioException Dio
isDownloading.value = false;
Get.back();
String errorMessage = '下载失败: 网络或服务器问题。';
if (e.type == DioExceptionType.badResponse) {
errorMessage = '下载失败: 服务器响应错误 (${e.response?.statusCode})';
Get.log('Dio响应错误: ${e.response?.data}');
} else if (e.type == DioExceptionType.connectionError) {
errorMessage = '下载失败: 连接错误,请检查网络。';
} else if (e.type == DioExceptionType.unknown) {
//
errorMessage = '下载失败: 未知错误。请检查存储权限或设备空间。';
Get.log('Dio未知错误: $e');
}
Get.snackbar('下载失败', errorMessage);
Get.log('下载失败 (DioException): $e');
} catch (e) {
isDownloading.value = false;
Get.back();
Get.snackbar('下载失败', '发生未知错误。');
Get.log('下载失败 (通用异常): $e');
}
}
//
void showDownloadProgressDialog() {
Get.dialog(
AlertDialog(
title: Text('正在下载更新...'),
content: Obx(
() => Column(
mainAxisSize: MainAxisSize.min,
children: [
LinearProgressIndicator(
value: totalSize.value == '0'
? null
: double.parse(downloadProgress.value) /
double.parse(totalSize.value),
),
SizedBox(height: 16),
Text('${downloadProgress.value} MB / ${totalSize.value} MB'),
],
),
),
),
barrierDismissible: false,
);
}
// APK
Future<void> installApk(String path) async {
//
var status = await Permission.requestInstallPackages.status;
if (status.isGranted) {
//
_openApkFile(path);
} else {
//
//
status = await Permission.requestInstallPackages.request();
if (status.isGranted) {
_openApkFile(path);
} else {
//
Get.snackbar(
'权限被拒绝',
'需要授权才能安装更新。请在系统设置中为本应用开启“安装未知应用”的权限。',
duration: Duration(seconds: 5),
);
}
}
}
//
Future<void> _openApkFile(String path) async {
final result = await OpenFile.open(path);
print('OpenFile result: ${result.type}, message: ${result.message}');
if (result.type != ResultType.done) {
Get.snackbar('安装失败', '无法启动安装程序: ${result.message}');
}
}
}

8
linux/flutter/generated_plugin_registrant.cc

@ -7,9 +7,17 @@
#include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h>
#include <open_file_linux/open_file_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) open_file_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "OpenFileLinuxPlugin");
open_file_linux_plugin_register_with_registrar(open_file_linux_registrar);
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);
}

2
linux/flutter/generated_plugins.cmake

@ -4,6 +4,8 @@
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
open_file_linux
url_launcher_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

8
macos/Flutter/GeneratedPluginRegistrant.swift

@ -7,12 +7,20 @@ import Foundation
import connectivity_plus
import file_selector_macos
import open_file_mac
import package_info_plus
import path_provider_foundation
import shared_preferences_foundation
import sqflite_darwin
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}

248
pubspec.lock

@ -169,6 +169,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.6"
csslib:
dependency: transitive
description:
name: csslib
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
dart_style:
dependency: transitive
description:
@ -389,6 +397,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.2"
html:
dependency: transitive
description:
name: html
sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.15.6"
http:
dependency: transitive
description:
@ -589,6 +605,78 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.5.0"
open_file:
dependency: "direct main"
description:
name: open_file
sha256: d17e2bddf5b278cb2ae18393d0496aa4f162142ba97d1a9e0c30d476adf99c0e
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.5.10"
open_file_android:
dependency: transitive
description:
name: open_file_android
sha256: "58141fcaece2f453a9684509a7275f231ac0e3d6ceb9a5e6de310a7dff9084aa"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.6"
open_file_ios:
dependency: transitive
description:
name: open_file_ios
sha256: "02996f01e5f6863832068e97f8f3a5ef9b613516db6897f373b43b79849e4d07"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.3"
open_file_linux:
dependency: transitive
description:
name: open_file_linux
sha256: d189f799eecbb139c97f8bc7d303f9e720954fa4e0fa1b0b7294767e5f2d7550
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.5"
open_file_mac:
dependency: transitive
description:
name: open_file_mac
sha256: "1440b1e37ceb0642208cfeb2c659c6cda27b25187a90635c9d1acb7d0584d324"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.3"
open_file_platform_interface:
dependency: transitive
description:
name: open_file_platform_interface
sha256: "101b424ca359632699a7e1213e83d025722ab668b9fd1412338221bf9b0e5757"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.3"
open_file_web:
dependency: transitive
description:
name: open_file_web
sha256: e3dbc9584856283dcb30aef5720558b90f88036360bd078e494ab80a80130c4f
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.4"
open_file_windows:
dependency: transitive
description:
name: open_file_windows
sha256: d26c31ddf935a94a1a3aa43a23f4fff8a5ff4eea395fe7a8cb819cf55431c875
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.3"
os_detect:
dependency: transitive
description:
name: os_detect
sha256: "7d87c0dd98c6faf110d5aa498e9a6df02ffce4bb78cc9cfc8ad02929be9bb71f"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.3"
package_config:
dependency: transitive
description:
@ -597,6 +685,22 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
package_info_plus:
dependency: "direct main"
description:
name: package_info_plus
sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.0.0"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.2.1"
path:
dependency: "direct main"
description:
@ -773,6 +877,62 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.0"
shared_preferences:
dependency: transitive
description:
name: shared_preferences
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.3"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: bd14436108211b0d4ee5038689a56d4ae3620fd72fd6036e113bf1345bc74d9e
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.13"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.4"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.3"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
shelf:
dependency: transitive
description:
@ -946,6 +1106,78 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.0"
upgrader:
dependency: "direct main"
description:
name: upgrader
sha256: a28de64108db70f77e5eacf8b87c1bdfaf9374ece9cab26f9aeac26ac3403eff
url: "https://pub.flutter-io.cn"
source: hosted
version: "12.1.0"
url_launcher:
dependency: transitive
description:
name: url_launcher
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.2"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: "81777b08c498a292d93ff2feead633174c386291e35612f8da438d6e92c4447e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.20"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.4"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.2.1"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.2.3"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.2"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.4"
uuid:
dependency: "direct main"
description:
@ -962,6 +1194,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
version:
dependency: transitive
description:
name: version
sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.2"
vm_service:
dependency: transitive
description:
@ -1002,6 +1242,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.3"
win32:
dependency: transitive
description:
name: win32
sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03"
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.14.0"
xdg_directories:
dependency: transitive
description:

5
pubspec.yaml

@ -1,7 +1,7 @@
name: problem_check_system
description: "A new Flutter project."
publish_to: "none"
version: 0.1.0
version: 1.0.0
environment:
sdk: ^3.8.1
@ -22,12 +22,15 @@ dependencies:
image_picker: ^1.1.2
intl: ^0.20.2
json_annotation: ^4.9.0
open_file: ^3.5.10
package_info_plus: ^9.0.0
path: ^1.9.1
path_provider: ^2.1.5
permission_handler: ^12.0.1
pretty_dio_logger: ^1.4.0
sqflite: ^2.4.2
tdesign_flutter: ^0.2.4
upgrader: ^12.1.0
uuid: ^4.5.1
dev_dependencies:

3
windows/flutter/generated_plugin_registrant.cc

@ -9,6 +9,7 @@
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
#include <file_selector_windows/file_selector_windows.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
@ -17,4 +18,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FileSelectorWindows"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}

1
windows/flutter/generated_plugins.cmake

@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus
file_selector_windows
permission_handler_windows
url_launcher_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

Loading…
Cancel
Save