Using iBeacons and Eddystone in Xamarin Forms

I’m working on a project where I need to get temperature from a wireless sensor into my phone app.  The exact sensor doesn’t matter – it just needs to be inexpensive.  Decent battery life would also be nice.  And so began yet another typical “searching for a sensor” trip for me.

After a little research, I ordered a SensePeanut.  Looked great.  Decent prototype cost. Available off-the-shelf and in a package.  Just what I need!  Except I got it in hand only to find out that you can get data from it only using their app, which they don’t give out the source for.  Soon they’ll have a “cloud SDK” that will let me get the data, but for a whole host of reasons, that just isn’t an option.

So I did a bit more research.  I needed a sensor that provided a “direct to the sensor” SDK.  I ended up ordering some proximity beacons from Estimote.  Proximity isn’t what I’m after, but they also can transmit temperature so it seemed promising.

Well last weekend I finally got time to start writing code.  Turns out that the SDKs they provide are, at least as far as I can tell, native binary SDKs for iOS and Android.  I’m a C# dev this week and I really want this to be cross platform, but they don’t have a Xamarin SDK.  Someone at Xamarin did create an SDK for the devices a few years back, but that project doesn’t actually work with the latest Android SDK – discovery returns nothing.  Evidently that’s not uncommon when using a library built against an older Android SDK.

Well it’s turns out that the existing Xamarin library is really just a bindings library that wraps the Java SDK.  So let me get the latest Estimote SDK and recompile.  Well, evidently the Estimote SDK is now deployed through JCenter (think NuGet for Java).  That appears to require that I install Java tools and I really have no desire to pollute my working machine with a toolchain I don’t intend to use.  No idea what can of worms that might open.

They don’t appear to have an AAR download, nor do they have the source for the SDK available – only source for some sample apps.

A little reverse-engineering with JCenter, however, let me to find the URL to direct-download the AAR.  I pulled it down and created a Xamarin Bindings Library project targeting it.  This is my first attempt at a Binding Library, but how hard could it be, right?  Turns out that the project generates a load of error, and this is not at all uncommon for a Bindings Library. Auto-generating wrapper code is hard, I realize that.  But I really don’t have the desire, or especially the time at this point, to climb the learning curve for Bindings Libraries, especially since I just want to read a simple temperature.

Maybe the existing Xamarin project can be used against the new Estimote AAR?  Surely the original dev had to solve these errors, right?  I loaded up the existing project and stuffed in the newer AAR.  Build and…still a bunch of errors.  Admittedly only about half the errors than the new project had, so it’s progress, but still isn’t getting me data.

I then spent a few hours reading and working on the project.  It’s a steep learning curve with not a whole lot of “Bindings-Libraries-for-Dummies” tutorials out there.  I got rid of maybe half the errors (the easy ones) and then got stuck.

Time to pivot again.  There’s got to be a way to do this.  Back to researching.  I found a Windows 10 C# library that can read data from iBeacons and Eddystone.  The Estimote can be configured to transmit the temperature in an Eddystone telemetry packet so that seems at least somewhat promising.  At least I have full source for the library.

I ran the sample app on my laptop and, lo-and-behold, I see temperature data which is hugely promising. Again, it’s a Windows 10 library but I’ve been making a career out of making desktop code mobile for a long time so it’s certainly in my wheelhouse.

First task was to port the library to .NET Standard so I’d have some expectation I’d be able to use it over on Android and iOS.  That required extracting the actual Bluetooth packet discovery out to an interface that was platform-specific.  The starting code was pretty well thought out and constructed so the task was not too hard and I actually had a UWP app receiving and displaying the data in just a couple hours.

The next job was to create the Android implementation of the Bluetooth discovery bits.  The UWP platform provided the Bluetooth data in a really nice format.  I’m sure it looks that way since the starting code I was working with was built specifically for it.  Fitting the reality of the packets that we get in Android into that structure wasn’t straightforward, but since Bluetooth and Eddystone are well documented it also wasn’t overly difficult.  It took me about a day of working with it to understand the spec well enough to get the incoming packets integrated into library.

I got a hold of Andreas Jakl, the original library author, let him know about my fork, and requested collaborator status.  He was gracious and added me to the project so my changes have all be back-integrated into the original tree, as well as fixes to the original sample non-Xamarin UWP app to use the new libraries.  We’re in teh process of getting the new stuff out as NuGet packages.

Getting BLE temperature data into my app certainly wasn’t as straightforward as I had hoped when I first ordered a sensor.  In fact, the journey to get there was nothing like what I’d hoped, or even expected once I started trying to write code for it.  In the end, however, I got it working (well in UWP and Android anyway, iOS will have to wait until I start porting the app that started this whole thing) and the work is public and open source.  I still have to manage the beacons with vendor-specific apps, which still irritates me, but at least we all now have a generic way to receive data from BLE beacons in our .NET apps.

 

OpenNETCF.Google.Analytics improvements

My original plan when building up the OpenNETCF Google Analytics library (which provides GA support to Xamarin Forms apps) was to make it 100% PCL.  A fine goal, but it turns out that it was unrealistic for a single reason: the User Agent string.  My original implementation had a “user agent generator” that successfully would tell GA whether you were using an Android or iOS device, but getting any finer grained was really not a simple task.  I considered – very, very briefly – keeping a long list of user agent strings and trying to figure out which one to use based on the platform, but that sounded like an unmaintainable nightmare.  Instead, I had to create a simple native piece for each platform for something that seems pretty basic.

