ReactiveUI icon indicating copy to clipboard operation
ReactiveUI copied to clipboard

[Bug]: WireUpControls throws exception in net8.0-android

Open gerardvanderkruijs opened this issue 1 year ago • 9 comments

Describe the bug 🐞

When calling ReactiveUI.ControlFetcherMixin.WireUpControls() in a .NET 8 Android app (net8.0-android) in non-debug configuration, even though the correct resource ID is specified, a MissingFieldException is thrown.

This issue was fixed with bug report #3714 , but only for Debug builds by the looks of it. When deploying Release builds the exception is still present. I narrowed it down to one specific .csproj property, that is this one:

<AndroidLinkMode>SdkOnly</AndroidLinkMode>

When I change this to <AndroidLinkMode>None</AndroidLinkMode> it all works perfectly.

Stracktrace:

07-08 10:38:08.523 I/MonoDroid( 5668): UNHANDLED EXCEPTION:
07-08 10:38:08.525 I/MonoDroid( 5668): Android.Runtime.JavaProxyThrowable: Exception_WasThrown, Android.Runtime.JavaProxyThrowable
07-08 10:38:08.525 I/MonoDroid( 5668): 
07-08 10:38:08.525 I/MonoDroid( 5668):   --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
07-08 10:38:08.525 I/MonoDroid( 5668): android.runtime.JavaProxyThrowable: [System.MissingFieldException]: Failed to wire up the Property XXXXXXX to a View in your layout with a corresponding identifier
07-08 10:38:08.525 I/MonoDroid( 5668): 	at ReactiveUI.ControlFetcherMixin.WireUpControls(Unknown Source:0)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at XXXXXXXX.StartActivity.OnCreate(Unknown Source:0)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(Unknown Source:0)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(Unknown Source:0)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at crc64763ea4d78b8a71b3.StartActivity.n_onCreate(Native Method)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at crc64763ea4d78b8a71b3.StartActivity.onCreate(StartActivity.java:42)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.Activity.performCreate(Activity.java:8595)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.Activity.performCreate(Activity.java:8573)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.os.Handler.dispatchMessage(Handler.java:106)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.os.Looper.loopOnce(Looper.java:205)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.os.Looper.loop(Looper.java:294)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at android.app.ActivityThread.main(ActivityThread.java:8177)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at java.lang.reflect.Method.invoke(Native Method)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
07-08 10:38:08.525 I/MonoDroid( 5668): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
07-08 10:38:08.525 I/MonoDroid( 5668): 

project .csproj file

<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<TargetFramework>net8.0-android</TargetFramework>
		<SupportedOSPlatformVersion>24</SupportedOSPlatformVersion>
		<RootNamespace>ReactiveUI_WireUpControls_Issue</RootNamespace>
		<OutputType>Exe</OutputType>
		<Nullable>enable</Nullable>
		<ImplicitUsings>enable</ImplicitUsings>
		<ApplicationId>com.companyname.ReactiveUI_WireUpControls_Issue</ApplicationId>
		<ApplicationVersion>1</ApplicationVersion>
		<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
		<Configurations>Debug;Release</Configurations>
		<WarningLevel>4</WarningLevel>
		<ReleaseVersion>1.0.0</ReleaseVersion>
		<RuntimeIdentifiers>android-arm;android-arm64;android-x86;android-x64</RuntimeIdentifiers>
		<AndroidDexTool>d8</AndroidDexTool>
		<EnableLLVM>false</EnableLLVM>
		<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
		<BundleAssemblies>false</BundleAssemblies>
	</PropertyGroup>
	<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
		<DebugSymbols>true</DebugSymbols>
		<DebugType>full</DebugType>
		<Optimize>false</Optimize>
		<ErrorReport>prompt</ErrorReport>
		<ConsolePause>false</ConsolePause>
		<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
		<AndroidUseAapt2>true</AndroidUseAapt2>
		<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>
		<AndroidEnableSGenConcurrent>false</AndroidEnableSGenConcurrent>
		<AndroidLinkMode>None</AndroidLinkMode>
	</PropertyGroup>
	<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
		<DebugSymbols>false</DebugSymbols>
		<DebugType>None</DebugType>
		<Optimize>true</Optimize>
		<AndroidLinkMode>SdkOnly</AndroidLinkMode>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="ReactiveUI" Version="19.6.12" />
	</ItemGroup>
</Project>

Step to reproduce

  1. Install .NET 8. (I installed 8.0.302)
  2. Create a new net8.0-android project using dotnet new android command.
  3. Add reference to ReactiveUI version 19.6.12
  4. Open MainActivity.cs and change it so that MainActivity inherits ReactiveUI.ReactiveActivity
public class MainActivity : ReactiveActivity
  1. Assign an ID(android:id) to the TextView in activity_main.xml and add a member to MainActivity.cs to wire it up.
    <TextView 
        android:id="@+id/app_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/app_text"
    />
    [WireUpResource("app_text")]
    public TextView AppText { get; private set; }
  1. Add a call to WireUpControls() after SetContentView() in OnCreate().
this.WireUpControls();
  1. Build and launch application with Release configuration
  2. MissingFieldException is thrown from WireUpControls().
  3. Also you could change AndroidLinkMode to SdkOnly in the Debug config, this will result in same exception.

Reproduction repository

https://github.com/gerardvanderkruijs/ReactiveUI-WireUpControls-Issue

Expected behavior

After launching the application In Release configuration, the TextView should be wired up correctly, and the initial screen should be displayed. AndroidLinkMode set to SdkOnly should not throw a MissingFieldException.

Screenshots 🖼️

No response

IDE

Rider macOS

Operating system

Android

Version

13

Device

Emulator

ReactiveUI Version

19.6.12

Additional information ℹ️

Since this report is almost identical to #3714 I mainly used all the info and sample project provided by @tommy10344, so thank you for that :-)

gerardvanderkruijs avatar Jul 08 '24 12:07 gerardvanderkruijs