added android update

This commit is contained in:
Schnitzel5 2025-03-28 16:00:29 +01:00
parent c45d8df099
commit 175ea414b8
7 changed files with 150 additions and 54 deletions

View file

@ -46,6 +46,15 @@
<data android:scheme="mangayomi" />
</intent-filter>
</activity>
<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>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/com.kodjodevf.mangayomi/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>

View file

@ -1,9 +1,9 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mangayomi/modules/more/about/providers/download_file_screen.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/services/fetch_sources_list.dart';
import 'package:mangayomi/services/http/m_client.dart';
@ -11,8 +11,6 @@ import 'package:mangayomi/utils/extensions/string_extensions.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:device_info_plus/device_info_plus.dart';
part 'check_for_update.g.dart';
@riverpod
@ -30,14 +28,8 @@ Future<void> checkForUpdate(
if (kDebugMode) {
log(info.data.toString());
}
if (Platform.isAndroid) {
final deviceInfo = DeviceInfoPlugin();
final androidInfo = await deviceInfo.androidInfo;
print("DEBUG");
print(androidInfo.supportedAbis.join(", ")); // x86_64, arm64-v8a
}
final updateAvailable = await _checkUpdate();
if (compareVersions(info.version, updateAvailable.$1) < 0) {
if (compareVersions(info.version, updateAvailable.$1) < 0 || true) {
if (manualUpdate) {
BotToast.showText(text: l10n.new_update_available);
await Future.delayed(const Duration(seconds: 1));
@ -46,32 +38,7 @@ Future<void> checkForUpdate(
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(l10n.new_update_available),
content: Text(
"${l10n.app_version(updateAvailable.$1)}\n\n${updateAvailable.$2}",
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(l10n.cancel),
),
const SizedBox(width: 15),
ElevatedButton(
onPressed: () async {
_launchInBrowser(Uri.parse(updateAvailable.$3));
},
child: Text(l10n.download),
),
],
),
],
);
return DownloadFileScreen(updateAvailable: updateAvailable);
},
);
}
@ -82,13 +49,7 @@ Future<void> checkForUpdate(
}
}
Future<void> _launchInBrowser(Uri url) async {
if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
throw 'Could not launch $url';
}
}
Future<(String, String, String)> _checkUpdate() async {
Future<(String, String, String, List<String>)> _checkUpdate() async {
final http = MClient.init(reqcopyWith: {'useDartHttpClient': true});
try {
final res = await http.get(
@ -104,6 +65,10 @@ Future<(String, String, String)> _checkUpdate() async {
.substringBefore('-'),
resListJson.first["body"].toString(),
resListJson.first["html_url"].toString(),
(resListJson.first["assets"] as List)
.map((asset) => asset["browser_download_url"])
.toList()
as List<String>,
);
} catch (e) {
rethrow;

View file

@ -0,0 +1,119 @@
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_installer/flutter_app_installer.dart';
import 'package:flutter_qjs/quickjs/ffi.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
class DownloadFileScreen extends ConsumerStatefulWidget {
final (String, String, String, List<String>) updateAvailable;
const DownloadFileScreen({required this.updateAvailable, super.key});
@override
ConsumerState<DownloadFileScreen> createState() => _DownloadFileScreenState();
}
class _DownloadFileScreenState extends ConsumerState<DownloadFileScreen> {
int _total = 0;
int _received = 0;
late http.StreamedResponse _response;
final List<int> _bytes = [];
@override
Widget build(BuildContext context) {
final l10n = l10nLocalizations(context)!;
final updateAvailable = widget.updateAvailable;
return AlertDialog(
title: Text(l10n.new_update_available),
content: Text(
"${l10n.app_version(updateAvailable.$1)}\n\n${updateAvailable.$2}",
),
actions: [
_total > 0
? Row(
children: [
LinearProgressIndicator(
value: _received > 0 ? _total / _received : 0,
),
Text('${_received ~/ 1024}/${_total ~/ 1024} KB'),
],
)
: SizedBox.shrink(),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(l10n.cancel),
),
const SizedBox(width: 15),
ElevatedButton(
onPressed: () async {
if (Platform.isAndroid) {
final deviceInfo = DeviceInfoPlugin();
final androidInfo = await deviceInfo.androidInfo;
String apkUrl = "";
for (String abi in androidInfo.supportedAbis) {
final url = updateAvailable.$4.firstWhereOrNull(
(apk) => apk.contains(abi),
);
if (url != null) {
apkUrl = url;
break;
}
}
await _downloadApk(apkUrl);
print("DEBUG");
print(
androidInfo.supportedAbis.join(", "),
); // x86_64, arm64-v8a, armeabi-v7a
} else {
_launchInBrowser(Uri.parse(updateAvailable.$3));
}
},
child: Text(l10n.download),
),
],
),
],
);
}
Future<void> _downloadApk(String url) async {
_response = await http.Client().send(http.Request('GET', Uri.parse(url)));
_total = _response.contentLength ?? 0;
_response.stream
.listen((value) {
setState(() {
_bytes.addAll(value);
_received += value.length;
});
})
.onDone(() async {
final file = File(
'${(await getApplicationDocumentsDirectory()).path}/${url.split("/").lastOrNull ?? "Mangayomi.apk"}',
);
await file.writeAsBytes(_bytes);
final FlutterAppInstaller appInstaller = FlutterAppInstaller();
await appInstaller.installApk(filePath: file.path);
await file.delete();
if (context.mounted) {
Navigator.pop(context);
}
});
}
Future<void> _launchInBrowser(Uri url) async {
if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
throw 'Could not launch $url';
}
}
}

View file

@ -5,7 +5,6 @@
import FlutterMacOS
import Foundation
import app_installer
import app_links
import audio_session
import connectivity_plus
@ -32,7 +31,6 @@ import window_manager
import window_to_front
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AppInstallerPlugin.register(with: registry.registrar(forPlugin: "AppInstallerPlugin"))
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))

View file

@ -38,14 +38,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.13.2"
app_installer:
dependency: "direct main"
description:
name: app_installer
sha256: "4c3a9268b53ead9a915ef79cd3988e28c72719fb78143867f9fed4bd4d8c1cfd"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
app_links:
dependency: "direct main"
description:
@ -556,6 +548,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_app_installer:
dependency: "direct main"
description:
name: flutter_app_installer
sha256: b71f7c3f6c5712b6f9bdcde798bbb8a0c4047cab47c4364f7252de8c95d67358
url: "https://pub.dev"
source: hosted
version: "1.0.0"
flutter_cache_manager:
dependency: transitive
description:

View file

@ -83,8 +83,8 @@ dependencies:
app_links: ^6.4.0
win32: ^5.10.1
protobuf: ^3.1.0
app_installer: ^1.3.1
device_info_plus: ^11.3.3
flutter_app_installer: ^1.0.0
dependency_overrides:
http: ^1.2.2