欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Android获取设备唯一ID的几种方式

程序员文章站 2023-11-24 08:09:28
先来看看几种比较单一的方式: imei 方式:telephonymanager.getdeviceid(): 问题 范围:只能支持拥有通话功能的...

先来看看几种比较单一的方式:

imei

方式:telephonymanager.getdeviceid():

问题

  1. 范围:只能支持拥有通话功能的设备,对于平板不可以。
  2. 持久性:返厂,数据擦除的时候不彻底,保留了原来的标识。
  3. 权限:需要权限:android.permission.read_phone_state
  4. bug: 有些厂家的实现有bug,返回一些不可用的数据

 mac地址

access_wifi_state权限

有些设备没有wifi,或者蓝牙,就不可以,如果wifi没有打开,硬件也不会返回mac地址,不建议使用

android_id
2.2(froyo,8)版本系统会不可信,来自主要生产厂商的主流手机,至少有一个普遍发现的bug,这些有问题的手机相同的android_id: 9774d56d682e549c

但是如果返厂的手机,或者被root的手机,可能会变

serial number

从android 2.3 (“gingerbread”)开始可用,可以通过android.os.build.serial获取,对于没有通话功能的设备,它会返回一个唯一的device id,

以下几个是*上评论较多的几个,没贴完,还有其他,综合的,用到以上的部分方式:

地址:

有兴趣的朋友可以再仔细看看

支持率比较高的(支持票数157):androidid --> 剔除2.2版本(api 8)中有问题的手机,使用uuid替代

import android.content.context; 
import android.content.sharedpreferences; 
import android.provider.settings.secure; 
import android.telephony.telephonymanager; 
 
import java.io.unsupportedencodingexception; 
import java.util.uuid; 
 
public class deviceuuidfactory { 
 
  protected static final string prefs_file = "device_id.xml"; 
  protected static final string prefs_device_id = "device_id"; 
  protected static volatile uuid uuid; 
 
