# Unique Identifier
[![pub package](https://img.shields.io/badge/pub-0.3.0-green.svg)](https://pub.dartlang.org/packages/unique_identifier_3)
A Flutter plugin to retrieve the `ANDROID_ID` for Android devices and `identifierForVendor` for iOS devices. This unique identifier allows you to track devices in a secure and platform-compliant way.
## Installation
To add this package to your project, update the dependencies in your `pubspec.yaml` file:
```yaml
dependencies:
unique_identifier_3: ^0.0.1
Import the Package
import 'package:unique_identifier_3/unique_identifier_3.dart';
Usage
Example Code
The following example demonstrates how to retrieve a unique identifier for the device and display it in a Flutter app:
import 'package:flutter/material.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();
}
// Method to initialize and retrieve the unique identifier
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\n'),
),
),
);
}
}
iOS App Tracking Transparency
If your app uses tracking on iOS, ensure that you request App Tracking Transparency (ATT) permission from users. The following code includes permission handling and a custom dialog prompt for iOS:
import 'package:flutter/material.dart';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
Future<void> initTrackingTransparency(BuildContext context) async {
final status = await AppTrackingTransparency.trackingAuthorizationStatus;
if (status == TrackingStatus.notDetermined || status == TrackingStatus.denied) {
// Show a custom dialog before the system's tracking dialog
await showCustomTrackingDialog(
context,
'We use tracking to enhance your experience and provide personalized content and ads. '
'Please consider enabling tracking for improved service.',
);
// Delay to allow the dialog animation to complete
await Future.delayed(const Duration(milliseconds: 1000));
// Request ATT permission
final newStatus = await AppTrackingTransparency.requestTrackingAuthorization();
if (newStatus == TrackingStatus.notDetermined || newStatus == TrackingStatus.denied) {
await showSettingsDialog(
context,
'To enhance your experience, please enable tracking in Settings > Privacy & Security > Tracking.',
);
}
}
// Retrieve the advertising identifier
final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
if (uuid == '00000000-0000-0000-0000-000000000000') {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Unable to track your device")),
);
}
}
// Custom dialog to explain tracking
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'),
),
],
),
);
}
// Settings dialog to guide the user to enable tracking
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 canLaunchUrlString(url)) {
await launchUrlString(url);
} else {
debugPrint('Could not launch $url');
}
Navigator.pop(context);
},
child: const Text('Settings'),
),
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Not Now'),
),
],
),
);
}
Bugs & Feature Requests
If you encounter any issues or have feature requests, please open an issue on GitHub. Contributions through pull requests are also welcome!
Additional Information
Platform-Specific Behavior
- Android (8.0 and above):
ANDROID_ID
is a unique, 64-bit hexadecimal string associated with each combination of app-signing key, user, and device. The value may change after a factory reset or if the app-signing key changes. - iOS: The
identifierForVendor
(IDFV) is unique per vendor and can change if all apps from a vendor are uninstalled from a device and reinstalled.
For more details, see the official Android 8.0 Behavior Changes documentation.
License
This project is licensed under the MIT License.