Reputation: 139
The documentation notes what identifier is used in iOS/Windows builds, but not Android builds. What identifier does SystemInfo.deviceUniqueIdentifier
use on Android?
Upvotes: 4
Views: 8440
Reputation: 125445
I don't understand why that is not mentioned in the Doc.
Last time I checked, Unity uses Secure.ANDROID_ID
to get the Android ID string then converts that to string. If you do that, you should the the-same value as SystemInfo.deviceUniqueIdentifier
. This is what's happening on my device.
Unfortunately, more things are going on in the background.
Unity documented their Unique Identifier Details implementation on their forum.
1. Get DeviceId with context.getSystemService(Context.TElEPHONY_SERVICE).getDeviceId()
2.If #1 fails, get Android ID with context.getContentResolver().getString(Secure.ANDROID_ID);
3.If #2 fails, get the Mac Address.
4.Convert result from #1, #2 or #3(which ever one that was successful) to MD5 Hash.
It's worth reading that forum post since the behavior is a little different on some Unity versions.
Here is a sample code provide by them on what it looks like:
// Hash an input string and return the hash as
// a 32 character hexadecimal string.
static string getMd5Hash(string input)
{
if (input == "")
return "";
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sBuilder.Append(data[i].ToString("x2"));
return sBuilder.ToString();
}
static string generateDeviceUniqueIdentifier(bool oldBehavior)
{
string id = "";
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = jc.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaClass contextClass = new AndroidJavaClass("android.content.Context");
string TELEPHONY_SERVICE = contextClass.GetStatic<string>("TELEPHONY_SERVICE");
AndroidJavaObject telephonyService = activity.Call<AndroidJavaObject>("getSystemService", TELEPHONY_SERVICE);
bool noPermission = false;
try
{
id = telephonyService.Call<string>("getDeviceId");
}
catch (Exception e) {
noPermission = true;
}
if(id == null)
id = "";
// <= 4.5 : If there was a permission problem, we would not read Android ID
// >= 4.6 : If we had permission, we would not read Android ID, even if null or "" was returned
if((noPermission && !oldBehavior) || (!noPermission && id == "" && oldBehavior))
{
AndroidJavaClass settingsSecure = new AndroidJavaClass("android.provider.Settings$Secure");
string ANDROID_ID = settingsSecure.GetStatic<string>("ANDROID_ID");
AndroidJavaObject contentResolver = activity.Call<AndroidJavaObject>("getContentResolver");
id = settingsSecure.CallStatic<string>("getString", contentResolver, ANDROID_ID);
if(id == null)
id = "";
}
if(id == "")
{
string mac = "00000000000000000000000000000000";
try
{
StreamReader reader = new StreamReader("/sys/class/net/wlan0/address");
mac = reader.ReadLine();
reader.Close();
}
catch (Exception e) {}
id = mac.Replace(":", "");
}
return getMd5Hash(id);
}
Upvotes: 5