Skip to main content

device_profile 0.1.1 copy "device_profile: ^0.1.1" to clipboard
device_profile: ^0.1.1 copied to clipboard

What the device is, in one read: its marketing name instead of the hardware code, its kind (phone, tablet, watch, TV) and whether the display is round.

device_profile #

pub package

A Flutter plugin that tells what the device is, from one read of the platform:

  • its name - "Redmi 9A", "Galaxy XCover 5", "iPhone 12 mini" - instead of the hardware code the platform reports ("M2006C3LG", "SM-G525F", "iPhone");
  • its kind - phone, tablet, foldable, watch, TV, car, desktop or headset;
  • the shape of its display - round or rectangular, which Flutter cannot tell: a round Wear OS face and a square one are both a square window to it.

A sessions screen needs the name: Build.MODEL is a code nobody recognizes on many Android phones, and on every iPhone it is just "iPhone". A watch layout needs the shape. Both come from what the device itself carries, read once. No single field holds the real name on every phone - each maker keeps it somewhere else; this plugin knows where, reads it, and picks the best one.

Features #

  • The maker's own name - read where each maker keeps it: Samsung, Xiaomi/Redmi/POCO, OPPO, realme, OnePlus, Huawei, Honor, vivo, Lenovo, Motorola, Tecno/Infinix/itel, ZTE/nubia, HMD, Sony, Asus, LG and more.
  • Never a wrong device - codes, placeholders and codenames are rejected; when nothing better is there, you get the brand and the code ("Samsung SM-G525F") and isMarketingName tells you so.
  • The device kind - phone, tablet, foldable, watch, TV, car, desktop or headset, for the right icon.
  • The shape of the display - round or rectangular, as Android's Configuration.isScreenRound reports it. A round Wear OS face and a square one are both a square window to Flutter; a watch layout that keeps clear of a round bezel needs to know which one it is on.
  • The user's own name, only if you want it - "Anna's XCover 5" tells two Galaxies apart, but it can carry a person's name, so it is off unless you ask.
  • Ready for a sessions list - fullName with the brand in front, a userAgentToken safe for a header, and distinctLabels for two devices that share a name.
  • Offline and small - no network, no device database: only what the device itself carries, plus a table of Apple identifiers.
  • No permissions, never throws.

Requirements #

  • Flutter 3.47 or later.
  • Android 7.0 (API 24) or later, built with Android Gradle Plugin 8.13 or later.
  • iOS 15 or later.

Installation #

dependencies:
  device_profile: ^0.1.1
flutter pub get

Usage #

import 'package:device_profile/device_profile.dart';

final device = await const PlatformDeviceProfile().read();

device?.name.name;            // "Galaxy Tab A7"
device?.name.fullName;        // "Samsung Galaxy Tab A7"
device?.name.isMarketingName; // true - false when only the brand and the code were left
device?.name.source;          // NameSource.factorySetting - where the name came from
device?.kind;                 // DeviceKind.tablet
device?.screenShape;          // ScreenShape.rectangular - ScreenShape.round on a round Wear OS face

read() returns null only on a platform it does not support (web, desktop) or when the platform could not be asked. The device is asked once; later calls answer from memory.

The name the user gave the device #

const PlatformDeviceProfile(userAssignedName: UserAssignedName.preferred);
Mode What you get on a renamed Galaxy XCover 5
never (default) "Galaxy XCover 5"
fallback the maker's name, and the user's name only where the maker's is missing
preferred "Anna's XCover 5" - the user's name first; a phone never renamed still gets "Galaxy XCover 5"

On iOS an app cannot read the name the user gave the device, so every mode gives the model name.

A list of devices #

// For a User-Agent header or any one-line field: no ; ( ), ASCII only.
device.name.userAgentToken; // "Lenovo Tab M8 [4th Gen]", "Ганна's M32" -> "%D0%93...'s M32"

// Two devices with one name:
distinctLabels([
  (name: 'Galaxy S24', detail: 'Android 15'),
  (name: 'Galaxy S24', detail: 'Android 14'),
]); // ["Galaxy S24 (Android 15)", "Galaxy S24 (Android 14)"]

