如何在Flutter中获取唯一设备ID?

118

在Android中,我们有Settings.Secure.ANDROID_ID。我不知道iOS的相应功能。 在Flutter中有没有插件或方法可以获取Android和iOS的唯一设备ID?


4
这个唯一标识会不会在任何情况下被更改,还是保持不变?如果有更改,哪些情况下会发生更改? - Ravi Garg
7
更新:由于这个帖子在 Google 上的排名很高,我想在这里提一下 device_id 包已经停止使用了。不过看起来 platform_device_id 这个包的功能类似,并且最近活动频繁。我们在 iOS 崩溃后日志中发现指向旧包的错误后将切换到新包。 - Adam Bellas
在Android设备上,可以有多个用户使用该设备。是否有一种方法可以获取每个用户在设备上的唯一ID? - Jarl
@spycbanda,你找到了你的问题的答案吗?我也有和你一样的问题。 - wahyu
1
我已经使用device_info_plus有一段时间了,发现安卓设备的Id并不是唯一的。使用相似设备的用户会有相似的Id。 - undefined
14个回答

138

空安全代码

使用由Flutter社区开发的device_info_plus插件。这是您可以在两个平台上获取ID的方法。

在您的pubspec.yaml文件中添加以下内容:

dependencies:
  device_info_plus: ^3.2.3
创建一个方法:
Future<String?> _getId() async {
  var deviceInfo = DeviceInfoPlugin();
  if (Platform.isIOS) { // import 'dart:io'
    var iosDeviceInfo = await deviceInfo.iosInfo;
    return iosDeviceInfo.identifierForVendor; // unique ID on iOS
  } else if(Platform.isAndroid) {
    var androidDeviceInfo = await deviceInfo.androidInfo;
    return androidDeviceInfo.androidId; // unique ID on Android
  }
}

使用方法:

String? deviceId = await _getId();

2
有时被认为是空的,它在文档中被描述为“可以在恢复出厂设置时更改”。使用时需自行承担风险,且在已获取 root 权限的手机上可轻松更改。 - Kamlesh
27
刚刚测试了一下:该 ID 会一直保持不变,直到程序被删除。如果重新安装,则 ID 会改变。 - William Terrill
1
有没有一种方法可以获得一个在安装过程中保持不变的ID? - user2233706
18
似乎在4.1.2版本中不存在androidDeviceInfo.androidId。 - Ville
8
针对device_info_plus:"移除androidId (已在方法通道中删除,因此始终返回null)。现在有一个新的、单独的pub.dev包来获取正确的androidId",所以你现在需要从"android_id"包中获取它。 - Unreality
显示剩余6条评论

98

有一个名为device_info的插件,你可以在这里获取它。

请查看官方示例

 static Future<List<String>> getDeviceDetails() async {
    String deviceName;
    String deviceVersion;
    String identifier;
    final DeviceInfoPlugin deviceInfoPlugin = new DeviceInfoPlugin();
    try {
      if (Platform.isAndroid) {
        var build = await deviceInfoPlugin.androidInfo;
        deviceName = build.model;
        deviceVersion = build.version.toString();
        identifier = build.androidId;  //UUID for Android
      } else if (Platform.isIOS) {
        var data = await deviceInfoPlugin.iosInfo;
        deviceName = data.name;
        deviceVersion = data.systemVersion;
        identifier = data.identifierForVendor;  //UUID for iOS
      }
    } on PlatformException {
      print('Failed to get platform version');
    }

//if (!mounted) return;
return [deviceName, deviceVersion, identifier];
}

您可以将此UUID存储在钥匙串中。这样,您就可以为设备设置唯一ID。

更新

device_info现在更名为device_info_plus


如何获取Android设备的ID? 它可以从device_info中检索吗? - Mattias
现在您应该使用device_info_plus:https://pub.dev/packages/device_info_plus - Navid
在iOS设备上,如果用户卸载然后重新安装您的应用程序,则identifierForVendor会更改,因此它不是100%可靠的常量。 - Lee Mordell
build.version会返回一个实例,我们应该使用哪个变量? - Arief Wijaya
在最新版本的插件中,androidId已被替换为仅使用id,并且不再是唯一的。我通过困难的方式学到了这一点。标识符=build.androidId->标识符=build.id; - KgaboL
显示剩余6条评论

