jeudi 10 octobre 2019

Building a SMARTER Placeholder Loading UI 2.0 using only C# for your UWP application [C#,Storyboard]

Previously to build my Placeholder UI I would be using a UserControl, that contained Grid, Storyboard, adding a gradient styling and a ContentControl.
However this could be quite resource intensive which is not great and also I was not happy with my initial implementation.

After a quick refactoring it was decided that a blinking rectangle would better fit the need and we would not need to have to animate something going to left to right.





To make things simple it was decided to create a new Class that would inherited from Grid:

public class PlaceholderSkeletonView : Grid

Next we just needed to add a Storyboard animation that will make this element "blink"

var blinkAnimation = new DoubleAnimation()
    {
         From = 1,
         To = 0.4,
         AutoReverse = true,
         //blink every 1sec
         Duration = new Windows.UI.Xaml.Duration(TimeSpan.FromSeconds(1)),
         RepeatBehavior = RepeatBehavior.Forever
    };

And lastly all we need is to add this blinking animation to our Storyboard:

 myLoadingStoryboard.Children.Add(blinkAnimation);

 Storyboard.SetTarget(myLoadingStoryboard, this);
 Storyboard.SetTargetProperty(blinkAnimation, "Opacity");

 Loaded += (a, e) => myLoadingStoryboard.Begin();

All in all it was


Full class here:


public class PlaceholderSkeletonView : Grid
{
        Storyboard myLoadingStoryboard { get; set; }
        public PlaceholderSkeletonView()
        {            
            myLoadingStoryboard = new Storyboard();
            var blinkAnimation = new DoubleAnimation()
            {
                From = 1,
                To = 0.4,
                AutoReverse = true,
                //blink every 1sec
                Duration = new Windows.UI.Xaml.Duration(TimeSpan.FromSeconds(1)),
                RepeatBehavior = RepeatBehavior.Forever
            };

            myLoadingStoryboard.Children.Add(blinkAnimation);

            Storyboard.SetTarget(myLoadingStoryboard, this);
            Storyboard.SetTargetProperty(blinkAnimation, "Opacity");

            Loaded += (a, e) => myLoadingStoryboard.Begin();
        }
}


In your XAML it would look as follows for example:


<StackPanel Orientation="Horizontal">
     <local:PlaceholderSkeletonView
                Width="120"
                Height="120"
                Margin="20"
                Background="#ebebeb" />
          <StackPanel Margin="20" Orientation="Vertical">
                <local:PlaceholderSkeletonView
                       Width="190"
                       Height="20"
                       Margin="10"
                       Background="#ebebeb" />
                <local:PlaceholderSkeletonView
                       Width="150"
                       Height="20"
                       Margin="10"
                       Background="#ebebeb" />
                <local:PlaceholderSkeletonView
                       Width="120"
                       Height="20"
                       Margin="10"
                       Background="#ebebeb" />
           </StackPanel>
</StackPanel>


Happy Coding!

Github repo:  https://github.com/Delaire/UIPlaceholder







dimanche 1 septembre 2019

