Skip to content

Commit a1810f6

Browse files
committed
Added auto-updater to example application
Former-commit-id: 93d0712617f66bb1251526122330a3bd1893ca4a [formerly 4243932] Former-commit-id: 4ed374d9669f1c2fc477678528bc6a71f88da30c
1 parent 30ab2bd commit a1810f6

File tree

8 files changed

+269
-4
lines changed

8 files changed

+269
-4
lines changed

example/lib/main.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import 'dart:io';
2+
13
import 'package:flutter/material.dart';
24
import 'package:flutter/services.dart';
35
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
46
import 'package:google_fonts/google_fonts.dart';
7+
import 'package:path/path.dart' as p;
58
import 'package:provider/provider.dart';
69
import 'package:shared_preferences/shared_preferences.dart';
710

@@ -57,6 +60,14 @@ void main() async {
5760
);
5861
}
5962

63+
final File newAppVersionFile = File(
64+
p.join(
65+
FMTC.instance.rootDirectory.access.real.path,
66+
'newAppVersion.${Platform.isWindows ? 'exe' : 'apk'}',
67+
),
68+
);
69+
if (await newAppVersionFile.exists()) await newAppVersionFile.delete();
70+
6071
runApp(const AppContainer());
6172
}
6273

example/lib/screens/main/main.dart

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:io';
2+
13
import 'package:badges/badges.dart';
24
import 'package:flutter/material.dart';
35
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
@@ -10,6 +12,7 @@ import 'pages/map/map_view.dart';
1012
import 'pages/recovery/recovery.dart';
1113
import 'pages/settingsAndAbout/settings_and_about.dart';
1214
import 'pages/stores/stores.dart';
15+
import 'pages/update/update.dart';
1316

1417
class MainScreen extends StatefulWidget {
1518
const MainScreen({Key? key}) : super(key: key);
@@ -56,8 +59,13 @@ class _MainScreenState extends State<MainScreen> {
5659
),
5760
const NavigationDestination(
5861
icon: Icon(Icons.settings),
59-
label: 'Settings',
62+
label: 'Settings & About',
6063
),
64+
if (Platform.isWindows || Platform.isAndroid)
65+
const NavigationDestination(
66+
icon: Icon(Icons.system_update_alt),
67+
label: 'Update App',
68+
),
6169
];
6270

6371
List<Widget> get _pages => [
@@ -70,6 +78,7 @@ class _MainScreenState extends State<MainScreen> {
7078
),
7179
RecoveryPage(moveToDownloadPage: () => _onDestinationSelected(2)),
7280
const SettingsAndAboutPage(),
81+
if (Platform.isWindows || Platform.isAndroid) const UpdatePage(),
7382
];
7483

