Android设备有唯一的ID吗?如果有,使用Java访问它的简单方法是什么?
当前回答
更新:在最近的Android版本中,Android_ID的许多问题已经得到解决,我相信这种方法不再是必要的。请看一下安东尼的回答。
完整披露:我的应用程序最初使用了以下方法,但现在不再使用这种方法,我们现在使用了emmby的答案链接所指向的Android开发者博客条目中概述的方法(即,生成并保存UUID#randomUUID())。
这个问题有很多答案,其中大多数只在“某些”时间有效,不幸的是,这还不够好。
根据我对设备的测试(所有手机,至少有一部未激活):
所有测试的设备都返回了TelephonyManager.getDeviceId()的值所有GSM设备(均使用SIM进行测试)都返回了TelephonyManager.getSimSerialNumber()的值对于getSimSerialNumber(),所有CDMA设备均返回null(如预期)添加了Google帐户的所有设备都返回了ANDROID_ID的值所有CDMA设备都为ANDROID_ID和TelephonyManager.getDeviceId()返回相同的值(或相同值的派生)——只要在安装过程中添加了Google帐户。我还没有机会测试没有SIM卡的GSM设备,没有添加谷歌账户的GSM设备或任何处于飞行模式的设备。
因此,如果您想要设备本身独有的东西,TM.getDeviceId()就足够了。显然,有些用户比其他用户更偏执,因此对这些标识符中的一个或多个进行散列可能会很有用,这样该字符串对于设备来说实际上仍然是唯一的,但不会明确标识用户的实际设备。例如,使用String.hashCode()并结合UUID:
final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
tmSerial = "" + tm.getSimSerialNumber();
androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
可能会导致类似的结果:00000000-54b3-e7c7-0000-000046bffd97
这对我来说足够好了。
正如Richard在下面提到的那样,不要忘记您需要权限才能读取TelephonyManager财产,因此请将此添加到您的清单中:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
导入库
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
其他回答
这个示例演示了如何在Android中获取和存储设备ID,但我使用的是Kotlin。
val textView: TextView = findViewById(R.id.textView)
val uniqueId: String = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
textView.text = "Device ID: $uniqueId"
有很多不同的方法可以解决ANDROID_ID问题(有时可能为空,或者特定型号的设备总是返回相同的ID),有利弊:
实现自定义ID生成算法(基于应该是静态且不会更改的设备财产->谁知道呢)滥用其他ID,如IMEI、序列号、Wi-Fi/蓝牙MAC地址(它们不会存在于所有设备上,或者需要额外的权限)
我自己更喜欢使用现有的OpenUDID实现(请参见https://github.com/ylechelle/OpenUDID)适用于Android(请参见https://github.com/vieux/OpenUDID). 它很容易集成并利用ANDROID_ID和上述问题的回退。
TelephonyManager.getDeviceId()返回唯一的设备ID,例如,GSM的IMEI和CDMA电话的MEID或ESN。
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
但我建议使用:
Settings.Secure.ANDROID_ID,将ANDROID ID作为唯一的64位十六进制字符串返回。
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
有时TelephonyManager.getDeviceId()将返回null,因此为了确保唯一的id,您将使用以下方法:
public String getUniqueID(){
String myAndroidDeviceId = "";
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null){
myAndroidDeviceId = mTelephony.getDeviceId();
}else{
myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
}
return myAndroidDeviceId;
}
Settings.Secure#ANDROID_ID返回每个用户64位十六进制字符串的唯一ANDROID ID。
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
另请阅读唯一标识符的最佳实践:https://developer.android.com/training/articles/user-data-ids
以下是我如何生成唯一id:
public static String getDeviceId(Context ctx)
{
TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
String tmDevice = tm.getDeviceId();
String androidId = Secure.getString(ctx.getContentResolver(), Secure.ANDROID_ID);
String serial = null;
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) serial = Build.SERIAL;
if(tmDevice != null) return "01" + tmDevice;
if(androidId != null) return "02" + androidId;
if(serial != null) return "03" + serial;
// other alternatives (i.e. Wi-Fi MAC, Bluetooth MAC, etc.)
return null;
}
推荐文章
- Android:为什么视图没有maxHeight ?
- 如何获得具有已知资源名称的资源id ?
- 在Android上将字符串转换为整数
- 为什么“System.out。”println“工作在Android?
- WebView显示err_cleartext_not_allowed尽管站点是HTTPS
- Android M权限:对shouldShowRequestPermissionRationale()函数的使用感到困惑
- 为什么构建类型与产品风味不同?
- 我如何在一个片段中访问getSupportFragmentManager() ?
- 调试在哪里。Android Studio中的密钥存储库
- 从资产中读取文件
- 在不活动的地方调用getLayoutInflater()
- 设置Android布局元素的背景颜色
- 错误:'keytool'不能被识别为内部或外部命令、可操作程序或批处理文件
- 在应用程序本身中更改Locale
- apk (.apk)和应用程序包(.aab)的区别