Xiaomi Band 10 is a basic, inexpensive smartband that offers essential features for health tracking. Unlike Apple Watch or many Wear OS devices, you don’t have to recharge the device every other day. You can use it without a smartphone app (except for the initial setup), but having one installed will send current weather and notifications onto your wrist. The app doesn’t get in your way, and explicitly asks before syncing your data to the cloud (allegedly).
Unfortunately, the watchface selection is mediocre. The global version of Mi Fitness has only, like, 100 to choose from, most of them are too colorful and distracting (or just ugly), and you can’t create or install the custom ones.
Table of Contents
Installing another companion app
If you are a tech-savvy owner of an Android device, you can try replacing Mi Fitness with one of these apps:
-
Gadgetbridge. It’s open source and should support the Band 10 out of the box. Sadly, I couldn’t make it work. You need to extract a pairing key from Mi Fitness app logs. I’ve entered a valid key, yet I still couldn’t pair the device, I got stuck at the “Looking for a device” screen. The troubleshooting instructions didn’t help.
-
Notify for Xiaomi. It’s an ad-supported / paid app, and feels like it was designed by a programmer. The UI is all over the place, and uses AI-generated images, yuck! But it works just fine once I remove the “nearby devices” permission from Mi Fitness. Notify can automatically download extra watchfaces, or install files you’ve found online.
-
Modded versions of Mi Fitness. Please don’t. I wouldn’t trust a random person from Russia with my health data. But you do you.
That’s why I still use Mi Fitness as my main app, but I keep Notify installed with all permissions removed. This is my workflow for installing unofficial watchfaces:
- Open Mi Fitness and make sure everything is up to date.
- Open system settings for Mi Fitness, and remove the “nearby devices” permission.
- Open system settings for Notify, and add the “nearby devices” permission.
- Open Notify, ignore all popups (click on an empty space), and install a watchface.
- Don’t forget to undo steps 3, 2, 1.
Creating a custom watchface
Most tools for creating custom watchfaces are only “okay”. They all seem to be based on some components from closed-source Xiaomi SDKs. There’s absolutely no documentation on the file format, and everything is reverse engineered.
Currently, the best solution is Mi Create. It’s supposed to run on Linux, but even on Windows I had so many problems:
- Installed as administrator, it didn’t even start because it couldn’t create a log file.
- I was moving the widgets around, and one of these got their X position became
a
float. The file has been saved successfully, but it couldn’t be opened anymore. - One time, it removed some PNG files because I’ve had them assigned twice to one widget.
- Random errors and crashes; it has even managed to bring the
explorer.exedown once. - The cherry on top is a data source named… “Weather something”.
Before you start using Mi Create, I recommend you install a text editor with XML highlighting. Create a Git repository; commit early, commit often. Or make backups frequently.
You will also need to draw some images (backgrounds, icons, fonts, etc.) Using Paint or GIMP is fine, or you can write a little script that will generate PNG files for you. This Node.js snippet creates assets for digits 0 to 9. It requires the canvas library, see MDN docs on how to use it.
import { createWriteStream } from "fs";
import { createCanvas, registerFont } from "canvas";
registerFont("Jua-Regular.ttf", { family: "Jua" });
for (const text of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
const canvas = createCanvas(80, 100);
const ctx = canvas.getContext("2d");
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "red";
ctx.strokeStyle = "none";
ctx.font = '100px "Jua", "Comic Sans MS", sans-serif';
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(text, canvas.width / 2, canvas.height / 2);
const filename = `images/digit${text}.png`;
canvas.createPNGStream().pipe(createWriteStream(filename));
}
Current time
The widget selection is very limited but should be enough for many use cases.
Let’s start with displaying simple numeric values, which can be done with the
“Digital Number” widget. You need to prepare 11 images: numbers 0 to 9 and a
minus sign. They must have the same width and height. Copy these PNG files to
the images directory of your project.
Tip: Avoid using too many transparent images, otherwise the watchface may fail to install.
Click the “+” button, and choose “Digital Number”. Select a data source (hour, minute, etc.), set how many digits to display, and pick an image file for each digit.
At this point, it’s worth checking if the watchface can be installed at all.
Create a 212×520 preview image (it must match the band’s screen
resolution) and copy it to the images directory. From the application menu,
choose “Build” and follow the on-screen instructions.
The resulting .face file can be installed with Gadgetbridge or Notify. Here’s
the result so far:
Could not install?
- If the previous version of a watchface is already installed, you need to remove it.
- If there are more than 10 watchfaces installed, you need to remove some.
- Do not open the file directly from the file manager, start from the app instead.
- Make sure Bluetooth is enabled and that app can connect to the band at all.
Current date
You can add extra “Digital Number” widgets for the current year, month, and day. These can share the same image set, just make sure each digit gets its own PNG file.
You may have already noticed that the date format (DD/MM vs MM/DD) depends on the watchface layout, so you would have to create separate watchface variants for US and UK English.
The current weekday (Sunday, Monday, …) is a bit trickier because it is stored as a value between 0 and 6. The “Image List” widget is the best choice here, as it can have an image assigned to any positive or negative ID.
Tip: you can use the “Image List” widget to display the current hour using Roman numerals.
Bluetooth status
It would be nice to have a visual indicator for any Bluetooth connection issues. Just like the current weekday, there’s a finite number of possible states: 0 (disconnected) and 1 (connected). In other words, it’s a boolean value. We can use the “Image List” widget once again.
For the “disconnected” state, I’ve downloaded a matching Lucide icon. For the “connected” state, I’ve created a blank image; it’s a normal state that doesn’t require any action.
Battery status
You can display the current battery state as a number using a “Digital Number” widget. You can also show a simple battery icon from the same data source, using an “Image List”.
Don’t worry, you don’t have to create 101 images. If you skip some IDs, the watchface will decrement the data source value by 1 until there’s a match.
Example 1: If you specify icons for ID 0, 50, and 100, and the battery is 99% full, it will show an icon for ID 50.
Example 2: I want to see the battery indicator only when it’s between 0% and 15%. I’ve added an “Image List” with two IDs: 0 and 16, and it works like this:
(This table can be scrolled horizontally on mobile.)
| Battery state | Icon shown |
|---|---|
| 0% | Low battery icon (ID 0) |
| 15% | Low battery icon (ID 0) |
| 16% | Good battery - blank icon (ID 16) |
| 100% | Good battery - blank icon (ID 16) |
Current temperature
The current temperature in Celsius or Fahrenheit can be added as a “Digital
Number” widget, but the °C or °F suffix won’t be shown automatically, you
need a related widget for that.
First, make sure the temperature value widget is properly positioned (X and Y coordinates) and aligned (left, center, right). It will be difficult to change that earlier.
Create a new “Image” widget and choose a valid PNG file. If your temperature
widget is named temperature, rename your unit widget so that its name ends
with _ref[temperature]. It should automatically change its position.
It won’t be previewed correctly, but it should look fine on a real device.
Current weather conditions
This data source is annoying, for multiple reasons:
-
There is no list of possible weather states, and you can’t guess how many there are.
-
If you decompile the Mi Weather app for Android, you will find a list of 43 known states! Mi Fitness must use the same data source, because both apps have “Haze” at ID 53.
-
What the heck is haze, anyway? Is it just a fog? What’s the difference between these two and dust, sand, sandstorm?
-
That’s right, some IDs are unused, there are gaps between them. Xiaomi has their API at hlth.io.mi.com. What if it returns an unused ID after an update?
-
Even official Xiaomi watchfaces have only 18 weather icons. You can’t check what they are mapped to, because UnpackMiColorFace (shipped with Mi Create as
unpack.exe) can’t parse the metadata. -
Weather conditions seem to be sourced from AccuWeather, and they have terrible accuracy where I live. AccuWeather claims it’s 4°C, yet I can read -6°C on my outside thermometer, and there’s a snow crust covering my backyard since the past few days.
The list of possible weather states, sorted by ID, is listed down below.
(This table can be scrolled horizontally on mobile.)
| ID | State | ID | State | ID | State |
|---|---|---|---|---|---|
| 0 | Clear | 13 | Snow flurry | 29 | Dust |
| 1 | Cloudy | 14 | Light snow | 30 | Sand |
| 2 | Overcast | 15 | Moderate snow | 31 | Sandstorm |
| 3 | Shower | 16 | Heavy snow | 32 | Dense foggy |
| 4 | Thundershower | 17 | Snowstorm | 33 | Snow |
| 5 | Thundershower with hail | 18 | Foggy | 49 | Severe foggy |
| 6 | Sleet | 19 | Ice rain | 53 | Haze |
| 7 | Light rain | 20 | Duststorm | 54 | Middle haze |
| 8 | Moderate rain | 21 | Light to moderate rain | 55 | Heavy haze |
| 9 | Heavy rain | 22 | Moderate to heavy rain | 56 | Severe haze |
| 10 | Storm | 23 | Heavy rain to storm | 57 | Heavy foggy |
| 11 | Heavy storm | 24 | Storm to heavy storm | 58 | Super severe foggy |
| 12 | Severe storm | 25 | Heavy to severe storm | 99 | No data |
| 26 | Light to moderate snow | 301 | Rain | ||
| 27 | Moderate to heavy snow | ||||
| 28 | Heavy snow to snowstorm |
I want to have weather conditions displayed as text. But there’s no text widget, so I need to use an “Image List”. Adding 43 images to the widget would be a pain in the butt, but you can add a first few of them, then continue in any text editor.
If you only really care about the weather icon, maybe you can get rid of some states.
Example: If you’d like to see a generic rain icon, remove icons for ID 8, 9, 10, 11, 12. They will all fall back to ID 7.
Download
And that’s it. I haven’t explored other features, such as “Analog Display” widget, clickable elements, or animated backgrounds, simply because I don’t need them.
You can download watchfaces I’ve designed, both the source code and installable
.face files, from my
mb10-goodies repository.