在android中识别物理设备
我正在开发一个应用程序,我想在其中唯一地标识每个设备。我不能使用在android中识别物理设备,android,Android,我正在开发一个应用程序,我想在其中唯一地标识每个设备。我不能使用imei,因为有些平板电脑不支持调用,所以在这些情况下,它将为空。我无法获取wifi/bluetooth mac地址,因为当它关闭时,它返回空值 我不能接受安卓id,因为在重置手机上,它会发生变化,当有一个设备有多个配置文件时,每个配置文件都有不同的安卓id,所以这也不是唯一的设备标识 识别物理设备而不是用户的最佳方法是什么 编辑 我已经读过了,但是我找不到我的答案。我建议可能使用mac地址,并将其哈希 您可以查看,但它仍然需要si
imei
,因为有些平板电脑不支持调用,所以在这些情况下,它将为空。我无法获取wifi/bluetooth mac地址,因为当它关闭时,它返回空值
我不能接受安卓id,因为在重置手机上,它会发生变化,当有一个设备有多个配置文件时,每个配置文件都有不同的安卓id,所以这也不是唯一的设备标识
识别物理设备而不是用户的最佳方法是什么
编辑
我已经读过了,但是我找不到我的答案。我建议可能使用mac地址,并将其哈希 您可以查看,但它仍然需要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"/>
在您的清单中。在我这边,我使用下面的代码。它实际上标识的是硬件,而不是用户或任何配置文件 尽管使用了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.
}
此代码需要在清单中具有以下权限:
这对我来说没有兼容性问题:Build.SERIAL
是在API 9中添加的,对于没有IMEI的平板电脑或其他设备非常有用。当API低于9时,所有的设备都是手机,所以它们都有IMEI(你还支持低于9的API级别吗,真的?)。因此,不存在以空ID或NoClassDefFoundError
结束的风险
作为旁注,
Build.SERIAL
应该是唯一的。我从来没有遇到一个实际的设备,既没有IMEI也没有这个序列号,所以我从来没有任何问题,如果可用的话 大多数用户将拥有一个链接到android设备的谷歌账户(只有极少数情况下不会)。您可以使用获取准确的gmail电子邮件地址(当然,这是唯一的)而无需添加任何权限即可获取帐户。
并使用电子邮件和电话型号或制造商或序列号的组合作为设备的唯一id。(用户可能使用两台设备,但其所有设备相同的可能性很低)
您的应用程序需要包括Google Play服务,但不需要
任何权限。
整个过程将在较旧版本的Android(2.2+is)上失败
<强> > <<强> >强>或者如果谷歌播放不可用<强>,所以你应该考虑
那个案子
源代码中的示例代码:
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);
}
}
上述信息的来源是:-对过去提出的一个类似但略有不同的问题
-还有一些很好的方法可以达到您的目的。这是一个非常重要和有趣的问题,所以我想详细回答它 有几种方法可以唯一地检测Android设备,但问题是,由于各种原因,大多数方法都不可靠 i) IMEI 这是目前最常用的方法,但仅适用于手机,需要此不必要的权限
android.permission.READ\u PHONE\u STATE
ii)Android ID
这也可以在工厂重置或设备根目录时更改。这不是一个非常可靠的唯一性方法
iii)无线局域网和蓝牙MAC地址
这要求设备具备这些功能,并具有像android.permission.ACCESS\u WIFI\u STATE
和android.permission.BLUETOOTH
这样的权限。如果关闭wifi或蓝牙,这也将不起作用
iv)电话号码或电子邮件ID
这是确定唯一性最不可靠的方法,如果不是完全必要的话,也不应作为一种选择方法
那么现在的出路是什么,伪唯一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可能会发生冲突,但这将是非常罕见的。所以从技术上讲,这是大多数用例都可以依赖的。我想到的一个简单方法是使用注册表服务器
使用这种方法,您的所有用户都需要将其应用程序(即相当于其设备)注册到注册表服务。然后注册表服务器依次为他们分配一个唯一的令牌,该令牌应随后在应用程序中使用。可能重复@RogueBaneling,我已经阅读了该线程。我找不到我正在寻找的答案。这要求wifi应该打开。如果为off,则返回null。。我已经在问题中提到了这一点,不
Build.SERIAL
change?@Williams它不应该作为硬件序列号更改。我所知道的一个事实是,我从未收到客户的投诉,他们突然发现他们的设备没有被识别,因为我从来没有因为一些混淆而出现问题。这就是为什么我要用这个。现在我更愿意看到API规范中写了这个。我们需要为android.os.Build.class.getField(“串行”)请求READ_PHONE_STATE权限吗??