dotnet / android

.NET for Android provides open-source bindings of the Android SDK for use with .NET managed languages such as C#
MIT License
1.93k stars 528 forks source link

LayoutBinding + AndroidX error CS0400 #6893

Closed AigioL closed 2 years ago

AigioL commented 2 years ago

Android application type

Classic Xamarin.Android (MonoAndroid12.0, etc.), Android for .NET (net6.0-android, etc.)

Affected platform version

VS 2022

Description

https://github.com/xamarin/xamarin-android/blob/main/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs#L91

protected T FindFragment<T> (int resourceId, global::Androidx.Fragment.App.Fragment __ignoreMe, ref T cachedField) where T: global::Androidx.Fragment.App.Fragment

Androidx is error namespace

Steps to Reproduce

use LayoutCodeBehind project

Did you find any workaround?

Use this file to replace the wen of the SDK in the VS installation directory https://github.com/BeyondDimension/SteamTools/blob/develop/src/LayoutBinding.cs C:\Program Files\Microsoft Visual Studio\2022*\MSBuild\Xamarin\Android\LayoutBinding.cs

Relevant log output

11>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Xamarin\Android\LayoutBinding.cs(91,56,91,64): error CS0400: 未能在全局命名空间中找到类型或命名空间名“Androidx”(是否缺少程序集引用?)
11>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Xamarin\Android\LayoutBinding.cs(91,135,91,143): error CS0400: 未能在全局命名空间中找到类型或命名空间名“Androidx”(是否缺少程序集引用?)
dellis1972 commented 2 years ago

@AigioL can you post the actual error message you get please?

AigioL commented 2 years ago

@AigioL你能发布你得到的实际错误消息吗?

I think it's pretty obvious that the bug is a namespace error, and that the implementation of the method is also wrong.

For example global::Androidx.Fragment.App.Fragment is not correct

The correct type is global::AndroidX.Fragment.App.Fragment

The correct implementation of this method would be as follows

        protected T FindFragment<T>(int resourceId, global::AndroidX.Fragment.App.Fragment __ignoreMe, ref T cachedField) where T : global::AndroidX.Fragment.App.Fragment
        {
            return __FindFragment(resourceId, (activity) =>
            {
                if (activity is AndroidX.Fragment.App.FragmentActivity activity_)
                {
                    var f = activity_.SupportFragmentManager.FindFragmentById(resourceId);
                    if (f is T t) return t;
                    return global::Android.Runtime.Extensions.JavaCast<T>(f);
                }
                else
                {
                    // It shouldn't be possible to happen here
                    throw new InvalidCastException(activity.GetType().ToString());
                }
            }, ref cachedField);
        }

The conversion of java package names to C# namespace rules is always wrong on AndroidX.

This error made it necessary for me to manually specify the hosting type on Android XML, as in the following example https://github.com/BeyondDimension/SteamTools/blob/develop/src/ST.Client.Mobile.Droid.Design/ui/src/main/res/layout/fragment_settings.xml#L25

Relevant log output

11>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Xamarin\Android\LayoutBinding.cs(91,56,91,64): error CS0400: 未能在全局命名空间中找到类型或命名空间名“Androidx”(是否缺少程序集引用?)
11>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Xamarin\Android\LayoutBinding.cs(91,135,91,143): error CS0400: 未能在全局命名空间中找到类型或命名空间名“Androidx”(是否缺少程序集引用?)
dellis1972 commented 2 years ago

PR is up #6894

jonpryor commented 2 years ago

@AigioL: What confuses me about this issue is how you get the error in the first place: as per commit 92cd68c7beb3a26dab55957b2e061faf6cdc1d89 (which introduced the feature), (1) AndroidX support was known to not work, as the feature predated AndroidX being bound:

Furthermore, only Android.App.Fragment is supported by default. The Support Fragment can be used by #defineing the __HAVE_SUPPORT__ symbol, and the (non-existent and won't compile!) AndroidX Fragment can be used by defining __HAVE_ANDROIDX__.

and (2) I don't understand how __HAVE_ANDROIDX__ is being defined for you. Simply building a project with -p:AndroidFragmentType=AndroidX.Fragment.App.Fragment -p:AndroidGenerateLayoutBindings=True is insufficient; I need to also define __HAVE_ANDROIDX__ to get a build failure.

AigioL commented 2 years ago

@AigioL: What confuses me about this issue is how you get the error in the first place: as per commit 92cd68c (which introduced the feature), (1) AndroidX support was known to not work, as the feature predated AndroidX being bound:

Furthermore, only Android.App.Fragment is supported by default. The Support Fragment can be used by #defineing the __HAVE_SUPPORT__ symbol, and the (non-existent and won't compile!) AndroidX Fragment can be used by defining __HAVE_ANDROIDX__.

and (2) I don't understand how __HAVE_ANDROIDX__ is being defined for you. Simply building a project with -p:AndroidFragmentType=AndroidX.Fragment.App.Fragment -p:AndroidGenerateLayoutBindings=True is insufficient; I need to also define __HAVE_ANDROIDX__ to get a build failure.

I added __HAVE_ANDROIDX__ to the csproj file because my previous code needed to use FindFragment to return a Fragment of type AndroidX.Fragment.App.Fragment

<Project Sdk="MSBuild.Sdk.Extras">

  <PropertyGroup>
    <TargetFrameworks>MonoAndroid12.0</TargetFrameworks>
    ...
    <DefineConstants>SHADOWSOCKS;__HAVE_ANDROIDX__;$(DefineConstants)</DefineConstants>
    <!--<DefineConstants>SHADOWSOCKS;V2RAY;__HAVE_ANDROIDX__;$(DefineConstants)</DefineConstants>-->
  </PropertyGroup>

https://github.com/BeyondDimension/SteamTools/blob/develop/src/ST.Client.Android/ST.Client.Android.csproj#L7-L8

jonpryor commented 2 years ago

@AigioL: thank you. That certainly explains how you hit the error in the first place.