Category

.NET

I ran into an issue where my Xamarin.Forms UWP app, which uses MvvmCross and SyncFusion SfCharts stopped showing charts once I created the app package for the Windows Store (i.e. created *.appxupload package with .NET native tool chain).

I went hunting for a fix and rather quickly found a post on the SyncFusion official support forum about that problem. I also found that there’s a official Knowledge Base article:

Post: https://www.syncfusion.com/forums/127258/chart-not-rendered-in-uwp-release-mode

Knowledge Base: https://www.syncfusion.com/kb/7149/how-to-make-syncfusion-xamarin-forms-chart-to-work-in-uwp-in-release-mode-when-net-native-tool-chain

Both saying the same thing, that one should go to their App.xaml.cs file and add an extra assembly (i.e. typeof(Syncfusion.SfChart.XForms.UWP.SfChartRenderer).GetTypeInfo().Assembly)
to their Xamarin.Forms.Init() parameter in the OnLaunched() method. Basically add this code:

Unfortunately, this doesn’t work with MvvmCross 6.1.2 (probably doesn’t work with 6.2.0 as well – haven’t checked though). The charts are still not showing, even though the SfCharts assembly got included.

I can’t be 100% sure of the reason behind this problem but I suspect it’s because of the fact, that MvvmCross framework is now handling the Xamarin.Forms initialization for you. Because of that the Xamarin.Forms.Init() method is called multiple times – once in the App.xaml.cs and once inside of the framework. Another assumption, based on the results we’re seeing, is that Xamarin.Forms.Init() works in a way that the last in is the one that gets served – meaning that if the App.xaml.cs call happens before the MvvmCross one, then the SfChart assembly is not going to be included and Native tool chain compilation will strip it out.

A bit more explanation on this: Mvx framework calls the Xamarin.Forms.Init() method inside of the base Setup file – MvxFormsWindowsSetup calling Xamarin.Forms.Init(). The remedy is simple, move the code from App.xaml.cs to the GetViewAssemblies() override in your Setup.cs file. The GetViewAssemblies() method is being called at the launch of the app by MvvmCross and it is designed to retrieve additional assemblies to pass as a parameter into the Xamarin.Forms.Init() method – which is exactly what we want.

That’s it – you should see your charts again!

 

I’ve stumbled upon this issue straight after I released my app into the store…

I did a brief search on the Internet what could be causing such behaviour and majority of posts were pointing at some issues with cached data by Google Play Store and/or Google Play Services somehow breaking installation process. They were suggesting cleaning cache of these to solve the problem. Combination of clearing cached data, uninstalling the app, restarting the device and even ejecting the SD card did not help

I didn’t give up though. I was fortunate enough to have a device at home, that I was able to reproduce this with. At least it showing some errors when trying to deploy and debug the app using Visual Studio – which was a good start. Each and every time I tried to deploy the app onto the device I was getting the error

