Skip to content
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

Cannot inherit android.app.IntentService with class-parse #717

Closed
jpobst opened this issue Sep 16, 2020 · 2 comments · Fixed by #718
Closed

Cannot inherit android.app.IntentService with class-parse #717

jpobst opened this issue Sep 16, 2020 · 2 comments · Fixed by #718
Labels
bug Component does not function as intended generator Issues binding a Java library (generator, class-parse, etc.)

Comments

@jpobst
Copy link
Contributor

jpobst commented Sep 16, 2020

If you try to bind a class that inherits android.app.IntentService with class-parse you get the following error:

Error while processing type '[Class] com.microsoft.intune.mam.client.app.MAMIntentService': 
Type 'android.app.IntentService' was not found.

This is because we have used metadata to move android.app.IntentService to mono.android.app.IntentService. https://github.com/xamarin/xamarin-android/blob/51f56aacd9946231672f8c173e265bfe68cb52da/src/Mono.Android/metadata#L570-L583

When class-parse attempts to resolve the android.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

@jpobst jpobst added bug Component does not function as intended generator Issues binding a Java library (generator, class-parse, etc.) labels Sep 16, 2020
jonpryor pushed a commit that referenced this issue Sep 18, 2020
…#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
jonpryor pushed a commit that referenced this issue Sep 18, 2020
…#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
jonpryor added a commit to jonpryor/xamarin-android that referenced this issue Sep 21, 2020
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)
jonpryor added a commit to dotnet/android that referenced this issue Sep 22, 2020
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)
@brendanzagaeski
Copy link
Contributor

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.

jonpryor pushed a commit to dotnet/android that referenced this issue Oct 20, 2020
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)
@brendanzagaeski
Copy link
Contributor

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Component does not function as intended generator Issues binding a Java library (generator, class-parse, etc.)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants