美文网首页
解决Android10 唯一标识的问题

解决Android10 唯一标识的问题

作者: liguiyun | 来源:发表于2020-07-09 15:02 被阅读0次

一,Android常见的唯一标识

IMEI,MEID,ESN,IMSI,android_id 目前用的最多的就是IMEI 现在Android10 是真的获取不到IMEI标识了!现在移动安全联盟出的那个架包 目前只支持国内手机,三星手机不支持,而且 国内手机也不一定全部支持

二,生成UUID保存在本地,

在Android10 之前,可以创建一个文件保存一个编号,多个应用都能访问,但是没删除掉了 或者 刷机,或者恢复出厂设置了 都不能用了,现在Android 储存权限更一步提升,保存的文件 应用卸载 文件就删除了!除非用mediaStore 保存多媒体文件,但是多个应用不能共享使用,这个问题非常头疼

三,解决方案

1,本地生成一个UUID当唯一标识
2,获取硬件的所有硬件编码和UUID进行绑定,上传数据库,如果应用本删除或者卸载,下次进入应用根据硬件编码 获取UUID,下面直接贴代码

一,生成UUID

  //生成15位唯一性的订单号
    private static String getUUID() {
        //随机生成一位整数
        int random = (int) (Math.random() * 9 + 1);
        String valueOf = String.valueOf(random);
        //生成uuid的hashCode值
        int hashCode = UUID.randomUUID().toString().hashCode();
        //可能为负数
        if (hashCode < 0) {
            hashCode = -hashCode;
        }
        String value = valueOf + String.format("%014d", hashCode);
        return value;
    }

二,获取目前能获取的唯一编号和硬件编码

   public static String getDeviceInformJson() {
        DeviceInformModel deviceInformModel = new DeviceInformModel();
        deviceInformModel.setMac(DeviceId.getMacAddress());//获取mac
        deviceInformModel.setAndroid_id(DeviceId.getAndroidID(App.getsInstance()));//获取AndroidId
        deviceInformModel.setSerial_no(DeviceId.getSerialNo());//获取Sim卡编码
        deviceInformModel.setImsi(DeviceId.getSubscriberId());//获取Imsi编码
        deviceInformModel.setSimserial(DeviceId.getSimSerialNumber());
        deviceInformModel.setFingerprint(DeviceId.getFingerprint());//获取指纹编码
        deviceInformModel.setSplitNo(DeviceId.getSplitNo());//多个字段拼接的编码
        deviceInformModel.setPhysics_info(HexUtil.long2Hex(PhysicsInfo.getHash(App.getsInstance())));//获取硬件编码信息
        deviceInformModel.setDark_physics_info(HexUtil.long2Hex(DarkPhysicsInfo.getHash(App.getsInstance())));//获取物理编码Hash值
        return GsonUtil.getInstance().GsonString(deviceInformModel);
    }

上面代码是获取硬件编码并转化成json字符串 和uuId一块传给后台的

三 ,获取硬件编码的代码

  package com.xhs.baselibrary.utils.device;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import com.xhs.baselibrary.App;
import com.xhs.baselibrary.utils.Encryption;

import java.lang.reflect.Method;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.UUID;

public class DeviceId {
    private static final byte[] HEX_DIGITS = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };

    private static final String INVALID_MAC_ADDRESS = "02:00:00:00:00:00";

    private static final String INVALID_ANDROID_ID = "9774d56d682e549c";

    private static final String INVALID_Serial_No = "unknown";

    private static byte[] getMacInArray() {
        try {
            Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
            if (enumeration == null) {
                return null;
            }
            while (enumeration.hasMoreElements()) {
                NetworkInterface netInterface = enumeration.nextElement();
                if (netInterface.getName().equals("wlan0")) {
                    return netInterface.getHardwareAddress();
                }
            }
        } catch (Exception e) {
            Log.e("tag", e.getMessage(), e);
        }
        return null;
    }

    public static long getLongMac() {
        byte[] bytes = getMacInArray();
        if (bytes == null || bytes.length != 6) {
            return 0L;
        }
        long mac = 0L;
        for (int i = 0; i < 6; i++) {
            mac |= bytes[i] & 0xFF;
            if (i != 5) {
                mac <<= 8;
            }
        }
        return mac;
    }

    public static String getMacAddress() {
        String mac = formatMac(getMacInArray());
        if (TextUtils.isEmpty(mac) || mac.equals(INVALID_MAC_ADDRESS)) {
            return "";
        }
        return mac;
    }

    private static String formatMac(byte[] bytes) {
        if (bytes == null || bytes.length != 6) {
            return "";
        }
        byte[] mac = new byte[17];
        int p = 0;
        for (int i = 0; i <= 5; i++) {
            byte b = bytes[i];
            mac[p] = HEX_DIGITS[(b & 0xF0) >> 4];
            mac[p + 1] = HEX_DIGITS[b & 0xF];
            if (i != 5) {
                mac[p + 2] = ':';
                p += 3;
            }
        }
        return new String(mac);
    }

    public static String getAndroidID(Context context) {
        if (context != null) {
            @SuppressLint("HardwareIds")
            String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            if (!TextUtils.isEmpty(androidId) && !INVALID_ANDROID_ID.equals(androidId)) {
                return androidId;
            }
        }
        return "";
    }

    /**
     * 获取手机序列号
     *
     * @return 手机序列号
     */
    public static String getSerialNo() {
        String serial = "";
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//9.0+
                if (ActivityCompat.checkSelfPermission(App.getsInstance(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                    serial = Build.getSerial();
                }
            } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+
                serial = Build.SERIAL;
            } else {//8.0-
                Class<?> c = Class.forName("android.os.SystemProperties");
                Method get = c.getMethod("get", String.class);
                serial = (String) get.invoke(c, "ro.serialno");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("e", "读取设备序列号异常:" + e.toString());
        }
        if (!TextUtils.isEmpty(serial) && !INVALID_Serial_No.equals(serial)) {
            return serial;
        }
        return "";
    }

    public static String getSubscriberId() {
        TelephonyManager mTelephonyMgr = (TelephonyManager) App.getsInstance().getSystemService(Context.TELEPHONY_SERVICE);
        if (ActivityCompat.checkSelfPermission(App.getsInstance(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            String imsi = mTelephonyMgr.getSubscriberId();
            if (!TextUtils.isEmpty(imsi)) {
                return imsi;
            }
            return imsi;
        }
        return "";
    }

    public static String getSimSerialNumber() {
        TelephonyManager mTelephonyMgr = (TelephonyManager) App.getsInstance().getSystemService(Context.TELEPHONY_SERVICE);
        //返回SIM卡的序列号
        if (ActivityCompat.checkSelfPermission(App.getsInstance(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            String simSerialNumber = mTelephonyMgr.getSimSerialNumber();
            if (!TextUtils.isEmpty(simSerialNumber)) {
                return simSerialNumber;
            }
        }
        return "";
    }

    public static String getSplitNo() {
        String serial = "";
        String m_szDevIDShort = "35" +
                Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
                Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
                Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
                Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
                Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
                Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
                Build.USER.length() % 10; //13 位
        serial = getSerialNo();
        //使用硬件信息拼凑出来的15位号码
        return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
    }

    public static String getFingerprint() {
        return Encryption.encrypByMD5(android.os.Build.FINGERPRINT);
    }

}

四, 后台逻辑

1,App 请求参数是本地uuId或者刚生成的UUId 和所有App硬件编码标识
2,后台先根据uuId查询是否存在这个编码,如果存在就返回 这条信息,如果没有 根据硬件编码标识 如果不为空,而且硬件编码标识和数据库里面 有两条一样的 那么把这条记录返回给客户端,那么返回的uuId 就是 之前保存的那个uuId

代码还有很多如果需要 我贴github上面,如果不明白其中逻辑的,可以评论咨询,时间忙 记录一下这个方案

相关文章

  • 解决Android10 唯一标识的问题

    一,Android常见的唯一标识 IMEI,MEID,ESN,IMSI,android_id 目前用的最多的就是...

  • Android设备唯一ID实现方案

    随着Google对隐私的重视以及Android10的逐渐普及,获取设备的唯一标识越来越来难,在Android10以...

  • 4-3-1-如何确定Android设备唯一识别码

    [TOC] 应用设备唯一识别码的解决方案 唯一标识必须满足两个特性才能完美解决定位唯一设备的问题,但这个问题的解决...

  • Android: 获取Android设备唯一识别码

    一、前言: 唯一标识必须满足两个特性才能完美解决定位唯一设备的问题,但这个问题的解决却注定只能极限接近完美:(1)...

  • scoket 通信简介

    1.解决识别唯一进程的原理 ,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主...

  • iOS下的TCP/IP

    一、网络中进程之间如何通信 首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一...

  • (Android)FileNotFoundException:

    三星机子升级为Android10后,遇到视频无法播放的问题 解决方法就是每个Activity使用MediaPlay...

  • Android获取设备唯一标识

    获取Android唯一标识 开发中,进程遇到需要获取设备唯一标识问题,有几种方法可以作为参考 使用IMEI 但是仅...

  • 唯一ID生成算法剖析

    引 在业务开发中,大量场景需要唯一ID来进行标识:用户需要唯一身份标识;商品需要唯一标识;消息需要唯一标识;事件需...

  • iOS-Socket网络通信-框架与API

    Socket基础概念 网络中进程之间如何通信? 网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则...

网友评论

      本文标题:解决Android10 唯一标识的问题

      本文链接:https://www.haomeiwen.com/subject/efxscktx.html