ADB0010: Unexpected install output: Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/vmdl1021324914.tmp/base.apk (at Binary XML file line #28): <service> does not have valid android:name]

It didn’t tell me much, so I started googling it. Some of the StackOverflow posts (#1, #2) that I found were pointing me at the problem with package name capital letters. Yep, I did put some capital letters in my app name (i.e. com.progrunning.AirQuality, which ultimately became com.progrunning.airquality). I changed the name of the app in the AndroidManifest.xml but I was still getting that error…I had no choice but to check what’s actually being generated/added by Xamarin.Forms into the AndroidManifest.xml when packaging the app. I went to my bin\Debug folder, to try to unzip the generated *.apk file – *.apk is just fancy *.zip file. Unfortunately, at this stage the AndroidManifest.xml file in the *.apk is nothing but binary data. Which looks something like this when opened with Visual Studio Code:

Fortunately, thanks to this StackOverflow answer, there’s a way of reading what’s in the *.apk package. I located the aapt.exe file, where my android sdk got installed (in my case it was C:\Programming\SDK\Android\android-sdk\build-tools\27.0.3) and ran the command

aapt.exe l -a “C:\Programming\Projects\Own\AirQuality\AirQuality\AirQuality.Android\bin\Debug\com.progrunning.airquality.apk”

The above prints out quite a bit of stuff (you can probably narrow it with some pipes and grep commands – I’m no expert on these though), but we’re interested only in the AndroidManifest.xml file. From the error that I got when trying to deploy and debug the app I knew that something that prevents this from happening is located at the line 28. I finally got my answer:

I used capital letters for my background service (biggggggggggggg mistake!):

Changing it to lowercase fixed the issue

 

EDIT: The problem didn’t seem to be happening for the Android versions 8.0+. It was only affecting 6.0 and 7.0 (maybe more but these two versions are definitely confirmed)

EDIT2: I ended up with my app name having capital letters in it – that was not the problem

This topic is going to be sort of continuation of my previous post about SQLiteWrapperUWP-PCL – an SQLite Wrapper for Windows 10 UWP applications. I’m writing “sort of” because it’s actually an update to that post. The project part – setting up the solution – hasn’t changed but the code part has. Please understand that the SQLiteWrapperUWP-PCL library is being constantly developed and improved, hence I need to explain how things has changed and how one should implement their database logic with latest release of SQLiteWrapperUWP-PCL NuGet package BuildIt SQLite.

For those who are not very familiar with Windows 10 and UWP application development please, before you start going through what’s written in here, refer to my previous post about SQLite Wrapper for Windows 10 UWP applications, where you can find guidelines how to set up your solution / project.

For those who can’t be bothered reading and/or want to figure things out by themselves I recommend looking at the GitHub repository GitHub repository where you can find some short guidance / information about how things work with SQLiteWrapperUWP-PCL BuildIt (Sqlite). Also there’s a CRUD database operations example CRUD database operations example which could be a good place to start your explorations.

EDIT: Apologies to all that wanted to try out the SQLiteWrapperUWP-PCL and some of the links weren’t working, but SQLiteWrapperUWP-PCL evolved from its own existence, to become a part of a bigger set of libraries, called BuildIt. Those libraries are a foundation that we rely on, in almost every project that we create @BuiltToRoam, so besides working with SQLite check out others, I can bet you will like it and use it.

The Code

Let’s start from the Core project and setting up the DatabaseService.

The base class, that DatabaseService inherits from, is an abstract class BasicDatabaseService which is a exemplary implementation of BaseDatabaseService. Both of which sit in the SQLiteWrapperUWP-PCL library and expose the IBasicDatabaseService and IBaseDatabaseService interfaces. In this case, deriving from Basic service, one have to provide only the implementation of CreateDatabaseTables method, which is responsible for creating database tables, and provide some constructor parameters, about which in a second.

I think it’s worth noting that one is left with an option to derive directly from BaseDatabaseService and in that case it opens a path where one could provide their own SQLite database connection creation (implement CreateSQLiteConnection method) handling.

Let’s explain a bit about DatabaseService constructor parameters and its purpose.

  • ISqlitePlatformProvider consists of one child, and its purpose is to provide core SQLite platform functionality, basically it’s the “heart” or “spine” to the SQLite database.
  • IDatabaseNameProvider is nothing more but a “fancy” way of saying “if you want a database you need to give it a name it”. With this interface implementation you need to provide a database name, and that’s it – one string
  • Last but not least is the ILocalFileService which is necessary to provide a way of getting physical path – RetrieveNativePath method – where the database file will be saved (on a hard drive)

You can find exemplary implementation of all of those in the GitHub repository

NOTE: In almost all of my projects I use mvvm cross-platform framework MvvmCross, which I highly recommend, and with it, out of the box, comes Dependency Injection (IoC) mechanisms. Those mechanism under the hood, create and inject automatically singletons for mentioned above interfaces (constructor parameters). You can find out more about it in the N+1 days of MvvmCross blog posts and videos. For those who are familiar with it and to spare you some time looking for how it could be initialized, here’s a sample code from Setup.cs file

 

Important thing, that has been changed in the latest release, is BaseEntity class. It was redesign to consists the update of representation of the entity logic (update of the database record). For example:

There’re two things to note in the above code. First is to do with self-reference generic class in the class declaration. It was purely designed this way so we could handle the update logic inside of the Entity class, which is called from the BaseRepository every time the Update logic on the entity is executed. UpdateFromEntity method – second thing that one should be aware of – should be a place where entity update is being handled.

 

Assuming you have an instance of DatabaseService handy (e.g. created with MvvmCross DI mechanisms) and with all this setup / knowledge we can now start working with our database, and it couldn’t be any easier. To create new database record (entity) one could write something as follows:

To retrieve all the table records or just one:

To delete record:

Those are Base CRUD methods, but if you’d like to write more sophisticated queries you should look into BaseRepository and Table property. It will allow you to perform some LINQ queries on it. For example:

NOTE: As it’s not perfectly obvious, the CreateSQLiteConnection method won’t create a new one every time it’s being called, but it will take the cached one.

NOTE: Another thing is that not all LINQ queries will be valid in terms of translating them to what database understands, hence sometimes it’s better to grab all table records (entities) and perform some queries on the values stored in memory.

 

I would highly recommend checking out the GitHub repository and the sample that is in it, as it consists all of what I’ve just wrote about, and you can easily compile and debug that code.

 

NOTE: For inspecting SQLite database file(s) I recommend using SQLiteBrowser