Skip to content

Commit eadb318

Browse files
authored
Closes: #2730 Context: xamarin/monodroid@2c64cd5 Context: xamarin/monodroid@fee3597 Context: xamarin/monodroid@b6f7c48 Context: https://learn.microsoft.com/dotnet/android/building-apps/build-properties#androidfastdeploymenttype Changes: xamarin/monodroid@9ca6d9f...93ab95e. * xamarin/monodroid@93ab95e18: Remove AndroidFastDeploymentType completely (xamarin/monodroid#1485) * xamarin/monodroid@99e6a1fe2: Update OneLocBuildToken (xamarin/monodroid#1484) * xamarin/monodroid@aa82e14e4: Bump to xamarin/android-sdk-installer@d73bc8bb (xamarin/monodroid#1482) * xamarin/monodroid@272999f3b: Bump to xamarin/xamarin-android/main@4e677ed1 (xamarin/monodroid#1483) * xamarin/monodroid@2c64cd5f5: Remove Enhanced Fast Deployment (xamarin/monodroid#1481) * xamarin/monodroid@0de39ae7a: Bump external/xamarin-android from `dcf9bf3` to `bbac9fe` (xamarin/monodroid#1480) * xamarin/monodroid@90b6ad39d: Bump external/android-sdk-installer from `0496b14` to `e2dfd8f` (xamarin/monodroid#1479) * xamarin/monodroid@6f58c4a07: Bump to xamarin/android-sdk-installer/main/0496b14 (xamarin/monodroid#1474) * xamarin/monodroid@d226aa4f5: Bump to xamarin/androidtools@9bccfcc (xamarin/monodroid#1475) * xamarin/monodroid@a629f52b0: Bump to xamarin/xamarin-android/main@dcf9bf3 (xamarin/monodroid#1477) * xamarin/monodroid@8bb0955c0: Localized file check-in by OneLocBuild Task: Build definition ID 18473: Build ID 9470432 (xamarin/monodroid#1472) What can be done to improve the "inner dev loop"? Part of the answer is "speed up app install", and an answer to *that* is [*Fast Deployment*][0]: instead of having assemblies be placed within the `.apk` (requiring that the `.apk` be rebuilt and reinstalled whenever an assembly changes), place the assemblies "somewhere else" and "side-load" them. This way, if the `.apk` doesn't need to be rebuilt, then we can *skip* recreating and reinstalling the `.apk`, decreasing installation time, and improving the inner dev loop UX. "Enhanced Fast Deployment" (xamarin/monodroid@b6f7c48b) née "Instant Run" (xamarin/monodroid@fee35977) attempted to expand this idea: What If™ in addition to assemblies, we could also side-load `.dex` files, Android Resources, Android Assets, by setting `$(AndroidFastDeploymentType)`=Assemblies:Dexes. Despite a fair bit of effort to make this work, we haven't been able to enable this by default, because of "bootstrapping": *some* Java code must be present within the `.apk` to run as part of process startup (in order to probe the side-load locations, "hack" into Android infrastructure, etc.), and part of this Java code *must* include the `android.app.Application` subclass, *and all dependencies* of the `Application` subclass. Meaning if you *don't* have a custom `Application` subclass, things can reasonably work. (Just don't squint at `[ContentProvider]`…) Once you *do* have a custom `Application` subclass, though, things break; from #2730: AndroidRuntime: FATAL EXCEPTION: main AndroidRuntime: Process: scratch.bxc55050, PID: 7870 AndroidRuntime: java.lang.IllegalAccessError: Illegal class access: 'mono.android.Runtime' attempting to access 'mono.android.GCUserPeer' (declaration of 'mono.android.Runtime' appears in /data/app/scratch.bxc55050--x-XSYlRTtX_PyHDVMsL9A==/base.apk) AndroidRuntime: at mono.android.Runtime.<clinit>(Runtime.java:8) AndroidRuntime: at mono.android.Runtime.init(Native Method) AndroidRuntime: at mono.MonoPackageManager.LoadApplication(MonoPackageManager.java:51) AndroidRuntime: at mono.MonoRuntimeProvider.attachInfo(MonoRuntimeProvider.java:42) AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:6402) AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:5949) AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5864) AndroidRuntime: at android.app.ActivityThread.access$1100(ActivityThread.java:200) AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1651) AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) AndroidRuntime: at android.os.Looper.loop(Looper.java:193) AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6680) AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) ActivityManager: Force finishing activity scratch.bxc55050/md58bfd9258c6beb71a97a5dd7a0600aa01.MainActivity There once was a `mainDexClasses` tool in `platform-tools` which would *help* in determining the closure of `Application` + dependencies, but that tool was removed in platform-tools 33.0.0 (*and* was quite buggy, too). Furthermore, .NET MAUI *requires the use of an `Application` subclass*. Which means that most of our customers cannot use Enhanced Fast Deployment. Enhanced Fast Deployment also complicates maintenance, often "breaking" new features, as they aren't tested with Enhanced Fast Deployment, because it isn't enabled by default and we forget about it. xamarin/monodroid@2c64cd5f5 removes support for `$(AndroidFastDeploymentType)='Assemblies:Dexes'`. Additionally, filter the fast deployment files on `%(Abi)` metadata, to ensure that we are only deploying files which match the device abi. Otherwise for things like MAUI apps we end up trying to fast deploy *all* ABIs, which can add up to 100s of assemblies. The default Fast Deployment of assemblies will still function as it currently does now. Only the side loading of `.dex`, `.so` and resources is being removed. Add an `XA1037` warning to tell users that the `$(AndroidFastDeploymentType)` MSBuild property is no longer supported. Add a new `BuildTest2.XA1037PropertyDeprecatedWarning()` test which makes sure that the areas using the generic `XA1037` warning are producing a correct message. [0]: https://learn.microsoft.com/dotnet/android/building-apps/build-process#fast-deployment
1 parent 1d24421 commit eadb318

