Android – 裝置的通用識別碼

開發者在開發 APP 時,若是有跟伺服器資料連接時,常常會為了一些理由,而會設法從裝置中取其識別碼來進行識別之用。可是,這個動作在 Android 設備中,其實也是一種很麻煩的動作,而這個麻煩就是源自於碎片化,各 OEM 廠商都會客製化自己的機器,或是配合當地的需求而有不同的差異化,比方說,有的機器其實並沒有藍芽、這時候要取得藍芽的 id 就是一件做不到的事情;像是 Nexus 7 2012 在一開始販售時,只有 Wifi,而這時候想要取得其 IMEI 也是無法的。

因此,在 Android 的開發世界中,要如何取得一個單純的識別碼,其實也是隱藏很多地雷在其中;所以本篇將為各位介紹幾種設備上 “直覺上” 會嘗試去取出當做識別碼的介面,以及現存可以查到的識別碼方法進行說明,並列出使用何者可能會發生的問題,希望有助於大家判斷何者適合於自己服務,減少踩到地雷的機會!

Device Id

本範例 APP:
Get it on Google Play

 

本篇將為各位介紹下列幾種在 Android 設備上,應該可以取得做為識別碼的方式:

  1. Device ID
  2. Subscriber ID
  3. Serial ID
  4. MAC Address
  5. Bluetooth Address
  6. Android ID
  7. UUID

 

1. Device ID (IMEI/MEID)


Device ID 看得是各地電信商提供什麼系統,若是 GSM 所取出的編碼就是 IMEI;若是 CDMA 取出的就是 MEID 或 ESN。

表面上,這應該是設備中最穩定的識別碼,但仍是有諸多 Android 設備是沒有的,像在 2012 年剛上市的 Nexus 7 就只有出 WIFI 的版本,就取不到這個識別碼。像現行有的電視盒或是展場上採用 Android 的設備,可能就是只有 WIFI ,在這種狀況下,取出來的值就是 null。

另外,要取得這個值,所需要的權限得用到「READ_PHONE_STATE」,這個權限其實頗大的,當使用者在安裝時,就會看到這個 APP 會要到的權限是「讀取手機狀態」,以現在 Android 病毒亂竄的狀況下,使用者會對這個權限是有疑心的,也可能因為這樣就不裝了。下圖所示的內容分別是從 4.1.2 以及 4.4.2 的設備中擷出來的畫面。

READ_PHONE_STATE

 

在 activity 中

需要在 Manifest 加上權限

返回索引

 

2. Subscriber ID


用戶唯一碼,若是 GSM 就是 IMSI 碼;若是使用者沒有插卡,這個值會為 null。而 CDMA 的卡片也取不到值。

和 1. 相同,這個權限需要用到「READ_PHONE_STATE」。

在 activity 中

需要在 Manifest 加上權限

返回索引

 

3. Serial ID


這個識別碼是由不分大小寫的英文字母跟數字所組成。此識別碼對比 1 跟 2,他不用任何權限就可以使用,也的確是唯一碼。但他需要在 Android 2.3 以上的設備才能取得,也就是說,自己的 APP 若是從 2.3 開始支援,用這個值原則上是沒問題的。

返回索引

 

4. MAC Address


設備網卡的編碼。這個在沒有 WIFI 的設備仍是取不到;除了前述問題,有可能會因為系統更新、重新設定、重新開機在還未連線的狀況下取不到的資料,所以也要小心。

在 activity 中

需要在 Manifest 加上權限

返回索引

 

5. Bluetooth Address


藍芽的設備碼。沒有藍芽的設備取不到;

需要在 Manifest 加上權限

返回索引

 

6. Android ID


這個 ID 的優點也是不需要任何權限,他是在設備出廠後第一次啟動時產生。

但是他在 2.2 以前是不可靠的,曾經有一批設備在出廠後,所產生的編號都是:9774d56d682e549c。

另外還有一個問題,當設備被執行「恢復原廠設定」時,這個 id 會被重新產生。

在 activity 中

返回索引

 

7. UUID


這個 ID 並不是由設備自動產生,是開發者自行寫在 APP 程式中,而且必需是寫在程式一開始就一定會執行到的地方,並立即將之存於設備裡。其最大的缺點就是當 APP 被執行「清除資料」或是移除重裝後的 ID 都會重新產生。因為要存入設備中,所以需要有寫入的權限。

這個函式是 android 內建,依循 RFC 4122 的規範隨機產出一組編號。

  • API Level:1 (Android Document)
  • 權限需求:WRITE_EXTERNAL_STORAGE
  • 程式碼:

在 android 官方的 developer blog 中,提供了一個演算法,大家可以自行連結到 Android 官方部落格參考。

返回索引

 

總結


最後歸納一下,各種識別碼可取出的 API 版本,以及可能遇到的問題:

  1. Device ID (IMEI/MEID)
    • API Level:1
    • Permission:READ_PHONE_STATE
    • 潛在問題:
      • 沒有 3G 介面的設備會取不到,如 Nexus 7 2012 WIFI only。
      • 要求的權限較大,可能會讓在意的使用者怯步。
  2. Subscriber ID
    • API Level:1
    • Permission:READ_PHONE_STATE
    • 潛在問題:
      • 和 Device ID 一樣,沒有 3G 介面一定會取不到。
      • 沒有插卡取不到。
      • CDMA 系統取不到。
      • 要求的權限較大,可能會讓在意的使用者怯步。
  3. Serial ID
    • API Level:9
    • Permission:無
    • 潛在問題:
      • 要版本 2.3 以上的手機才有值。
  4. MAC Address
    • API Level:1
    • Permission:ACCESS_WIFI_STATE
    • 潛在問題:
      • 有的設備沒有 WIFI。
      • 有可能因為沒有連線,而取不到值。
  5. Bluetooth Address
    • API Level:5
    • Permission:BLUETOOTH
    • 潛在問題:
      • 有的設備沒有藍芽。
      • 可能因為沒開啟,而拿不到值。
  6. Android ID
    • API Level:3
    • Permission:無
    • 潛在問題:
      • 有一批設備全部都會產生「9774d56d682e549c」。
      • 執行「恢復原廠設定」後,會重新產生一組。
  7. UUID
    • API Level:1
    • Permission:WRITE_EXTERNAL_STORAGE
    • 潛在問題:
      • 要自己寫演算法。要留意 APP 一被執行就要產生,並存在設備中,同時留意不會被重覆執行到。
      • 該 APP 被「清除資料」就會重新產生。
      • 該 APP 被移除重裝後,會重新產生。

這樣看下來,其實這其中並沒有一個「完美」的方案,所以,建議大家可以自行依需求判斷,多重搭配著使用來避開一些地雷。

本範例 APP:
Get it on Google Play

 

本部落格採用創用CC 姓名標示-非商業性-禁止改作 3.0 台灣 授權條款授權,如欲轉載請記得註明「莫希爾(Mosil) 手札

Loading Facebook Comments ...

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *