Android设备有唯一的ID吗?如果有,使用Java访问它的简单方法是什么?
当前回答
这是Reto Meier在今年的Google I/O演示中使用的代码,用于为用户获取唯一id:
private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
public synchronized static String id(Context context) {
if (uniqueID == null) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = sharedPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
}
}
return uniqueID;
}
如果你将此与备份策略相结合,将首选项发送到云(Reto的演讲中也有描述),你应该有一个与用户相关的id,在设备被擦除甚至更换后,它会一直存在。我计划在未来的分析中使用此项(换句话说,我还没有做过这一点:)。
其他回答
Google实例ID
2015年I/O发布;在Android上需要播放服务7.5。
https://developers.google.com/instance-id/https://developers.google.com/instance-id/guides/android-implementation
InstanceID iid = InstanceID.getInstance( context ); // Google docs are wrong - this requires context
String id = iid.getId(); // blocking call
谷歌似乎打算使用这个ID来识别Android、Chrome和iOS的安装。
它标识的是安装而不是设备,但同样,ANDROID_ID(这是公认的答案)现在也不再标识设备。使用ARC运行时,会为每个安装生成一个新的ANDROID_ID(此处详细信息),就像这个新的实例ID一样。此外,我认为识别安装(而不是设备)是我们大多数人真正需要的。
实例ID的优点
在我看来,谷歌打算将其用于此目的(识别您的安装),它是跨平台的,可以用于许多其他目的(请参阅上面的链接)。
如果您使用GCM,那么您最终将需要使用此实例ID,因为您需要它来获取GCM令牌(它取代了旧的GCM注册ID)。
缺点/问题
在当前的实现(GPS 7.5)中,当应用程序请求实例ID时,会从服务器检索实例ID。这意味着上面的调用是一个阻塞调用-在我的非科学测试中,如果设备处于联机状态,则需要1-3秒,如果设备离线,则需要0.5-1.0秒(大概这是在放弃并生成随机ID之前等待的时间)。这是在北美使用Android 5.1.1和GPS 7.5在Nexus 5上测试的。
如果您将ID用于他们想要的目的,例如应用程序认证、应用程序识别、GCM,我认为这1-3秒可能会令人讨厌(当然,这取决于您的应用程序)。
只获取一次设备ID,然后将其存储在数据库或文件中。在这种情况下,如果它是应用程序的第一次启动,它将生成一个ID并存储它。下次,它将只获取存储在文件中的ID。
以下是获得AAID的简单答案,测试工作正常2019年6月
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
String token = null;
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
} catch (IOException e) {
// ...
} catch ( GooglePlayServicesRepairableException e) {
// ...
} catch (GooglePlayServicesNotAvailableException e) {
// ...
}
String android_id = adInfo.getId();
Log.d("DEVICE_ID",android_id);
return android_id;
}
@Override
protected void onPostExecute(String token) {
Log.i(TAG, "DEVICE_ID Access token retrieved:" + token);
}
};
task.execute();
请在此处详细阅读完整答案:
Android在Android O之后限制硬件相关Id,Android_Id是唯一Id的解决方案,但当反射设备,它将生成新的android_id以克服此问题问题是我们可以使用DRUMID。
val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
val drumIDByteArray = MediaDrm(WIDEVINE_UUID).getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID)
val drumID = android.util.Base64.encodeToString(drumIDByteArray,android.util.Base64.DEFAULT)
这是一个简单的问题,没有简单的答案。
此外,这里所有现有的答案要么过时,要么不可靠。
因此,如果您正在寻找2020年后的解决方案。
以下是需要记住的几点:
所有基于硬件的标识符(IMEI、MAC、序列号等)对于非谷歌设备(Pixels和Nexuses除外)都是不可靠的,从统计上看,这些设备是世界上大多数android活动设备。因此,官方Android标识符最佳实践明确指出:
避免使用硬件标识符,如IMEI、MAC地址等。。。
这使得这里的大多数答案无效。同样由于不同的android安全更新,其中一些需要更新和更严格的运行时权限,用户可以简单地拒绝。
例如,CVE-2018-9489影响上述所有基于WIFI的技术。
这使得这些标识符不仅不可靠,而且在许多情况下无法访问。
所以简单地说:不要使用这些技术。
这里的许多其他答案都建议使用AdvertisingIdClient,这也是不兼容的,因为它是专为广告分析而设计的。官方参考文件中也有说明
仅将广告ID用于用户分析或广告用例
它不仅对设备识别不可靠,而且您还必须遵守有关广告跟踪的用户隐私政策,该政策明确规定用户可以随时重置或阻止它。
所以也不要使用它。
因为您无法获得所需的静态全局唯一和可靠的设备标识符。Android的官方参考建议:
在所有其他使用情况下,尽可能使用Firebase安装ID(FID)或私人存储的GUID,支付欺诈预防和电话除外。
它对于设备上的应用程序安装来说是独一无二的,因此当用户卸载应用程序时,它会被删除,因此它不是100%可靠,但它是次佳选择。
注意:截至目前,FirebaseInstanceId已弃用,您应改用FirebaseInstallations。
要使用FirebaseInstallations,请将最新的firebase消息传递依赖项添加到您的等级中
implementation 'com.google.firebase:firebase-messaging:23.0.0'
并使用以下代码获取firebase ID:
FirebaseInstallations.getInstance().getId().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
String firebaseIdentifier = task.getResult();
// Do what you need with firebaseIdentifier
}
});
如果您需要将设备标识存储在远程服务器上,那么不要按原样存储(纯文本),而是使用带盐的哈希。
今天,这不仅是一种最佳实践,实际上,您必须根据GDPR标识符和类似法规依法进行。
推荐文章
- 如何隐藏动作栏之前的活动被创建,然后再显示它?
- 是否有一种方法以编程方式滚动滚动视图到特定的编辑文本?
- 在Android中将字符串转换为Uri
- 如何在NestedScrollView内使用RecyclerView ?
- 移动到另一个EditText时,软键盘下一步点击Android
- Android应用中的GridView VS GridLayout
- Activity和FragmentActivity的区别
- 右对齐文本在android TextView
- 权限拒绝:start前台需要android.permission.FOREGROUND_SERVICE
- 如何更改android操作栏的标题和图标
- Android Split字符串
- 让一个链接在安卓浏览器启动我的应用程序?
- 如何在Android工作室的外部库中添加一个jar ?
- GridLayout(不是GridView)如何均匀地拉伸所有子元素
- 如何让一个片段删除自己,即它的等效完成()?