File tree

12 files changed

+35
-156
lines changed

12 files changed

+35
-156
lines changed

.external

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
xamarin/monodroid:main@9ca6d9f64fce11f04d668ece50ada36de1d7efce
1+
xamarin/monodroid:main@93ab95e18077d56d9d55ce7b4069a534e2dea35e

Documentation/docs-mobile/building-apps/build-properties.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,8 @@ Support for Fast Deploying resources and assets via that system was
549549
removed in commit [f0d565fe](https://github.com/xamarin/xamarin-android/commit/f0d565fe4833f16df31378c77bbb492ffd2904b9). This was becuase it required the use of
550550
deprecated API's to work.
551551

552+
**Support for this feature was removed in .NET 9
553+
552554
**Experimental**.
553555

554556
## AndroidFragmentType

build-tools/automation/azure-pipelines.yaml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,6 @@ extends:
220220
artifactSource: bin/Test$(XA.Build.Configuration)/$(DotNetTargetFramework)-android/Xamarin.Android.JcwGen_Tests-Signed.apk
221221
artifactFolder: $(DotNetTargetFramework)-Default
222222

223-
- template: /build-tools/automation/yaml-templates/apk-instrumentation.yaml@self
224-
parameters:
225-
configuration: $(XA.Build.Configuration)
226-
testName: Xamarin.Android.JcwGen_Tests_FastDev
227-
project: tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj
228-
testResultsFiles: TestResult-Xamarin.Android.JcwGen_Tests-$(XA.Build.Configuration).xml
229-
artifactSource: bin/Test$(XA.Build.Configuration)/$(DotNetTargetFramework)-android/Xamarin.Android.JcwGen_Tests-Signed.apk
230-
artifactFolder: $(DotNetTargetFramework)-FastDev_Assemblies_Dexes
231-
extraBuildArgs: /p:AndroidFastDeploymentType=Assemblies:Dexes
232-
233223
- template: /build-tools/automation/yaml-templates/run-nunit-tests.yaml@self
234224
parameters:
235225
testRunTitle: Xamarin.Android.Tools.Aidl-Tests - macOS

src/Xamarin.Android.Build.Tasks/Tasks/ProcessAssemblies.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static bool IsFromAKnownRuntimePack (ITaskItem assembly)
142142
static ITaskItem? GetOrCreateSymbolItem (Dictionary<string, ITaskItem> symbols, ITaskItem assembly)
143143
{
144144
var symbolPath = Path.ChangeExtension (assembly.ItemSpec, ".pdb");
145-
if (!symbols.TryGetValue (symbolPath, out var symbol)) {
145+
if (!symbols.TryGetValue (symbolPath, out var symbol) || !string.IsNullOrEmpty (symbol.GetMetadata ("DestinationSubDirectory"))) {
146146
// Sometimes .pdb files are not included in @(ResolvedFileToPublish), so add them if they exist
147147
if (File.Exists (symbolPath)) {
148148
symbols [symbolPath] = symbol = new TaskItem (symbolPath);

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,26 @@ public void BuildHasNoWarnings (bool isRelease, bool xamarinForms, bool multidex
268268
}
269269
}
270270

271+
[Test]
272+
[TestCase ("AndroidFastDeploymentType", "Assemblies", true, false)]
273+
[TestCase ("AndroidFastDeploymentType", "Assemblies", false, false)]
274+
[TestCase ("_AndroidUseJavaLegacyResolver", "true", false, true)]
275+
[TestCase ("_AndroidUseJavaLegacyResolver", "true", true, true)]
276+
[TestCase ("_AndroidEmitLegacyInterfaceInvokers", "true", false, true)]
277+
[TestCase ("_AndroidEmitLegacyInterfaceInvokers", "true", true, true)]
278+
public void XA1037PropertyDeprecatedWarning (string property, string value, bool isRelease, bool isBindingProject)
279+
{
280+
XamarinAndroidProject proj = isBindingProject ? new XamarinAndroidBindingProject () : new XamarinAndroidApplicationProject ();
281+
proj.IsRelease = isRelease;
282+
proj.SetProperty (property, value);
283+
284+
using (ProjectBuilder b = isBindingProject ? CreateDllBuilder (Path.Combine ("temp", TestName)) : CreateApkBuilder (Path.Combine ("temp", TestName))) {
285+
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
286+
Assert.IsTrue (StringAssertEx.ContainsText (b.LastBuildOutput, $"The '{property}' MSBuild property is deprecated and will be removed"),
287+
$"Should not get a warning about the {property} property");
288+
}
289+
}
290+
271291
[Test]
272292
public void ClassLibraryHasNoWarnings ()
273293
{

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ public void LibraryProjectsShouldSkipGetPrimaryCpuAbi ()
601601
var proj = new XamarinAndroidLibraryProject ();
602602
using (var b = CreateDllBuilder (Path.Combine ("temp", TestName))) {
603603
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
604-
Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should be skipped!");
604+
Assert.IsTrue (b.Output.IsTargetSkipped (target, defaultIfNotUsed: true), $"`{target}` should be skipped!");
605605
}
606606
}
607607

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ public static class KnownProperties
3232
public const string OutputPath = "OutputPath";
3333
public const string IntermediateOutputPath = "IntermediateOutputPath";
3434
public const string OutputType = "OutputType";
35-
public const string AndroidFastDeploymentType = "AndroidFastDeploymentType";
3635
public const string AndroidClassParser = "AndroidClassParser";
3736
public const string _AndroidAllowDeltaInstall = "_AndroidAllowDeltaInstall";
3837
public const string Nullable = "Nullable";

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,6 @@ public string LinkTool {
129129
set { SetProperty (KnownProperties.AndroidLinkTool, value); }
130130
}
131131

132-
public string AndroidFastDeploymentType {
133-
get { return GetProperty (KnownProperties.AndroidFastDeploymentType); }
134-
set { SetProperty (KnownProperties.AndroidFastDeploymentType, value); }
135-
}
136-
137132
public bool UseJackAndJill {
138133
get { return string.Equals (GetProperty (KnownProperties.UseJackAndJill), "True", StringComparison.OrdinalIgnoreCase); }
139134
set { SetProperty (KnownProperties.UseJackAndJill, value.ToString ()); }

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,11 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
535535
ResourceName="XA1035"
536536
Condition=" '$(BundleAssemblies)' == 'true' "
537537
/>
538+
<AndroidWarning Code="XA1037"
539+
ResourceName="XA1037"
540+
FormatArguments="AndroidFastDeploymentType;9"
541+
Condition=" '$(AndroidFastDeploymentType)' != '' "
542+
/>
538543
</Target>
539544

540545
<!--

tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -137,37 +137,16 @@ public void ClassLibraryMainLauncherRuns ([Values (true, false)] bool preloadAss
137137
static object [] DebuggerCustomAppTestCases = new object [] {
138138
new object[] {
139139
/* embedAssemblies */ true,
140-
/* fastDevType */ "Assemblies",
141140
/* activityStarts */ true,
142141
/* packageFormat */ "apk",
143142
},
144143
new object[] {
145144
/* embedAssemblies */ false,
146-
/* fastDevType */ "Assemblies",
147145
/* activityStarts */ true,
148146
/* packageFormat */ "apk",
149147
},
150148
new object[] {
151149
/* embedAssemblies */ true,
152-
/* fastDevType */ "Assemblies:Dexes",
153-
/* activityStarts */ true,
154-
/* packageFormat */ "apk",
155-
},
156-
new object[] {
157-
/* embedAssemblies */ false,
158-
/* fastDevType */ "Assemblies:Dexes",
159-
/* activityStarts */ false,
160-
/* packageFormat */ "apk",
161-
},
162-
new object[] {
163-
/* embedAssemblies */ true,
164-
/* fastDevType */ "Assemblies",
165-
/* activityStarts */ true,
166-
/* packageFormat */ "aab",
167-
},
168-
new object[] {
169-
/* embedAssemblies */ true,
170-
/* fastDevType */ "Assemblies:Dexes",
171150
/* activityStarts */ true,
172151
/* packageFormat */ "aab",
173152
},
@@ -177,7 +156,7 @@ public void ClassLibraryMainLauncherRuns ([Values (true, false)] bool preloadAss
177156
[Test, Category ("Debugger")]
178157
[TestCaseSource (nameof (DebuggerCustomAppTestCases))]
179158
[Retry(5)]
180-
public void CustomApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool activityStarts, string packageFormat)
159+
public void CustomApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, bool activityStarts, string packageFormat)
181160
{
182161
AssertCommercialBuild ();
183162
SwitchUser ();
@@ -190,7 +169,6 @@ public void CustomApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, st
190169

191170
var proj = new XamarinAndroidApplicationProject () {
192171
IsRelease = false,
193-
AndroidFastDeploymentType = fastDevType,
194172
};
195173
proj.SetAndroidSupportedAbis (DeviceAbi);
196174
proj.SetProperty ("EmbedAssembliesIntoApk", embedAssemblies.ToString ());
@@ -299,79 +277,55 @@ public override void OnCreate ()
299277
static object [] DebuggerTestCases = new object [] {
300278
new object[] {
301279
/* embedAssemblies */ true,
302-
/* fastDevType */ "Assemblies",
303280
/* allowDeltaInstall */ false,
304281
/* user */ null,
305282
/* packageFormat */ "apk",
306283
/* useLatestSdk */ true,
307284
},
308285
new object[] {
309286
/* embedAssemblies */ true,
310-
/* fastDevType */ "Assemblies",
311287
/* allowDeltaInstall */ false,
312288
/* user */ null,
313289
/* packageFormat */ "apk",
314290
/* useLatestSdk */ false,
315291
},
316292
new object[] {
317293
/* embedAssemblies */ false,
318-
/* fastDevType */ "Assemblies",
319-
/* allowDeltaInstall */ false,
320-
/* user */ null,
321-
/* packageFormat */ "apk",
322-
/* useLatestSdk */ true,
323-
},
324-
new object[] {
325-
/* embedAssemblies */ false,
326-
/* fastDevType */ "Assemblies",
327-
/* allowDeltaInstall */ true,
328-
/* user */ null,
329-
/* packageFormat */ "apk",
330-
/* useLatestSdk */ true,
331-
},
332-
new object[] {
333-
/* embedAssemblies */ false,
334-
/* fastDevType */ "Assemblies:Dexes",
335294
/* allowDeltaInstall */ false,
336295
/* user */ null,
337296
/* packageFormat */ "apk",
338297
/* useLatestSdk */ true,
339298
},
340299
new object[] {
341300
/* embedAssemblies */ false,
342-
/* fastDevType */ "Assemblies:Dexes",
343301
/* allowDeltaInstall */ true,
344302
/* user */ null,
345303
/* packageFormat */ "apk",
346304
/* useLatestSdk */ true,
347305
},
348306
new object[] {
349307
/* embedAssemblies */ true,
350-
/* fastDevType */ "Assemblies",
351308
/* allowDeltaInstall */ false,
352309
/* user */ DeviceTest.GuestUserName,
353310
/* packageFormat */ "apk",
354311
/* useLatestSdk */ true,
355312
},
356313
new object[] {
357314
/* embedAssemblies */ false,
358-
/* fastDevType */ "Assemblies",
359315
/* allowDeltaInstall */ false,
360316
/* user */ DeviceTest.GuestUserName,
361317
/* packageFormat */ "apk",
362318
/* useLatestSdk */ true,
363319
},
364320
new object[] {
365321
/* embedAssemblies */ true,
366-
/* fastDevType */ "Assemblies",
367322
/* allowDeltaInstall */ false,
368323
/* user */ null,
369324
/* packageFormat */ "aab",
370325
/* useLatestSdk */ true,
371326
},
372327
new object[] {
373328
/* embedAssemblies */ true,
374-
/* fastDevType */ "Assemblies",
375329
/* allowDeltaInstall */ false,
376330
/* user */ DeviceTest.GuestUserName,
377331
/* packageFormat */ "aab",
@@ -383,7 +337,7 @@ public override void OnCreate ()
383337
[Test, Category ("Debugger"), Category ("WearOS")]
384338
[TestCaseSource (nameof(DebuggerTestCases))]
385339
[Retry (5)]
386-
public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username, string packageFormat, bool useLatestSdk)
340+
public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, bool allowDeltaInstall, string username, string packageFormat, bool useLatestSdk)
387341
{
388342
AssertCommercialBuild ();
389343
SwitchUser ();
@@ -424,7 +378,6 @@ public Foo ()
424378
ProjectName = "App",
425379
IsRelease = false,
426380
EmbedAssembliesIntoApk = embedAssemblies,
427-
AndroidFastDeploymentType = fastDevType
428381
};
429382
if (!useLatestSdk) {
430383
lib.TargetFramework = "net8.0-android";

0 commit comments

Comments
 (0)