app更新功能,尚未完成

This commit is contained in:
胡天 2023-07-25 23:44:15 +08:00
parent fe9ce04456
commit 91678fdfef
8 changed files with 290 additions and 4 deletions

View File

@ -40,4 +40,11 @@
</application>
<!-- 设置网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- installation package permissions -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- read permissions for external storage -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- write permissions for external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

60
lib/data/model/app.dart Normal file
View File

@ -0,0 +1,60 @@
/*
app
*/
class AppUpdateRequest {
String? device;
String? channel;
String? architecture;
String? model;
AppUpdateRequest({
this.device,
this.channel,
this.architecture,
this.model,
});
factory AppUpdateRequest.fromJson(Map<String, dynamic> json) =>
AppUpdateRequest(
device: json["device"],
channel: json["channel"],
architecture: json["architecture"],
model: json["model"],
);
Map<String, dynamic> toJson() => {
"device": device,
"channel": channel,
"architecture": architecture,
"model": model,
};
}
class AppUpdateResponse {
String? shopUrl;
String? fileUrl;
String? latestVersion;
String? latestDescription;
AppUpdateResponse({
this.shopUrl,
this.fileUrl,
this.latestVersion,
this.latestDescription,
});
factory AppUpdateResponse.fromJson(Map<String, dynamic> json) =>
AppUpdateResponse(
shopUrl: json["shopUrl"],
fileUrl: json["fileUrl"],
latestVersion: json["latestVersion"],
latestDescription: json["latestDescription"],
);
Map<String, dynamic> toJson() => {
"shopUrl": shopUrl,
"fileUrl": fileUrl,
"latestVersion": latestVersion,
"latestDescription": latestDescription,
};
}

View File

@ -0,0 +1,22 @@
import 'package:news_getx/config/storage.dart';
import 'package:news_getx/data/model/app.dart';
import 'package:news_getx/data/model/categories.dart';
import 'package:news_getx/data/model/channels.dart';
import 'package:news_getx/data/model/news.dart';
import 'package:news_getx/data/model/tag.dart';
import 'package:news_getx/utils/http.dart';
/// AppAPI
class AppUpdateAPI {
///
/// refresh
static Future<AppUpdateResponse> update({
required AppUpdateRequest request,
}) async {
var response = await HttpUtil().post(
"/app/update",
data: request.toJson(),
);
return AppUpdateResponse.fromJson(response);
}
}

View File

@ -0,0 +1,8 @@
import 'package:news_getx/data/model/app.dart';
import 'package:news_getx/data/provider/app.dart';
class AppRepository {
Future<AppUpdateResponse> update(AppUpdateRequest request) {
return AppUpdateAPI.update(request: request);
}
}

View File

