Daddoon / BlazorMobile

Create full C# driven hybrid-apps for iOS, Android, UWP & Desktop with Blazor!
MIT License
413 stars 55 forks source link

[question] Where is the assemblies locations on mobile apps? How to load them? #222

Closed arivera12 closed 4 years ago

arivera12 commented 4 years ago

I have a component implementation for managing the resource manager in blazor app called Resourcer.

The resourcer is working properly on regular blazor but when installed in android as an app the resourcer location goes missing and the resourcer doesn't load the resource file.

Here you can find the resourcer implementation: https://github.com/arivera12/OneLine/blob/master/OneLine.Blazor/Components/Resourcer/Resourcer.cs

This is how I load it which works properly on blazor on browser but not on blazor mobile:

<Resourcer OnLoadCompleted="OnResoureManagerLoadCompleted"
              Resourcers=@Resourcers
              DefaultResourcerAssembly=@typeof(Languages).Assembly
              DefaultResourcerSource="Relax.Common.Translations.en" />

[Parameter] public IReadOnlyDictionary<string, Tuple<string, string, Assembly>> Resourcers { get; set; } = Languages.Resourcers;

public class Languages
    {
        public static IReadOnlyDictionary<string, Tuple<string, string, Assembly>> Resourcers = new Dictionary<string, Tuple<string, string, Assembly>>()
        {
            { "en", Tuple.Create("English", "Relax.Common.Translations.en", typeof(Languages).Assembly) },
            { "es", Tuple.Create("Español", "Relax.Common.Translations.es", typeof(Languages).Assembly) }
        };
    }

It's seems there are issue loading the assemblies on blazor mobile as far as a I can see.

Btw, I tried working with some assemblies yesterday and doing some reflection stuff to override Http Services base address after blazor loads the IConfiguration file and didn't never worked as I wanted to be.

I wanted to load all HttpServices from a specific assembly and override by a loop all the Http Services base address in that assembly that were already loaded in the service provider of blazor.

I ended doing something else to workaround using explicit override for this but for my Resourcer I don't find any other way to work around it.

Any thoughts?

Daddoon commented 4 years ago

Before going further, how is your plugin working ? Is it used as a Razor Class Library ?

Generally, keep in mind that while you are working in Visual Studio in Debug (or even Release), under the hood, some Microsoft components for Razor / Blazor are soft linking some packages and assemblies even if they are not located in the right place you would see when your app is in publish mode. Example, that's why linking a Razor Class Library within your app work even if the file is not yet published in the _component folder (if my memory is right) that don't exist yet as the app is not published. Instead there is some kind of soft linking within the NuGet packages cache folder instead that simulate that everything is linked as expected.

My first assumption would be: Try to publish your regular Blazor app (right click on the project, then publish), and try to launch it from a webserver you like (IIS for example).

If you see that it doesn't work either for the same reason you mentionned, that mean that some files are maybe missing while using the publishing process, and the idea would be to check that the files are in facts present in the folder published by Visual Studio.

BlazorMobile use the publishing feature before packaging, so it should have the same content as a regular published Blazor app.

arivera12 commented 4 years ago

My first assumption would be: Try to publish your regular Blazor app (right click on the project, then publish), and try to launch it from a webserver you like (IIS for example).

Already done this and it works properly but for blazor mobile seems to be broken.

arivera12 commented 4 years ago

Before going further, how is your plugin working ? Is it used as a Razor Class Library ?

It's a component that its already included some others components and working as expected but my resourcer works for regular blazor but is still broken for blazor mobile.

I am changing this implementation to use a simple *.json file using the IConfiguration and reading the locales from the wwwroot since this its very well supported and works everywhere.

Also .json are more lightweight and more portable to other platforms than *.resx.

Daddoon commented 4 years ago

I don't have the time yet to see or test. Did you test was on WASM or Server side implementation project ?

arivera12 commented 4 years ago

Did you test was on WASM or Server side implementation project ?

Yes, and they work as expected there.

Daddoon commented 4 years ago

For your informations, i'm already using .resx localization assemblies on a Business project for a client, and i had no issue. I don't use any specific plugin to use it, i use it "as is" like a regular .RESX resource manager, i just change the global thread UI before rendering in order to localize the app in the expected language.

arivera12 commented 4 years ago

using blazor mobile? or regular blazor web?

Daddoon commented 4 years ago

Both.

arivera12 commented 4 years ago

I builded a new repository to manage translation using .json file using IConfiguration under the hood. This will be an alternative to Microsoft ResourceManager. Take a look https://github.com/arivera12/JsonLanguageLocalizerNet. I already test it reading remote json files and works as expected.

arivera12 commented 4 years ago

Both.

Still weird to me since this loads on web but not on blazor mobile for me.

Anyway I am changing my current implementation to use json files instead.

Since I found .json translations more flexible and lightweight than .resx files.

Daddoon commented 4 years ago

Just for feedback, resources are working as expected on my business project.

Before rendering the UI, with this event:

BlazorMobileService.OnBlazorMobileLoaded

If have written this part of code in my delegate:

                string culture = await AppMetadata.GetXamarinBridge().GetDeviceCulture();

                //WARNING: This must be done before BrowserHelper.InitAsync, as this method will cache current ressource for Javascript
                //so returned resources values must be set in the correct Thread Culture !
                if (culture != string.Empty)
                {
                    ConsoleHelper.LogInfo($"New thread culture is: {culture}");

                    CultureInfo currentCulture = new CultureInfo(culture);

                    CultureInfo.DefaultThreadCurrentCulture = currentCulture;
                    CultureInfo.DefaultThreadCurrentUICulture = currentCulture;
                    CultureInfo.CurrentCulture = currentCulture;
                    CultureInfo.CurrentUICulture = currentCulture;
                    Thread.CurrentThread.CurrentCulture = currentCulture;
                    Thread.CurrentThread.CurrentUICulture = currentCulture;
                }

Where the culture returned in GetDeviceCulture is the culture configured in Native / Xamarin.Forms, not what is detected in the browser or the default language whatever in Blazor.

Then i render the app.

arivera12 commented 4 years ago

I started interfacing xamarin apis specially the ones that are on Xamarin.Essentials some of them works and some of them not. When the xamarin.essential object is a static property for some reason xamarin bridge doesn't work but when it's a static method it works out of the box. I think xamarin bridge need to support this at some moment. I will open another issue later with this and actual cases that works and somes that doesn't work.

arivera12 commented 4 years ago

btw I use to manage the current culture and language selected using the SecureStorage class from xamarin.essentials and works flawless! Cake!