16

我刚刚发布了一个插件,为你提供解决方案。 它在Android上使用Settings.Secure.ANDROID_ID,在iOS上依赖于identifierForVendor和keychain,以使行为等同于Android的。 这是链接。


我无法使用这个插件构建我的项目,与SWIFT相关的问题... - Marco Alves
干得好!那正是我所需要的。 - hrishikesh rajwade

16

更新于2021年1月3日:现在推荐使用名为device_info_plus的扩展社区插件,它支持比device_info更多的平台,并旨在支持flutter支持的所有平台。以下是使用示例:

import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:device_info_plus/device_info_plus.dart';
import 'dart:io';

Future<String> getDeviceIdentifier() async {
  String deviceIdentifier = "unknown";
  DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();

  if (Platform.isAndroid) {
    AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
    deviceIdentifier = androidInfo.androidId;
  } else if (Platform.isIOS) {
    IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
    deviceIdentifier = iosInfo.identifierForVendor;
  } else if (kIsWeb) {
    // The web doesnt have a device UID, so use a combination fingerprint as an example
    WebBrowserInfo webInfo = await deviceInfo.webBrowserInfo;
    deviceIdentifier = webInfo.vendor + webInfo.userAgent + webInfo.hardwareConcurrency.toString();
  } else if (Platform.isLinux) {
    LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo;
    deviceIdentifier = linuxInfo.machineId;
  } 
  return deviceIdentifier;
}

6
根据AndroidIOS文档,androidId和identifierForVendor可能会随时间变化。 - Maël Pedretti
3
针对 device_info_plus: "移除 androidId(已从方法通道中删除,因此始终返回 null)。现在有一个新的、独立的 pub.dev 包用于获取正确的 androidId",因此您现在需要从包“android_id”中获取它。 - Unreality

10
截至2022年12月,获取设备ID的最新状态如下:
device_info_plus不再提供唯一的设备ID。因此,我开始使用platform_device_id包。
我在Android上对其进行了测试,与之前的device_info相同,并提供相同的ID值。它还具有简单的用法:
   String deviceId = await PlatformDeviceId.getDeviceId;

这个包使用更新的Android嵌入版本,并且还支持空安全。


该软件包已被废弃,因为最后一次更新是20个月前。 - Tony Hart
1
设备信息:^2.0.3 平台设备ID:^1.0.1这两个包已经过时且陈旧。 然而,每个人都可以仅针对Android使用android_id:^0.1.3+1包。 - Sanny khan
1
虽然 platform_device_id 是一个旧的包,但它与 Dart 3 兼容,并且给我提供了唯一的设备 ID,而不像 device_info_plus。感谢 @cansu 提到它。 - Solomon Tesfaye

8

最新消息:

插件device_info已经发布了弃用通知,并被device_info_plus替换。

示例:

dependencies:
  device_info_plus: ^9.0.2

使用方法:

import 'package:device_info_plus/device_info_plus.dart';

DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();

AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
print('Running on ${androidInfo.model}');  // e.g. "Moto G (4)"

IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
print('Running on ${iosInfo.utsname.machine}');  // e.g. "iPod7,1"

WebBrowserInfo webBrowserInfo = await deviceInfo.webBrowserInfo;
print('Running on ${webBrowserInfo.userAgent}');  // e.g. "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0"

您可以在这里查看完整示例:

获取唯一标识符:

您可以使用以下代码来获取唯一标识符:

String deviceIdentifier = '';
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
if (kIsWeb) {
  final WebBrowserInfo webInfo = await deviceInfo.webBrowserInfo;
  deviceIdentifier = webInfo.vendor! +
      webInfo.userAgent! +
      webInfo.hardwareConcurrency.toString();
} else {
  if (Platform.isAndroid) {
    final AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
    deviceIdentifier = androidInfo.id;
  } else if (Platform.isIOS) {
    final IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
    deviceIdentifier = iosInfo.identifierForVendor!;
  } else if (Platform.isLinux) {
    final LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo;
    deviceIdentifier = linuxInfo.machineId!;
  }
}