@ -1,16 +1,33 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:news_getx/config/storage.dart';
import 'package:news_getx/data/services/storage.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info/device_info.dart';
class ConfigService extends GetxService {
static ConfigService get to => Get.find();
bool isFirstOpen = false;
RxBool isGrayFilter = false.obs;
PackageInfo? _platform;
///
static String channel = "xxx";
/// ios
static bool isIOS = Platform.isIOS;
/// android
static AndroidDeviceInfo? androidDeviceInfo;
/// ios
static IosDeviceInfo? iosDeviceInfo;
String get version => _platform?.version ?? "-";
bool get isRelease => bool.fromEnvironment("dart.vm.product");
@ -24,9 +41,20 @@ class ConfigService extends GetxService {
];
@override
void onInit() {
void onInit() async {
super.onInit();
isFirstOpen = StorageService.to.getBool(StorageDeviceFirstOpenKey);
//
getPlatform();
//
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
if (isIOS) {
iosDeviceInfo = await deviceInfoPlugin.iosInfo;
} else {
androidDeviceInfo = await deviceInfoPlugin.androidInfo;
}
}
void changeGrayTheme() {

126
lib/utils/update.dart Normal file
View File

@ -0,0 +1,126 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:install_plugin/install_plugin.dart';
import 'package:news_getx/data/model/app.dart';
import 'package:news_getx/data/repository/app_repository.dart';
import 'package:news_getx/data/services/config.dart';
import 'package:path_provider/path_provider.dart';
// todo
class DownloadController extends GetxController {
//
var _progressValue = 0.0.obs;
double get progressValue => _progressValue.value;
set progressValue(double value) {
_progressValue.value = value;
}
/// &
Future<void> _downloadAPKAndSetup(fileUrl) async {
_progressValue.value = 0.0;
//
Directory? externalDir = await getExternalStorageDirectory();
if (externalDir == null) {
return;
}
//
String fullPath = "${externalDir.path}/release.apk";
// Dio dio = Dio(BaseOptions(
// responseType: ResponseType.bytes,
// followRedirects: false,
// validateStatus: (status) {
// return status! < 500;
// }
// ));
//
// // APP文件
// Response response = await dio.get(fileUrl);
//
// //
// File file = File(fullPath);
// var raf = file.openSync(mode: FileMode.write);
// raf.writeByteSync(response.data);
// await raf.close();
await Dio().download(fileUrl, fullPath, onReceiveProgress: (count, total) {
final value = count / total;
if (_progressValue.value != value) {
if (_progressValue.value < 1.0) {
_progressValue.value = count / total;
} else {
_progressValue.value = 0.0;
}
print("${(_progressValue * 100).toStringAsFixed(0)}%");
}
});
//
await InstallPlugin.installApk(fullPath);
}
}
/// App
class AppUpdateUtil {
static AppUpdateUtil _instance = AppUpdateUtil._internal();
factory AppUpdateUtil() => _instance;
AppUpdateUtil._internal();
AppUpdateResponse? _appUpdateInfo;
///
Future run() async {
//
AppUpdateRequest appUpdateRequest = AppUpdateRequest(
device: Platform.isIOS ? "ios" : "android",
channel: ConfigService.channel,
architecture: ConfigService.isIOS
? ConfigService.iosDeviceInfo!.utsname.machine
: ConfigService.androidDeviceInfo!.device,
model: ConfigService.isIOS
? ConfigService.iosDeviceInfo!.name
: ConfigService.androidDeviceInfo!.brand,
);
_appUpdateInfo = await AppRepository().update(appUpdateRequest);
_runAppUpdate();
}
///
Future _runAppUpdate() async {
//
final isNewVersion =
_appUpdateInfo!.latestVersion!.compareTo(ConfigService.to.version) > 0;
//
if (isNewVersion) {
// todo
Get.defaultDialog(
title: "发现新版本 ${_appUpdateInfo!.latestVersion}",
content: GetBuilder<DownloadController>(
init: DownloadController(),
builder: (controller) {
return LinearProgressIndicator(value: controller.progressValue);
},
),
);
// _appUpdateConformDialog(
//
// );
}
}
///
void _appUpdateConformDialog(VoidCallback onPressed) {}
}

View File

@ -301,6 +301,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.17"
install_plugin:
dependency: "direct main"
description:
name: install_plugin
sha256: "6fb67ba0781e75de4f2f2266ed25e835bfd277c5bfc2ed034af52774355857c6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
intl:
dependency: "direct main"
description:
@ -457,10 +465,26 @@ packages:
dependency: "direct main"
description:
name: permission_handler
sha256: e968207ce71d8b40d719aeca3e5a8b684494ecbe9a577dd67cc701216bcccf0a
sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81"
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.2.0"
version: "10.4.3"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "37cedf9e5d530582bc813f63ed278e4a9dc42bb0948b68316e253cb0cd56a4b1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.3.1"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: "7a187b671a39919462af2b5e813148365b71a615979165a119868d667fe90c03"
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.1.3"
permission_handler_platform_interface:
dependency: transitive
description:
@ -469,6 +493,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.11.1"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.3"
petitparser:
dependency: transitive
description:

View File

@ -86,7 +86,7 @@ dependencies:
path_provider: ^2.0.1
# permission 权限
permission_handler: ^7.1.0
permission_handler: ^10.4.3
# 错误收集
sentry: ^5.0.0
@ -97,6 +97,9 @@ dependencies:
# 通过 scheme 打开APP 获取 参数
uni_links: ^0.5.1
# app 更新
install_plugin: ^2.1.0
dev_dependencies:
flutter_test:
sdk: flutter