In iOS, this was all that was needed:

using (var webView = new UIWebView(CGRect.Empty))
{
    m_userAgent = webView.EvaluateJavascript("navigator.userAgent");
}

In Android it was even less:

m_userAgent = Java.Lang.JavaSystem.GetProperty("http.agent")

But it had to be done native.

I’ve updated the library in NuGet, and now GA will show you exactly what type of device was connected and tracking, which I feel was more than worth the added complexity.

Xamarin Forms Navigation with OpenNETCF IoC

The OpenNETCF IoC library has been around for a long time.  I needed a DI container that was simple and fast that provided some cool features like event aggregation and module plugins.  I still use it heavily in every project I work on.

When I started working with Xamarin Forms, I still needed a DI container.  Now I know that Xamarin provides one, but I already know how to use OpenNETCF’s IoC and the syntax for it is pretty much muscle memory for me at this point.  I didn’t want to learn a new paradigm when the one I have solves the problem just fine and it will let me continue to use the same syntax on Windows desktop, Web APIs, Xamarin and still the occasional Windows CE project.

The lack of Reflection support in a PCL assembly forced me to rework things a bit, so I lost event aggregation and plug-ins, but it’s still a really simple and fast DI container that supports both singletons and named instances.

What was missing, however, was a navigation structure.  So I created one and added it to the Xamarin build of IoC.  Here’s a very, very quick overview of how you can use it.

The NavigationService class is the root of what you’ll you and it’s a static to make it easier to use.  I don’t want or need to create or find an instance of it every time I want to use it.

The first step is to create a View/ViewModel pair.  The View must derive from Page.  The ViewModel must implement the provided IViewModel interface (which simply implements INotifyPropertyChanged and nothing else at this point).  Basically it’s a near drop-in for any Xamarin Forms project.

So let’s assume I have a simple app with two pages: Home and Detail.

I’d create the following classes: HomeView, HomeViewModel, DetailsView and DetailsViewModel.  The Views are just the out-of-the-box Pages.  The ViewModels would simply derive from IViewModel and add in the PropertyChanged event (which you probably have already).

Setting things up for using the Navigation service is straightforward.  You simply register the View/ViewModel types.  Note that you don’t actually create any instances of the Views or ViewModels:


NavigationService.Register<HomeView, HomeViewModel>();
NavigationService.Register<DetailsView, DetailsViewModel>();

This registration tells the NavigationService the relationship so that when you need to display a View, it can ensure that the ViewModel also exists and then it can inject it as the BindingSource for you.

Once we’ve registered our Views and ViewModels, we can start up the app like this:


NavigationService.SetMainView<HomeView>(true);

Things to note here are that we don’t directly set the Application.MainView, we simply tell the navigation service the Type we want to use.  We also pass in true here as a parameter to tell the service we want it to wrap the Page in a NavigationPage for us.  If your MainView already derives from NavigationPage, you’d pass in false. Yes, this could probably be made automatic, but for now it’s not.

Now that you have you main page, you can navigate between pages forward and back.  For example, to go from the MainView to the DetailsView, you’d use this (true telling the NavigationService to show animation for the navigation):

 NavigationService.NavigateForward<DetailsView>(true); 

And if you’re on the DetailsView and you want to go back?  That’s as simple as this:

NavigationService.NavigateBack(true);

Google Analytics for Xamarin Forms

I recently needed to add Google Analytics support to a couple Xamarin Forms applications I am working on.  I was a bit surprised that I didn’t find anything that was simply ready-built out in NuGet – it seems like a lot of people would, or at least should, be using some form of analytics for their mobile applications.

Since I’m a fan of generating APIs, and since I like freely sharing things that aren’t part of core business functions, I wrote a simple PCL library, pushed the code out to Github and published it to NuGet.

I didn’t add everything that GA supports – I don’t currently need features for ECommerce or Social Interactions.  What it does provide it the ability to publish Events, Screen Views and Timing information.

First, you’ll need a GA account and then a Tracking ID for your application.  Once that’s done, you just spin up an AnalyticsService instance:

var analytics = new AnalyticsService("UA-XXXXXXXX-X", applicationName: "My Xamarin App");

That’s all there is to it.  You’re now ready to start tracking.  GA has the ability to track things in a “session”, which allows you to get a feel for all of the activities a user did during that session.  I typically start a session when the user opens the app or logs in, and close the session when they leave or log out.  It’s as simple as this:

analytics.TrackSessionStart();

// do stuff you want to track

analytics.TrackSessionEnd();

Tracking a screen view is just as simple:


analytics.TrackScreenView("HomePage");

If you want to track a specific event, let’s say a user clicking on a button click (Help, for example), you’d simply do something along these lines:


analytics.TrackEvent("user action", "button click", label: "help");

If you want to keep track of how long something takes – anything from data loads to how long a user sits on a page or whatever, you can track Timing like this:


analytics.TrackTiming("navigation", "Screen1", 5000);

While these are powerful, they do require you as a developer to do a fair bit of work to track everything you want.  To simplify that, I also added support for GA directly into the OpenNETCF IoC library’s NavigationService.  I’ll do a separate blog entry on how that works, but basically all you have to do is initialize tracking with your Tracking ID and the NavigationService will track all of your screen changes and timings for you with zero added code on your part.