Skip to content

Commit

Permalink
Move adb check to DevicesPage
Browse files Browse the repository at this point in the history
Improve adb check
  • Loading branch information
Fernthedev committed Nov 23, 2023
1 parent 9137f59 commit 45e32ae
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 75 deletions.
7 changes: 1 addition & 6 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:desktop_adb_file_browser/pages/adb_check.dart';
import 'package:desktop_adb_file_browser/pages/browser.dart';
import 'package:desktop_adb_file_browser/pages/devices.dart';
import 'package:desktop_adb_file_browser/pages/logger.dart';
Expand All @@ -10,11 +9,7 @@ import 'package:flutter/services.dart';
import 'package:routemaster/routemaster.dart';

final routes = RouteMap(routes: {
'/': (_) => const MaterialPage(
key: ValueKey("adbcheck"),
child: ADBCheck(
redirectPage: '/devices',
)),
'/': (_) => const Redirect('/devices'),

'/devices': (_) =>
const MaterialPage(key: ValueKey("devices"), child: DevicesPage()),
Expand Down
114 changes: 74 additions & 40 deletions lib/pages/adb_check.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:desktop_adb_file_browser/utils/adb.dart';
import 'package:dio/dio.dart';
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:flutter/material.dart';
import 'package:routemaster/routemaster.dart';

class ADBCheck extends StatefulWidget {
const ADBCheck({super.key, required this.redirectPage});
Expand All @@ -16,23 +16,7 @@ class _ADBCheckState extends State<ADBCheck> {
@override
void initState() {
super.initState();
_showADBDownload(context);
}

Future<void> _showADBDownload(BuildContext context) async {
try {
await Adb.runAdbCommand(null, ["start-server"]);
} catch (e) {
if (context.mounted) {
await showDialog(
builder: (context) => const ADBDownloadDialog(),
context: context,
barrierDismissible: false,
);
}
}
if (!mounted) return;
Routemaster.of(context).replace(widget.redirectPage);
checkAndPromptADB(context);
}

@override
Expand All @@ -57,37 +41,87 @@ class _ADBDownloadDialogState extends State<ADBDownloadDialog> {
int? current;
int? total;
CancelToken cancelToken = CancelToken();
Error? _error;

@override
Widget build(BuildContext context) {
if (current == null || total == null) return _initialDownloadDialog();
if (current == null || total == null) return _promptDownloadState();
if (_error != null) return _errorState();

return _loadingState();
}

AlertDialog _loadingState() {
return AlertDialog(
title: const Text("Downloading ADB"),
content: LinearProgressIndicator(
value: current!.toDouble() / total!.toDouble(),
));
title: const Text("Downloading ADB"),
content: LinearProgressIndicator(
value: current!.toDouble() / total!.toDouble(),
),
);
}

Widget _initialDownloadDialog() {
Widget _promptDownloadState() {
return AlertDialog(
title: const Text("ADB not found"),
content: const Text("Do you want to download ABD?"),
actions: [
TextButton(
onPressed: () async {
await Adb.downloadADB((c, t) {
setState(() {
current = c;
total = t;
});
}, cancelToken);

if (!mounted) return;
Navigator.of(context, rootNavigator: true).pop();
},
child: const Text("Ok"))
],
content: const Text("Do you want to download ADB?"),
actions: [TextButton(onPressed: _download, child: const Text("Ok"))],
);
}

Widget _errorState() {
String messages = "Do you wish to continue anyways?";

if (_error != null) {
messages += "\nMessage: $_error";
}

return AlertDialog(
icon: const Icon(FluentIcons.error_circle_48_regular),
title: const Text("Suffered error downloading"),
content: Text(messages),
actions: [TextButton(onPressed: _continue, child: const Text("Ok"))],
);
}

void _download() async {
try {
await Adb.downloadADB((c, t) {
setState(() {
current = c;
total = t;
});
}, cancelToken);

if (!mounted) return;
_continue();
} catch (e) {
// ignore: avoid_print
print("Suffered error while downloading!\n$e");
if (e is Error) {
setState(() {
_error = e;
});
}
}
}

void _continue() {
Navigator.of(context).pop();
}
}

Future<void> checkAndPromptADB(BuildContext context) async {
try {
await Adb.runAdbCommand(null, ["start-server"]);
} catch (e) {
if (!context.mounted) {
return;
}

await showDialog(
builder: (context) => const ADBDownloadDialog(),
context: context,
barrierDismissible: false,
);
}
}
19 changes: 14 additions & 5 deletions lib/pages/devices.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:desktop_adb_file_browser/pages/adb_check.dart';
import 'package:desktop_adb_file_browser/utils/adb.dart';
import 'package:desktop_adb_file_browser/widgets/device_card.dart';
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
Expand All @@ -14,11 +15,20 @@ class DevicesPage extends StatefulWidget {
}

class _DevicesPageState extends State<DevicesPage> {
Future<List<Device>> _deviceListFuture = Adb.getDevices();
//Future.delayed(const Duration(seconds: 2), Adb.getDevices);
Future<List<Device>>? _deviceListFuture;

@override
void initState() {
super.initState();

// Check if ADB is installed
checkAndPromptADB(context).then((value) => _refreshDevices());
}

void _refreshDevices() {
_deviceListFuture = Adb.getDevices();
setState(() {
_deviceListFuture = Adb.getDevices();
});
}

@override
Expand Down Expand Up @@ -49,7 +59,6 @@ class _DevicesPageState extends State<DevicesPage> {
floatingActionButton: FloatingActionButton(
onPressed: () {
_refreshDevices();
setState(() {});
},
tooltip: 'Refresh',
// TODO: Animate easeInOut spin
Expand Down Expand Up @@ -111,7 +120,7 @@ class _DevicesPageState extends State<DevicesPage> {

await showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
barrierDismissible: true,
builder: (BuildContext context) => WirelessConnectDialog(
ipController: ipController, portController: portController),
);
Expand Down
63 changes: 39 additions & 24 deletions lib/utils/adb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,8 @@ abstract class Adb {
"https://dl.google.com/android/repository/platform-tools-latest-";

static const String _adbTempFolder = "adb-platform-tools";

static String? _adbCurrentPath;

static Future<Directory> _getDownloadPath() async {
try {
return Directory(hostPath.join(
(await getApplicationSupportDirectory()).path, _adbTempFolder));
} on MissingPlatformDirectoryException catch (_) {
} on UnimplementedError catch (_) {}

return Directory(
hostPath.join(await PlatformUtils.configPath(_adbTempFolder)));
}

static Future<File> _getADBDownloadPath() async {
var downloadPath = await _getDownloadPath();
return File(hostPath.join(downloadPath.path, "platform-tools", "adb"));
}

static Future<void> downloadADB(
DownloadProgressCallback c, CancelToken cancelToken) async {
Expand Down Expand Up @@ -67,26 +51,52 @@ abstract class Adb {
final archive = ZipDecoder().decodeBuffer(InputStream(stream));

extractArchiveToDisk(archive, downloadPath.path);
_adbCurrentPath = (await _getADBDownloadPath()).path;
_adbCurrentPath = (await _getADBInstalledExecPath()).path;
await Process.run("chmod", ["+x", _adbCurrentPath!]);
}

static Future<String> _getAdbPath() async {

static Future<Directory> _getDownloadPath() async {
try {
return Directory(hostPath.join(
(await getApplicationSupportDirectory()).path, _adbTempFolder));
} on MissingPlatformDirectoryException catch (_) {
} on UnimplementedError catch (_) {}

return Directory(
hostPath.join(await PlatformUtils.configPath(_adbTempFolder)));
}

static Future<File> _getADBInstalledExecPath() async {
var downloadPath = await _getDownloadPath();

var adbExecName = Platform.isWindows ? "adb.exe" : "adb";

var adbFile =
File(hostPath.join(downloadPath.path, "platform-tools", adbExecName));

return adbFile;
}

static Future<String> _locateAdbPath() async {
if (_adbCurrentPath != null) {
return _adbCurrentPath!;
}

var downloadPath = await _getDownloadPath();
var downloadPath = await _getADBInstalledExecPath();
if (await downloadPath.exists()) {
_adbCurrentPath = (await _getADBDownloadPath()).path;
_adbCurrentPath = downloadPath.path;
} else if (Platform.isWindows) {
// Use adb in path
_adbCurrentPath = "adb.exe";
} else {
// Use adb in path

_adbCurrentPath = "adb";
}

// ignore: avoid_print
print("Using adb in $_adbCurrentPath");

return _adbCurrentPath!;
}
Expand All @@ -95,8 +105,12 @@ abstract class Adb {
String? serial, List<String> args) async {
var newArgs = serial != null ? ["-s", serial, ...args] : args;

var process =
await Process.run(await _getAdbPath(), newArgs, runInShell: true);
var adbPath = await _locateAdbPath();

// ignore: avoid_print
print("Running adb command: \"$adbPath ${newArgs.join(" ")}\"");

var process = await Process.run(adbPath, newArgs, runInShell: true);
if (process.stderr != null && process.stderr.toString().isNotEmpty) {
final error = process.stderr;
debugPrint("Error $error");
Expand All @@ -113,7 +127,8 @@ abstract class Adb {
String? serial, List<String> args) async {
var newArgs = serial != null ? ["-s", serial, ...args] : args;

return await Process.start(await _getAdbPath(), newArgs, runInShell: true);
return await Process.start(await _locateAdbPath(), newArgs,
runInShell: true);
}

static String normalizeOutput(String output) {
Expand Down

0 comments on commit 45e32ae

Please sign in to comment.