编辑:自v4.1.0起,androidId已经不存在。


1
这不是一个好的解决方案,因为“iosInfo”会随着每次应用程序升级/重新安装而改变。 - Oliver Dixon
hardwareConcurrency 不是一个好的例子。它将返回机器上的核心数,不是非常独特的。 - Oliver Dixon
对于device_info_plus: "移除androidId(已从方法通道中在4.0.0中移除,因此始终返回null)现在有一个新的、独立的pub.dev包来获取正确的androidId",所以现在您需要从包“android_id”中获取它。 - Unreality
更新:device_info_plus不再提供唯一的androidId。 - Z. Cajurao
在 Web 平台上,您不应使用浏览器信息或用户代理来生成唯一标识符,而应使用 uuid 包生成一个唯一标识符。 - Mahesh Jamdade

7

使用Flutter社区开发的device_info_plus包。这是你可以在两个平台上获取ID的方法。

在你的pubspec.yaml文件中添加以下内容:

dependencies:
  device_info_plus: ^3.2.3

创建一个方法:
Future<String> getUniqueDeviceId() async {
  String uniqueDeviceId = '';

  var deviceInfo = DeviceInfoPlugin();

  if (Platform.isIOS) { // import 'dart:io'
    var iosDeviceInfo = await deviceInfo.iosInfo;
    uniqueDeviceId = '${iosDeviceInfo.name}:${iosDeviceInfo.identifierForVendor}'; // unique ID on iOS
  } else if(Platform.isAndroid) {
    var androidDeviceInfo = await deviceInfo.androidInfo;
    uniqueDeviceId = '${androidDeviceInfo.name}:${androidDeviceInfo.id}' ; // unique ID on Android
  }
  
  return uniqueDeviceId;

}

使用方法:

String deviceId = await getUniqueDeviceId();

输出:

M2102J20SG::SKQ1.211006.001

注意:

  1. 不要使用 androidDeviceInfo.androidId。当您的 MAC 地址更改时,这会发生变化。 Android OS 10/11以上的移动设备将生成随机 MAC。除非手动禁用,否则此功能默认启用。这会导致在网络切换时 androidId 发生变化。您可以通过将上面的 androidDeviceInfo.id 更改为 androidDeviceInfo.androidId 来确认此问题。

  2. 您可能只需使用 androidDeviceInfo.name,因为它永远不会更改。

  3. 如果操作系统更新,则 androidDeviceInfo.id 也可能更改,因为它是 Android 操作系统版本。

  4. 仅当设备使用固定 MAC 地址时,才应使用 androidDeviceInfo.androidId 如第1点所述。否则,仅使用 *.nameandroidDeviceInfo.id*.name 一起使用。


7
使用device_id插件。
  1. Add in your following code in your .yaml file.

    device_id: ^0.1.3
    
  2. Add import in your class

    import 'package:device_id/device_id.dart';
    
  3. Now get device id from:

    String deviceid = await DeviceId.getID;
    

2
这将强制你的应用程序拥有android.permission.READ_PHONE_STATE权限。这将导致在发布应用程序到Play商店时出现警告,因为“在APK中使用这些权限的应用程序需要设置隐私政策”。 - Sisir
14
该插件已停止更新。 - Banjoe

5
v4.1.0版本之后,androidID已被移除。请查看changelog
建议使用android_id包获取正确的androidId

5

我发布了一个新的Flutter插件client_information,它可能会有所帮助。它提供了一种简单的方式,从您的应用程序用户那里获取一些基本设备信息。

  1. 将其添加到pubspec.yaml中
  dependencies:
    ...
    client_information: ^1.0.1
  1. 将代码导入到您的项目中
import 'package:client_information/client_information.dart';
  1. 然后您可以像这样获取设备ID
/// Support on iOS, Android and web project
Future<String> getDeviceId() async {
  return (await ClientInformation.fetch()).deviceId;
}


1
如果我重新安装APP,这里的androidId会改变吗? - Nicholas Jela
1
它总是返回 null - user123456

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接