XAMARIN Tizen for Tvs and .NET Standard 2.0 [9-2019][XAML, C#]

My return of Experience on XAMARIN for TIZEN TVs the 1st of September 2019.

Here is documentation where you can find about Xamarin Forms for Tizen:

After a long summer of slowly migrating all of my app libraries to .NET Standard 2 I could finally really test Tizen to see how much code I could share between my Xbox One UWP app and a new Tizen TV app.

Framework versions:
  • Tizen.NET (5.0.0.14562)
  • Tizen.TV.UIControls (1.0.0)
  • Tizen.NET.Sdk (1.0.1) (this nuget would not update to the latest version 1.0.3)
  • Xamarin.Forms(4.1.0.709249) (forms 4.2.0.709249 was generating an error when building the app)

I discovered a new library called Tizen.TV.UIControls  which greatly improve the UI layout for the TV.  This library contains awesome features like:

MediaPlayer












RecycleItemsView


Horizontal lists


 
 
You can find the github repo here.

Tizen TV Xamarin C#


To get started I wanted to do a simple HTTP call to get data and set this data into a horizontal list, well I never got passed this step...

As for all applications you need to tell the app that it will have special privileges.  First you will need to start by adding  http://tizen.org/privilege/internet which is located in the file tizen-manifest.xml and then the tab Privileges. 

Next here is the code I am using to get weather information:


HttpClient client;
        private async System.Threading.Tasks.Task GetWeatherServiceAsync()
        {             
            var uri = new Uri("https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22");

            try
            {
                client = new HttpClient();

                var response = await client.GetAsync(uri);

                if (response.IsSuccessStatusCode)
                {
                    var responseContent = await response.Content.ReadAsStringAsync();

                }
            }
            catch (Exception ex)
            {
                var error = ex;
            }

        }


And the issue is that no matter what I tried client would never be initialized:



So as of today I cant do an HTTP call on my Tizen .NET Xamarin application, ill keep you posted as soon as I find a solution.

After looking more closely at all of the GitHub Sample for Tizen TV app they all generate their sample data by hand which probably means that their is an issue somewhere for TV apps, I do hope Samsung fix this ASAP as a TV app without being able to do HTTP calls is not very practical...


Happy coding

- UPDATE 5 Septembre 2019 - 
After discussion with Samsung it was found that I was using an old build of the Tizen emulator.
BuildInfo: "tizen_20181210.1228946"
BuildDate : "20181210_063435"

When I should have been using a 2019 Build, once I updated to the latest build everything was working.  IMO inside Visual Studio I wish I have had a warning telling me that I was using an old build.

mardi 20 août 2019

UWP ARM build to release : error APPX0002: Task 'GenerateAppxManifest' failed. An item with the same key has already been added.

Today I was about to release a new version of an application when I go this error.  This new build was mainly a classic sprint incrimination where I migrated my UWP libraries to .netstandard 2.0 and reworked and renamed small parts of the app to improve architecture of the app. No new features no major refactoring...


My day started with Azure DevOPs (VSTS) telling me:

- AppTest.ABC is not compatible with uap10.0.17134 (UAP,Version=v10.0.17134). Project AppTest.ABC supports: netstandard2.0 (.NETStandard,Version=v2.0)

I had a heart attack! netstandard2.0  doesn't support uap10.0.17134 since when ?!?

Looking at https://docs.microsoft.com/en-us/dotnet/standard/net-standard we can clearly see that the support starts at 10.0.16299 so this cant be the issue.

Next:

Having a deeper look at the logs in Visual Studio in Output window I saw that the nuget restore was telling me that I had

Incompatible projects: 3

Which is where I started my morning hunt to find the 3 rogue projects.

  •  To find these projects I looked at the logs and checked to see which libraries has issue
I was quickly able to find this one:
Checking compatibility for NotificationsExtensions.Win10 14332.0.2 with UAP,Version=v10.0.17134 (win10-arm) 
This was an old nuget package that I was not using anymore (don't ask me why it was not removed before), and having a second look I also saw that I had a NotificationsExtensions nuget package by removing these 2 packages I only had one incompatible projects left to find.

Nuget

Not being to find the last incompatible project I decided to look into my nuget packages to see what I could do. Here is the documentation https://docs.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders

Next I decided to clear all of my nuget packages:

You can clear all caches with this command:
nuget locals all -clear

This did not fix my issue, however when building the app in Debug ARM I was getting a new error: error APPX1101: Payload contains two or more files with the same destination path 'System.Memory.dll'.

 Full error:


6>"C:\AppTest\uap\src\AppTest.csproj" (_GenerateAppxPackage target) (1) ->
6>(_ComputeAppxPackagePayload target) -> 
6>  C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\AppxPackage\Microsoft.AppXPackage.Targets(1793,5): error APPX1101: Payload contains two or more files with the same destination path 'System.Memory.dll'. Source files: 
6>C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\AppxPackage\Microsoft.AppXPackage.Targets(1793,5): error APPX1101: C:\Users\damie\.nuget\packages\runtime.win10-arm-aot.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-arm-aot\lib\uap10.0.15138\System.Memory.dll
6>C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\AppxPackage\Microsoft.AppXPackage.Targets(1793,5): error APPX1101: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\System.Memory.dll
6>

Something is going terribly wrong, I am building my app in 10.0.17134 and it is pulling a 10.0.15138 package version WHY??

runtime.win10-arm-aot.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-arm-aot\lib\uap10.0.15138\System.Memory.dll

Looking a Visual Studio

I decide to check the Compile with .NET Native tool chain for the ARM builds to see if this would fix my error. The Compile with .NET chain was already active for my builds in x86 but not for ARM

Under My Project => Properties=>Build I checked :


Using the .NET Native tool chain allowed me to fix my issue as the application was now using these bits to build the app.

Now that I have my ARM builds working in Debug but still not in Release, to make things simpler I just opened my .csproj file and edited it as follows:


<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
    <OutputPath>bin\x86\Release\</OutputPath>
    <DefineConstants>$(DefineConstants);TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x86</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
    <CodeAnalysisRuleSet />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\ARM\Debug\</OutputPath>
    <DefineConstants>$(DefineConstants);DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>ARM</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <CodeAnalysisRuleSet />
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
    <OutputPath>bin\ARM\Release\</OutputPath>
    <DefineConstants>$(DefineConstants);TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>ARM</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
    <CodeAnalysisRuleSet />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x64\Debug\</OutputPath>
    <DefineConstants>$(DefineConstants);DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <CodeAnalysisRuleSet />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
    <OutputPath>bin\x64\Release\</OutputPath>
    <DefineConstants>$(DefineConstants);TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
    <CodeAnalysisRuleSet />
    <EnableGatekeeperAnalysis>true</EnableGatekeeperAnalysis>
  </PropertyGroup> 

In the end all I really needed to do was to enable
 <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
on my ARM builds which means to not have been the case before.

In the end I was able to once again build and release my application, I hope that this has helped you.


vendredi 1 mars 2019

XAMARIN Tizen for Tvs and .NET Standard 2.0 [2019][XAML, C#]

My return of Experience on XAMARIN for TIZEN TVs the 1st of March 2019

Here is documentation where you can find about Xamarin Forms for Tizen:

Having reseted my laptop since last time I had used Xamarin Tizen I needed to go through the all the different steps to re install Tizen, you can find the full steps here:

TIP: took me 10 minutes to figure out why I could not create an emulator image , make sure that in your package manager you install the Tizen 4 TV emulator and the Tizen SDK tools. Under Extensions SDK make sure you also select TV extensions, the download of all of the SDK and emulators can take up quite a long time so in the mean time I had recommended that you head over to Microsoft Docs for Tizen for some light reading =).

My Findings:

Last year when I used the Preview of Xamarin for Tizen here where my initial findings, you had the sensation that the SDK was not fully finish (being a preview that seemed normal), the emulator was very buggy and often crashed, the debugger did not work (unable to set a break point).

Framework versions:

  • Tizen.NET (5.0.0.14562)
  • Tizen.NET.Sdk (1.0.1)
  • Xamarin.Forms(3.6.0.26487)


The application that I built is on one page for now, it receives and formats my data into a a list that contains a list. It will populate a ListView, this first ListView data template will hold another ListView so that we can show data horizontally (imagine the Netflix application).

Universal Windows Platform (UWP) 

When creating this application I first started by the UWP as I thought it would be quicker,  the first issue that I was that the debugger did not want to stop on my break points I had the follow error:

"The breakpoint will not currently be hit. No symbols have been loaded for this document"

which is not practical (at all!).

To fix this issue I removed all of the bin and obj folders in my UWP app and removed this options
Debug=>Options=>General => Remove the check mark for "Enable Just My Code"
and it did the trick for me.

Here is what it looks like on the UWP app:


Not pretty but it gets the job done.

Next on Tizen for TV

For the Tizen, application the debugger is still "weak", it will break on you often unfortunately, another issue I found was that I was not not able to move the debug back when it hit a break point.

After a sometime even Visual Studio was telling me that something was wrong:


To be fair it was not all doom and gloom because the debugger did work sometimes:

And you could go inside the properties and investigate, this is a great improvement over the last time I tested this platform. On other issue that I found was that the debugger did not resurface errors, even when explicitly crating an error it never surfaced it.

When launching the app in the Tizen Emulator it can take a few seconds for everything to lunch.

Here is what the same app looks like in the Tizen emulator:

 It would seem that some of the binding elements are not 100% finished, none of the images will load. Also navigating inside the app is very very slow, from what I am seeing you might better off buying a Samsung TV to debug then using the emulator!

All in all here are a summary of my findings:

  1. Tizen 5 Tv SDK is working much better then the Tizen 4 Tv Sdk
  2. The emulator really works this time (last year I needed hacks to get it working), however only the version 5 worked for me and not the version 4, also you must arm yourself with patience for the app to load.  Everything is very lagy in the emulator.
  3. the debugger from Visual Studio is now working"ish", it can crash your Visual Studio but at least this time around you cant setup break points in your code.
  4. Binding still seems to be an issue, maybe this is a Xamarin issue ill have to investigate




lundi 14 janvier 2019

[how to] Using Multilingual App Toolkit to translate your UWP application

In this post we are going to see who easy it is to make your application multilingual using Microsoft Multilingual App Toolkit to translate your UWP application.

First you need a class that will allow us to get the translated string by using the ResourceLoader property.


 public class MyLocalizedClass
 {
        private static ResourceLoader _localizedResources;

        public ResourceLoader LocalizedResources
        {
            get
            {
                if (_localizedResources == null)
                {
                    _localizedResources = new ResourceLoader();
                }

                return _localizedResources;
            }
        }


        public string this[string key]
        {
            get
            {
                if (_localizedResources == null)
                {
                    _localizedResources = new ResourceLoader();
                }

                return _localizedResources.GetString(key);
            }
        }
}

You will need to bind all of the text in your application to your resource file, you can do this as follow:


         <TextBlock
                    x:Name="Header"
                    Style="{StaticResource TitleTextBlockStyle}"
                    Text="{Binding Path=[MyApplicationHeader], Source={StaticResource LocalizedStrings}, FallbackValue='MyApplicationHeader'}"                    TextWrapping="NoWrap" />

My MyApplicationHeader key will need to be added in resources.resw with a value as follows:



Next we will need to structure our application to with a folder string at the root of the app, this folder will also need to add a folder en and then add a resource file that we will call: Resources.resw

It should look as follows:




Next you will need to install Multilingual App Toolkit v4.0 (VS 2017), which you can find here. Once installed in Visual Studio under Tools your should see Multilingual App Toolkit:

you will need to Enable selection in the Multilingual App Toolkit.


Next you are going to need to install the Multilingual App Toolkit 4.0 Editor.

Now we are going to add translation languages to the application, again make sure you have enable Multilingual App Toolkit in your UWP application next click on the project, select Multilingual App Toolkit and click on Add translation as follows:



I will add french:



A new folder should be created inside you Strings folder:


We are going to right click on the project and use automatic translate from English to French using machine translations:



If you select Generate machine translations and you have errors most likely the issue is that you don't have the correct credentials to use Cognitive Services, you can fix this by reading this.

Once you have fixed your credential issues or if you don't have any issues you should see that the resources file under fr has been updated with french translated strings:



Now to test this new language you can force your application in French by overriding the application language as follows:


 Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "fr"

Happy coding!