2013-02-14 83 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