Android 如何检索Android设备的唯一ID

关于本文档

Android的开发者在一些特定情况下都需要知道手机中的唯一设备ID例如,跟踪应用程序的安装,生成用于复制保护的DRM时需要使用设备的唯一ID在本文档结尾处提供了作为参考的示例代码片段。

范围

本文提供有关如何读取各种Android设备的 ID的介绍,用以使用标识号。本文假定用户已经安装了Android以及开发应用程序必要的工具。并且,本文假定用户已了解Android的基本知识。

简介在搭载Android操作系统的设备中,已经存在好几种类型的设备标识号。先前的所有Android设备都具有电话功能,因此查找每部设备硬件唯一的IMEIMEID,或ESN也很容易。但仅能使用Wifi的设备或音乐播放器没有电话硬件,所以没有这种类型的唯一标识号。本文阐述了如何读取不同Android设备的标识号。检索Android设备ID各种方式

以下是Android设备不同类型的识别设备ID

· 唯一编号(IMEIMEIDESNIMSI

· MAC地址

· 序列号

· ANDROID_ID

唯一编号(IMEIMEIDESNIMSI

说明在以前,当Android设备均作为电话使用时,寻找唯一标识号比较简单:()可用于找到(取决于网络技术)手机硬件唯一的IMEIMEIDESNIMSI编号。

TelephonyManager.getDeviceId

IMEIMEIDESNIMSI的定义如下:

•IMEI(国际移动设备识别码)唯一编号,用于识别 GSMWCDMA手机以及一些卫星电话(移动设备识别码)全球唯一编号,用于识别CDMA移动电台设备的物理硬件,MEID出现的目的是取代ESN号段(电子序列号)(电子序列号)唯一编号,用于识别CDMA手机(国际移动用户识别码)与所有GSMUMTS网络手机用户相关联的唯一识别编号如需要检索设备的ID,在项目中要使用以下代码:

•MEID

•ESN

•IMSI

[java] view plaincopy
  1. import android.telephony.TelephonyManager;     
  2.    
  3. import android.content.Context;                                                        
  4.   
  5.    
  6.    
  7. String   imeistring = null;                                                           
  8.   
  9. String   imsistring = null;                                                                                        
  10.   
  11. {                                                                                      
  12.   
  13.     TelephonyManager    telephonyManager;                                              
  14.    
  15.                                                                                        
  16.   
  17.     telephonyManager =   
  18.   
  19.          ( TelephonyManager )getSystemService( Context.TELEPHONY_SERVICE );  
  20.    
  21.                        
  22.   
  23.     /* 
  24.   
  25.       * getDeviceId() function Returns the unique device ID. 
  26.   
  27.      * for example,the IMEI for GSM and the MEID or ESN for CDMA phones.  
  28.  
  29.      */                                                                 
  30.   
  31.     imeistring = telephonyManager.getDeviceId();  
  32.    
  33.      
  34.   
  35.    /* 
  36.   
  37.     * getSubscriberId() function Returns the unique subscriber ID, 
  38.   
  39.  * for example, the IMSI for a GSM phone. 
  40.   
  41.  */  
  42.    
  43.    imsistring = telephonyManager.getSubscriberId();     
  44.   
  45. }  


如要只读取手机的状态,则需添加READ_PHONE_STATE许可到AndroidManifest.xml文件中。

[java] view plaincopy
  1. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  


 

缺点

•Android设备要具有电话功能

其工作不是很可靠

序列号

当其工作时,该值保留了设备的重置信息(恢复出厂设置),从而可以消除当客户删除自己设备上的信息,并把设备转另一个人时发生的错误。

Mac地址
说明

可通过检索找到设备的Wi - Fi或蓝牙硬件的Mac地址。但是,不推荐使用Mac地址作为唯一的标识号。

缺点设备要具备Wi – Fi功能(并非所有的设备都有Wi – Fi功能)如果设备目前正在使用Wi - Fi,则不能报告Mac地址

序列号

Android 2.3姜饼)开始,通过android.os.Build.SERIAL方法序列号可被使用。没有电话功能的设备也都需要上给出唯一的设备ID; 某些手机也可以需要这样做。序列号可以用于识别MID(移动互联网设备)或PMP(便携式媒体播放器),这两种设备都没有电话功能。通过读取系统属性值“ro.serialno”的方法,可以使用序列号作为设备ID 如检索序列号并作为设备ID使用,请参考下面的代码示例。

[java] view plaincopy
  1. import java.lang.reflect.Method;                                    
  2.   
  3.    
  4.    
  5. String serialnum = null;                                                                                                                                          
  6.    
  7. try {                                                              
  8.   
  9.  Class<?> c = Class.forName("android.os.SystemProperties");   
  10.    
  11.  Method get = c.getMethod("get", String.class, String.class );       
  12.    
  13.  serialnum = (String)(   get.invoke(c, "ro.serialno""unknown" )  );     
  14.    
  15. }                                                                                  
  16.    
  17. catch (Exception ignored)                                                          
  18.    
  19. {                                
  20.    
  21. }  


 

缺点

序列号无法在所有Android设备上使用。

ANDROID_ID

说明

更具体地说,Settings.Secure.ANDROID_ID 是一串64位的编码(十六进制的字符串),是随机生成的设备的第一个引导,其记录着一个固定值,通过它可以知道设备的寿命(在设备恢复出厂设置后,该值可能会改变)。 ANDROID_ID也可视为作为唯一设备标识号的一个好选择。如要检索用于设备ID 的ANDROID_ID,请参阅下面的示例代码

[java] view plaincopy
  1. String androidId = Settings.Secure.getString(getContentResolver(),Settings.Secure.ANDROID_ID);  


 

缺点

• 对于Android 2.2(“Froyo”)之前的设备不是100%的可靠

• 此外,在主流制造商的畅销手机中至少存在一个众所周知的错误,每一个实例都具有相同的ANDROID_ID

结论

对于绝大多数应用来说,只需识别特定的安装配置,而不需要识别物理设备。所幸是,这样做就省去了麻烦。

下面是部分使用设备ID的最佳途径:

支持各种设备类型的另一种方法是使用getDeviceID()APIro.serialno的组合

有许多值得参考的原因,来提醒开发者避免试图识别特定的设备。对于那些想做一下这方面尝试的用户,最好的办法可能是使用ANDROID_ID,并在一些传统设备上做尝试。

示例代码

下面是用于追踪Android设置的示例代码

: ReadDeviceID.java

[java] view plaincopy
  1. package com.deviceid;  
  2.    
  3.    
  4.    
  5. import java.lang.reflect.Method;  
  6.    
  7.    
  8.    
  9. import android.app.Activity;  
  10.    
  11. import android.content.Context;  
  12.    
  13. import android.os.Bundle;  
  14.    
  15. import android.provider.Settings;  
  16.    
  17. import android.telephony.TelephonyManager;  
  18.    
  19. import android.view.View;  
  20.    
  21. import android.view.View.OnClickListener;  
  22.    
  23. import android.widget.Button;  
  24.    
  25. import android.widget.TextView;  
  26.    
  27.    
  28.    
  29. public class ReadDeviceID extends Activity {  
  30.    
  31.    
  32.    
  33.  Button bt;  
  34.    
  35.  TextView idView;  
  36.    
  37.    
  38.    
  39.     /** Called when the activity is first created. */  
  40.    
  41.     @Override  
  42.    
  43.     public void onCreate(Bundle savedInstanceState) {  
  44.    
  45.         super.onCreate(savedInstanceState);  
  46.    
  47.         setContentView(R.layout.main);  
  48.    
  49.    
  50.    
  51.         bt=(Button)findViewById(R.id.button1);  
  52.    
  53.         idView=(TextView)findViewById(R.id.textView1);         
  54.   
  55.         bt.setOnClickListener(new OnClickListener() {     
  56.   
  57.  @Override  
  58.    
  59.  public void onClick(View v) {  
  60.    
  61.    String imeistring=null;      
  62.   
  63.               String imsistring=null;  
  64.    
  65.      
  66.   
  67.  TelephonyManager   telephonyManager =   
  68.    
  69. ( TelephonyManager)getSystemService( Context.TELEPHONY_SERVICE );  
  70.    
  71.          
  72.   
  73.             /* 
  74.   
  75.  * getDeviceId() function Returns the unique device ID. 
  76.   
  77.  * for example,the IMEI for GSM and the MEID or ESN for CDMA phones.  
  78.  
  79.  */         
  80.   
  81.  imeistring = telephonyManager.getDeviceId();  
  82.    
  83.  idView.append("IMEI No : "+imeistring+" ");      
  84.    
  85.             /* 
  86.   
  87.              * getSubscriberId() function Returns the unique subscriber ID, 
  88.   
  89.              * for example, the IMSI for a GSM phone. 
  90.   
  91.              */                                                                                           
  92.    
  93.   imsistring = telephonyManager.getSubscriberId();                 
  94.    
  95.   idView.append("IMSI No : "+imsistring+" ");  
  96.    
  97.          
  98.    
  99.             /* 
  100.   
  101.   * System Property ro.serialno returns the serial number as unique number 
  102.   
  103.   * Works for Android 2.3 and above         
  104.   
  105.   */  
  106.    
  107.          
  108.    
  109.   String hwID = android.os.SystemProperties.get("ro.serialno""unknown");  
  110.    
  111.   idView.append( "hwID : " + hwID + " " );  
  112.    
  113.       String serialnum = null;       
  114.    
  115.   try {          
  116.    
  117.     Class<?> c = Class.forName("android.os.SystemProperties");                            
  118.    
  119.     Method get = c.getMethod("get", String.class, String.class );                  
  120.    
  121.                serialnum = (String)(   get.invoke(c, "ro.serialno""unknown" )  );  
  122.    
  123.      idView.append( "serial : " + serialnum + " " );  
  124.    
  125.          } catch (Exception ignored) {        
  126.    
  127.            }  
  128.    
  129.  String serialnum2 = null;  
  130.    
  131.            try {  
  132.    
  133.  Class myclass = Class.forName( "android.os.SystemProperties" );  
  134.    
  135.         Method[] methods = myclass.getMethods();  
  136.    
  137.         Object[] params = new Object[] { new String( "ro.serialno" ) , new String(   
  138.    
  139.               "Unknown" ) };           
  140.    
  141.          serialnum2 = (String)(methods[2].invoke( myclass, params ));           
  142.    
  143.             idView.append( "serial2 : " + serialnum2 + " " );  
  144.    
  145.            }catch (Exception ignored)  
  146.    
  147.  {         
  148.    
  149.  }    
  150.    
  151.    /* 
  152.   
  153.     * Settings.Secure.ANDROID_ID returns the unique DeviceID 
  154.   
  155.     * Works for Android 2.2 and above         
  156.   
  157.     */  
  158.    
  159.  String androidId = Settings.Secure.getString(getContentResolver(),   
  160.    
  161.                                                     Settings.Secure.ANDROID_ID);           
  162.    
  163.             idView.append( "AndroidID : " + androidId + " " );     
  164.    
  165.          }  
  166.    
  167.     });  
  168.    
  169.          
  170.    
  171.     }  
  172.    
  173. }  


: SystemProperties.java

[java] view plaincopy
  1. package android.os;  
  2.    
  3.    
  4.    
  5. /** 
  6.   
  7.  * Gives access to the system properties store. The system properties 
  8.   
  9.  * store contains a list of string key-value pairs. 
  10.   
  11.  * 
  12.   
  13.  * {@hide} 
  14.   
  15.  */  
  16.    
  17. public class SystemProperties  
  18.    
  19. {  
  20.    
  21.     public static final int PROP_NAME_MAX = 31;  
  22.    
  23.     public static final int PROP_VALUE_MAX = 91;  
  24.    
  25.     private static native String native_get(String key);  
  26.    
  27.     private static native String native_get(String key, String def);  
  28.    
  29.     private static native int native_get_int(String key, int def);  
  30.    
  31.     private static native long native_get_long(String key, long def);  
  32.    
  33.     private static native boolean native_get_boolean(String key, boolean def);  
  34.    
  35.     private static native void native_set(String key, String def);  
  36.    
  37.    
  38.    
  39.     /** 
  40.   
  41.      * Get the value for the given key. 
  42.   
  43.      * @return an empty string if the key isn't found 
  44.   
  45.      * @throws IllegalArgumentException if the key exceeds 32 characters 
  46.   
  47.      */  
  48.    
  49.     public static String get(String key) {  
  50.    
  51.         if (key.length() > PROP_NAME_MAX) {  
  52.    
  53.             throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);  
  54.    
  55.         }  
  56.    
  57.         return native_get(key);  
  58.    
  59.     }  
  60.    
  61.    
  62.    
  63.     /** 
  64.   
  65.      * Get the value for the given key. 
  66.   
  67.      * @return if the key isn't found, return def if it isn't null, or an empty string otherwise 
  68.   
  69.      * @throws IllegalArgumentException if the key exceeds 32 characters 
  70.   
  71.      */  
  72.    
  73.     public static String get(String key, String def) {  
  74.    
  75.         if (key.length() > PROP_NAME_MAX) {  
  76.    
  77.             throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);  
  78.    
  79.         }  
  80.    
  81.         return native_get(key, def);  
  82.    
  83.     }  
  84.    
  85.    
  86.    
  87.     /** 
  88.   
  89.      * Get the value for the given key, and return as an integer. 
  90.   
  91.      * @param key the key to lookup 
  92.   
  93.      * @param def a default value to return 
  94.   
  95.      * @return the key parsed as an integer, or def if the key isn't found or 
  96.   
  97.      *         cannot be parsed 
  98.   
  99.      * @throws IllegalArgumentException if the key exceeds 32 characters 
  100.   
  101.      */  
  102.    
  103.     public static int getInt(String key, int def) {  
  104.    
  105.         if (key.length() > PROP_NAME_MAX) {  
  106.    
  107.             throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);  
  108.    
  109.         }  
  110.    
  111.         return native_get_int(key, def);  
  112.    
  113.     }  
  114.    
  115.    
  116.    
  117.     /** 
  118.   
  119.      * Get the value for the given key, and return as a long. 
  120.   
  121.      * @param key the key to lookup 
  122.   
  123.      * @param def a default value to return 
  124.   
  125.      * @return the key parsed as a long, or def if the key isn't found or 
  126.   
  127.      *         cannot be parsed 
  128.   
  129.      * @throws IllegalArgumentException if the key exceeds 32 characters 
  130.   
  131.      */  
  132.    
  133.     public static long getLong(String key, long def) {  
  134.    
  135.         if (key.length() > PROP_NAME_MAX) {  
  136.    
  137.             throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);  
  138.    
  139.         }  
  140.    
  141.         return native_get_long(key, def);  
  142.    
  143.     }  
  144.    
  145.    
  146.    
  147.     /** 
  148.   
  149.      * Get the value for the given key, returned as a boolean. 
  150.   
  151.      * Values 'n', 'no', '0', 'false' or 'off' are considered false. 
  152.   
  153.      * Values 'y', 'yes', '1', 'true' or 'on' are considered true. 
  154.   
  155.      * (case insensitive). 
  156.   
  157.      * If the key does not exist, or has any other value, then the default 
  158.   
  159.      * result is returned. 
  160.   
  161.      * @param key the key to lookup 
  162.   
  163.      * @param def a default value to return 
  164.   
  165.      * @return the key parsed as a boolean, or def if the key isn't found or is 
  166.   
  167.      *         not able to be parsed as a boolean. 
  168.   
  169.      * @throws IllegalArgumentException if the key exceeds 32 characters 
  170.   
  171.      */  
  172.    
  173.     public static boolean getBoolean(String key, boolean def) {  
  174.    
  175.         if (key.length() > PROP_NAME_MAX) {  
  176.    
  177.             throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);  
  178.    
  179.         }  
  180.    
  181.         return native_get_boolean(key, def);  
  182.    
  183.     }  
  184.    
  185.    
  186.    
  187.     /** 
  188.   
  189.      * Set the value for the given key. 
  190.   
  191.      * @throws IllegalArgumentException if the key exceeds 32 characters 
  192.   
  193.      * @throws IllegalArgumentException if the value exceeds 92 characters 
  194.   
  195.      */  
  196.    
  197.     public static void set(String key, String val) {  
  198.    
  199.         if (key.length() > PROP_NAME_MAX) {  
  200.    
  201.             throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);  
  202.    
  203.         }  
  204.    
  205.         if (val != null && val.length() > PROP_VALUE_MAX) {  
  206.    
  207.             throw new IllegalArgumentException("val.length > " +  
  208.    
  209.                 PROP_VALUE_MAX);  
  210.    
  211.         }  
  212.    
  213.         native_set(key, val);  
  214.    
  215.     }  
  216.    
  217. }  