7584
void _onDestinationSelected(int index) {
@@ -105,9 +114,9 @@ class _MainScreenState extends State<MainScreen> {
105114
onDestinationSelected: _onDestinationSelected,
106115
selectedIndex: _currentPageIndex,
107116
destinations: _destinations,
108-
labelBehavior: MediaQuery.of(context).size.width > 450
117+
labelBehavior: MediaQuery.of(context).size.width > 650
109118
? null
110-
: NavigationDestinationLabelBehavior.onlyShowSelected,
119+
: NavigationDestinationLabelBehavior.alwaysHide,
111120
),
112121
body: Row(
113122
children: [
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:flutter/material.dart';
2+
3+
class FailedToCheck extends StatelessWidget {
4+
const FailedToCheck({
5+
Key? key,
6+
}) : super(key: key);
7+
8+
@override
9+
Widget build(BuildContext context) => Center(
10+
child: Column(
11+
mainAxisAlignment: MainAxisAlignment.center,
12+
children: const [
13+
Icon(
14+
Icons.error,
15+
size: 38,
16+
color: Colors.red,
17+
),
18+
SizedBox(height: 10),
19+
Text(
20+
'Failed To Check For Updates',
21+
textAlign: TextAlign.center,
22+
),
23+
],
24+
),
25+
);
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:google_fonts/google_fonts.dart';
3+
4+
class Header extends StatelessWidget {
5+
const Header({
6+
Key? key,
7+
required this.title,
8+
}) : super(key: key);
9+
10+
final String title;
11+
12+
@override
13+
Widget build(BuildContext context) => Text(
14+
title,
15+
style: GoogleFonts.openSans(
16+
fontWeight: FontWeight.bold,
17+
fontSize: 24,
18+
),
19+
);
20+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'package:flutter/material.dart';
2+
3+
class UpToDate extends StatelessWidget {
4+
const UpToDate({
5+
Key? key,
6+
}) : super(key: key);
7+
8+
@override
9+
Widget build(BuildContext context) => Center(
10+
child: Column(
11+
mainAxisAlignment: MainAxisAlignment.center,
12+
children: const [
13+
Icon(
14+
Icons.done,
15+
size: 38,
16+
),
17+
SizedBox(height: 10),
18+
Text(
19+
'Up To Date',
20+
textAlign: TextAlign.center,
21+
),
22+
],
23+
),
24+
);
25+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:google_fonts/google_fonts.dart';
3+
4+
Center buildUpdateAvailableWidget({
5+
required BuildContext context,
6+
required String availableVersion,
7+
required String currentVersion,
8+
required void Function() updateApplication,
9+
}) =>
10+
Center(
11+
child: Flex(
12+
mainAxisAlignment: MainAxisAlignment.center,
13+
direction: MediaQuery.of(context).size.width < 400
14+
? Axis.vertical
15+
: Axis.horizontal,
16+
children: [
17+
Column(
18+
mainAxisAlignment: MainAxisAlignment.center,
19+
children: [
20+
Text(
21+
'New Version Available!',
22+
style: GoogleFonts.openSans(
23+
fontWeight: FontWeight.bold,
24+
fontSize: 24,
25+
),
26+
textAlign: TextAlign.center,
27+
),
28+
Text(
29+
'$availableVersion > $currentVersion',
30+
style: const TextStyle(fontSize: 20),
31+
),
32+
],
33+
),
34+
const SizedBox(
35+
width: 30,
36+
height: 12,
37+
),
38+
IconButton(
39+
iconSize: 38,
40+
icon: const Icon(
41+
Icons.download,
42+
color: Colors.green,
43+
),
44+
onPressed: updateApplication,
45+
),
46+
],
47+
),
48+
);
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import 'dart:io';
2+
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter/services.dart' show rootBundle;
5+
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
6+
import 'package:http/http.dart' as http;
7+
import 'package:open_file/open_file.dart';
8+
import 'package:path/path.dart' as p;
9+
import 'package:version/version.dart';
10+
11+
import '../../../../shared/components/loading_indicator.dart';
12+
import 'components/failed_to_check.dart';
13+
import 'components/header.dart';
14+
import 'components/up_to_date.dart';
15+
import 'components/update_available.dart';
16+
17+
class UpdatePage extends StatefulWidget {
18+
const UpdatePage({Key? key}) : super(key: key);
19+
20+
@override
21+
State<UpdatePage> createState() => _UpdatePageState();
22+
}
23+
24+
class _UpdatePageState extends State<UpdatePage> {
25+
static const String versionURL =
26+
'https://raw.githubusercontent.com/JaffaKetchup/flutter_map_tile_caching/main/example/currentAppVersion.txt';
27+
static const String windowsURL =
28+
'https://github.com/JaffaKetchup/flutter_map_tile_caching/blob/main/prebuiltExampleApplications/WindowsApplication.exe?raw=true';
29+
static const String androidURL =
30+
'https://github.com/JaffaKetchup/flutter_map_tile_caching/blob/main/prebuiltExampleApplications/AndroidApplication.apk?raw=true';
31+
32+
bool updating = false;
33+
34+
Future<void> updateApplication() async {
35+
setState(() => updating = true);
36+
37+
final http.Response response = await http.get(
38+
Uri.parse(Platform.isWindows ? windowsURL : androidURL),
39+
);
40+
final File file = File(
41+
p.join(
42+
FMTC.instance.rootDirectory.access.real.path,
43+
'newAppVersion.${Platform.isWindows ? 'exe' : 'apk'}',
44+
),
45+
);
46+
47+
await file.create();
48+
await file.writeAsBytes(response.bodyBytes);
49+
50+
if (Platform.isWindows) {
51+
await Process.start(file.absolute.path, []);
52+
} else {
53+
await OpenFile.open(file.absolute.path);
54+
}
55+
56+
exit(0);
57+
}
58+
59+
@override
60+
Widget build(BuildContext context) => Scaffold(
61+
body: SafeArea(
62+
child: Padding(
63+
padding: const EdgeInsets.all(12),
64+
child: Column(
65+
crossAxisAlignment: CrossAxisAlignment.start,
66+
children: [
67+
const Header(title: 'Update App'),
68+
const SizedBox(height: 12),
69+
Expanded(
70+
child: updating
71+
? const LoadingIndicator(
72+
message:
73+
'Downloading New Application Installer...\nWill automatically exit application and run installer once downloaded',
74+
)
75+
: FutureBuilder<String>(
76+
future: rootBundle.loadString(
77+
'currentAppVersion.txt',
78+
cache: false,
79+
),
80+
builder: (context, currentVersion) => currentVersion
81+
.hasData
82+
? FutureBuilder<String>(
83+
future: http.read(Uri.parse(versionURL)),
84+
builder: (context, availableVersion) =>
85+
availableVersion.hasError
86+
? const FailedToCheck()
87+
: availableVersion.hasData
88+
? Version.parse(
89+
availableVersion.data!
90+
.trim(),
91+
) >
92+
Version.parse(
93+
currentVersion.data!
94+
.trim(),
95+
)
96+
? buildUpdateAvailableWidget(
97+
context: context,
98+
availableVersion:
99+
availableVersion.data!
100+
.trim(),
101+
currentVersion:
102+
currentVersion.data!
103+
.trim(),
104+
updateApplication:
105+
updateApplication,
106+
)
107+
: const UpToDate()
108+
: const LoadingIndicator(
109+
message:
110+
'Checking For Updates...',
111+
),
112+
)
113+
: const LoadingIndicator(
114+
message: 'Loading App Version Information...',
115+
),
116+
),
117+
),
118+
],
119+
),
120+
),
121+
),
122+
);
123+
}

example/pubspec.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ dependencies:
2222
http: ^0.13.4
2323
intl: ^0.17.0
2424
latlong2: ^0.8.1
25+
open_file: ^3.2.1
2526
osm_nominatim: ^2.0.1
27+
path: ^1.8.1
2628
provider: ^6.0.3
2729
shared_preferences: ^2.0.15
2830
stream_transform: ^2.0.0
2931
validators: ^3.0.0
32+
version: ^3.0.2
3033

3134
dev_dependencies:
32-
flutter_app_name: ^0.1.0
3335
flutter_launcher_icons: ^0.10.0
3436
flutter_test:
3537
sdk: flutter
@@ -46,3 +48,4 @@ flutter:
4648
uses-material-design: true
4749
assets:
4850
- assets/icons/
51+
- currentAppVersion.txt

0 commit comments

Comments
 (0)