2013-02-14 14 views
6

Wenn ich über einzigartige Android IDs spreche, bin ich sicher, dass jeder this gesehen hat, aber ich versuche auch, eine Lösung zu finden, um jedes Android-Gerät eindeutig zu identifizieren. Ich wäre froh, einen öffentlich veröffentlichten Kurs zu verwenden, aber ich muss noch einen finden.Erstellen eines weltweit einzigartigen Android Identifier

In meiner Situation besteht die Anforderung darin, Geräte mit einer Internetverbindung (wie GPRS oder Wi-Fi) eindeutig identifizieren zu können und auf API-Ebene 8 (v2.2 Froyo) zu laufen. Mir sind keine Geräte bekannt, die kein WLAN oder eine SIM-Karte haben. Lassen Sie mich wissen, ob es welche gibt!

Wir lösten dieses Problem in iOS mit einem Hash der Wi-Fi-Mac-Adresse wie alle iOS-Geräte sollten dies haben. Für Android beziehen sich Techniken (wie die Antworten auf den oben genannten SO-Post) jedoch auf die Klasse TelephonyManager, die null zurückgeben kann (z. B. wenn das Gerät keine SIM-Verbindung hat, wie beim Nexus 7) oder getContext().getContentResolver(), Secure.ANDROID_ID zu here ist nicht 100% zuverlässig auf Versionen vor Froyo (was für mich glücklich ist). Es gibt jedoch keine Probleme Post-Froyo so wieder, wenn es welche gibt, lass es mich wissen! Ich habe auch gelesen das kann null zurückgeben. Laut here kann es sich bei einem Werksreset ändern, aber das ist kein großes Problem.

Also habe ich dies zusammengestellt, um eine hoffentlich-einzigartige GUID zu erzeugen: [Diese Methode ist nicht vollständig!]

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(); 
} 

So können Sie tmDeviceId wird auf null, in diesem Fall finden die die customHash wird das gleiche, unabhängig von dem Gerät sein, aber dann soll dies in Kombination mit androidIDString global eindeutig sein. Ich denke. Offensichtlich muss ich herausfinden, ob tmDeviceId AND androidIDString nicht verfügbar sind und dort eine Ausnahme auslösen.

Also ... ist das Overkill? Wenn ja, ist es sicher, einfach context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID zu verwenden?

+1

"In meiner Situation ist die Anforderung in der Lage, alle Geräte eindeutig zu identifizieren" - wenn Sie dies benötigen, um gerootete Gerätebenutzer zu decken, ist dies unmöglich AFAIK. Natürlich können alle Teile, die Sie verwenden, von jemandem mit root-Rechten geändert werden. "Mir sind keine Geräte bekannt, die kein WLAN oder eine SIM-Karte haben. Lassen Sie mich wissen, ob es welche gibt!" - Google TV-Geräte verfügen möglicherweise nicht über WLAN und sind mit Ethernet verbunden. Wenn Sie über den Play Store hinaus vertrieben werden, gibt es möglicherweise auch andere Geräte ohne mobile Daten oder WLAN. – CommonsWare

+0

@CommonsWare Danke für Ihre Antwort. Meine anfänglichen Gedanken sind, das Gerät einfach nicht zu unterstützen, wenn die Methoden, über die ich in der Frage gesprochen habe, alle "null" sind. Glaubst du, dass es sicher ist, 'Secure.ANDROID_ID' auf etwas von Froyo zu verwenden? Außerdem glaube ich nicht, dass ein gerootetes Gerät ein Hauptanliegen ist. Ich denke, es würde jemandem erlauben, ein anderes Gerät von jemand anderem zu parodieren, zumindest, wenn sie wüssten, was sie tun, aber ich dachte, dass ich einen Schlüssel hinzufügen würde (wo ich 'stringBuilder.append (" someRandomData ") hatte;') würde es schwierig machen, die endgültige zurückgegebene Geräte-ID zu generieren. –

+0

"Glaubst du, dass es sicher ist, Secure.ANDROID_ID von Froyo zu verwenden?" - Nutzer mit gerooteten Geräten können dies ändern, und Geräte, auf denen der Play Store nicht legitim ist, haben möglicherweise keine eindeutigen Werte. – CommonsWare

Antwort

3

Warum erhalten Sie die MAC-Adresse des Geräts nicht wie in iOS? Dies kann auch in Android-Geräten durchgeführt werden.

Ich werde einen Code-Schnipsel geben, die MAC-Adresse des Gerätes erhält ..

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() wird MAC-Adresse des Geräts zurückzukehren.

EDIT: Wenn Mac-Adresse nicht für Ihre Situation geeignet ist. Folgendes kann nützlich sein!

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; 
    } 
} 

Vergessen Sie nicht nach Erlaubnis zu Ihrer AndoridManifest.xml Datei hinzufügen, wenn Sie getDeviceId Methode verwenden.

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

Dies ist, was ich am Ende getan habe, das Problem ist, ich glaube, Sie können die MAC-Adresse spoofen, wenn Sie Root-Zugang haben. –

+0

Ja, du hast absolut recht. Wenn Sie ein Root-Gerät haben, können Sie das tun. Hast du android.os.Build.SERIAL versucht? Sie können Hardware-Seriennummer erhalten, indem Sie dies verwenden? Überprüfen Sie diese [link] (http://developer.android.com/reference/android/os/Build.html#SERIAL) Es kann für Sie hilfreich sein. – gokhanakkurt

+0

Danke, ich werde das überprüfen. Ist 'android.os.Build.SERIAL' etwas, das garantiert existiert? –