Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrading old Android project to F# 6 #5

Closed
gaelian opened this issue May 7, 2022 · 9 comments
Closed

Upgrading old Android project to F# 6 #5

gaelian opened this issue May 7, 2022 · 9 comments

Comments

@gaelian
Copy link

gaelian commented May 7, 2022

I'm trying to upgrade an old Fabulous project (Xamarin Forms, iOS and Android app) to .NET 6/F# 6. The shared project and iOS project seem to have gone OK but the Android project is giving me these build errors:

FS0039	The type 'Android' is not defined.
FS0039	The value, constructor, namespace or type 'Layout' is not defined.
FS0039	The value, constructor, namespace or type 'Style' is not defined.

The errors refer to the AssemblyInfo.fs file.

I have changed the Xamarin.Android.FSharp.ResourceProvider package reference to FSharp.Android.Resource and I have removed the <AndroidResgenFile>Resources/Resource.designer.cs</AndroidResgenFile> from my project file. The <AndroidUseIntermediateDesignerFile>false</AndroidUseIntermediateDesignerFile> line did not appear in my project file so didn't need to be removed. However, the above build errors persist. The Android app is targeting Android 11, I don't know if that makes a difference to anything.

I gather my project is of the old kind, e.g. it has an AssemblyInfo.fs file and a packages.config file. Is it necessary to upgrade to the PackageReference style of project as seen over in FSharp.Mobile.Templates? Or is there some way to get things working with the old project format? If the project format needs to change, does this just need to be done manually?

@TimLariviere
Copy link
Member

Is it necessary to upgrade to the PackageReference style of project as seen over in FSharp.Mobile.Templates?

No, this is not required. It will work with packages.config as well.
https://github.com/fabulousfx/FSharp.Android.Resource/tree/main/tests/App.Android.NetFX is an example of that.

The value, constructor, namespace or type 'Layout' is not defined.

Did you try to build a 2nd time?
There is a limitation with this library: the very first build will generate the DLL for the resources, but the build of the app will fail. Subsequent builds should be fine though.

@gaelian
Copy link
Author

gaelian commented May 19, 2022

I have tried to build a second time, without success.

Just going back over things in my old project, I switched to the FSharp.Android.Resource NuGet package in my packages.config file:

  <!--<package id="Xamarin.Android.FSharp.ResourceProvider" version="1.0.0.28" targetFramework="monoandroid11.0" />-->
  <package id="FSharp.Android.Resource" version="1.0.2" targetFramework="monoandroid11.0" />

I commented out this line in my .fsproj file (there was no AndroidUseIntermediateDesignerFile entry in my .fsproj file to remove):

<!--<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>-->

In an effort to avoid potential issues, I removed the reference to the old Xamarin.Android.FSharp.ResourceProvider from my .fsproj file:

<ItemGroup>
-  <Reference Include="Xamarin.Android.FSharp.ResourceProvider.Runtime"> - 
-  <HintPath>..\packages\Xamarin.Android.FSharp.ResourceProvider.1.0.0.28\lib\monoandroid81\Xamarin.Android.FSharp.ResourceProvider.Runtime.dll</HintPath>
-  </Reference>
</ItemGroup>

I have checked that the new FSharp.Android.Resource package, version 1.0.2, is installed for the Android project. But unfortunately, the same build errors still occur:

FS0039	The type 'Android' is not defined.
FS0039	The value, constructor, namespace or type 'Layout' is not defined.
FS0039	The value, constructor, namespace or type 'Style' is not defined.

With the new FSharp.Android.Resource package, is the Resource.designer.cs file still relevant? Sorry if this is a silly question, I don't have a deep view of how the labyrinthine internals of Xamarin all hangs together.

@TimLariviere
Copy link
Member

TimLariviere commented May 19, 2022

With the new FSharp.Android.Resource package, is the Resource.designer.cs file still relevant?

Yes. FSharp.Android.Resource is a simple task that makes sure Resource.designer.cs is compiled so you can use it in your F# project.

