Bug 18350 - Application deriving only works with OnCreate() method
Summary: Application deriving only works with OnCreate() method
Status: REOPENED
Alias: None
Product: Android
Classification: Xamarin
Component: General (show other bugs)
Version: 4.13.x
Hardware: PC Windows
: Normal normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
: 41631 (view as bug list)
Depends on:
Blocks:
 
Reported: 2014-03-13 08:43 UTC by Gerco Brandwijk
Modified: 2016-06-27 23:14 UTC (History)
5 users (show)

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


Attachments
Testcase project (16.87 KB, application/x-zip-compressed)
2014-03-13 09:05 UTC, Gerco Brandwijk
Details

Description Gerco Brandwijk 2014-03-13 08:43:53 UTC
Hello,

I'm deriving the Android.App.Application. This class has a static property named Current with the type of the class where he is in (in my case ApplicationImplementation). This ApplicationImplementation has only a constructor:
public ApplicationImplementation(IntPtr handle, JniHandleOwnership : base(handle,transfer)
{
    Current = this;
}

This constructor is only called when there is a OnCreate method. This method needs only to contain the base.OnCreate(), and after that it works. (visual studio told me that this method is not used, so I can remove it, but than it doesn't work anymore).

See the attachment for the testcase. When you comment the lines 26 till 29 in the ApplicationImplementation, then the message "ApplicationImplementation.Context.Current = NULL" is displayed.

I have spent an hour before I solved it. Now it's working, and it is an easy solution, but it is very frustrating.

Regards,
Gerco
Comment 1 Gerco Brandwijk 2014-03-13 09:05:10 UTC
Created attachment 6300 [details]
Testcase project
Comment 2 Udham Singh 2014-03-13 11:20:11 UTC
I have checked and debug this issue with Testcase project attached in comment 1. Here are my observations:

1. The constructor(ApplicationImplementation) is only called when there is a OnCreate method in class "ApplicationImplementation".

2. If I comment the method OnCreate in class "ApplicationImplementation" and run the application then "ApplicationImplementation.Context.Current = NULL" message is displayed.

3. When I run the application without commenting OnCreate method in class "ApplicationImplementation " then "ApplicationImplementation.Context.Current != NULL" message is displayed and Visual studio does not show any message that this method is not used. I am getting same message if I comment the base.OnCreate() in ApplicationImplementation class and code is working fine.

Environment Info:
Windows 8.1
VS 2013
Xamarin.Android 4.12.01000
Comment 3 Gerco Brandwijk 2014-03-13 11:25:50 UTC
The message of an unused method is a feature of ReSharper, not Visual Studio. So when you don't see thats message you don't have installed ReSharper.

But as you described: the problem exists also on you side :) Thanks for testing.

I hope Xamarin will fix it. I can get it working with an OnCreate method, but is unnecessary I my opinion, and it is very frustrating for new users, because it's not described anywhere that the OnCreate method is required for this.
Comment 4 Jonathan Pryor 2014-03-13 15:35:25 UTC
Workaround to appease ReSharper: set Current in OnCreate(), not the constructor:

    [Application]
    public class ApplicationImplementation : Application
    {
        public static ApplicationImplementation Current { get; private set; }
        
        public ApplicationImplementation(IntPtr handle, JniHandleOwnership transfer)
            : base(handle,transfer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();
            Current = this;
        }
    }

This is tricky to fix because Application (and Instrumentation) is "special": when the Java-side constructor is executed, no managed constructor is executed, because Mono hasn't been initialized yet. Consequently, the only time the Application will be instantiated -- through the (IntPtr, JniHandleOwnership) constructor -- is when Application.onCreate() is invoked, which will implicitly create the ApplicationImplementation instance.

It should be possible to revisit this as most runtime initialization has been moved into a ContentProvider, but this isn't a very high priority.
Comment 5 Gerco Brandwijk 2014-03-14 03:29:48 UTC
I understand that this is a low priority. But perhaps add the need of the OnCreate() method to the documentation at http://androidapi.xamarin.com/?link=T%3aAndroid.App.Application?
Comment 6 Jonathan Pryor 2014-03-14 09:59:52 UTC
People actually read the docs?! (Wow!)

Docs updated in android-api-docs/2604e3c3, though I don't know when those will get percolated to the server...
Comment 7 Gerco Brandwijk 2014-03-14 10:04:27 UTC
Yes, I did when I got stuck into this problem! :p

Thanks for updating. I'm resolving this item!
Comment 8 Jonathan Pryor 2014-03-14 10:13:14 UTC
I'm reopening, as there is a "proper" fix here (Comment #4 eludes to it), and this bug can track it.
Comment 9 Atsushi Eno 2015-10-30 09:59:09 UTC
We shouldn't try to support whatever "we cannot do in Java Android land".

Can we run arbitrary code within custom Application's static or instance constructor before the Application's onCreate() method is invoked? No, we can't.

The only valid way to initialize the monodroid runtime is to do that within some ContentProvider, which is what we are doing nowadays.

Expecting Application initialization code within C# code out of Android application lifecycle is like expecting constructor code to work when we use FormatterServices.GetUninitializedObject(). That is an invalid expectation.

We SHOULD NOT support that. Like, Microsoft _could_ support constructor invocation, we _could_ support some kind of initialization, but we SHOULDN'T. That's not Android application that conforms to platform's manner anymore.
Comment 10 Jonathan Pryor 2016-06-15 02:27:31 UTC
*** Bug 41631 has been marked as a duplicate of this bug. ***
Comment 11 Mikhail Melnik 2016-06-27 05:17:06 UTC
Got same issue when updated to 6.1.1.1. Xamarin Android completely ignores custom application class marked with [Application] attribute if OnCreate is not overridden even if the base class did it.

using System;
using System.Diagnostics;
using Android.App;
using Android.Content.Res;
using Android.OS;
using Android.Runtime;

namespace customapp
{
	[Application]
	public class MyApplication : Application
	{
		public MyApplication (IntPtr javaReference, JniHandleOwnership transfer)
			: base (javaReference, transfer)
		{
			Debugger.Break ();
		}

		//Uncomment OnCreate to make runtime use this application class.
		//public override void OnCreate ()
		//{
		//	base.OnCreate ();
		//}

		public override void OnConfigurationChanged (Configuration newConfig)
		{
			base.OnConfigurationChanged (newConfig);
		}
	}

	[Activity (MainLauncher = true)]
	public class MainActivity : Activity
	{
		protected override void OnCreate (Bundle savedInstanceState)
		{
			base.OnCreate (savedInstanceState);

			Debugger.Break ();
		}
	}
}
Comment 12 Jonathan Pryor 2016-06-27 23:14:52 UTC
Comment #11 is a DUPE of Bug #41342.

Note You need to log in before you can comment on or make changes to this bug.