Bug 5927 - JAR binding not creating a binding for derived class from android.app.IntentService
Summary: JAR binding not creating a binding for derived class from android.app.IntentS...
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Bindings ()
Version: 4.2.x
Hardware: PC Windows
: Lowest normal
Target Milestone: ---
Assignee: Atsushi Eno
URL:
Depends on:
Blocks:
 
Reported: 2012-06-29 10:52 UTC by Akshay
Modified: 2016-09-05 12:03 UTC (History)
3 users (show)

Tags: XATriaged
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Akshay 2012-06-29 10:52:07 UTC
Using the new GCM (Google Cloud Messaging) library. The JAR contains 4 files, 3 of them work correctly, but the abstract  GCMBaseIntentService does not.
Comment 2 Atsushi Eno 2012-09-13 06:47:49 UTC
Fixed the bug description which was too bloat.
Comment 3 Jonathan Pryor 2012-09-13 10:42:57 UTC
The problem is due to insufficient levels of magic. ;-)

Rather, the underlying problem is subclassing android.app.IntentService:

    http://developer.android.com/reference/android/app/IntentService.html

IntentService contains no default constructors, and thus long ago the binding for IntentService didn't contain a default constructor either. However:

(1) Services need to have a default constructor in order to be usable
(2) For (my) sanity (i.e. minimal magic) an ACW can only have a constructor if the base class (a) contains a constructor with the same signature (to permit `super(args...)`), or (b) the base class contains a default constructor (allowing `super();`).

Since IntentService didn't have a default constructor, there was thus no way for the ACW to contain a default constructor, meaning that IntentService subclasses weren't usable:

    https://bugzilla.novell.com/show_bug.cgi?id=655342

We "fixed" this by making Android.App.IntentService actually bind mono.android.app.IntentService, which DOES have a default constructor, allowing C# code to subclass IntentService and have it actually be usable.

    http://docs.xamarin.com/android/about/limitations#Limited_Java_Generation_Support

For example, imagine you have this C# class:

    // C#
    public class MyService : IntentService {
        public MyService ()
            : base (GetSomeRandomName ())
        {
        }
    }

The ACW needs to be "pure Java"; what can we possibly do for the constructor?

    // Java
    public class MyService : android.app.IntentService {
        public MyService ()
        {
            super (/* SOMETHING needs to go here, but what?! */);
            if (getClass () == MyService.class)
                mono.android.TypeManager.Activate ( /* ... */ );
        }
    }

The conclusion for #655342 was that there is NOTHING we can generate for /* SOMETHING needs to go here, but what?! */, and thus we "hid" android.app.IntentService and replaced it with mono.android.app.IntentService, thus permitting:

    // Java
    public class MyService : mono.android.app.IntentService {
        public MyService ()
        {
            // we have a default constructor!
            super ();
            if (getClass () == MyService.class)
                mono.android.TypeManager.Activate ( /* ... */ );
        }
    }

Then things Just Work™ (mostly), and IntentService can be subclassed + used from C#.

"Surely", one might say, "that the [Export] attribute can fix this!" Alas, no; the ACW still needs to have a valid Java constructor, and thus we STILL need "something" for "/* SOMETHING needs to go here, but what?! */", and short of adding an implicit [Export] for GetSomeRandomName() (gah!), NOTHING has changed here in the last ~2 years, and the only "real" fix would be Java `native` constructor declarations...which Java doesn't allow, and thus isn't actually a solution.
Comment 4 Atsushi Eno 2012-09-13 13:17:56 UTC
The question then is: do we need to "hide" this?

The documentation for IntentService constructor says:

public IntentService (String name) Since: API Level 3

  Creates an IntentService. Invoked by your subclass's constructor.

  Parameters
    name 	Used to name the worker thread, important only for debugging. 

... so, I think this /* SOMETHING needs to go here, but what?! */ can be actually anything.

I assume this can be reimplemented to not hide it but create different type that provides a default constructor that dispatches to another .ctor(String) for valid parent invocation hierarchy.
Comment 5 Jonathan Pryor 2012-09-14 10:42:42 UTC
> The question then is: do we need to "hide" this?

I'm not sure I understand the question. Do you mean, "should we hide the IntentService(string) constructor"? We can't (ABI break), but we could certainly [Obsolete] it...

> ... so, I think this /* SOMETHING needs to go here, but what?! */ can be
> actually anything.

If at all possible, I would prefer to avoid special-casing types in the ACW-generation code. (Not necessarily possible in all circumstances, but I'd prefer to avoid special-casing things unless absolutely necessary, e.g. Android.App.Application...)

> I assume this can be reimplemented to not hide it but create different type
> that provides a default constructor that dispatches to another .ctor(String)
> for valid parent invocation hierarchy.

I'm even more confused now. :-/

Can you rephrase?
Comment 6 Atsushi Eno 2012-09-18 05:02:15 UTC
I'll explain with the actual code in private comment.
Comment 7 Atsushi Eno 2012-09-18 05:30:01 UTC
OK, I was sort of confused either, and I'm not going to post private comment either. I thought it was hiding some metadata for android.app.IntentService (which is not really true).

I thought we can alter the existing managed .ctor() to be like:

public IntentService () : this ("some_string") {}

Since the string can be anything it should work.
Comment 8 Atsushi Eno 2016-09-05 12:03:31 UTC
old issue. There should be no mono.android.app.IntentService anymore.