Skip to content

Commit

Permalink
UpdateChecker
Browse files Browse the repository at this point in the history
  • Loading branch information
jing332 committed Jan 16, 2024
1 parent e1f5435 commit a7d99e0
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ public interface Android {
@NonNull
Boolean isRunning();

@NonNull
String getDeviceCPUABI();

@NonNull
String getAListVersion();

Expand Down Expand Up @@ -386,6 +389,28 @@ static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable Android ap
Boolean output = api.isRunning();
wrapped.add(0, output);
}
catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.getDeviceCPUABI", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
try {
String output = api.getDeviceCPUABI();
wrapped.add(0, output);
}
catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.jing332.alistflutter.bridge

import android.content.Context
import android.content.Intent
import android.os.Build
import com.github.jing332.alistflutter.AListService
import com.github.jing332.alistflutter.BuildConfig
import com.github.jing332.alistflutter.R
Expand Down Expand Up @@ -36,9 +37,19 @@ class AndroidBridge(private val context: Context) : GeneratedApi.Android {
}

override fun isRunning() = AListService.isRunning

override fun getAListVersion() = BuildConfig.ALIST_VERSION
override fun getVersionName() = BuildConfig.VERSION_NAME


override fun getDeviceCPUABI(): String {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Build.SUPPORTED_ABIS[0]
} else {
android.os.Build.CPU_ABI
}
}

override fun getVersionName() = BuildConfig.VERSION_NAME
override fun getVersionCode() = BuildConfig.VERSION_CODE.toLong()


Expand Down
27 changes: 27 additions & 0 deletions lib/generated_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,33 @@ class Android {
}
}

Future<String> getDeviceCPUABI() async {
const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.getDeviceCPUABI';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList =
await __pigeon_channel.send(null) as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
throw PlatformException(
code: __pigeon_replyList[0]! as String,
message: __pigeon_replyList[1] as String?,
details: __pigeon_replyList[2],
);
} else if (__pigeon_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (__pigeon_replyList[0] as String?)!;
}
}

Future<String> getAListVersion() async {
const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.getAListVersion';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
Expand Down
27 changes: 27 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'package:alist_flutter/pages/alist/alist.dart';
import 'package:alist_flutter/pages/app_update_dialog.dart';
import 'package:alist_flutter/pages/settings/settings.dart';
import 'package:alist_flutter/pages/web/web.dart';
import 'package:alist_flutter/router.dart';
import 'package:alist_flutter/utils/UpdateChecker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Expand Down Expand Up @@ -76,6 +78,31 @@ class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 0;
final PageController _pageController = PageController();

@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final checker = UpdateChecker(owner: "jing332", repo: "AListFlutter");
await checker.downloadData();
final hasNewVersion = await checker.hasNewVersion();
if (hasNewVersion) {
showDialog(
context: context,
barrierDismissible: false,
barrierColor: Colors.black.withOpacity(0.5),
builder: (context) {
return AppUpdateDialog(
content: checker.getUpdateContent(),
apkUrl: checker.getApkDownloadUrl(),
htmlUrl: checker.getHtmlUrl(),
version: checker.getTag(),
);
});
}
});

}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand Down
51 changes: 51 additions & 0 deletions lib/pages/app_update_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'package:flutter/material.dart';

import '../utils/intent_utils.dart';

class AppUpdateDialog extends StatelessWidget {
final String content;
final String apkUrl;
final String htmlUrl;
final String version;

const AppUpdateDialog(
{super.key,
required this.content,
required this.apkUrl,
required this.version,
required this.htmlUrl});

@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text("发现新版本"),
content: Column(mainAxisSize: MainAxisSize.min, children: [
Text("v$version"),
Text(content),
]),
actions: <Widget>[
TextButton(
child: const Text('取消'),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: const Text('发布页面'),
onPressed: () {
Navigator.pop(context);
IntentUtils.getUrlIntent(htmlUrl).launchChooser("发布页面");
},
),
TextButton(
child: const Text('下载APK'),
onPressed: () {
Navigator.pop(context);
IntentUtils.getUrlIntent(apkUrl).launchChooser("下载APK");

},
),
],
);
}
}
10 changes: 4 additions & 6 deletions lib/pages/web/web.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:alist_flutter/generated_api.dart';
import 'package:alist_flutter/utils/intent_utils.dart';
import 'package:android_intent_plus/android_intent.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -85,17 +86,14 @@ class _WebScreenState extends State<WebScreen> {
mainButton: Column(children: [
TextButton(
onPressed: () {
final intent = AndroidIntent(
action: "action_view", data: url.url.toString());
intent.launchChooser("选择应用");
IntentUtils.getUrlIntent(url.url.toString())
.launchChooser("选择应用");
},
child: const Text('选择应用下载'),
),
TextButton(
onPressed: () {
final intent = AndroidIntent(
action: "action_view", data: url.url.toString());
intent.launch();
IntentUtils.getUrlIntent(url.url.toString()).launch();
},
child: const Text('下载'),
),
Expand Down
102 changes: 79 additions & 23 deletions lib/utils/UpdateChecker.dart
Original file line number Diff line number Diff line change
@@ -1,29 +1,85 @@
import 'dart:js_interop_unsafe';
import 'dart:convert';
import 'dart:core';
import 'dart:developer';
import 'dart:io';

import 'package:get/get_connect/http/src/response/response.dart';
import 'package:alist_flutter/generated_api.dart';

class UpdateChecker {
static Future<bool> checkForUpdate() async {
final version = Android().getVersion
final PackageInfo info = await PackageInfo.fromPlatform();
final String currentVersion = info.version;
final String url =
'https://raw.githubusercontent.com/iamSahdeep/liquid_swipe_flutter/master/pubspec.yaml';
try {
final http.Response response = await http.get(url);
if (response.statusCode == 200) {
final String body = response.body;
final List<String> list = body.split('\n');
final String latestVersion = list
.firstWhere((String element) => element.contains('version'))
.split(': ')[1];
if (currentVersion.compareTo(latestVersion) < 0) {
return true;
}
String owner;
String repo;

Map<String, dynamic>? _data;

UpdateChecker({required this.owner, required this.repo});

String _versionName = "";
String _systemABI = "";

downloadData() async {
_data = await _getLatestRelease(owner, repo);
_versionName = await Android().getVersionName();
_systemABI = await Android().getDeviceCPUABI();
}

Map<String, dynamic> get data {
if (_data == null) {
throw Exception('Data not downloaded');
}
return _data!;
}

static Future<Map<String, dynamic>> _getLatestRelease(
String owner, String repo) async {
HttpClient client = HttpClient();
final req = await client.getUrl(
Uri.parse('https://api.github.com/repos/$owner/$repo/releases/latest'));
final response = await req.close();

if (response.statusCode == HttpStatus.ok) {
final body = await response.transform(utf8.decoder).join();
return json.decode(body);
} else {
throw Exception(
'Failed to get latest release, status code: ${response.statusCode}');
}
}

String getTag() {
return data['tag_name'];
}

Future<bool> hasNewVersion() async {
final latestVersion = getTag();
final currentVersion = _versionName;

log('latestVersion: $latestVersion, currentVersion: $currentVersion');
// return true;
return _extractNumbers(latestVersion) > _extractNumbers(currentVersion);
}

String getApkDownloadUrl() {
final assets = data['assets'];
for (var asset in assets) {
if (asset['name'].contains(_systemABI)) {
return asset['browser_download_url'];
}
} catch (e) {
print(e);
}
return false;

throw Exception('Failed to get apk download url');
}

String getUpdateContent() {
return data['body'];
}

String getHtmlUrl() {
return data['html_url'];
}

// 1.24.011609 to Int
static int _extractNumbers(String input) {
final s = input.replaceAll(RegExp(r'[^0-9]'), '');
return int.parse(s);
}
}
}
7 changes: 7 additions & 0 deletions lib/utils/intent_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:android_intent_plus/android_intent.dart';

class IntentUtils {
static AndroidIntent getUrlIntent(String url) {
return AndroidIntent(action: "action_view", data: url);
}
}
3 changes: 2 additions & 1 deletion pigeons/pigeon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ abstract class Android {

bool isRunning();

String getDeviceCPUABI();

String getAListVersion();

String getVersionName();
Expand All @@ -38,7 +40,6 @@ abstract class Android {
void longToast(String msg);
}


@FlutterApi()
abstract class Event {
void onServiceStatusChanged(bool isRunning);
Expand Down
16 changes: 16 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.2"
http:
dependency: "direct main"
description:
name: http
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
url: "https://pub.dev"
source: hosted
version: "1.1.2"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
js:
dependency: transitive
description:
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ dependencies:
pigeon: ^16.0.0
flutter_inappwebview: ^6.0.0
android_intent_plus: ^4.0.3

http: ^1.1.2

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit a7d99e0

Please sign in to comment.