Version 1.0.2 had some issues, so I just pushed a version 1.0.3 which should be better.
Also updated the readme instructions.

I switched to the FSharp.Android.Resource NuGet package in my packages.config file:

I would recommend you use the NuGet Package Manager of your IDE to do that, otherwise you need to do a few things by yourself.

If you update packages.config manually, you have to update the fsproj file:

  • Make sure to remove any reference to Xamarin.Android.FSharp.ResourceProvider
  • Make sure FSharp.Android.Resource.targets is imported
<Import Project="..\packages\FSharp.Android.Resource.1.0.3\build\FSharp.Android.Resource.targets" Condition="Exists('..\packages\FSharp.Android.Resource.1.0.3\build\FSharp.Android.Resource.targets')" />

After that, it should be better. Follow the instructions on the README and it should work.

@gaelian
Copy link
Author

gaelian commented May 20, 2022

I would recommend you use the NuGet Package Manager of your IDE to do that, otherwise you need to do a few things by yourself.

Noted.

I appreciate the help, @TimLariviere, the build errors now seem to be solved.

@gaelian
Copy link
Author

gaelian commented Jun 18, 2022

My apologies for resurrecting this issue again, but I seem to have run into a further problem. My (Fabulous v1) Android project does now build in Visual Studio. But when deploying from Visual Studio to a physical device (Samsung S10) for debugging, the app installs on the phone successfully, but when starting, it goes into break mode and shows this error in Visual Studio:

Java.Lang.NoClassDefFoundError: 'Failed resolution of: Landroidx/appcompat/R$drawable;'

Screenshot:
Screen Shot 2022-06-18 at 1 33 01 pm

I have been trying to figure out what the issue may be for some days now, without any luck. Any ideas on how I might be able to narrow down the cause? Or is this something that would be better raised with the AndroidX people?

In any case, could I ask at which point is the Resource.designer.cs file supposed to be generated? In an effort to try and better understand things, I had temporarily removed the Resource.designer.cs file from my project in order to see if it could be regenerated and perhaps might be different upon regeneration. But (re)building, unloading/loading the project, uninstalling/installing the FSharp.Android.Resource NuGet package, closing/opening Visual Studio etc. doesn't seem to trigger generation of the file. So I put the old file back in place once more, which allows for a successful build, but the break mode error remains upon deployment to the physical device.

@TimLariviere
Copy link
Member

TimLariviere commented Jun 22, 2022

In any case, could I ask at which point is the Resource.designer.cs file supposed to be generated?

This file is generated during the build of the Android project. FSharp.Android.Resource injects itself just after it to build the C# dll before trying to inject it for the F# build.

But (re)building, unloading/loading the project, uninstalling/installing the FSharp.Android.Resource NuGet package, closing/opening Visual Studio etc. doesn't seem to trigger generation of the file

Maybe try to remove obj/bin folders?
This should trigger the generation of Resource.designer.cs. If not, it means your build is failing before that step.
You can debug that via the command line by building with MSBuild in verbose mode
msbuild -v diagnostic YourAndroidProject.fsproj

the app installs on the phone successfully, but when starting, it goes into break mode and shows this error in Visual Studio:

Does it work in the Android Emulator?

Java.Lang.NoClassDefFoundError: 'Failed resolution of: Landroidx/appcompat/R$drawable;'

Maybe it is related to the fact you need to explicitly call Resource.UpdateIdValues(), otherwise the resource ids are not matching the correct ones and Android ends up crashing because it was trying to load an image and got a layout.

type MainActivity() =
    inherit Activity()
    
    // This is required for the app to pick up the right resources
    do YourProject.Resource.UpdateIdValues()
    
    member _.OnCreate(bundle) =
      base.OnCreate(bundle)
      
      // Now you can use Resource like usual
      this.SetContentView(Resource.Layout.Main)

@gaelian
Copy link
Author

gaelian commented Jun 24, 2022

Thanks yet again for your help, @TimLariviere.

Looking through the build log after running msbuild on the command line, I noticed that the ultimate error was:

