Skip to content

Commit 9654659

Browse files
authored
Add AndroidSdk.sdkManagerPath, sdkManagerVersion (flutter#14247)
Convenience getters for the the path to the Android SDK manager and the currently installed version of the tool. Pre-factoring to support better checks around the --android-licenses command, which uses a feature of the SDK manager that is unsupported in older versions of the tool.
1 parent 032de5f commit 9654659

File tree

3 files changed

+86
-8
lines changed

3 files changed

+86
-8
lines changed

packages/flutter_tools/lib/src/android/android_sdk.dart

+17
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:meta/meta.dart';
99
import '../base/common.dart';
1010
import '../base/context.dart';
1111
import '../base/file_system.dart';
12+
import '../base/io.dart' show ProcessResult;
1213
import '../base/os.dart';
1314
import '../base/platform.dart';
1415
import '../base/process_manager.dart';
@@ -285,6 +286,22 @@ class AndroidSdk {
285286
_latestVersion = _sdkVersions.isEmpty ? null : _sdkVersions.last;
286287
}
287288

289+
/// Returns the filesystem path of the Android SDK manager tool or null if not found.
290+
String get sdkManagerPath {
291+
return fs.path.join(directory, 'tools', 'bin', 'sdkmanager');
292+
}
293+
294+
/// Returns the version of the Android SDK manager tool or null if not found.
295+
String get sdkManagerVersion {
296+
if (!processManager.canRun(sdkManagerPath))
297+
throwToolExit('Android sdkmanager not found. Update to the latest Android SDK to resolve this.');
298+
final ProcessResult result = processManager.runSync(<String>[sdkManagerPath, '--version']);
299+
if (result.exitCode != 0) {
300+
throwToolExit('sdkmanager --version failed: ${result.exitCode}', exitCode: result.exitCode);
301+
}
302+
return result.stdout.trim();
303+
}
304+
288305
@override
289306
String toString() => 'AndroidSdk: $directory';
290307
}

packages/flutter_tools/lib/src/android/android_workflow.dart

+2-6
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,9 @@ class AndroidWorkflow extends DoctorValidator implements Workflow {
186186
fs.path.dirname(javaBinary) + os.pathVarSeparator + platform.environment['PATH'];
187187
}
188188

189-
final String sdkManagerPath = fs.path.join(
190-
androidSdk.directory, 'tools', 'bin',
191-
platform.isWindows ? 'sdkmanager.bat' : 'sdkmanager',
192-
);
193189
final Process process = await runCommand(
194-
<String>[sdkManagerPath, '--licenses'],
195-
environment: sdkManagerEnv,
190+
<String>[androidSdk.sdkManagerPath, '--licenses'],
191+
environment: sdkManagerEnv,
196192
);
197193

198194
waitGroup<Null>(<Future<Null>>[

packages/flutter_tools/test/android/android_sdk_test.dart

+67-2
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,25 @@
55
import 'package:file/memory.dart';
66
import 'package:flutter_tools/src/android/android_sdk.dart';
77
import 'package:flutter_tools/src/base/file_system.dart';
8+
import 'package:flutter_tools/src/base/io.dart' show ProcessResult;
89
import 'package:flutter_tools/src/base/platform.dart';
910
import 'package:flutter_tools/src/base/config.dart';
11+
import 'package:mockito/mockito.dart';
12+
import 'package:process/process.dart';
1013
import 'package:test/test.dart';
1114

15+
import '../src/common.dart';
1216
import '../src/context.dart';
1317

18+
class MockProcessManager extends Mock implements ProcessManager {}
19+
1420
void main() {
1521
MemoryFileSystem fs;
22+
MockProcessManager processManager;
1623

1724
setUp(() {
1825
fs = new MemoryFileSystem();
26+
processManager = new MockProcessManager();
1927
});
2028

2129
group('android_sdk AndroidSdk', () {
@@ -48,6 +56,56 @@ void main() {
4856
FileSystem: () => fs,
4957
});
5058

59+
testUsingContext('returns sdkmanager path', () {
60+
sdkDir = _createSdkDirectory();
61+
Config.instance.setValue('android-sdk', sdkDir.path);
62+
63+
final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
64+
expect(sdk.sdkManagerPath, fs.path.join(sdk.directory, 'tools', 'bin', 'sdkmanager'));
65+
}, overrides: <Type, Generator>{
66+
FileSystem: () => fs,
67+
});
68+
69+
testUsingContext('returns sdkmanager version', () {
70+
sdkDir = _createSdkDirectory();
71+
Config.instance.setValue('android-sdk', sdkDir.path);
72+
73+
final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
74+
when(processManager.canRun(sdk.sdkManagerPath)).thenReturn(true);
75+
when(processManager.runSync(<String>[sdk.sdkManagerPath, '--version']))
76+
.thenReturn(new ProcessResult(1, 0, '26.1.1\n', ''));
77+
expect(sdk.sdkManagerVersion, '26.1.1');
78+
}, overrides: <Type, Generator>{
79+
FileSystem: () => fs,
80+
ProcessManager: () => processManager,
81+
});
82+
83+
testUsingContext('throws on sdkmanager version check failure', () {
84+
sdkDir = _createSdkDirectory();
85+
Config.instance.setValue('android-sdk', sdkDir.path);
86+
87+
final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
88+
when(processManager.canRun(sdk.sdkManagerPath)).thenReturn(true);
89+
when(processManager.runSync(<String>[sdk.sdkManagerPath, '--version']))
90+
.thenReturn(new ProcessResult(1, 1, '26.1.1\n', 'Mystery error'));
91+
expect(() => sdk.sdkManagerVersion, throwsToolExit(exitCode: 1));
92+
}, overrides: <Type, Generator>{
93+
FileSystem: () => fs,
94+
ProcessManager: () => processManager,
95+
});
96+
97+
testUsingContext('throws on sdkmanager version check if sdkmanager not found', () {
98+
sdkDir = _createSdkDirectory(withSdkManager: false);
99+
Config.instance.setValue('android-sdk', sdkDir.path);
100+
101+
final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
102+
when(processManager.canRun(sdk.sdkManagerPath)).thenReturn(false);
103+
expect(() => sdk.sdkManagerVersion, throwsToolExit());
104+
}, overrides: <Type, Generator>{
105+
FileSystem: () => fs,
106+
ProcessManager: () => processManager,
107+
});
108+
51109
group('ndk', () {
52110
const <String, String>{
53111
'linux': 'linux-x86_64',
@@ -102,8 +160,12 @@ void main() {
102160
});
103161
}
104162

105-
Directory _createSdkDirectory(
106-
{bool withAndroidN: false, String withNdkDir, bool withNdkSysroot: false}) {
163+
Directory _createSdkDirectory({
164+
bool withAndroidN: false,
165+
String withNdkDir,
166+
bool withNdkSysroot: false,
167+
bool withSdkManager: true,
168+
}) {
107169
final Directory dir = fs.systemTempDirectory.createTempSync('android-sdk');
108170

109171
_createSdkFile(dir, 'platform-tools/adb');
@@ -121,6 +183,9 @@ Directory _createSdkDirectory(
121183
_createSdkFile(dir, 'platforms/android-N/build.prop', contents: _buildProp);
122184
}
123185

186+
if (withSdkManager)
187+
_createSdkFile(dir, 'tools/bin/sdkmanager');
188+
124189
if (withNdkDir != null) {
125190
final String ndkCompiler = fs.path.join(
126191
'ndk-bundle',

0 commit comments

Comments
 (0)