Commit df03443e by tanghuan

H5 版本检测和下载升级

1 parent f50fadd3
......@@ -2,8 +2,9 @@ class Constant {
/// 应用内部 http 服务
static const int localServerPort = 35982;
static const String localServerHost = '127.0.0.1';
// static const String localServerHost = 'appdev-xj.banxiaoer.net';
static const String localServerHost = '127.0.0.1';
static const String localServerUrl = 'http://$localServerHost:$localServerPort';
static const String localFileUrl = 'http://127.0.0.1:$localServerPort';
......@@ -19,15 +20,17 @@ class Constant {
static const String appVersion = '1.0.0';
static const String h5Version = '1.0.0';
/// 内部 H5 dist 目录
static const String h5DistDir = 'http_dist_assets';
/// IM SDK
static const int imSdkAppId = 1400310691;
static const String imClientSecure = 'kM4yqbehB3io9UiLvH6eHvM7xAhfYxoyyaO1tLoHgKltcaI7MZXkUbpFaWdeQIqe';
/// 测试阶段使用的 h5 服务地址
static const String h5Server = 'appdev-xj.banxiaoer.net';
// static const String h5Server = 'appdev-th.banxiaoer.net';
// static const String h5Server = '192.168.1.136';
static const String h5Server = 'appdev-xj.banxiaoer.net';
/// 测试阶段使用
static const bool needIM = true;
......
......@@ -36,6 +36,7 @@ import 'package:appframe/services/im_service.dart';
import 'package:appframe/services/local_server_service.dart';
import 'package:appframe/services/player_service.dart';
import 'package:appframe/services/recorder_service.dart';
import 'package:appframe/services/upgrade_service.dart';
import 'package:fluwx/fluwx.dart';
import 'package:get_it/get_it.dart';
import 'package:shared_preferences/shared_preferences.dart';
......@@ -183,6 +184,9 @@ Future<void> setupLocator() async {
/// local server
getIt.registerSingleton<LocalServerService>(LocalServerService());
/// upgradeService
getIt.registerSingleton<UpgradeService>(UpgradeService());
/// apiService
getIt.registerLazySingleton<ApiService>(
() => ApiService(baseUrl: 'https://dev.banxiaoer.net'),
......
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/services/im_service.dart';
import 'package:appframe/services/upgrade_service.dart';
import 'package:flutter/material.dart';
import 'app.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await setupLocator();
// IM SDK 初始化
if (Constant.needIM) {
await getIt.get<ImService>().initSdk();
}
// H5版本检测和升级
getIt.get<UpgradeService>().start();
runApp(const App());
}
......@@ -2,7 +2,6 @@ import 'dart:io';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/services/upgrade_service.dart';
import 'package:appframe/utils/zip_util.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
......@@ -13,9 +12,6 @@ class LocalServerService {
// 启动本地HTTP服务器
Future<HttpServer> startLocalServer() async {
// 检测和升级
// await getIt.get<UpgradeService>().upgrade();
// 测试情况下, 每次启动服务,先解压dist文件
_extractDist();
......@@ -152,10 +148,10 @@ class LocalServerService {
var version = getIt.get<SharedPreferences>().getString('h5_version') ?? Constant.h5Version;
if (Platform.isAndroid) {
var direct = await getExternalStorageDirectory();
_httpDirectory = '${direct?.path}/http_dist_assets_/$version';
_httpDirectory = '${direct?.path}/${Constant.h5DistDir}/$version';
} else if (Platform.isIOS || Platform.isMacOS) {
var direct = await getApplicationSupportDirectory();
_httpDirectory = '${direct.path}/http_dist_assets_/$version';
_httpDirectory = '${direct.path}/${Constant.h5DistDir}/$version';
}
}
......
import 'dart:io';
import 'dart:isolate';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/utils/zip_util.dart';
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
......@@ -11,23 +12,34 @@ import 'package:uuid/uuid.dart';
class UpgradeService {
String configUrl = "https://bxe-obs.banxiaoer.com/conf/xeapp_conf_dev.json";
Future<void> upgrade() async {
await _handleUpgrade();
///
/// Isolate 中检测升级
///
void start() {
final token = ServicesBinding.rootIsolateToken;
Isolate.spawn(_handleUpgrade, {'token': token});
}
Future<bool> _handleUpgrade() async {
Future<bool> _handleUpgrade(Map<dynamic, dynamic> params) async {
final RootIsolateToken? token = params['token'];
if (token != null) {
BackgroundIsolateBinaryMessenger.ensureInitialized(token);
}
print('开始检测升级...');
Dio dio = Dio();
try {
Response response = await dio.get('$configUrl?t=${DateTime.now().millisecondsSinceEpoch}');
if (response.statusCode != 200) {
return false;
}
String version = response.data['version'] as String;
String zip = response.data['zip'] as String;
// 获取版本信息
var info = await _getVersionInfo(dio);
String version = info['version'] as String;
String zip = info['zip'] as String;
// 检测版本号
// 在新 Isolate 中不能使用主 Isolate 的 getIt
var sharedPreferences = await SharedPreferences.getInstance();
// 版本号相同,则不需要升级
if (version == (getIt.get<SharedPreferences>().getString('h5_version') ?? Constant.h5Version)) {
if (version == (sharedPreferences.getString('h5_version') ?? Constant.h5Version)) {
print('版本号相同,不需要升级');
return true;
}
......@@ -35,29 +47,25 @@ class UpgradeService {
// 下载zip文件
var tempDir = await getTemporaryDirectory();
var saveFilePath = '${tempDir.path}/${Uuid().v4()}.zip';
var downloadResult = await _downloadFile(dio, '$zip$version.zip', saveFilePath);
if (!downloadResult) {
return false;
}
await _downloadFile(dio, '$zip$version.zip', saveFilePath);
// 解压zip文件
String? httpDirect;
if (Platform.isAndroid) {
var direct = await getExternalStorageDirectory();
httpDirect = '${direct?.path}/http_dist_assets_/$version';
httpDirect = '${direct?.path}/${Constant.h5DistDir}/$version';
} else if (Platform.isIOS || Platform.isMacOS) {
var direct = await getApplicationSupportDirectory();
httpDirect = '${direct.path}/http_dist_assets_/$version';
httpDirect = '${direct.path}/${Constant.h5DistDir}/$version';
}
var result = await ZipUtil.extractZipFile(saveFilePath, httpDirect!);
if (!result) {
print('解压失败');
return false;
}
// 设置版本标识
var sharedPreferences = getIt.get<SharedPreferences>();
sharedPreferences.setString('h5_version', version);
return true;
......@@ -65,24 +73,28 @@ class UpgradeService {
print('升级请求失败: $e');
return false;
} finally {
// 请求结束
dio.close(force: true);
}
}
Future<bool> _downloadFile(Dio dio, String url, String savePath) async {
try {
Response response = await dio.download(url, savePath);
if (response.statusCode == 200) {
print('文件下载成功: $savePath');
return true;
} else {
print('文件下载失败: ${response.statusCode}');
return false;
}
} catch (e) {
print('文件下载失败: $e');
return false;
Future<Map<String, String>> _getVersionInfo(Dio dio) async {
Response response = await dio.get('$configUrl?t=${DateTime.now().millisecondsSinceEpoch}');
if (response.statusCode != 200) {
throw Exception('获取版本信息失败');
}
String version = response.data['version'] as String;
String zip = response.data['zip'] as String;
return {
'version': version,
'zip': zip,
};
}
Future<void> _downloadFile(Dio dio, String url, String savePath) async {
Response response = await dio.download(url, savePath);
if (response.statusCode != 200) {
throw Exception('文件下载失败');
}
}
}
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!