  public deviceuuidfactory(context context) { 
    if (uuid == null) { 
      synchronized (deviceuuidfactory.class) { 
        if (uuid == null) { 
          final sharedpreferences prefs = context 
              .getsharedpreferences(prefs_file, 0); 
          final string id = prefs.getstring(prefs_device_id, null); 
          if (id != null) { 
            // use the ids previously computed and stored in the 
            // prefs file 
            uuid = uuid.fromstring(id); 
          } else { 
            final string androidid = secure.getstring( 
              context.getcontentresolver(), secure.android_id); 
            // use the android id unless it's broken, in which case 
            // fallback on deviceid, 
            // unless it's not available, then fallback on a random 
            // number which we store to a prefs file 
            try { 
              if (!"9774d56d682e549c".equals(androidid)) { 
                uuid = uuid.nameuuidfrombytes(androidid 
                    .getbytes("utf8")); 
              } else { 
                final string deviceid = ((telephonymanager)  
                    context.getsystemservice( 
                      context.telephony_service) 
                      .getdeviceid(); 
                uuid = deviceid != null ? uuid 
                    .nameuuidfrombytes(deviceid 
                        .getbytes("utf8")) : uuid 
                    .randomuuid(); 
              } 
            } catch (unsupportedencodingexception e) { 
              throw new runtimeexception(e); 
            } 
            // write the value out to the prefs file 
            prefs.edit() 
                .putstring(prefs_device_id, uuid.tostring()) 
                .commit(); 
          } 
        } 
      } 
    } 
  } 
 
  /** 
   * returns a unique uuid for the current android device. as with all uuids, 
   * this unique id is "very highly likely" to be unique across all android 
   * devices. much more so than android_id is. 
   * 
   * the uuid is generated by using android_id as the base key if appropriate, 
   * falling back on telephonymanager.getdeviceid() if android_id is known to 
   * be incorrect, and finally falling back on a random uuid that's persisted 
   * to sharedpreferences if getdeviceid() does not return a usable value. 
   * 
   * in some rare circumstances, this id may change. in particular, if the 
   * device is factory reset a new device id may be generated. in addition, if 
   * a user upgrades their phone from certain buggy implementations of android 
   * 2.2 to a newer, non-buggy version of android, the device id may change. 
   * or, if a user uninstalls your app on a device that has neither a proper 
   * android id nor a device id, this id may change on reinstallation. 
   * 
   * note that if the code falls back on using telephonymanager.getdeviceid(), 
   * the resulting id will not change after a factory reset. something to be 
   * aware of. 
   * 
   * works around a bug in android 2.2 for many devices when using android_id 
   * directly. 
   * 
   * @see http://code.google.com/p/android/issues/detail?id=10603 
   * 
   * @return a uuid that may be used to uniquely identify your device for most 
   *     purposes. 
   */ 
  public uuid getdeviceuuid() { 
    return uuid; 
  } 
} 

根据版本进行判断的方式:serial序列号-->uuid (支持数31)

通过serial 即可,在覆盖率上,你已经成功的获得了98.4%的用户,剩下的1.6%的用户系统是在9 以下的。

通过androidid获取,前面已经说过,在8上,有些商家的手机会有一些bug,返回相同的androidid,如果serial和androidid都不行

/** 
 * return pseudo unique id 
 * @return id 
 */ 
public static string getuniquepsuedoid() 
{ 
  // if all else fails, if the user does have lower than api 9 (lower 
  // than gingerbread), has reset their phone or 'secure.android_id' 
  // returns 'null', then simply the id returned will be solely based 
  // off their android device information. this is where the collisions 
  // can happen. 
  // thanks http://www.pocketmagic.net/?p=1662! 
  // try not to use display, host or id - these items could change. 
  // if there are collisions, there will be overlapping data 
  string m_szdevidshort = "35" + (build.board.length() % 10) + (build.brand.length() % 10) + (build.cpu_abi.length() % 10) + (build.device.length() % 10) + (build.manufacturer.length() % 10) + (build.model.length() % 10) + (build.product.length() % 10); 
 
  // thanks to @roman sl! 
  // http://*.com/a/4789483/950427 
  // only devices with api >= 9 have android.os.build.serial 
  // http://developer.android.com/reference/android/os/build.html#serial 
  // if a user upgrades software or roots their phone, there will be a duplicate entry 
  string serial = null; 
  try 
  { 
    serial = android.os.build.class.getfield("serial").get(null).tostring(); 
 
    // go ahead and return the serial for api => 9 
    return new uuid(m_szdevidshort.hashcode(), serial.hashcode()).tostring(); 
  } 
  catch (exception e) 
  { 
    // string needs to be initialized 
    serial = "serial"; // some value 
  } 
 
  // thanks @joe! 
  // http://*.com/a/2853253/950427 
  // finally, combine the values we have found by using the uuid class to create a unique identifier 
  return new uuid(m_szdevidshort.hashcode(), serial.hashcode()).tostring(); 
} 

不用read_phone_state权限直接获取rom信息的方式:(支持率较低 16)

string m_szdevidshort = "35" + //we make this look like a valid imei 
      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 digits 

最后贴上自己在项目中用的:

public static string getdeviceid(context context) { 
    string deviceid = ""; 
    if (deviceid != null && !"".equals(deviceid)) { 
     return deviceid; 
   } 
    if (deviceid == null || "".equals(deviceid)) { 
      try { 
        deviceid = getlocalmac(context).replace(":", ""); 
      } catch (exception e) { 
        e.printstacktrace(); 
      } 
    } 
    if (deviceid == null || "".equals(deviceid)) { 
      try { 
        deviceid = getandroidid(context); 
      } catch (exception e) { 
        e.printstacktrace(); 
      } 
    } 
    if (deviceid == null || "".equals(deviceid)) { 
       
      if (deviceid == null || "".equals(deviceid)) { 
        uuid uuid = uuid.randomuuid(); 
        deviceid = uuid.tostring().replace("-", ""); 
        writedeviceid(deviceid); 
      } 
    } 
    return deviceid; 
  } 
// imei码 
  private static string getimiestatus(context context) { 
    telephonymanager tm = (telephonymanager) context 
        .getsystemservice(context.telephony_service); 
    string deviceid = tm.getdeviceid(); 
    return deviceid; 
  } 
 
  // mac地址 
  private static string getlocalmac(context context) { 
    wifimanager wifi = (wifimanager) context 
        .getsystemservice(context.wifi_service); 
    wifiinfo info = wifi.getconnectioninfo(); 
    return info.getmacaddress(); 
  } 
 
  // android id 
  private static string getandroidid(context context) { 
    string androidid = settings.secure.getstring( 
        context.getcontentresolver(), settings.secure.android_id); 
    return androidid; 
  } 
 
  public static void savedeviceid(string str) { 
    try { 
      fileoutputstream fos = new fileoutputstream(file); 
      writer out = new outputstreamwriter(fos, "utf-8"); 
      out.write(str); 
      out.close(); 
    } catch (ioexception e) { 
      e.printstacktrace(); 
    } 
  } 
 
  public static string readdeviceid() { 
    stringbuffer buffer = new stringbuffer(); 
    try { 
      fileinputstream fis = new fileinputstream(file); 
      inputstreamreader isr = new inputstreamreader(fis, "utf-8"); 
      reader in = new bufferedreader(isr); 
      int i; 
      while ((i = in.read()) > -1) { 
        buffer.append((char) i); 
      } 
      in.close(); 
      return buffer.tostring(); 
    } catch (ioexception e) { 
      e.printstacktrace(); 
      return null; 
    } 
  } 

对于获取设备唯一id并没有绝对的方案,这一点在android的官方博客中也提到了,不过以上几种方案,应该可以满足平时的需求,大家可以选择其中自己认为比较好的,用于自己的项目中。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。