Android 如何获取设备唯一标识

作者:pany 时间:2022-09-03 10:47:48 

目录
  • 一. 先简单总结一下比较常见的几个解决方案的弊端:

    • 1. IMEI

    • 2. Android ID

    • 3. MAC地址

  • 二. uuid + 本地文件,实现一个通用解决方案

    • 1. 思路

    • 2. 解决手机访问SDK权限问题

    • 3. 适配 Android 11

    • 4. Flutter 代码实践

一. 先简单总结一下比较常见的几个解决方案的弊端:

1. IMEI

Android 10 中官方明确说明第三方应用无法获取到IMEI码:Android 10 中的隐私权变更,

Android 10 以下的版本,需要申请READ_PHONE_STATE权限。

2. Android ID

Android ID 不具有真正的唯一性,

ROOT、刷机、恢复出厂设置、不同签名的应用等都会导致获取的 Android ID 发生改变,

并且不同厂商定制的系统的BUG会导致不同的设备可能会产生相同的 Android ID。

3. MAC地址

Android 10 中 MAC地址具有随机化的特征:Android 10 中的隐私权变更—MAC地址,

虽然目前大部分手机还不支持这个特性,但是随着厂商的跟进,这个方案就会逐渐作废

在上面这些设备自带的标识不够满足需求时,我们就要采用另外的方法了。

二. uuid + 本地文件,实现一个通用解决方案

1. 思路

启动APP时,检查并读取根目录下保存有uuid的文件,若没有该文件,则视为一台新设备,创建文件并写入uuid。

并且要确保卸载应用时,该文件不会被系统携带着删除(这也是为什么要在根目录下创建的原因)。

2. 解决手机访问SDK权限问题

Android 6 以下,添加权限:


<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Android 6 及其以上,则需要在此基础上申请动态权限。

Android 10 及其以上,文件存储机制修改成了沙盒模式,即应用只能访问自己沙盒下的文件和公共媒体文件。

“得益”于沙盒机制,应用创建的文件属于自己的沙盒,那么当应用卸载时,也会随之删除。

目前可以添加以下一行代码解决沙盒问题:


<application
 ...
 android:requestLegacyExternalStorage="true">

这样我们就能在“根目录”创建自己文件了。

3. 适配 Android 11

Android 11 会强制执行沙盒模式,在这之前存储权限可以简单的分为“禁止”和“允许”,在这之后存储权限可以简单的分为“禁止”、“允许访问媒体文件”和“允许访问所有文件”。

“允许访问媒体文件”这是绝大多数应用能够申请到的,而“允许访问所有文件”只有文件管理类应用可以申请到。假如你不是该类应用但又申请了该权限,那么就会通不过Google Play的审核。

允许访问所有文件:android.permission.MANAGE_EXTERNAL_STORAGE

介绍到这儿,其实一个方案已经出来了:直接申请“允许访问所有文件”权限,后果就是不能通过Google Play的审核。

另外还有一个办法:我们暂时不升级SDK,针对 Android 10 (SDK 29)来开发应用,这样的话由于“向后兼容机制”,我们的应用是能够正常跑在 Android 11 系统上的。

4. Flutter 代码实践


import 'dart:io';
import 'package:uuid/uuid.dart';

// 本地持久化存储uuid代码实践
class Storage {
static File file;

// 入口
static Future<String> init() async {
 bool boolCreateFile = await createFile();
 if (boolCreateFile) {
  String uuid = await readData();
  return uuid;
 } else {
  await writeData();
  String uuid = await readData();
  return uuid;
 }
}

// 创建文件
static Future<bool> createFile() async {
 file = File('/storage/emulated/0/uuid.ini'); // 指向根目录下的文件uuid
 bool exists = await file.exists();
 return exists;
}

// 写入数据
static writeData() async {
 // 如果文件存在,会将原来的内容覆盖, 如果不存在,则创建文件
 String uuid = await getUuid();
 file.writeAsString('$uuid');
}

// 读取文件
static Future<String> readData() async {
 try {
  String uuid = await file.readAsString();
  return uuid;
 } catch (e) {
  return null;
 }
}

// 获取uuid,采用的插件:uuid
static Future<String> getUuid() async {
 Uuid uuidObj = Uuid();
 String uuid = uuidObj.v1();
 return uuid;
}
}

来源:https://juejin.cn/post/6943484676640571399

标签:Android,设备,标识
0
投稿

猜你喜欢

  • 对C# 多态的理解

    2022-10-17 02:37:26
  • C#简单实现文件上传功能

    2022-10-03 17:29:41
  • Android Studio 3.0中mipmap-anydpi-v26是什么东东

    2023-10-11 01:17:44
  • Spring框架基于注解开发CRUD详解

    2021-08-04 03:39:03
  • C#如何删除指定文件或文件夹

    2022-06-30 21:28:49
  • IntelliJ IDEA 2020 安装和常用配置(推荐)

    2021-12-22 15:03:53
  • Java实现合并两个有序序列算法示例

    2021-09-06 23:23:53
  • 详解Android中Drawable方法

    2021-06-12 12:40:05
  • SpringBoot深入探究四种静态资源访问的方式

    2021-11-30 02:42:46
  • 使用java为pdf添加书签的方法(pdf书签制作)

    2022-03-07 14:59:11
  • Go&java算法之最大数示例详解

    2023-10-30 08:54:56
  • Android-Service实现手机壁纸自动更换

    2022-05-21 23:15:35
  • c#基于opencv,开发摄像头播放程序

    2023-06-20 11:54:29
  • 输出的文本实现对齐的方法(超简单)

    2023-06-19 03:57:09
  • Android实现启动页倒计时效果

    2021-07-26 20:50:14
  • 编写Java代码对HDFS进行增删改查操作代码实例

    2023-07-08 11:46:42
  • Android获取app应用程序大小的方法

    2023-09-18 15:02:18
  • 详解java WebSocket的实现以及Spring WebSocket

    2023-11-24 13:16:25
  • Java多线程回调方法实例解析

    2023-11-04 01:40:01
  • 基于Android实现点击某个按钮让菜单选项从按钮周围指定位置弹出

    2021-09-13 23:03:40
  • asp之家 软件编程 m.aspxhome.com