-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathAndroidSdkInfo.cs
More file actions
248 lines (206 loc) · 7.62 KB
/
AndroidSdkInfo.cs
File metadata and controls
248 lines (206 loc) · 7.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace Xamarin.Android.Tools
{
public class AndroidSdkInfo
{
AndroidSdkBase sdk;
public AndroidSdkInfo (Action<TraceLevel, string>? logger = null, string? androidSdkPath = null, string? androidNdkPath = null, string? javaSdkPath = null)
{
logger = logger ?? DefaultConsoleLogger;
sdk = CreateSdk (logger);
sdk.Initialize (androidSdkPath, androidNdkPath, javaSdkPath);
// shouldn't happen, in that sdk.Initialize() should throw instead
if (string.IsNullOrEmpty (AndroidSdkPath))
throw new InvalidOperationException ($"Could not determine Android SDK location. Please provide `{nameof (androidSdkPath)}`.");
if (string.IsNullOrEmpty (JavaSdkPath))
throw new InvalidOperationException ($"Could not determine Java SDK location. Please provide `{nameof (javaSdkPath)}`.");
}
static AndroidSdkBase CreateSdk (Action<TraceLevel, string> logger)
{
return OS.IsWindows
? (AndroidSdkBase) new AndroidSdkWindows (logger)
: (AndroidSdkBase) new AndroidSdkUnix (logger);
}
public IEnumerable<string> GetBuildToolsPaths (string preferredBuildToolsVersion)
{
if (!string.IsNullOrEmpty (preferredBuildToolsVersion)) {
var preferredDir = Path.Combine (AndroidSdkPath, "build-tools", preferredBuildToolsVersion);
if (Directory.Exists (preferredDir))
return new[] { preferredDir }.Concat (GetBuildToolsPaths ().Where (p => p!= preferredDir));
}
return GetBuildToolsPaths ();
}
public IEnumerable<string> GetBuildToolsPaths ()
{
var buildTools = Path.Combine (AndroidSdkPath, "build-tools");
if (Directory.Exists (buildTools)) {
var sorted = SortedSubdirectoriesByVersion (buildTools);
foreach (var d in sorted)
yield return d;
var preview = Directory.EnumerateDirectories (buildTools)
.Where(x => TryParseVersion (Path.GetFileName (x)) == null)
.Select(x => x);
foreach (var d in preview)
yield return d;
}
var ptPath = Path.Combine (AndroidSdkPath, "platform-tools");
if (Directory.Exists (ptPath))
yield return ptPath;
}
static IEnumerable<string> SortedSubdirectoriesByVersion (string dir)
{
return from p in Directory.EnumerateDirectories (dir)
let version = TryParseVersion (Path.GetFileName (p))
where version != null
orderby version descending
select p;
}
static Version? TryParseVersion (string v)
{
if (Version.TryParse (v, out var version))
return version;
return null;
}
public IEnumerable<AndroidVersion> GetInstalledPlatformVersions (AndroidVersions versions)
{
if (versions == null)
throw new ArgumentNullException (nameof (versions));
return versions.InstalledBindingVersions
.Where (p => TryGetPlatformDirectoryFromApiLevel (p.Id, versions) != null) ;
}
public string GetPlatformDirectory (int apiLevel)
{
return GetPlatformDirectoryFromId (apiLevel.ToString ());
}
public string GetPlatformDirectoryFromId (string id)
{
return Path.Combine (AndroidSdkPath, "platforms", "android-" + id);
}
public string? TryGetPlatformDirectoryFromApiLevel (string idOrApiLevel, AndroidVersions versions)
{
var id = versions.GetIdFromApiLevel (idOrApiLevel);
if (id == null)
return null;
string? dir = GetPlatformDirectoryFromId (id);
if (Directory.Exists (dir))
return dir;
// Only fall back to major API level if we weren't explicitly requesting a minor version.
// For example, if "36.1" was requested but android-36.1 doesn't exist, don't fall back to android-36
// because the minor version may have APIs that the major version doesn't have.
// See: https://github.com/dotnet/android/issues/10720
if (Version.TryParse (id, out var version) && version.Minor != 0) {
return null;
}
var level = versions.GetApiLevelFromId (id);
dir = level.HasValue ? GetPlatformDirectory (level.Value) : null;
if (dir != null && Directory.Exists (dir))
return dir;
// Starting with API 37, Google's SDK Manager installs platforms to
// "android-37.0" instead of "android-37". Try the "{major}.0" fallback.
// See: https://github.com/dotnet/android-tools/issues/319
if (int.TryParse (id, out _)) {
dir = GetPlatformDirectoryFromId (id + ".0");
if (Directory.Exists (dir))
return dir;
}
return null;
}
public bool IsPlatformInstalled (int apiLevel)
{
return apiLevel != 0 && Directory.Exists (GetPlatformDirectory (apiLevel));
}
public string? AndroidNdkPath {
get { return sdk.AndroidNdkPath; }
}
public string AndroidSdkPath {
get { return sdk.AndroidSdkPath!; }
}
public string [] AllAndroidSdkPaths {
get {
return sdk.AllAndroidSdks ?? new string [0];
}
}
public string JavaSdkPath {
get { return sdk.JavaSdkPath!; }
}
public string AndroidNdkHostPlatform {
get { return sdk.NdkHostPlatform; }
}
public static void SetPreferredAndroidNdkPath (string path, Action<TraceLevel, string>? logger = null)
{
logger = logger ?? DefaultConsoleLogger;
var sdk = CreateSdk (logger);
sdk.SetPreferredAndroidNdkPath(path);
}
internal static void DefaultConsoleLogger (TraceLevel level, string message)
{
switch (level) {
case TraceLevel.Error:
Console.Error.WriteLine (message);
break;
default:
Console.WriteLine ($"[{level}] {message}");
break;
}
}
public static void SetPreferredAndroidSdkPath (string path, Action<TraceLevel, string>? logger = null)
{
logger = logger ?? DefaultConsoleLogger;
var sdk = CreateSdk (logger);
sdk.SetPreferredAndroidSdkPath (path);
}
public static void SetPreferredJavaSdkPath (string path, Action<TraceLevel, string>? logger = null)
{
logger = logger ?? DefaultConsoleLogger;
var sdk = CreateSdk (logger);
sdk.SetPreferredJavaSdkPath (path);
}
public static void DetectAndSetPreferredJavaSdkPathToLatest (Action<TraceLevel, string>? logger = null)
{
if (OS.IsWindows)
throw new NotImplementedException ("Windows is not supported at this time.");
logger = logger ?? DefaultConsoleLogger;
var latestJdk = JdkInfo.GetSupportedJdkInfos (logger).FirstOrDefault ();
if (latestJdk == null)
throw new NotSupportedException ("No Microsoft OpenJDK could be found. Please re-run the Visual Studio installer or manually specify the JDK path in settings.");
var sdk = CreateSdk (logger);
sdk.SetPreferredJavaSdkPath (latestJdk.HomePath);
}
public string? TryGetCommandLineToolsPath ()
{
return GetCommandLineToolsPaths ("latest").FirstOrDefault ();
}
public IEnumerable<string> GetCommandLineToolsPaths (string preferredCommandLineToolsVersion)
{
if (!string.IsNullOrEmpty (preferredCommandLineToolsVersion)) {
var preferredDir = Path.Combine (AndroidSdkPath, "cmdline-tools", preferredCommandLineToolsVersion);
if (Directory.Exists (preferredDir))
return new[] { preferredDir }.Concat (GetCommandLineToolsPaths ().Where (p => p != preferredDir));
}
return GetCommandLineToolsPaths ();
}
public IEnumerable<string> GetCommandLineToolsPaths ()
{
var cmdlineToolsDir = Path.Combine (AndroidSdkPath, "cmdline-tools");
if (Directory.Exists (cmdlineToolsDir)) {
var latestDir = Path.Combine (cmdlineToolsDir, "latest");
if (Directory.Exists (latestDir))
yield return latestDir;
foreach (var d in SortedSubdirectoriesByVersion (cmdlineToolsDir)) {
var version = Path.GetFileName (d);
if (version == "latest")
continue;
yield return d;
}
}
var toolsDir = Path.Combine (AndroidSdkPath, "tools");
if (Directory.Exists (toolsDir)) {
yield return toolsDir;
}
}
}
}