Cross Platform C#
Track Your Fitness with a Fitbit and Xamarin
Wally shows you how to use Xamarin.iOS to create a pedometer app for a Fitbit that employs the CoreMotion Framework.
I’ve been a Fitbit user for several years. I enjoy using it, reading the material and hoping that if I push myself it will help my level of fitness (probably not). What I don’t like is that:
- It’s another device that I have to keep track of. Sure, it's on my wrist, but I still have to maintain it.
- I have to keep it charged. My current daily driver is a Fitbit Charge2 that holds a charge for seven days – that's great, but it still has to be charged. So, I also have to keep track of a charger, which adds to the hassle.
Those two things aside, I've found that the device's usefulness far outweighs the hassles. I've even developed a pedometer app for it, which I'll show in this column.
The app uses the CoreMotion iOS framework, which is used for determining number of steps walked/run.
Note No. 1: It will be a hassle to do some things with the iPhone. For example, trying to determine the number of steps taken while riding a bicycle will be somewhat problematic. You will be able to do other things with the iPhone, such as determine the distance traveled and such.
Note No. 2: This article features a native application using Xamarin.iOS.
CoreMotion
CoreMotion is an iOS framework that allows an application to receive information regarding the motion of the device and to then process that data. The framework contains a number of classes that allow it to access the motion events, including:
- CMAltimeter: Handles altitude-related information.
- CMDeviceMotion: Provides a set of measurements for the altitude, rotation rate and acceleration of a device
- CMMotionActivityManager: Provides access to the motion data that’s stored in a device. With this data, it can be determined if the user with the phone is walking, running, not moving, in a moving car and so on.
- CMMotionManager: As the gateway to the motion services, an application can determine the accelerometer, rotation rate, compass data and other motion information using this class.
- CMPedometer: Allows an application to track the step data the phone’s user goes through.
- CMSensorRecorder: Controls the gathering and recording of accelerometer data in a device.
There are additional classes, constants and other objects within CoreMotion, but this is just a quick overview of some of the objects that are available.
Hardware Requirements
There are a number of devices out in the iOS ecosystem. Not all of these devices are the most up-to-date. Does anyone really remember what the iPhone 5 supports? Instead of hardcoding in the application the devices and what they support, a better option is built into CoreMotion. CoreMotion allows you to query the device to see if it supports a given feature. Some of the features that are possible to query for are:
- IsCadenceAvailable
- IsDistanceAvailable
- IsFloorcountingAvailable
- IsPaceAvailable
- IsStepCountingAvailable
Thanks to these methods, an application merely calls these static methods on the CMPedometer class to determine what functionality is available on the specific hardware. These methods return true if the device supports the functionality and false if the device doesn’t support it.
Underneath iOS, there’s some hardware to provide support for these iOS calls. The hardware is the Apple motion coprocessors. The motion coprocessor, called the M7, was introduced with the iPhone 5s. Each new version of the iPhone has received an updated coprocessor. The coprocessors collect data even if the device is asleep. This reduces the power needed from the battery.
Note: To make a call into the hardware, the application will most likely need to have a security entry in the Info.plist file. For this specific example, you will need to set "Privacy - Motion Usage Description" to a value of YES.
Note: You will need to specify the reason for using motion data. This is done by setting the NSMotionUsageDescription in the Info.plist file.
Exercise That Code
Let’s take a look at some example code (Listing 1). In this code, a very simple UI is created with two labels. One label shows the number of steps that have been taken in the last 24 hours, and the other shows the phone’s current pace.
The code in Listing 1 itself is fairly simple. After the UI is created, a CMPedometer instance is created, and then a test is made of the device to see if it will support pedometer events. If that’s true, the number of steps taken in the previous 24 hours is determined. Finally, the current rate is displayed.
Listing 1: Pedometer UI Using CoreMotion
public override void ViewDidLoad()
{
base.ViewDidLoad();
uil = new UILabel();
var vwFrame = this.View.Frame;
uil.Frame = new CoreGraphics.CGRect(10.0, 50.0, vwFrame.Width - 20.0, 25.0);
this.View.Add(uil);
uilNow = new UILabel();
uilNow.Frame = new CoreGraphics.CGRect(10, 85.0, vwFrame.Width - 20.0, 25);
this.View.Add(uilNow);
cmp = new CoreMotion.CMPedometer();
}
public override async void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (CoreMotion.CMPedometer.IsPedometerEventTrackingAvailable)
{
cmp.StartPedometerUpdates(new Foundation.NSDate(), handlePedoUpdates);
var pedData = await cmp.QueryPedometerDataAsync((new Foundation.NSDate()).AddSeconds(
-86400), new Foundation.NSDate());
uil.Text = String.Format("Last 24 hours: {0}", pedData.NumberOfSteps);
}
}
public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
if (CoreMotion.CMPedometer.IsPedometerEventTrackingAvailable)
{
cmp.StopPedometerUpdates();
}
}
private void handlePedoUpdates(CMPedometerData data, Foundation.NSError error)
{
if(error == null)
{
InvokeOnMainThread(() => {
uilNow.Text = String.Format("Pace; {0}", data.CurrentPace);
});
}
}
The result of running this code and displaying it on an iPhone 7+ is shown in Figure 1, which shows that the phone had approximately 4,700 steps in the past 24 hours and was currently moving at a pace of about .86 meters per second. For this phone, that’s approximately correct. It also shows the most recent set of steps with the phone and the current pace of the device.
So, what should you do with this data? There are multiple options. Some of these are:
- Leave the content on the iPhone. There’s nothing wrong with leaving it on the phone and using it for future reference.
- Store the information in some type of database out on the Web. This would allow for easy cross-platform reporting on it.
- One of the ideas that I have always had is to use the information from movement in the health sciences area. Doctors could use this to determine the actual amount of aerobic exercise that patients were getting and prescribe necessary changes for a healthier outcome.
- Gym/fitness clubs and trainers could use this for assisting their customers, as well.
Note: There may be legal or ethical questions in using this data and with where it’s shared. I hope that organizations would consult their legal departments regarding how to use this data. No statement here is an indication that this meets any legal requirement.
Wrapping Up
Xamarin.iOS provides access to all of the features of the device. It’s fairly easy to access anything associated with the published iOS API. The Pedometer is one of these features that allows an application to provide a very personal experience to the phone’s owner.
Good luck!
About the Author
Wallace (Wally) B. McClure has authored books on iPhone programming with Mono/Monotouch, Android programming with Mono for Android, application architecture, ADO.NET, SQL Server and AJAX. He's a Microsoft MVP, an ASPInsider and a partner at Scalable Development Inc. He maintains a blog, and can be followed on Twitter.