unique_identifier_3 0.1.0 copy "unique_identifier_3: ^0.1.0" to clipboard
unique_identifier_3: ^0.1.0 copied to clipboard

A Flutter plugin for retrieving a device's unique identifier across Android, iOS, Web, macOS, Linux, and Windows platforms.

Unique Identifier #

pub package License: MIT

A Flutter plugin for retrieving a device's unique identifier across Android, iOS, Web, macOS, Linux, and Windows platforms.

Platform Method
🤖 Android ANDROID_ID (scoped to app-signing key, user, and device)
🍎 iOS UIDevice.identifierForVendor
💻 macOS IOPlatformUUID via IOKit (uses kIOMainPortDefault on macOS 12+, falls back to kIOMasterPortDefault for macOS 11)
🐧 Linux Reads /etc/machine-id
🪟 Windows Reads registry value MachineGuid from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
🌐 Web Attempts to read UUID from localStorage. If missing/invalid, generates from browser fingerprint. Falls back to random UUID generation. Stores result in localStorage for persistence.

Features #

  • Android: Retrieves ANDROID_ID (64-bit hex string scoped to app-signing key, user, and device)
  • iOS: Retrieves identifierForVendor (IDFV unique per vendor)
  • macOS: Retrieves IOPlatformUUID via IOKit framework
  • Linux: Reads /etc/machine-id
  • Windows: Reads MachineGuid from registry
  • Web: Generates/persists UUID via localStorage with fingerprint fallback
  • Cross-platform support with a single API
  • Privacy-compliant device tracking
  • Swift Package Manager support on iOS

Installation #

Add the following to your pubspec.yaml:

dependencies:
  unique_identifier_3: ^0.1.0

Then run:

flutter pub get

Import the Package #

import 'package:unique_identifier_3/unique_identifier_3.dart';

Usage #

Basic Example #

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:unique_identifier_3/unique_identifier_3.dart';

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _identifier = 'Unknown';

  @override
  void initState() {
    super.initState();
    initUniqueIdentifier();
  }

  Future<void> initUniqueIdentifier() async {
    String identifier;
    try {
      identifier = await UniqueIdentifier.serial;
    } on PlatformException {
      identifier = 'Failed to get Unique Identifier';
    }

    if (!mounted) return;

    setState(() {
      _identifier = identifier;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Unique Identifier Example'),
        ),
        body: Center(
          child: Text('Device ID: $_identifier'),
        ),
      ),
    );
  }
}

Platform-Specific Behavior #

Android #

  • Uses ANDROID_ID, a 64-bit hexadecimal string
  • Unique to each combination of app-signing key, user, and device
  • Value may change after:
    • Factory reset
    • App-signing key change

iOS #

  • Uses identifierForVendor (IDFV)
  • Unique per vendor across all apps from the same vendor
  • Value may change if:
    • All apps from the vendor are uninstalled and reinstalled

macOS #

  • Uses IOPlatformUUID via IOKit framework
  • Automatically uses kIOMainPortDefault on macOS 12+ (no deprecation warning)
  • Falls back to kIOMasterPortDefault for compatibility with macOS 11 and earlier

Linux #

  • Reads /etc/machine-id
  • Returns the machine ID as stored by the system

Windows #

  • Reads MachineGuid from registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
  • Returns the system's unique machine identifier

Web #

  • Attempts to read a UUID from window.localStorage
  • If the value is missing or invalid, it tries to generate one based on browser fingerprint
  • If fingerprinting fails, generates a new UUID using Dart code
  • The newly generated UUID is stored in localStorage for future reuse
  • Ensures the same UUID persists across reloads and sessions
  • Users can manually clear the UUID through browser storage settings

Notes #

  • On iOS and Android, the UUID may change after uninstalling and reinstalling the app
  • macOS implementation avoids deprecated APIs on macOS 12+
  • On Web, the UUID persists across reloads and sessions but can be cleared by the user

iOS App Tracking Transparency #

If your app uses tracking on iOS, consider requesting App Tracking Transparency (ATT) permission. Below is an example using the app_tracking_transparency package:

import 'package:flutter/material.dart';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:url_launcher/url_launcher.dart';

Future<void> initTrackingTransparency(BuildContext context) async {
  final status = await AppTrackingTransparency.trackingAuthorizationStatus;

  if (status == TrackingStatus.notDetermined || status == TrackingStatus.denied) {
    await showCustomTrackingDialog(
      context,
      'We use tracking to enhance your experience and provide personalized content and ads.',
    );

    await Future.delayed(const Duration(milliseconds: 1000));

    final newStatus = await AppTrackingTransparency.requestTrackingAuthorization();
    if (newStatus == TrackingStatus.notDetermined || newStatus == TrackingStatus.denied) {
      await showSettingsDialog(
        context,
        'Please enable tracking in Settings > Privacy & Security > Tracking.',
      );
    }
  }

  final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
  if (uuid == '00000000-0000-0000-0000-000000000000') {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text("Unable to track your device")),
    );
  }
}

Future<void> showCustomTrackingDialog(BuildContext context, String message) async {
  return showDialog<void>(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text('Attention'),
      content: Text(message),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Continue'),
        ),
      ],
    ),
  );
}

Future<void> showSettingsDialog(BuildContext context, String message) async {
  return showDialog<void>(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text('Settings Required'),
      content: Text(message),
      actions: [
        TextButton(
          onPressed: () async {
            const url = 'app-settings:';
            if (await canLaunchUrl(Uri.parse(url))) {
              await launchUrl(Uri.parse(url));
            }
            Navigator.pop(context);
          },
          child: const Text('Settings'),
        ),
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Not Now'),
        ),
      ],
    ),
  );
}

Bugs & Feature Requests #

Please open an issue on GitHub for bugs or feature requests. Pull requests are welcome!

License #

This project is licensed under the MIT License.

4
likes
140
points
131
downloads

Documentation

API reference

Publisher

verified publisherjinosh.site

Weekly Downloads

A Flutter plugin for retrieving a device's unique identifier across Android, iOS, Web, macOS, Linux, and Windows platforms.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, flutter_web_plugins, plugin_platform_interface, web

More

Packages that depend on unique_identifier_3

Packages that implement unique_identifier_3