2013-02-14 75 views
6

當談論獨特的Android ID時,我確信每個人都看過this,但是我也試圖想出一個唯一標識任何Android設備的解決方案。我很樂意使用公開發布的課程,但我還沒有找到。創建一個全球唯一的Android標識符

在我的情況下,要求是能夠唯一標識任何具有某種形式的互聯網連接(如GPRS或Wi-Fi)並在API級別8(v2.2 Froyo)上運行的設備。我不知道任何沒有Wi-Fi或SIM卡的設備,因此請告訴我是否有任何設備!

我們在iOS中通過使用Wi-Fi mac地址的散列來解決了這個問題,因爲所有的iOS設備都應該有。然而,對於Android,技術(例如上面引用的SO帖子的答案)是指TelephonyManager類,其可以返回null(例如,當設備沒有SIM連接時,如Nexus7)或getContext().getContentResolver(), Secure.ANDROID_ID,其根據到here在Froyo之前的版本(這對我來說是幸運的)不是100%可靠的。但是,如果有任何問題,請不要在Froyo之後提出任何問題,請告訴我!我也讀過這可以返回null。根據here,它可以在出廠重置時更改,但這不是主要問題。

所以我把這個放在一起生成一個希望唯一的GUID: [這種方法不完整!]

public static String GetDeviceId(Context context) 
{ 
    // Custom String Hash 1 
    StringBuilder stringBuilder = new StringBuilder(); 
    stringBuilder.append("someRandomData"); // Not really needed, but means the stringBuilders value won't ever be null 

    // TM Device String 
    final TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
    String tmDeviceId = tm.getDeviceId(); // Could well be set to null! 
    LogMsg.Tmp("TM Device String [" + tmDeviceId + "]"); 

    // Custom String Hash 2 
    stringBuilder.append(tmDeviceId); 
    int customHash = stringBuilder.toString().hashCode(); 
    LogMsg.Tmp("Custom String hash [" + customHash + "]"); 

    // Device ID String 
    String androidIDString = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); 
    LogMsg.Tmp("Device ID String [" + androidIDString + "]"); 

    // Combined hashes as GUID 
    UUID deviceUuid = new UUID(androidIDString.hashCode(), ((long)customHash << 32)); 
    LogMsg.Tmp("Combined hashes as GUID [" + deviceUuid.toString() + "]"); 

    return deviceUuid.toString(); 
} 

所以,你可能會發現tmDeviceId被設置爲null,在這種情況下,該customHash將是相同的,不管設備,但隨後這與androidIDString結合應該是全球唯一的。我認爲。很顯然,如果tmDeviceIdandroidIDString不可用,並且在那裏拋出異常,我將需要解決。

所以......這是否過分矯枉過正?如果是這樣,僅使用context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID安全嗎?

+1

「在我的情況,要求是能夠唯一地識別任何設備」 - 如果你需要這個覆蓋植根設備的用戶,這是不可能的AFAIK。當然,您正在使用的任何部分都可以由具有root權限的人修改。 「我不知道任何沒有Wi-Fi或SIM卡的設備,所以請告訴我是否有任何設備!」 - Google TV設備可能沒有WiFi,只能使用以太網。如果您在Play商店之外進行分發,則可能會有其他設備沒有移動數據或WiFi。 – CommonsWare 2013-02-14 17:07:24

+0

@CommonsWare感謝您的回覆。我最初的想法是,如果我在問題中討論的方法都返回null,則不支持該設備。你認爲在Froyo的任何東西上使用Secure.ANDROID_ID是安全的嗎?另外,我不認爲根植設備是一個主要問題。我猜這會讓別人欺騙別人的其他設備,至少,如果他們知道他們在做什麼,但我想通過添加一個鍵(我有'stringBuilder.append(「someRandomData」);'' )會使得難以生成最終返回的設備ID。 – 2013-02-15 09:36:55

+0

「你認爲從Froyo的任何東西上使用Secure.ANDROID_ID是安全的嗎?」 - 固定的設備用戶可以更改它,而不合法擁有Play商店的設備可能沒有唯一的值。 – CommonsWare 2013-02-15 12:32:11

回答

3

爲什麼不像您在iOS中那樣獲取設備的MAC地址?這也可以在Android設備上執行。

我給的代碼片段獲取設備的MAC地址..

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 

public class HardwareUtil { 

    public static String getMacAddress() 
    { 
     try{ 
      Process process = Runtime.getRuntime().exec("cat /sys/class/net/eth0/address"); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 
      int read; 
      char[] buffer = new char[4096]; 
      StringBuffer output = new StringBuffer(); 
      while ((read = reader.read(buffer)) > 0){ 
       output.append(buffer, 0, read); 
      } 
      reader.close(); 
      process.waitFor(); 
      String hwaddr = output.toString(); 
      return hwaddr; 
     }catch (IOException e) { 
      e.printstacktrace(); 
     }catch (InterruptedException e){ 
      e.printstacktrace(); 
     } 
    } 

} 

HardwareUtil.getMacAddress()將返回設備的MAC地址。

編輯:如果mac地址不適合您的情況。以下可能有用!

public static String getDeviceId(Context context) { 
    final String deviceId = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); 
    if (deviceId != null) { 
     return deviceId; 
    } else { 
     return android.os.Build.SERIAL; 
    } 
} 

不要忘記,如果你使用getDeviceId方法下列權限添加到您的AndoridManifest.xml文件。

<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
+0

這就是我最後所做的,問題是我相信你可以僞造MAC地址,如果你有root權限的話。 – 2013-10-07 16:10:20

+0

是的,你是絕對正確的。如果你有root設備,你可以做到這一點。你有沒有嘗試android.os.Build.SERIAL?你可以通過使用這個獲得硬件序列號?看看這個[鏈接](http://developer.android.com/reference/android/os/Build.html#SERIAL)它可能對你有所幫助。 – gokhanakkurt 2013-10-08 07:06:11

+0

謝謝,我會檢查一下。是'android.os.Build.SERIAL'保證存在的東西嗎? – 2013-10-08 10:51:55