Bug 16805 - Class reference in <Fragment class=""> not properly resolved in Library project
Summary: Class reference in <Fragment class=""> not properly resolved in Library project
Status: VERIFIED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 4.10.1
Hardware: PC Windows
: Normal enhancement
Target Milestone: 5.1
Assignee: Atsushi Eno
URL:
: 13617 ()
Depends on:
Blocks:
 
Reported: 2013-12-15 10:25 UTC by Frank R
Modified: 2015-03-12 17:50 UTC (History)
5 users (show)

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


Attachments
bxc-16805.zip (68.31 KB, application/zip)
2013-12-16 14:45 UTC, Jonathan Pryor
Details
Example project demonstrating the issue (68.21 KB, application/x-zip-compressed)
2013-12-16 19:03 UTC, Frank R
Details
bxc-16805-Busted.zip (70.70 KB, application/zip)
2013-12-17 11:05 UTC, Jonathan Pryor
Details


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:
VERIFIED FIXED

Description Frank R 2013-12-15 10:25:57 UTC
App consists of application and library.

In application: public class MainActivity : LibraryActivity { ... }
In library (assembly MyLibrary): public class LibraryActivity: Activity { ... }

The LibraryActivity uses a layout that is defined as a resource in the library. This works: if the layout consists of some basic view (e.g., TextView) the app works fine.

But the layout consists of fragments. It contains fragments like:

   ...
   <fragment class="MyNamspace.LibraryFragment" ... />
   ...

This works fine as long as the class is part of the application, not the library. Problem is that the layout is interpreted in the context of the application, so the class is not found.

I would expect that I had to change the class reference to:

   ...
   <fragment class="MyNamspace.LibraryFragment,MyLibrary" ... />
   ...

.NET is able to resolve the reference: Type.GetType ("MyNamspace.LibraryFragment,MyLibrary") called from the constructor of MainActivity returns the type from the library. But when the app is run, there's an exception thrown (Binary XML file line #1: Error inflating class fragment) that ultimately is caused by a java.lang.ClassNotFoundException for class "MyNamspace.LibraryFragment,MyLibrary".

Apparently the Xamarin/Mono code does translate .NET class names, otherwise it was not possible to use .NET class names when layouts are part of the main application. But it does not function correctly if the class is not part of the main application; it then assumes the reference must be a Java class.

There seems to be a workaround by using the class reference "mynamspace.LibraryFragment" (inspired by a posting on StackOverflow), which is apparently the Java class corresponding to the .NET class. However, if you ever decide to change the class name translation, my code won't compile anymore. And what happens if two libraries have the same full class name, how can the correct one be found?
Comment 1 Jonathan Pryor 2013-12-16 14:44:05 UTC
> This works fine as long as the class is part of the application, not the library

This _shouldn't_ be correct; that is, it _should_ work if the type is in a Library project as well.

BUT!

It's still the same syntax, i.e.:

   <fragment class="MyNamspace.LibraryFragment" ... />

If that doesn't work, please provide a complete test case.

The //fragment/@class attribute does not support assembly-qualified names. Nor, for that matter, does Layout XML -- you can't do <MyNamespace.LibraryFragment,MyAssembly ... />, least of all because ',' isn't a valid element character, though I suppose '-' could be used....

(Aside: How does XAML handle this? Does it?)

> what happens if two libraries have the same full class name, how can the correct one be found?

That is not currently supported, at all; see e.g. https://bugzilla.xamarin.com/show_bug.cgi?id=15205#c1

I've created a better bug for this: https://bugzilla.xamarin.com/show_bug.cgi?id=16826
Comment 2 Jonathan Pryor 2013-12-16 14:45:53 UTC
Created attachment 5672 [details]
bxc-16805.zip

My attempted testcase. This contains a LibProject with a LibProject.DemoFragment fragment, and an Application project which uses <fragment class="LibProject.DemoFragment" .../>

This project Works For Me™.
Comment 3 Frank R 2013-12-16 19:03:54 UTC
Created attachment 5674 [details]
Example project demonstrating the issue

In my case, the layouts are also part of the library module. I've modified the example to reflect that case. Apart from this bug, there also seems to be a problem with rebuilding the layouts, but I can't put my finger on that.


What I've changed wrt bxc-16805:
- All code moved to LibFragment and put into LibFragment namespace
- MainActivity changed to LibActivity in LibFragment
- New MainActivity derived from LibActivity
- In the MainActivity constructor I've added

      Type.GetType ("LibFragment.TitlesFragment,LibFragment") 

  to show that it works.

If you run the project, you'll see that it works. But that is because I've modified the two activity_main.axml files in the Layout folder of LibFragment.

If you remove the fragments that use the libfragment namespace in main.axml and uncomment the original fragment references (using LibFragment), you'll see that it doesn't work anymore.
Comment 4 Jonathan Pryor 2013-12-17 11:05:31 UTC
Created attachment 5680 [details]
bxc-16805-Busted.zip

This is Attachment #5674 [details] with the changes mentioned in Comment #3 already performed.
Comment 5 Jonathan Pryor 2013-12-17 11:08:49 UTC
Here's the bug: Library project resources are not fixed up.

During the build process, we .axml/etc. files are processed to "appease" Android, converting .NET-style type names into the corresponding Java ACW names, e.g. "LibFragment.TitlesFragment" becomes "libfragment.TitlesFragment".

The bug is that this fixup process is only being applied to resources within the Application project, not to resources coming from Library projects or EmbeddedResources. Fixup needs to happen to _everything_.
Comment 6 Jonathan Pryor 2013-12-17 11:10:05 UTC
Comment on attachment 5672 [details]
bxc-16805.zip

Obsoleting Attachment #5672 [details] as it's no longer relevant.
Comment 7 Atsushi Eno 2014-02-07 11:44:54 UTC
Fixed in master [5b8a95f].
Comment 8 Ram Chandra 2014-06-04 07:31:35 UTC
I have checked this issue with master build.

To check this issue I have download the  attached project (bxc-16805-Busted.zip) and deploy the project on XS. 

I observed that when I uncomment the following syntax in the "activity_main_layout.axml" of "Library project" 

<fragment
        class="LibFragment.TitlesFragment"
        android:id="@+id/titles_fragment"
        android:layout_weight="1"
        android:layout_width="0px"
        android:layout_height="match_parent" />
    <fragment
        class="LibFragment.DemoFragment"
        android:id="@+id/demo_fragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

and deploy the project on device I am not getting any  exception (Binary XML file line #1: Error inflating class fragment) and sample is working fine.

I observed that now fixup process is being applied to resources within the application project as well as  for resources of Library projects.

Environment Info:

=== Xamarin Studio ===

Version 5.1 (build 302)
Installation UUID: 3b924754-5196-440a-b42b-05ebb3a3082e
Runtime:
 Microsoft .NET 4.0.30319.18408
 GTK+ 2.24.22 (MS-Windows theme)
 GTK# 2.12.25

=== Xamarin.Android ===

Version: 4.15.0 (Enterprise Edition)
Android SDK: E:\AndroidSDK
 Supported Android versions:
  1.6   (API level 4)
  2.1   (API level 7)
  2.2   (API level 8)
  2.3   (API level 10)
  3.1   (API level 12)
  3.2   (API level 13)
  4.0   (API level 14)
  4.0.3 (API level 15)
  4.1   (API level 16)
  4.2   (API level 17)
  4.3   (API level 18)
  4.4   (API level 19)
Java SDK: C:\Program Files\Java\jdk1.6.0_31
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b05)
Java HotSpot(TM) Client VM (build 20.6-b01, mixed mode, sharing)

=== Build Information ===

Release ID: 501000302
Git revision: 37edec4110ed93f02581f1331d2ff5b38f9a3aa9
Build date: 2014-05-30 12:45:30-04
Xamarin addins: b4105598b2afb41dac2f91a523ce94dbb3f1efdf

=== Operating System ===

Windows 6.1.7601.65536
Comment 9 Jonathan Pryor 2014-07-30 11:18:37 UTC
*** Bug 13617 has been marked as a duplicate of this bug. ***
Comment 10 Jonathan Pryor 2014-10-15 22:00:27 UTC
As of monodroid/eb04c91c, assembly-qualified names may be used in the //fragment/@android:name value, e.g.:

>  <fragment
>          android:name="Mono.Samples.Hello.MyFragment, Hello"
>          android:id="@+id/csharp_partial_assembly"
>          android:layout_width="match_parent"
>          android:layout_height="wrap_content"
>  />
>  <fragment
>          android:name="Mono.Samples.Hello.MyFragment, Hello, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
>          android:id="@+id/csharp_full_assembly"
>          android:layout_width="match_parent"
>          android:layout_height="wrap_content"
>  />

Note that this IS whitespace sensitive.