Skip to content

Commit aad97f1

Browse files
committed
Add AndroidVersions
Commit [xamarin-android/8e7d37bb][xa8e] contains a sign of duplication: in order to use a `Mono.Android.dll` binding assembly, not only do we need to *build* the binding assembly, but we *also* need to update `Xamarin.Android.Build.Utilities.dll`/etc. to "know" about the new binding version (to map API level to `$(TargetFrameworkVersion)`). [xa8e]: dotnet/android@8e7d37bb Even "better" (worse), if the new API level is a *preview*, there is no *consistent* API level. For example, with API-O, `android.jar` isn't at: $(AndroidSdkDirectory)\platforms\android-@API_LEVEL@\android.jar where `@API_LEVEL@` is 26 (because various codepaths require that the "api level" be an integer). Instead, it's installed at: $(AndroidSdkDirectory)\platforms\android-O\android.jar where `O` is the "id" of the preview API level. This "id" is "leaky", in turn requiring that `Xamarin.Android.Build.Tasks.dll` *also* be updated to deal with the mappings. Even "better" (worse), if we *forget* to cross all our our 't's and dot all of our 'i's, we'll have a binding assembly which can't be used. (Which is why we needed [xamarin-android/8e7d37bb][xe8e]; without it, the API-O binding can't be used!) This is all obviously madness. ;-) [xamarin-android/8942eca0][xa89] contains a fix: [xa89]: dotnet/android@8942eca 1. The build system is updated to create a new `AndroidApiInfo.xml` file within the `$(TargetFrameworkVersion)` directory. This contains all the information needed to map Android API levels to Ids and Android OS versions and `$(TargetFrameworkVersion)` values: ```xml <AndroidApiInfo> <Id>10</Id> <Level>10</Level> <Name>Gingerbread</Name> <Version>v2.3</Version> </AndroidApiInfo> ``` 2. Add a new `Xamarin.Android.Build.Utilities.AndroidVersions` type was added which parses the `AndroidApiInfo.xml` files. The advantage to all this is that we can support new API level bindings by just building a new `Mono.Android.dll` and placing an `AndroidApiInfo.xml` into the appropriate location (next to `Mono.Android.dll`). No further code changes would be required. This is all well and good...but it's not entirely useful if *only* Xamarin.Android makes use of this functionality. The IDEs also need to be updated to make use of these files. Copy over `Xamarin.Android.Build.Utilities.AndroidVersions` into the **xamarin-android-tools** repo as `Xamarin.Android.Tools.AndroidVersions`, so that we have a path for eventual IDE support of the new paradigm.
1 parent e875d77 commit aad97f1

File tree

8 files changed

+548
-110
lines changed

8 files changed

+548
-110
lines changed

src/Xamarin.Android.Tools.AndroidSdk/AndroidSdk.cs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,7 @@ public static void Refresh (string androidSdkPath = null, string androidNdkPath
2020
sdk.Initialize (androidSdkPath ?? sdk.PreferedAndroidSdkPath, androidNdkPath ?? sdk.PreferedAndroidNdkPath,
2121
javaSdkPath ?? sdk.PreferedJavaSdkPath);
2222
if (IsInstalled) {
23-
var levels = GetInstalledPlatformVersions ().Select (l => l.ApiLevel.ToString ()).ToArray ();
24-
string levelList;
25-
if (levels == null || levels.Length == 0)
26-
levelList = "(none)";
27-
else
28-
levelList = string.Join (", ", levels);
29-
AndroidLogger.LogInfo (null, "Found Android SDK. API levels: {0}", levelList);
23+
AndroidLogger.LogInfo (null, "Found Android SDK.");
3024
} else {
3125
AndroidLogger.LogInfo (null, "Did not find Android SDK");
3226
}
@@ -80,13 +74,6 @@ static Version TryParseVersion (string v)
8074
return null;
8175
}
8276

83-
// it was useful when android-21 was android-L, or android-23 was android-MNC.
84-
// We will use this when similar preview release is out.
85-
static string ToApiName (int apiLevel)
86-
{
87-
return apiLevel.ToString ();
88-
}
89-
9077
static string ValidatePath (string path)
9178
{
9279
if (String.IsNullOrEmpty (path))
@@ -96,30 +83,33 @@ static string ValidatePath (string path)
9683

9784
public static string GetPlatformDirectory (int apiLevel)
9885
{
99-
return Path.Combine (AndroidSdkPath, "platforms", "android-" + ToApiName (apiLevel));
86+
return GetPlatformDirectoryFromId (apiLevel.ToString ());
10087
}
10188

102-
public static string GetPlatformDirectory (string osVersion)
89+
public static string GetPlatformDirectoryFromId (string id)
10390
{
104-
var level = AndroidVersion.TryOSVersionToApiLevel (osVersion);
105-
if (level == 0)
106-
return null;
107-
return GetPlatformDirectory (level);
91+
return Path.Combine (AndroidSdkPath, "platforms", "android-" + id);
10892
}
10993

110-
public static bool IsPlatformInstalled (int apiLevel)
94+
public static string TryGetPlatformDirectoryFromApiLevel (string apiLevel, AndroidVersions versions)
11195
{
112-
return apiLevel != 0 && Directory.Exists (GetPlatformDirectory (apiLevel));
96+
var id = versions.GetIdFromApiLevel (apiLevel);
97+
var dir = GetPlatformDirectoryFromId (id);
98+
99+
if (Directory.Exists (dir))
100+
return dir;
101+
102+
var level = versions.GetApiLevelFromId (id);
103+
dir = level.HasValue ? GetPlatformDirectory (level.Value) : null;
104+
if (dir != null && Directory.Exists (dir))
105+
return dir;
106+
107+
return null;
113108
}
114109

115-
public static IEnumerable<AndroidVersion> GetInstalledPlatformVersions ()
110+
public static bool IsPlatformInstalled (int apiLevel)
116111
{
117-
var knownAndInstalledSdkLevels = AndroidVersion.KnownVersions.Where (v => IsPlatformInstalled (v.ApiLevel));
118-
119-
return knownAndInstalledSdkLevels.Where (version => {
120-
var apiLevel = MonoDroidSdk.GetApiLevelForFrameworkVersion (version.OSVersion);
121-
return MonoDroidSdk.IsSupportedFrameworkLevel (apiLevel);
122-
});
112+
return apiLevel != 0 && Directory.Exists (GetPlatformDirectory (apiLevel));
123113
}
124114

125115
public static bool IsInstalled {
Lines changed: 55 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,84 @@
11
using System;
2+
using System.IO;
3+
using System.Xml.Linq;
24

35
namespace Xamarin.Android.Tools
46
{
57
public class AndroidVersion
68
{
7-
public static readonly int MaxApiLevel = 24;
9+
// Android API Level. *Usually* corresponds to $(AndroidSdkPath)/platforms/android-$(ApiLevel)/android.jar
10+
public int ApiLevel { get; private set; }
811

9-
public AndroidVersion (int apilevel, string osVersion)
10-
{
11-
this.ApiLevel = apilevel;
12-
this.OSVersion = osVersion;
13-
}
12+
// Android API Level ID. == ApiLevel on stable versions, will be e.g. `N` for previews: $(AndroidSdkPath)/platforms/android-N/android.jar
13+
public string Id { get; private set; }
1414

15-
AndroidVersion (int apilevel, string osVersion, string codeName, Version version)
16-
{
17-
this.ApiLevel = apilevel;
18-
// TODO: remove osVersion from parameter list and generate from version
19-
this.OSVersion = osVersion;
20-
this.CodeName = codeName;
21-
this.Version = version;
22-
}
15+
// Name of an Android release, e.g. "Oreo"
16+
public string CodeName { get; private set; }
2317

24-
public int ApiLevel { get; private set; }
25-
public string OSVersion { get; private set; }
26-
public string CodeName { get; private set; }
27-
public Version Version { get; private set; }
18+
// Android version number, e.g. 8.0
19+
public string OSVersion { get; private set; }
2820

29-
public static int OSVersionToApiLevel (string osVersion)
30-
{
31-
int ret = TryOSVersionToApiLevel (osVersion);
32-
if (ret == 0)
33-
throw new ArgumentOutOfRangeException ("OS version not recognized: " + osVersion);
34-
return ret;
35-
}
21+
// Xamarin.Android $(TargetFrameworkVersion) value, e.g. 8.0
22+
public Version TargetFrameworkVersion { get; private set; }
3623

37-
public static int TryOSVersionToApiLevel (string frameworkVersion)
24+
// TargetFrameworkVersion *with* a leading `v`, e.g. "v8.0"
25+
public string FrameworkVersion { get; private set; }
26+
27+
// Is this API level stable? Should be False for non-numeric Id values.
28+
public bool Stable { get; private set; }
29+
30+
// Alternate Ids for a given API level. Allows for historical mapping, e.g. API-11 has alternate ID 'H'.
31+
internal string[] AlternateIds { get; set; }
32+
33+
public AndroidVersion (int apiLevel, string osVersion, string codeName = null, string id = null, bool stable = true)
3834
{
39-
// Use MonoDroidSdk.GetApiLevelForFrameworkVersion because that will translate XA versions >= 5.xx to the correct api level
40-
var apiLevelText = MonoDroidSdk.GetApiLevelForFrameworkVersion (frameworkVersion);
41-
int apiLevel;
42-
int.TryParse (apiLevelText, out apiLevel);
43-
return apiLevel;
35+
if (osVersion == null)
36+
throw new ArgumentNullException (nameof (osVersion));
37+
38+
ApiLevel = apiLevel;
39+
Id = id ?? ApiLevel.ToString ();
40+
CodeName = codeName;
41+
OSVersion = osVersion;
42+
TargetFrameworkVersion = Version.Parse (osVersion);
43+
FrameworkVersion = "v" + osVersion;
44+
Stable = stable;
4445
}
4546

46-
public static string ApiLevelToOSVersion (int apiLevel)
47+
public override string ToString ()
4748
{
48-
string ret = TryApiLevelToOSVersion (apiLevel);
49-
if (ret == null)
50-
throw new ArgumentOutOfRangeException ("API level not recognized: " + apiLevel);
51-
return ret;
49+
return $"(AndroidVersion: ApiLevel={ApiLevel} Id={Id} OSVersion={OSVersion} CodeName='{CodeName}' TargetFrameworkVersion={TargetFrameworkVersion} Stable={Stable})";
5250
}
5351

54-
public static string TryApiLevelToOSVersion (int apiLevel)
52+
public static AndroidVersion Load (Stream stream)
5553
{
56-
var osVersion = MonoDroidSdk.GetFrameworkVersionForApiLevel (apiLevel.ToString ());
57-
if (!string.IsNullOrEmpty (osVersion))
58-
return osVersion.TrimStart ('v');
59-
return null;
54+
var doc = XDocument.Load (stream);
55+
return Load (doc);
6056
}
6157

62-
public static string TryOSVersionToCodeName (string frameworkVersion)
58+
public static AndroidVersion Load (string uri)
6359
{
64-
// match on API level, the framework version might not match what we have here (>= XA 5.x uses a different version scheme)
65-
var apiLevel = TryOSVersionToApiLevel (frameworkVersion);
66-
67-
foreach (AndroidVersion version in KnownVersions)
68-
if (version.ApiLevel == apiLevel)
69-
return version.CodeName;
70-
return null;
60+
var doc = XDocument.Load (uri);
61+
return Load (doc);
7162
}
7263

73-
public static string TryFrameworkVersionToOSVersion (string frameworkVersion)
64+
// Example:
65+
// <AndroidApiInfo>
66+
// <Id>26</Id>
67+
// <Level>26</Level>
68+
// <Name>Oreo</Name>
69+
// <Version>v8.0</Version>
70+
// <Stable>True</Stable>
71+
// </AndroidApiInfo>
72+
static AndroidVersion Load (XDocument doc)
7473
{
75-
// match on API level, the framework version might not match what we have here (>= XA 5.x uses a different version scheme)
76-
var apiLevel = TryOSVersionToApiLevel (frameworkVersion);
74+
var id = (string) doc.Root.Element ("Id");
75+
var level = (int) doc.Root.Element ("Level");
76+
var name = (string) doc.Root.Element ("Name");
77+
var version = (string) doc.Root.Element ("Version");
78+
var stable = (bool) doc.Root.Element ("Stable");
7779

78-
foreach (AndroidVersion version in KnownVersions)
79-
if (version.ApiLevel == apiLevel)
80-
return version.OSVersion;
81-
return null;
80+
return new AndroidVersion (level, version.TrimStart ('v'), name, id, stable);
8281
}
83-
84-
public static AndroidVersion[] KnownVersions = new[] {
85-
new AndroidVersion (4, "1.6", "Donut", new Version (1, 6)),
86-
new AndroidVersion (5, "2.0", "Eclair", new Version (2, 0)),
87-
new AndroidVersion (6, "2.0.1", "Eclair", new Version (2, 0, 1)),
88-
new AndroidVersion (7, "2.1", "Eclair", new Version (2, 1)),
89-
new AndroidVersion (8, "2.2", "Froyo", new Version (2, 2)),
90-
new AndroidVersion (10, "2.3", "Gingerbread", new Version (2, 3)),
91-
new AndroidVersion (11, "3.0", "Honeycomb", new Version (3, 0)),
92-
new AndroidVersion (12, "3.1", "Honeycomb", new Version (3, 1)),
93-
new AndroidVersion (13, "3.2", "Honeycomb", new Version (3, 2)),
94-
new AndroidVersion (14, "4.0", "Ice Cream Sandwich", new Version (4, 0)),
95-
new AndroidVersion (15, "4.0.3", "Ice Cream Sandwich", new Version (4, 0, 3)),
96-
new AndroidVersion (16, "4.1", "Jelly Bean", new Version (4, 1)),
97-
new AndroidVersion (17, "4.2", "Jelly Bean", new Version (4, 2)),
98-
new AndroidVersion (18, "4.3", "Jelly Bean", new Version (4, 3)),
99-
new AndroidVersion (19, "4.4", "Kit Kat", new Version (4, 4)),
100-
new AndroidVersion (20, "4.4.87", "Kit Kat + Wear support", new Version (4, 4, 87)),
101-
new AndroidVersion (21, "5.0", "Lollipop", new Version (5, 0)),
102-
new AndroidVersion (22, "5.1", "Lollipop", new Version (5, 1)),
103-
new AndroidVersion (23, "6.0", "Marshmallow", new Version (6, 0)),
104-
new AndroidVersion (24, "7.0", "Nougat", new Version (7, 0)),
105-
};
10682
}
10783
}
10884

0 commit comments

Comments
 (0)