使用"ReadDeviceID" activity 创建"com.deviceid"项目。将布局"main.xml"改写成下面的代码

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.    
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.    
  5.     android:orientation="vertical"  
  6.    
  7.     android:layout_width="fill_parent"  
  8.    
  9.     android:layout_height="fill_parent"  
  10.    
  11.     >  
  12.    
  13. <TextView   
  14.    
  15.     android:layout_width="fill_parent"  
  16.    
  17.     android:layout_height="wrap_content"  
  18.    
  19.     android:text="@string/hello"  
  20.    
  21.     />  
  22.    
  23. <Button  
  24.    
  25.     android:text="GetDeviceID"  
  26.    
  27.     android:id="@+id/button1"  
  28.    
  29.     android:layout_width="wrap_content"  
  30.    
  31.     android:layout_height="wrap_content">  
  32.    
  33. </Button>  
  34.    
  35. <TextView      
  36.    
  37.     android:id="@+id/textView1"     
  38.    
  39.     android:layout_width="fill_parent"  
  40.    
  41.     android:layout_height="wrap_content">  
  42.    
  43. </TextView>  
  44.    
  45. </LinearLayout>  


在"AndroidManifest.xml"文件中添加"READ_PHONE_STATE"许可,使应用程序可以登陆互联网。

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.    
  3. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  4.    
  5.       package="com.deviceid"  
  6.    
  7.       android:versionCode="1"  
  8.    
  9.       android:versionName="1.0">  
  10.    
  11.     <uses-sdk android:minSdkVersion="7" />  
  12.    
  13.    
  14.    
  15.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  16.    
  17.         <activity android:name=".ReadDeviceID"  
  18.    
  19.                   android:label="@string/app_name">  
  20.    
  21.             <intent-filter>  
  22.    
  23.                 <action android:name="android.intent.action.MAIN" />  
  24.    
  25.                 <category android:name="android.intent.category.LAUNCHER" />  
  26.    
  27.             </intent-filter>  
  28.    
  29.         </activity>  
  30.    
  31.    
  32.    
  33.     </application>  
  34.    
  35.      
  36.   
  37.     <uses-permission  
  38.    
  39.             android:name="android.permission.READ_PHONE_STATE" >  
  40.    
  41.       </uses-permission>  
  42.    
  43.      
  44.    
  45. </manifest>  


 

输出结果

上方示例代码的输出结果如下图所示:

原文地址:https://www.cnblogs.com/lanzhi/p/6469639.html