1. 程式人生 > >獲取 Android 裝置的唯一標識碼

獲取 Android 裝置的唯一標識碼

這個問題有很多答案,但是他們中的大部分只在某些情況下有效。

根據測試:

  • 所有的裝置都可以返回一個 TelephonyManager.getDeviceId()
  • 所有的GSM裝置 (測試裝置都裝載有SIM卡) 可以返回一個TelephonyManager.getSimSerialNumber()
  • 所有的CDMA 裝置對於 getSimSerialNumber() 卻返回一個空值!
  • 所有新增有谷歌賬戶的裝置可以返回一個 ANDROID_ID
  • 所有的CDMA裝置對於 ANDROID_ID 和 TelephonyManager.getDeviceId() 返回相同的值(只要在設定時添加了谷歌賬戶)
  • 目前尚未測試的:沒有SIM卡的GSM裝置、沒有新增谷歌賬戶的GSM裝置、處於飛航模式的裝置。

所以如果你想得到裝置的唯一序號, TelephonyManager.getDeviceId() 就足夠了。但很明顯暴露了DeviceID會使一些使用者不滿,所以最好把這些id加密了。實際上加密後的序號仍然可以唯一的識別該裝置,並且不會明顯的暴露使用者的特定裝置,例如,使用 String.hashCode() ,結合UUID:

1 2 3 4 5 6 7 8 9 final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, tmPhone, androidId; tmDevice = "" + tm.getDeviceId(); tmSerial = "" + tm.getSimSerialNumber(); androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); UUID deviceUuid = new UUID(androidId.hashCode(), ((
long)tmDevice.hashCode() << 32) | tmSerial.hashCode()); String uniqueId = deviceUuid.toString();

最後的deviceID可能是這樣的結果: 00000000-54b3-e7c7-0000-000046bffd97


---------------------------------------------------------------------------------------------------------------------------------------------------------------

最近一直在搞註冊的問題,想要獲得android的一個唯一標識,但是各種方法都有弊病,先詳細分析一下:

1. DEVICE_ID

假設我們確實需要用到真實裝置的標識,可能就需要用到DEVICE_ID。在以前,我們的Android裝置是手機,這個DEVICE_ID可以同通過TelephonyManager.getDeviceId()獲取,它根據不同的手機裝置返回IMEI,MEID或者ESN碼,但它在使用的過程中會遇到很多問題:

  • 非手機裝置: 如果只帶有Wifi的裝置或者音樂播放器沒有通話的硬體功能的話就沒有這個DEVICE_ID
  • 許可權: 獲取DEVICE_ID需要READ_PHONE_STATE許可權,但如果我們只為了獲取它,沒有用到其他的通話功能,那這個許可權有點大才小用
  • bug:在少數的一些手機裝置上,該實現有漏洞,會返回垃圾,如:zeros或者asterisks的產品

2. MAC 地址

我們也可以通過手機的Wifi或者藍芽裝置獲取MAC ADDRESS作為DEVICE ID,但是並不建議這麼做,因為並不是所有的裝置都有Wifi,並且,如果Wifi沒有開啟,那硬體裝置無法返回MAC地址,這裡所說的wifi沒有開啟是指開機後wifi一直沒有開啟,若開啟過一次就能得到mac地址,附上開啟wifi的程式碼:

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
  if (!wifi.isWifiEnabled()) {
            wifi.setWifiEnabled(true);
  }

這裡需要新增允許開啟wifi的許可權:<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

3. Serial Number

在Android 2.3可以通過android.os.Build.SERIAL獲取,非手機裝置可以通過該介面獲取。

4. ANDROID_ID

ANDROID_ID是裝置第一次啟動時產生和儲存的64bit的一個數,當裝置被wipe後該數重置

ANDROID_ID似乎是獲取Device ID的一個好選擇,但它也有缺陷:

  • 它在Android <=2.1 or Android >=2.3的版本是可靠、穩定的,但在2.2的版本並不是100%可靠的
  • 在主流廠商生產的裝置上,有一個很經常的bug,就是每個裝置都會產生相同的ANDROID_ID:9774d56d682e549c

