Version 3 Release
We took our time, but we feel version 3 touched everything and we did it in our free time, so its a pretty huge release. Everything from new platforms, new features, new architecture, smaller footprints and new documentation. We hope you like it.
There’s a ton to talk about and we’ll only scratch the surface here. Be sure to check out our Shiny NEW Shiny documentation for more information.
Features
MAUI Support + .NET 7 + Mac Catalyst
One of our biggest features was our own hosting framework to allow Shiny to plugin into any of the .NET ecosystem including classic Xamarin targets because even some of my applications aren’t moved yet. We’ve also added Mac Catalyst support to almost all of the Shiny modules.
Obviously, our prime target with v3 though… was .NET MAUI. .NET MAUI makes it easier than ever to get going with Shiny or any other ecosystem plugin.
To get Shiny working with MAUI, install Shiny.Hosting.Maui from nuget and add the following to your MauiProgram.cs
HTTP Transfers
HTTP Transfers is honestly, one of the most key components to most apps these days. Any apps that are sending photos, videos, or other large files need to be able to do this in the background as users tend to “fire and forget” (add the photo, return to home screen). I’m also surprised how many apps do downloads these days, but show indeterministic spinners…!? Let me know how long you think things are going to take and how much progress has been made. This is another mechanism that is available as part of v3.
As much as you would like to just open up an HTTP client, download a file or upload a stream to a directory… it doesn’t quite work like that on native platforms. iOS & Android
will both kill your transfer within seconds of the app going to the background… unless you play by the rules. On iOS, you hand over to a native process to let it do the hard work.
On Android, well… you get the HTTP client, but you need to do something to keep it alive. There is a built in download manager in Android, but it’s old and doesn’t offer a ton of features, so
we ditched it.
Let’s take a look at how to setup just basic background transfer for now. We’ll cover other features in the docs and future blog posts:
First create your delegate
Next, add it to your MAUI app builder or host builder setup
Finally, queue up your transfer(s) for upload or download - let them carry on in the background without a worry
GPS & Geofencing
MAUI/Xamarin Essentials are great. They hit all of the platforms. Once you get past the essentials though and get into big enterprise applications, you need some stronger issues. The only provider currently offering full blown background GPS tracking for Android & iOS on .NET.
Geofencing hasn’t changed much from v3 API wise and still continues to be the only known geofence provider for .NET mobile.
BluetoothLE
With BLE, we reevaluated the entire API surface for simplicity while shedding some of the fat.
First off, When working with a peripheral, all methods are fired from the peripheral instead of digging down into the service and characterisitic objects. Undernearth the hood, we can keep track of all the characteristics properly across connections which is notoriously a difficult problem with BLE.
As part of our simplified API, we’ve also introduced many Task/Async based methods where you don’t need the full power of reactive extensions.
You’ll notice all of the methods above use strings for UUID arguments. In version 2, we used GUIDs which made it harder for users to work with 16bit UUIDs.
And lastly, in version 2, we have the Managed Peripheral that took care of things like reconnecting, rehooking characteristics, and funky stuff that generally makes BLE hard. This is now all built into the regular peripheral. As long as you hook a characteristic, we’ll restore it across connection blips and disconnections.
BEFORE - you would have had to monitor the IPeripheral.WhenConnected(), then get the characteristic, and lastly hook it. This sucked and it wasn’t without its pain.
We’ve also taken the time to review and remove a lot of junk code that just wasn’t needed in our efforts to reduce our footprint.
BluetoothLE Hosting
We’ve made all of our events async which is a big deal in the fact that everything is async these days. We also added a new “managed model” that makes setting up a hosted characteristic dead simple. Check it out:
Periodic Job
Periodic Jobs as a whole looks the same, but under the hood - we’ve made a bunch of improvements to cleaning out old jobs (type was deleted or moved will now remove the job) and ensuring system jobs are registered “fresh” every time to ensure consistency. We’ve also made jobs work much like our stateful services where you can make your job look like a viewmodel and have its state persisted across app restarts and runs with nothing more than a simple get/set mvvm style.
We’ve also added a base job that you can have to record things
Example of stateful job
Push Notifications
This is one of our “smaller” modules, but we still love it. Push providers come and go, but the underlying push mechanisms remain the same. As such, we’ve split the provider from the native mechansim and thus allowing you to work with the native mechanism the same way all the time, but plugging in a provider “on top” that Shiny will call into. Take a look at our Push Provider Documentation for more info.
Out of the box, we obviously support native, but we also support basic features for Azure Notification Hubs and Firebase (Android Native, but also iOS)
Push is small in terms of feature set.
- Ability to swap providers in one line of code
- We handle all of the underneath complexity to receive notifications & manage the incoming entry (user tapped on the notification)
- We deal with all of the registration/deregistration of the native tokens (as well as when they update). All of those weird corner cases are covered
Local Notifications
We believe we offer the best of breed in local notifications for Xamarin/MAUI ecosystem. Local notifications are more of a “bonus feature” with Shiny, but you end needing them in so many background scenarios that we continue to build on our module. This is actually one of the more feature rich modules due to the vast amount of features (and complexities) in the native notification API surfaces.
In v3, we added a bunch of new features:
- Geofencing Notifications for Android & iOS
- Repeat Interval Notifications - Great for reminders
- Android 13 Permissions
- On Android, we moved off our job engine and on to the Android alarm manager to allow for precision times on notifications
- Native Arguments on iOS & Android (great in multitarget projects) - Honestly… there is so many argument differences between iOS & Android, we had to do this.
App Background Centric Logging
Nothing special here - just the entire way you log your backend. Background services, unlike foreground debugging, are hard to hit. Thus, you need to write to an online service like AppCenter or perhaps a local SQLite database so you can read it back later. We built our loggers against the excellent Microsoft.Extensions.Logging.
Our AppCenter logger hasn’t changed at all for v3, but we added Shiny.Logging.SQLite for local test logging. Our templates include a page for reading the SQLite logs when you install the SQLite logger.
App Centric Logging
Shiny.Extensions.Configuration adds platform embedded JSON configuration to the Microsoft.Extensions.Configuration library. What’s really cool for this library is that you can configure for all or on a per platform basis.
- AppSettings.json - used by ALL platforms
- AppSettings.apple.json - used by iOS & Mac Catalyst
- AppSettings.ios.json - iOS only
- AppSettings.maccatalyst.json - Mac Catalyst only
- AppSettings.android.json - Android only
Other Features
We still have our speech-to-text module (Shiny.SpeechRecognition), but now that this exists in the Maui.CommunityToolkit, we will be deprecating this module in the future. We also have our iBeacon library. We’ve updated it to use Android foreground services when monitoring. For the most part, Beacons seem to be dying off. We aren’t deprecating beacons at this time since it isn’t a ton of work to keep around.
Architecture
A nasty comment we hear from the “not so nice” consumer base is how “Shiny tries to do too much”. This actually isn’t true. Our Core in v2 did have a lot of support functionality for our modules, but it was trimmed when it wasn’t needed. We’ve taken this a step further by separating support modules out to secondary libraries and linking them into modules where they are needed.
Hosting Model
Our Core module now only contains our truly core functionality including hosting. Some will ask, well why hosting if MAUI already has it? Well - the .NET application ecosystem is fragmented right now. Some users are stuck on Xamarin Forms, Xamarin Full Native, some are moving to MAUI, and some are even looking at newer pastures like Uno Platform. Our hosting model allows us to plugin into this different ecosystems and gives us 1 plugin base to rule them all.
Dependency Injection All The Way
We believe strongly in dependency injection for clean architecture. Many users have certain logging and configuration needs, along with their own sets of services that they make use of in Shiny delegates. This would be very hard to enable without dependency injection. It allows for a very pluggable & testable model. We realize some don’t like this, but this is unfortunately a hill we will die on. For those places where DI can’t reach, Shiny has Shiny.Hosting.Host.GetService for you.
Reactive Extensions
Core parts of Shiny are built with Reactive programming especially our BluetoothLE module where things like configurable timeout, method chaining, and event structure matter. We understand this can sometimes present new paradigms to users, so we add async equivalent methods where applicable. Please review our BluetoothLE feature set above.
Some won’t like Reactive programming and that’s fine - as with any free open source, you can use other libraries. We don’t like events, they leak memory and lack functionality that is easily available in RX. Even the C# inventors have said they regret events.
Documentation
We have new documentation - you’re in it already :) We think its starting to look pretty awesome. We’ve built it using the amazing Astro Build for those who are curious.
There will be some gaps at the time of our release, but we continue to improve things. Feel free to contribute as we can use all the help we can get!
Have an existing app and just need to get a list of what configuration you need to plug Shiny into your app, take a look at our new App Builder that will give a list of every piece of boilerplate you will need to add. Simply select the Shiny libraries you want and let it show you the rest.
Templates
Our templates make starting net new apps a breeze with support for many popular Xamarin/MAUI 3rd party libraries including Shiny. Our template takes care of setting up ALL of the boilerplate plists, manifests, projects, etc and works for Visual Studio for Windows & Mac (2022)
To Install - simply run the following from command line
dotnet new install Shiny.Templates
Check out all of the options in this monster
Samples
Our samples do fall under the “kitchen sink” category, but we cover almost everything you can do with the library. We use Prism & ReactiveUI within our samples, but you don’t need them. It just makes life easier for us to build the samples, but you don’t need them to use Shiny. Our samples also include some basic APIs to show you how to use ASP.NET Core to receive and send HTTP transfers.
The Road Ahead (Roadmap)
We have a ton of modules that we haven’t released to the wild and are considering bringing out piece by piece. Shiny was a platform to build on top as our its modules.
We have already started work on WebAssembly along with some preliminary work on Windows. Windows is not a platform that I currently work on, so any contributors are certainly welcome!
Be Kind
Remember, this is all given away for free. Don’t like something, offer constructive and POLITE feedback. Please also understand that feedback doesn’t mean we’ll change something, but we want to make something MOST people will like. I also make mistakes, so bugs, oversights, missed features will happen!
Have some of that constructive & polite feedback - go here and let us know GitHub Issues