Commit df03443e by tanghuan

H5 版本检测和下载升级

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