5.手機卡的資訊(IMSI)

如果你想得到手機的手機號,目前來看還有一定的難度,主要是有的卡的資訊是放在服務提供商的伺服器上,但是不要著急,我們能夠得到手機卡的唯一標識:

TelephonyManager tm=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);

tm.getSubscriberId();//IMSI

現在主要問題是有些手機的mac地址會變,這個不受程式控制,每開關一個wifi,mac地址都會變一次(不過大部分的是不變的),android手機各種各樣,要考慮全部的肯定是考慮不過來,所以推薦使用手機卡的IMSI。

現在我也沒有找到最優的,歡迎大家交流!

可不可以在手機端放一個uuid作為唯一標識,因為你說的哪些可能都或多或少有點問題,不能真正作為唯一標識。

什麼是UUID,Java中怎麼產生UUID?

GUID是一個128位長的數字,一般用16進製表示。演算法的核心思想是結合機器的網絡卡、當地時間、一個隨機數來生成GUID。從理論上講,如果一臺機器每秒產生10000000個GUID,則可以保證(概率意義上)3240年不重複。 
UUID是1.5中新增的一個類,在java.util下,用它可以產生一個號稱全球唯一的ID。
import java.util.UUID;
public class Test {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID(); 
System.out.println (uuid);
} }
請問目前想要標識一個裝置(android平板),一般採用什麼方法。比如用什麼ID作為唯一標識ID。謝謝
Java code
     private String getMyUUID(){

   final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(this.TELEPHONY_SERVICE);   
   final String tmDevice, tmSerial, tmPhone, androidId;   
   tmDevice = "" + tm.getDeviceId();  
   tmSerial = "" + tm.getSimSerialNumber();   
   androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(),android.provider.Settings.Secure.ANDROID_ID);   
   UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());   
   String uniqueId = deviceUuid.toString();
   Log.d("debug","uuid="+uniqueId);
   return uniqueId;
  }
獲取唯一且不變的UUID。
2L的可以採納,另外MAC地址一般也可以作為唯一標識~~!
------------------------------------------------------------------------------------------------------------------------------------------------------------------- 補充內容:

以上四種方式都有或多或少存在的一定的侷限性或者bug,在這裡,有另外一種方式解決,就是使用UUID,該方法無需訪問裝置的資源,也跟裝置型別無關。

這種方式是通過在程式安裝後第一次執行後生成一個ID實現的,但該方式跟裝置唯一標識不一樣,它會因為不同的應用程式而產生不同的ID,而不是裝置唯一ID。因此經常用來標識在某個應用中的唯一ID(即Installtion ID),或者跟蹤應用的安裝數量。很幸運的,Google Developer Blog提供了這樣的一個框架:

public class Installation {
    private static String sID = null;
    private static final String INSTALLATION = "INSTALLATION";

    public synchronized static String id(Context context) {
        if (sID == null) {  
            File installation = new File(context.getFilesDir(), INSTALLATION);
            try {
                if (!installation.exists())
                    writeInstallationFile(installation);
                sID = readInstallationFile(installation);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return sID;
    }

    private static String readInstallationFile(File installation) throws IOException {
        RandomAccessFile f = new RandomAccessFile(installation, "r");
        byte[] bytes = new byte[(int) f.length()];
        f.readFully(bytes);
        f.close();
        return new String(bytes);
    }

    private static void writeInstallationFile(File installation) throws IOException {
        FileOutputStream out = new FileOutputStream(installation);
        String id = UUID.randomUUID().toString();
        out.write(id.getBytes());
        out.close();
    }
}


綜合以上所述,為了實現在裝置上更通用的獲取裝置唯一標識,我們可以實現這樣的一個類,為每個裝置產生唯一的UUID,以ANDROID_ID為基礎,在獲取失敗時以TelephonyManager.getDeviceId()為備選方法,如果再失敗,使用UUID的生成策略