(CompileResourceDesignerForFSharp target) ->
  CSC : error CS2001: Source file 'C:\Path\To\Project\Project.Android\Project.Android.fsproj\Resources/Resource.designer.cs' could not be found.

Looking further up in the build log I noticed in the _UpdateAndroidResgen target, the AndroidResgenFilename property was not being set:

Set Property: AndroidResgenFilename=

So I thought what if I add the <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile> line back into my .fsproj file? The build was then successful and I could see in the log that the AndroidResgenFilename was being set as expected (Set Property: AndroidResgenFilename=Resource.designer.cs). I tried deploying my app to my physical testing device, and it worked!

So then I was curious as to whether this was just some idiosyncrasy of my whacky project. I created a brand new Fabulous v2 project (dotnet new fabulous-xf-vswin -n FabXamApp) built the Android project a couple of times so that it built successfully, then I commented out the <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile> line in the .fsproj file and deleted the bin/obj folders and the Resource.designer.cs file. I then built again from the command line. The build failed:

"C:\Projects\FabXamApp\FabXamApp.Android\FabXamApp.Android.fsproj" (default target) (1) ->
(CompileResourceDesignerForFSharp target) ->
  CSC : error CS2001: Source file 'C:\Projects\FabXamApp\FabXamApp.Android\Resources/Resource.designer.cs' could not be found. [C:\Projects\FabXamApp\FabXamApp.Android\FabXamApp.Android.fsproj]

I then uncommented the <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile> line in the .fsproj file and built again from the command line. The first build failed as expected. The second build succeeded.

So it seems I can reproduce my error even in an out-of-the-box Fabulous v2 Android project by:

  1. Get Android project to the stage where it builds successfully (i.e. build it twice)
  2. Delete bin/obj folders and Resource.designer.cs file
  3. Comment out <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile> in .fsproj file
  4. Build Android project, the build error will be: CSC : error CS2001: Source file 'C:\Projects\FabXamApp\FabXamApp.Android\Resources/Resource.designer.cs' could not be found.

Conclusion: it seems best to leave the <AndroidResgenFile>Resources/Resource.designer.cs</AndroidResgenFile> in the .fsproj file. I'm not sure if there's a better resolution?

@TimLariviere
Copy link
Member

TimLariviere commented Jun 24, 2022

@gaelian Would it be a backward slash \ vs forward slash / issue?

I see when you comment out, the path is C:\Projects\FabXamApp\FabXamApp.Android\Resources/Resource.designer.cs
When you don't, it's C:\Projects\FabXamApp\FabXamApp.Android\Resources\Resource.designer.cs

What happens if you explicitly set <AndroidResgenFile>Resources/Resource.designer.cs</AndroidResgenFile> (with the forward slash)?

I believe you're testing on Windows only, right?
I didn't see this issue on MacOS

@gaelian
Copy link
Author

gaelian commented Jun 25, 2022

Would it be a backward slash \ vs forward slash / issue?

Yes, I noticed this also, it was one of the first things I tried. But on my machine at least (I'm actually using a Win 10 VM on a Macbook Pro, as I prefer Visual Studio for Windows, but yes, I'm testing on Windows), either of <AndroidResgenFile>Resources/Resource.designer.cs</AndroidResgenFile> or <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile> works, as long as it's present in the .fsproj file. If the line is not present, the build will fail as before.

I also tried removing the line from my .fsproj file and then modifying line 4 in the FSharp.Android.Resource.targets file within the FSharp.Android.Resource NuGet package to have a backslash:

<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>

But this too fails in the same way. So no matter what I've tried so far (and I've been at this for quite some time now!), all signs point to me needing to keep the <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile> or <AndroidResgenFile>Resources/Resource.designer.cs</AndroidResgenFile> line in my .fsproj file. ¯\_(ツ)_/¯

I have moved to testing on an out of the box Fabulous v2 project now, so I would hope this issue should be easy enough for someone else testing on Windows to reproduce.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants