Using Xamarin.Forms DependencyService to Read Device Battery Level in Legacy Apps
Learn how to use Xamarin.Forms DependencyService to read the device battery level from shared code, with a step‑by‑step example and best‑practice trade‑offs for legacy Xamarin projects.
11 Oct 2025, 20:07 UTC

The Problem: Shared Code Needs Native Data
In a Xamarin.Forms solution the majority of the logic lives in a .NET Standard library. That library can’t call Android’s BatteryManager or iOS’s UIDevice directly. If you need to show the battery percentage in a shared page you have to bridge the gap.
Why DependencyService?
The DependencyService is a lightweight service locator built into Xamarin.Forms. It lets you declare a contract in the shared project, implement that contract on each platform, and then resolve the implementation at runtime. It’s not a full dependency‑injection container, but it is the simplest way to keep platform code out of the shared layer.
Step 1 – Define a Contract
Place an interface in the shared project. Keep it minimal; only expose what the UI really needs.
public interface IDeviceBattery
{
int GetBatteryLevel(); // Returns 0‑100 or -1 if unavailable
}
Step 2 – Implement on Android
In the Android project create a public class with a public parameterless constructor. The class must be public for the service locator to instantiate it. Register it with an assembly attribute that lives outside the namespace block.
[assembly: Xamarin.Forms.Dependency(typeof(YourApp.Droid.BatteryService))]
namespace YourApp.Droid
{
public class BatteryService : IDeviceBattery
{
public int GetBatteryLevel()
{
var context = Android.App.Application.Context;
var batteryStatus = context.RegisterReceiver(null, new IntentFilter(Intent.ActionBatteryChanged));
if (batteryStatus == null)
return -1;
int level = batteryStatus.GetIntExtra(BatteryManager.ExtraLevel, -1);
int scale = batteryStatus.GetIntExtra(BatteryManager.ExtraScale, -1);
if (level == -1 || scale == -1)
return -1;
return (int)((level / (float)scale) * 100f);
}
}
}
Step 3 – Implement on iOS
The iOS implementation is similar in structure. Use UIDevice to read the battery level. Remember to enable battery monitoring in AppDelegate or before the call.
[assembly: Xamarin.Forms.Dependency(typeof(YourApp.iOS.BatteryService))]
namespace YourApp.iOS
{
public class BatteryService : IDeviceBattery
{
public int GetBatteryLevel()
{
UIDevice.CurrentDevice.BatteryMonitoringEnabled = true;
var level = UIDevice.CurrentDevice.BatteryLevel;
if (level < 0)
return -1;
return (int)(level * 100);
}
}
}
Step 4 – Consume in Shared Code
In any ViewModel or Page you can resolve the service. Always check for null because the registration may be missing or the platform may not support the feature.
public class BatteryViewModel : BindableObject
{
private readonly IDeviceBattery _battery;
public int BatteryPercent { get; private set; }
public BatteryViewModel()
{
_battery = Xamarin.Forms.DependencyService.Get();
if (_battery != null)
BatteryPercent = _battery.GetBatteryLevel();
else
BatteryPercent = -1; // Feature not available
}
}
Verification Checklist
- Build the solution – the compiler must not complain about missing references.
- Run on an Android device or emulator. The
BatteryServiceshould return a value between 0 and 100. - Run on an iOS device or simulator. The
BatteryServiceshould return a value between 0 and 100. - Remove the
[assembly: Dependency]attribute from one platform and re‑run.DependencyService.Get<IDeviceBattery>()should returnnulland the UI should handle that gracefully.
Trade‑offs and Limitations
- Service‑Locator Pattern – Because
Get<T>()is static, it’s harder to mock in unit tests. A common pattern is to wrap the call in an interface that can be injected into the ViewModel. - Fragmented Logic – If you overuse platform services, your shared code becomes thin and the business logic is scattered across platform projects.
- Deprecated Framework – Xamarin.Forms reached end‑of‑support in 2025. New projects should target .NET MAUI, which has a similar
IServiceProviderapproach. The DependencyService pattern still works in legacy Xamarin.Forms apps, but it won’t be available in MAUI. - Runtime Failures – Forgetting the assembly attribute or a missing public constructor results in
nullat runtime. Always guard against this.
Bottom Line
For a legacy Xamarin.Forms app that still needs native APIs, DependencyService is a quick way to surface platform data like battery level. Just remember its service‑locator nature and the fact that Xamarin.Forms is no longer actively developed. If you’re starting a new project, consider .NET MAUI’s dependency injection system instead.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.