Uri.decodeComponent turns a userAgentToken back into the name.

The same escaping is there for any other value that goes into the same header, such as the model you send when read() gave no name:

userAgentToken(device?.name.fullName ?? model); // model as device_info_plus reports it: "SM-G525F"

Testing #

Depend on the DeviceProfileReader interface and pass a fake:

class FakeDeviceProfile implements DeviceProfileReader {
  @override
  Future<DeviceProfile?> read() async => const DeviceProfile(
    name: DisplayName('Pixel 9', NameSource.model),
    kind: DeviceKind.phone,
    screenShape: ScreenShape.rectangular,
  );
}

Where the name comes from #

Platform Source
Android Only the keys of the device's own maker are read, in this order: the maker's factory name in settings (Samsung default_device_name, Huawei unified_default_device_name, vivo's hotspot name), the maker's marketing properties (ro.product.marketname on Xiaomi, ro.vendor.oplus.market.name on OPPO/realme/OnePlus, ro.config.marketing_name on Huawei and so on), Build.MODEL when it already is a name (Pixel, Motorola), the brand and the code.
iOS The hardware identifier (iPhone13,1) looked up in a table of Apple identifiers; the identifier itself for a device newer than the table.
Others null.

The kind comes from the Android system features, the build's own ro.build.characteristics and the screen width, or from the iOS interface idiom. The shape comes from Android's Configuration.isScreenRound; on iOS it is always rectangular, since no iPhone or iPad display is round.

Things to know #

  • A few vivo models keep their name from apps. vivo Y100, Y22 and Y21 carry no name an app may read; they get the brand and the code ("vivo V2239").
  • Honor and Asus keys come from firmware research and have not been run on a real phone yet.
  • New iPhones need the table updated: dart run tool/apple_identifiers/generate.dart, with tool/apple_identifiers/overrides.json for models the upstream list does not have yet.
  • The user's name is personal data. Keep userAssignedName at never unless the name stays with the user, such as a list of their own devices.
  • The name is as the maker writes it - "motorola edge 50 fusion" in lower case, "Lenovo Tab M8 (4th Gen)" with parentheses. Use userAgentToken where those characters matter.
Verified devices - 42 Android devices and two iOS simulators

The example app at targetSdk 36. The kind is phone unless the name says otherwise. "Run": device - a device at hand; BrowserStack - a BrowserStack App Live device; BrowserStack values - the values a BrowserStack device reported, the name checked by a unit test; simulator - an iOS simulator. preferred is the name in that mode where it differs; (owner) stands for the name of the person who renamed the phone.

Maker Device Android Name Source preferred Run
Xiaomi Redmi 9A 10 Redmi 9A ro.product.marketname Redmi 9A (persist.sys.device_name) device
Xiaomi Redmi A5 15 Redmi A5 ro.product.marketname device
Xiaomi Redmi Note 11 11 Redmi Note 11 ro.product.marketname BrowserStack
Xiaomi Redmi Note 12 4G 13 Redmi Note 12 ro.product.marketname BrowserStack
Xiaomi Redmi Note 12 Pro 12 Redmi Note 12 Pro 5G ro.product.marketname BrowserStack
Xiaomi Redmi Note 13 Pro 5G 14 Redmi Note 13 Pro 5G ro.product.marketname BrowserStack
Xiaomi Redmi Note 14 Pro 5G 15 Redmi Note 14 Pro 5G ro.product.marketname BrowserStack
Samsung Galaxy XCover 5 14 Galaxy XCover 5 default_device_name (owner)'s XCover 5 device
Samsung Galaxy M32 13 Galaxy M32 default_device_name (owner)'s M32 device
Samsung Galaxy Tab A7 12 Galaxy Tab A7 - tablet default_device_name device
Samsung Galaxy S26 16 Galaxy S26 default_device_name BrowserStack
Samsung Galaxy S22+ 12 Galaxy S22+ default_device_name BrowserStack
Huawei nova 11i 12 HUAWEI nova 11i unified_default_device_name device
Huawei nova 11 SE 12 HUAWEI nova 11 SE unified_default_device_name, brand added BrowserStack values
Huawei nova 13 12 HUAWEI nova 13 unified_default_device_name, brand added BrowserStack values
Lenovo Tab M8 (4th Gen) 13 Lenovo Tab M8 (4th Gen) - tablet ro.odm.lenovo.series device
Google Pixel 9 17 Pixel 9 Build.MODEL device
OPPO Reno8 T 5G 14 OPPO Reno8 T 5G ro.vendor.oplus.market.name BrowserStack
OPPO A78 5G 13 OPPO A78 5G ro.vendor.oplus.market.name BrowserStack
OPPO A54 11 OPPO A54 ro.vendor.oplus.market.name BrowserStack
OPPO A96 12 OPPO A96 ro.vendor.oplus.market.name BrowserStack
OPPO F29 5G 15 OPPO F29 5G ro.vendor.oplus.market.name BrowserStack
OPPO K14x 5G 16 OPPO K14x 5G ro.vendor.oplus.market.enname BrowserStack
realme 11x 5G 13 realme 11x 5G ro.vendor.oplus.market.enname BrowserStack
realme 12+ 5G 14 realme 12+ 5G ro.vendor.oplus.market.name BrowserStack
realme P3 5G 15 realme P3 5G ro.vendor.oplus.market.name BrowserStack
realme P4 Power 5G 16 realme P4 Power 5G ro.vendor.oplus.market.name BrowserStack
OnePlus 11R 5G 13 OnePlus 11R 5G ro.vendor.oplus.market.name BrowserStack
OnePlus 12R 14 OnePlus 12R ro.vendor.oplus.market.name BrowserStack
OnePlus 13R 15 OnePlus 13R ro.vendor.oplus.market.name BrowserStack
OnePlus 15R 16 OnePlus 15R ro.vendor.oplus.market.name BrowserStack
Motorola edge 40 neo 13 motorola edge 40 neo Build.MODEL BrowserStack
Motorola edge 50 fusion 14 motorola edge 50 fusion Build.MODEL BrowserStack
Motorola edge 60 fusion 15 motorola edge 60 fusion Build.MODEL BrowserStack
Motorola edge 70 fusion 16 motorola edge 70 fusion Build.MODEL BrowserStack
Motorola moto g71 5G 11 moto g71 5G Build.MODEL BrowserStack
vivo V30 14 vivo V30 wifi_hotspot_default_name BrowserStack values
vivo T4x 5G 15 vivo T4x 5G wifi_hotspot_default_name BrowserStack values
vivo T5x 5G 16 vivo T5x 5G ro.vivo.product.release.name, brand added BrowserStack values
vivo Y100 13 vivo V2239 brand and code - nothing readable names it BrowserStack
vivo Y22 12 vivo V2207 brand and code (the name is only in bluetooth_name, closed to apps on API 32+) BrowserStack
vivo Y21 11 vivo V2111 brand and code (as Y22) BrowserStack
Apple iPhone 17e iOS simulator iPhone 17e - phone identifier table simulator
Apple iPad Pro 13-inch (M5) iOS simulator iPad Pro 13-inch (M5) - tablet identifier table simulator

The device kind was checked on Galaxy Tab A7 and Lenovo Tab M8 (tablet), Redmi A5, HUAWEI nova 11i and Galaxy M32 (phone) and both simulators; a round Wear OS emulator (192 dp) gave watch and ScreenShape.round. A foldable and a TV have not been run.

Repository #

Path What
lib/ the plugin
example/ an example app that shows the name, the kind, the shape and every source the plugin read
tool/apple_identifiers/ generates the table of Apple identifiers

License #

MIT - see LICENSE.

0
likes
160
points
184
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

What the device is, in one read: its marketing name instead of the hardware code, its kind (phone, tablet, watch, TV) and whether the display is round.

Repository (GitHub)
View/report issues

Topics

#device #device-info #android #ios #wear-os

License

MIT (license)

Dependencies

flutter

More

Packages that depend on device_profile

Packages that implement device_profile