-
Notifications
You must be signed in to change notification settings - Fork 57
Cannot inherit android.app.IntentService with class-parse #717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
…#718) Fixes: #717 A long time ago (2011-Jan-28), [Novell Bug #655342][0] was filed: the following fragment was expected to work, but didn't: // C# [Service] class MyService : Android.App.IntentService { public MyService() { } protected override void OnHandleIntent(Intent intent) { } } Why didn't it work? Two reasons: 1. `android.app.IntentService` has no default constructor; it only has an [`IntentService(String)`][1] constructor. 2. In 2011, there was no way for a C# type to provide constructor parameters to the Java constructor. The result is that the Java Callable Wrapper for `MyService` was not valid Java code, as it attempted to use a non-existent constructor: // Java /* partial */ class MyService extends android.app.IntentService { public MyService() { super(); // javac error; no such constructor exists // … } } Note that there's no way to make `MyService() : base("name")` work, which would be the "obvious" solution, unless `jcw-gen` contains an IL interpreter to determine what parameters were provided to the base class constructor, and…no. Too complicated. Not happening. Note: (2) later got "solved" [in 2013][2] by adding the [`ExportAttribute.SuperArgumentsString` property][3], which would allow: [Service] partial class MyService : Android.App.IntentService { [Export(SuperArgumentsString="\"name\"")] public MyService() : base ("name") { } } --End note. Lacking a time machine, [the 2011 fix][4] was to "fudge" it: 1. Add a new [`mono.android.app.IntentService`][5] Java type which contains a default constructor. 2. ["Rename"][6] `android.app.IntentService` as `mono.android.app.IntentService`. That way, the original C# declaration would generate a Java Callable Wrapper resembling: // Java /* partial */ class MyService extends mono.android.app.IntentService { public MyService() { super(); // now valid; it exists! // … } } Unfortunately, this doesn't properly address *bindings*: what happens if a *Java* type inherits `android.app.IntentService`, as is the case in [`Microsoft.Intune.MAM.SDK.aar`][7], and that type is bound? In the original `jar2xml` world order, it worked: [`jar2xml`][8] is a Java app, and for it to run `$CLASSPATH` needed to contain `android.jar`, which *did* have `android.app.IntentService`. Thus, all required types could be resolved. In the new `class-parse` world order, this isn't the case: `class-parse` directly reads Java bytecode; no JVM is used. The result is that binding projects which move from `jar2xml` to `class-parse` could now get a new error: Error while processing type '[Class] com.microsoft.intune.mam.client.app.MAMIntentService': Type 'android.app.IntentService' was not found. `android.app.IntentService` wasn't found because `Mono.Android.dll` doesn't contain a binding for that type; it only binds `mono.android.app.IntentService`. The fix for this unfortunate state of affairs is Yet Another Kludge to maintain backward compatibility: update `JavaApiTypeResolverExtensions.FindNonGenericType()` so that it knows about the 2011 kludge: if `android.app.IntentService` is requested, hand it back the `JavaType` instance for `mono.android.app.IntentService`. [0]: http://bugzilla.novell.com/show_bug.cgi?id=655342 [1]: https://developer.android.com/reference/android/app/IntentService#IntentService(java.lang.String) [2]: xamarin/monodroid@a6c3497 [3]: https://docs.microsoft.com/en-us/dotnet/api/java.interop.exportattribute.superargumentsstring [4]: xamarin/monodroid@7a42b46a39 [5]: https://github.com/xamarin/xamarin-android/blob/a7bda88d05b58efd26c17be3956c7140d05868e1/src/Mono.Android/java/mono/android/app/IntentService.java [6]: https://github.com/xamarin/xamarin-android/blob/a7bda88d05b58efd26c17be3956c7140d05868e1/src/Mono.Android/metadata#L570-L583 [7]: https://github.com/msintuneappsdk/ms-intune-app-sdk-android/blob/master/Microsoft.Intune.MAM.SDK.aar [8]: https://github.com/xamarin/jar2xml
…#718) Fixes: #717 A long time ago (2011-Jan-28), [Novell Bug #655342][0] was filed: the following fragment was expected to work, but didn't: // C# [Service] class MyService : Android.App.IntentService { public MyService() { } protected override void OnHandleIntent(Intent intent) { } } Why didn't it work? Two reasons: 1. `android.app.IntentService` has no default constructor; it only has an [`IntentService(String)`][1] constructor. 2. In 2011, there was no way for a C# type to provide constructor parameters to the Java constructor. The result is that the Java Callable Wrapper for `MyService` was not valid Java code, as it attempted to use a non-existent constructor: // Java /* partial */ class MyService extends android.app.IntentService { public MyService() { super(); // javac error; no such constructor exists // … } } Note that there's no way to make `MyService() : base("name")` work, which would be the "obvious" solution, unless `jcw-gen` contains an IL interpreter to determine what parameters were provided to the base class constructor, and…no. Too complicated. Not happening. Note: (2) later got "solved" [in 2013][2] by adding the [`ExportAttribute.SuperArgumentsString` property][3], which would allow: [Service] partial class MyService : Android.App.IntentService { [Export(SuperArgumentsString="\"name\"")] public MyService() : base ("name") { } } --End note. Lacking a time machine, [the 2011 fix][4] was to "fudge" it: 1. Add a new [`mono.android.app.IntentService`][5] Java type which contains a default constructor. 2. ["Rename"][6] `android.app.IntentService` as `mono.android.app.IntentService`. That way, the original C# declaration would generate a Java Callable Wrapper resembling: // Java /* partial */ class MyService extends mono.android.app.IntentService { public MyService() { super(); // now valid; it exists! // … } } Unfortunately, this doesn't properly address *bindings*: what happens if a *Java* type inherits `android.app.IntentService`, as is the case in [`Microsoft.Intune.MAM.SDK.aar`][7], and that type is bound? In the original `jar2xml` world order, it worked: [`jar2xml`][8] is a Java app, and for it to run `$CLASSPATH` needed to contain `android.jar`, which *did* have `android.app.IntentService`. Thus, all required types could be resolved. In the new `class-parse` world order, this isn't the case: `class-parse` directly reads Java bytecode; no JVM is used. The result is that binding projects which move from `jar2xml` to `class-parse` could now get a new error: Error while processing type '[Class] com.microsoft.intune.mam.client.app.MAMIntentService': Type 'android.app.IntentService' was not found. `android.app.IntentService` wasn't found because `Mono.Android.dll` doesn't contain a binding for that type; it only binds `mono.android.app.IntentService`. The fix for this unfortunate state of affairs is Yet Another Kludge to maintain backward compatibility: update `JavaApiTypeResolverExtensions.FindNonGenericType()` so that it knows about the 2011 kludge: if `android.app.IntentService` is requested, hand it back the `JavaType` instance for `mono.android.app.IntentService`. [0]: http://bugzilla.novell.com/show_bug.cgi?id=655342 [1]: https://developer.android.com/reference/android/app/IntentService#IntentService(java.lang.String) [2]: xamarin/monodroid@a6c3497 [3]: https://docs.microsoft.com/en-us/dotnet/api/java.interop.exportattribute.superargumentsstring [4]: xamarin/monodroid@7a42b46a39 [5]: https://github.com/xamarin/xamarin-android/blob/a7bda88d05b58efd26c17be3956c7140d05868e1/src/Mono.Android/java/mono/android/app/IntentService.java [6]: https://github.com/xamarin/xamarin-android/blob/a7bda88d05b58efd26c17be3956c7140d05868e1/src/Mono.Android/metadata#L570-L583 [7]: https://github.com/msintuneappsdk/ms-intune-app-sdk-android/blob/master/Microsoft.Intune.MAM.SDK.aar [8]: https://github.com/xamarin/jar2xml
Fixes: dotnet/java-interop#682 Fixes: dotnet/java-interop#717 Context: dotnet/java-interop#719 Changes: dotnet/java-interop@a807961...79d9533 * dotnet/java-interop@79d95334: [generator] Use GC.KeepAlive for reference type method parameters. (dotnet#722) * dotnet/java-interop@1a19ec04: [Xamarin.Android.Tools.Bytecode] Hide Kotlin nested types inside (dotnet#723) * dotnet/java-interop@24a9abdb: [Xamarin.Android.Tools.ApiXmlAdjuster] Find app.android.IntentService (dotnet#718)
Fixes: dotnet/java-interop#682 Fixes: dotnet/java-interop#717 Context: dotnet/java-interop#719 Changes: dotnet/java-interop@a807961...79d9533 * dotnet/java-interop@79d95334: [generator] Use GC.KeepAlive for reference type method parameters. (#722) * dotnet/java-interop@1a19ec04: [Xamarin.Android.Tools.Bytecode] Hide Kotlin nested types inside (#723) * dotnet/java-interop@24a9abdb: [Xamarin.Android.Tools.ApiXmlAdjuster] Find app.android.IntentService (#718)
Release status update A new Preview version of Xamarin.Android has now been published that includes the fix for this item. The fix is not yet included in a Release version. I will update this item again when a Release version is available that includes the fix. Fix included in Xamarin.Android SDK version 11.1.0.15. Fix included on Windows in Visual Studio 2019 version 16.8 Preview 4. To try the Preview version that includes the fix, check for the latest updates in Visual Studio Preview. Fix included on macOS in Visual Studio 2019 for Mac version 8.8 Preview 4. To try the Preview version that includes the fix, check for the latest updates on the Preview updater channel. |
Fixes: dotnet/java-interop#461 Fixes: dotnet/java-interop#682 Fixes: dotnet/java-interop#717 Fixes: dotnet/java-interop#719 Fixes: dotnet/java-interop#728 Changes: dotnet/java-interop@ac914ce...b991bb8 * dotnet/java-interop@b991bb86: [generator] Revert change to use auto-properties in EventArgs classes (#736) * dotnet/java-interop@ee50d89b: Bump to xamarin/xamarin-android-tools/master@f2af06f2 (#733) * dotnet/java-interop@a0b895c1: [build] Suppress NuGet warnings (#730) * dotnet/java-interop@8b1b0507: [generator] Fix parsing of complex generic types (#729) * dotnet/java-interop@ee7afeed: [generator] Prevent generating duplicate EventArgs classes (#726) * dotnet/java-interop@1f21f38c: [generator] Use GC.KeepAlive for reference type method parameters. (#725) * dotnet/java-interop@5136ef98: [Xamarin.Android.Tools.Bytecode] Hide Kotlin nested types inside (#723) * dotnet/java-interop@53d60513: [jnimarshalmethod-gen] Fix registration on Windows (#721) * dotnet/java-interop@5a834d42: [jnimarshalmethod-gen] Avoid creating AppDomains (#720) * dotnet/java-interop@a76edb8c: [Xamarin.Android.Tools.ApiXmlAdjuster] Find app.android.IntentService (#718) * dotnet/java-interop@6cde0877: [Java.Interop] Emit a reference assembly for Java.Interop.dll (#716) * dotnet/java-interop@b858dc59: [generator] Provide line/col numbers for api.xml warnings (#715) * dotnet/java-interop@9be92a04: [ci] Don't kick off CI for documentation only changes. (#712) * dotnet/java-interop@03c22722: [jnimarshalmethod-gen] Fix type resolution crash (#706)
Release status update A new Release version of Xamarin.Android has now been published that includes the fix for this item. Fix included in Xamarin.Android SDK version 11.1.0.17. Fix included on Windows in Visual Studio 2019 version 16.8. To get the new version that includes the fix, check for the latest updates or install the most recent release from https://visualstudio.microsoft.com/downloads/. Fix included on macOS in Visual Studio 2019 for Mac version 8.8. To get the new version that includes the fix, check for the latest updates on the Stable updater channel. |
If you try to bind a class that inherits
android.app.IntentService
withclass-parse
you get the following error:This is because we have used
metadata
to moveandroid.app.IntentService
tomono.android.app.IntentService
. https://github.com/xamarin/xamarin-android/blob/51f56aacd9946231672f8c173e265bfe68cb52da/src/Mono.Android/metadata#L570-L583When
class-parse
attempts to resolve theandroid.app.IntentService
type it cannot be found.This works with
jar2xml
because it resolves Java types using the Java jars, where the type is correct. By contrast,class-parse
resolves Java types using the[Register]
attribute in the C# assemblies which has the "moved" type name.It is likely that we cannot "undo" this move now without breaking back-compatibility. Likely we are going to have to add a hack to
generator
to know this type was moved and we need to update references to it.Repo:
https://github.com/msintuneappsdk/ms-intune-app-sdk-android/blob/master/Microsoft.Intune.MAM.SDK.aar
The text was updated successfully, but these errors were encountered: