我正在开发一个应用程序,我想在其中识别每个设备。我无法使用imei
,因为某些平板电脑不支持呼叫,因此在这些情况下它将为空。我不能使用wifi /蓝牙mac地址,因为当它关闭时它会返回null。
我无法使用android _id,因为在重置手机上它会发生变化,当有一个设备有多个配置文件时,每个配置文件都有不同的android_id,所以这也不是识别设备的唯一身份。
识别物理设备而非用户的最佳方法是什么。
我已经阅读了Is there a unique Android device ID?,但我找不到答案。
答案 0 :(得分:0)
我建议使用一个mac地址,然后哈希吧。
您可以查看this answer,但仍需要SIM卡。
您可以像这样获得Mac地址:
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
String address = info.getMacAddress();
然后在它上面做一个md5哈希。
我认为它会正常工作。
不要忘记添加
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
在你的清单中。
答案 1 :(得分:0)
在我这边,我正在使用下面的代码。它实际上标识硬件,而不是用户或任何配置文件。
我认为尽管使用了IMEI号码,但你需要的东西很好,因为它被认为是可选的:
public static String getUniqueId(Context ctx) {
final TelephonyManager tm = (TelephonyManager)ctx.getSystemService(Context.TELEPHONY_SERVICE);
String id = tm.getDeviceId();
if (id == null) {
id = Build.SERIAL;
}
return DigestHelper.getSHADigest(id); // I'm using a SHA for convenience, and for not being able to reverse it, but you can do anything needed with this String.
}
此代码需要您的Manifest中的以下权限:<uses-permission android:name="android.permission.READ_PHONE_STATE" />
。
这适用于我而没有兼容性问题:Build.SERIAL
添加了API 9,对于没有IMEI的平板电脑或其他设备非常有用。使用低于9的API,所有设备都是手机,因此它们都有IMEI(你仍然支持低于9的API级别,真的吗?)。因此,没有风险可以使用空ID或NoClassDefFoundError
。
作为旁注,Build.SERIAL
应该是唯一的“if available”。我从未遇到过既没有IMEI也没有这个序列号的实际设备,所以我从来没有遇到任何“如果可用”的问题。
答案 2 :(得分:0)
大多数用户都有一个链接到Android设备的Google帐户(仅在极少数情况下他们赢了)。您可以使用AccountPicker 获取确切的Gmail电子邮件地址(当然,这将是唯一的),而无需添加任何权限来获取帐户。
并使用电子邮件和手机型号或制造商或序列号的组合作为设备的唯一ID。(可能该用户可能使用两台设备,但所有设备的可能性非常低同样的)
您的应用需要包含Google Play服务但不需要 任何权限。
整个过程将在旧版本的Android上失败(2.2+ 必需),或Google Play不可用,因此您应该考虑 那种情况。
来自源代码的示例代码:
private static final int REQUEST_CODE_EMAIL = 1;
private TextView email = (TextView) findViewById(R.id.email);
// ...
try {
Intent intent = AccountPicker.newChooseAccountIntent(null, null,
new String[] { GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE }, false, null, null, null, null);
startActivityForResult(intent, REQUEST_CODE_EMAIL);
} catch (ActivityNotFoundException e) {
// TODO
}
// ...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_EMAIL && resultCode == RESULT_OK) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
email.setText(accountName);
}
}
上述信息的来源是:This Answer on SO - 过去提出的类似但略有不同的问题。
This Post - 也有一些很好的方法可以达到您的目的。
答案 3 :(得分:0)
这是一个非常重要且有趣的问题,所以想详细解答。
有多种方法可以唯一地检测Android设备,但问题是由于各种原因,大多数方法都不可靠。
i) IMEI
这是迄今为止最常用的方法,但仅适用于手机,需要此不必要的权限android.permission.READ_PHONE_STATE
ii) Android ID
这也可以在恢复出厂设置或设备已植根时更改。不是一种非常可靠的独特方式。
iii) WLAN和蓝牙MAC地址
这要求设备具有这些功能,并具有android.permission.ACCESS_WIFI_STATE
和android.permission.BLUETOOTH
等权限。如果关闭wifi或蓝牙,这也不起作用。
iv)电话号码或电子邮件ID
这是确定唯一性的最不可靠的方法,如果不是完全必要的话,不应该是一种选择方法。
现在的方法是什么, Pseudo Unique ID 。您可以从设备创建自己的“几乎唯一的ID ”,而无需任何额外的权限。
听起来不错?让我们直接进入该方法。
/**
* Return pseudo unique ID
* @return ID
*/
public static String getUniquePsuedoID() {
// If all else fails, if the user does have lower than API 9 (lower
// than Gingerbread), has reset their device or 'Secure.ANDROID_ID'
// returns 'null', then simply the ID returned will be solely based
// off their Android device information. This is where the collisions
// can happen.
// Thanks http://www.pocketmagic.net/?p=1662!
// Try not to use DISPLAY, HOST or ID - these items could change.
// If there are collisions, there will be overlapping data
String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
// Thanks to @Roman SL!
// http://stackoverflow.com/a/4789483/950427
// Only devices with API >= 9 have android.os.Build.SERIAL
// http://developer.android.com/reference/android/os/Build.html#SERIAL
// If a user upgrades software or roots their device, there will be a duplicate entry
String serial = null;
try {
serial = android.os.Build.class.getField("SERIAL").get(null).toString();
// Go ahead and return the serial for api => 9
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
// String needs to be initialized
serial = "serial"; // some value
}
// Thanks @Joe!
// http://stackoverflow.com/a/2853253/950427
// Finally, combine the values we have found by using the UUID class to create a unique identifier
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}
在为任何Android设备生成伪唯一ID时需要考虑各种因素。但这并不完美。
这些ID可能会发生冲突,但这种情况很少见,非常罕见。从技术上讲,这是大多数用例可以依赖的东西。
答案 4 :(得分:0)
我想到的一个简单方法是使用注册表服务器。
使用此方法,您的所有用户都需要将其应用程序(即等效的设备)注册到注册服务。然后,注册服务器又为它们分配一个唯一的令牌,该令牌随后应该在应用程序中使用。