Eno*_*Eno 114 android serial-number
我需要为Android应用程序使用唯一的ID,我认为该设备的序列号将是一个很好的候选人.如何在我的应用中检索Android设备的序列号?
has*_*man 104
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();
Run Code Online (Sandbox Code Playgroud)
getSystemService是Activity类的一个方法.getDeviceID()将根据手机使用的无线电(GSM或CDMA)返回设备的MDN或MEID.
每个设备必须在这里返回一个唯一值(假设它是一部手机).这适用于任何带有SIM卡插槽或CDMA无线电的Android设备.你自己使用Android驱动的微波炉;-)
emm*_*mby 71
正如Dave Webb所提到的,Android开发人员博客有一篇文章介绍了这一点.
我与Google的某位人士进行了交谈,以便对一些项目进行一些额外的澄清.以下是我在上述博文中未提及的内容:
根据Google的建议,我实现了一个类,它将为每个设备生成一个唯一的UUID,在适当的情况下使用ANDROID_ID作为种子,必要时返回TelephonyManager.getDeviceId(),如果失败,则使用随机生成的唯一UUID这是在应用程序重新启动时保留的(但不是应用程序重新安装).
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
public class DeviceUuidFactory {
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
protected static volatile UUID uuid;
public DeviceUuidFactory(Context context) {
if (uuid == null) {
synchronized (DeviceUuidFactory.class) {
if (uuid == null) {
final SharedPreferences prefs = context
.getSharedPreferences(PREFS_FILE, 0);
final String id = prefs.getString(PREFS_DEVICE_ID, null);
if (id != null) {
// Use the ids previously computed and stored in the
// prefs file
uuid = UUID.fromString(id);
} else {
final String androidId = Secure.getString(
context.getContentResolver(), Secure.ANDROID_ID);
// Use the Android ID unless it's broken, in which case
// fallback on deviceId,
// unless it's not available, then fallback on a random
// number which we store to a prefs file
try {
if (!"9774d56d682e549c".equals(androidId)) {
uuid = UUID.nameUUIDFromBytes(androidId
.getBytes("utf8"));
} else {
final String deviceId = ((TelephonyManager)
context.getSystemService(
Context.TELEPHONY_SERVICE))
.getDeviceId();
uuid = deviceId != null ? UUID
.nameUUIDFromBytes(deviceId
.getBytes("utf8")) : UUID
.randomUUID();
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// Write the value out to the prefs file
prefs.edit()
.putString(PREFS_DEVICE_ID, uuid.toString())
.commit();
}
}
}
}
}
/**
* Returns a unique UUID for the current android device. As with all UUIDs,
* this unique ID is "very highly likely" to be unique across all Android
* devices. Much more so than ANDROID_ID is.
*
* The UUID is generated by using ANDROID_ID as the base key if appropriate,
* falling back on TelephonyManager.getDeviceID() if ANDROID_ID is known to
* be incorrect, and finally falling back on a random UUID that's persisted
* to SharedPreferences if getDeviceID() does not return a usable value.
*
* In some rare circumstances, this ID may change. In particular, if the
* device is factory reset a new device ID may be generated. In addition, if
* a user upgrades their phone from certain buggy implementations of Android
* 2.2 to a newer, non-buggy version of Android, the device ID may change.
* Or, if a user uninstalls your app on a device that has neither a proper
* Android ID nor a Device ID, this ID may change on reinstallation.
*
* Note that if the code falls back on using TelephonyManager.getDeviceId(),
* the resulting ID will NOT change after a factory reset. Something to be
* aware of.
*
* Works around a bug in Android 2.2 for many devices when using ANDROID_ID
* directly.
*
* @see http://code.google.com/p/android/issues/detail?id=10603
*
* @return a UUID that may be used to uniquely identify your device for most
* purposes.
*/
public UUID getDeviceUuid() {
return uuid;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 32
String serial = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
} catch (Exception ignored) {
}
Run Code Online (Sandbox Code Playgroud)
此代码使用隐藏的Android API返回设备序列号.
Ant*_*ney 16
String deviceId = Settings.System.getString(getContentResolver(),
Settings.System.ANDROID_ID);
Run Code Online (Sandbox Code Playgroud)
虽然,但不保证Android ID将是唯一标识符.
Dav*_*ebb 14
Android Developer's Blog上有一篇很好的帖子讨论这个问题.
它建议不要使用,TelephonyManager.getDeviceId()因为它不适用于不是平板电脑等手机的Android设备,它需要获得READ_PHONE_STATE许可才能在所有手机上无法正常使用.
相反,您可以使用以下之一:
这篇文章讨论了每种方法的优点和缺点,值得一读,这样你就可以找出最适合你的方法.
Edw*_*rey 12
对于设备唯一且对其生命周期保持不变的简单数字(禁止出厂重置或黑客攻击),请使用Settings.Secure.ANDROID_ID.
String id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
Run Code Online (Sandbox Code Playgroud)
要使用设备序列号("系统设置/关于/状态"中显示的序列号)(如果可用)并回退到Android ID:
String serialNumber = Build.SERIAL != Build.UNKNOWN ? Build.SERIAL : Secure.getString(getContentResolver(), Secure.ANDROID_ID);
Run Code Online (Sandbox Code Playgroud)
IMEI很好但仅适用于带手机的Android设备.您应该考虑支持没有手机的平板电脑或其他Android设备.
你有一些选择:构建类成员,BT MAC,WLAN MAC,甚至更好 - 所有这些的组合.
我在博客上的一篇文章中解释了这些细节,请参阅:http: //www.pocketmagic.net/?p = 1662
由于这里没有回答提到一个完美的,防故障的ID,它通过系统更新持久存在并且存在于所有设备中(主要是因为没有来自Google的个别解决方案),我决定发布一个方法,通过组合两个可用的标识符,以及在运行时在它们之间进行选择的检查,是下一个最好的事情.
在代码之前,3个事实:
TelephonyManager.getDeviceId()(akaIMEI)对于非GSM,3G,LTE等设备不能很好地工作或者根本不能工作,但是当相关硬件存在时,即使没有插入SIM卡,或者甚至没有SIM卡插槽,也总会返回唯一的ID(一些OEM已经这样做了).
由于Gingerbread(Android 2.3)android.os.Build.SERIAL 必须存在于任何不提供IMEI的设备上,即根据Android策略不存在上述硬件.
由于事实(2.),这两个唯一标识符中的至少一个始终存在,并且SERIAL 可以与IMEI同时存在.
注意:事实(1.)和(2.)基于Google声明
解
根据上述事实,通过检查是否存在IMEI绑定硬件,可以始终具有唯一标识符,并且当不存在时,可以返回SERIAL,因为无法检查现有SERIAL是否有效.以下静态类提供了两种检查此类状态并使用IMEI或SERIAL的方法:
import java.lang.reflect.Method;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
public class IDManagement {
public static String getCleartextID_SIMCHECK (Context mContext){
String ret = "";
TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if(isSIMAvailable(mContext,telMgr)){
Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId());
return telMgr.getDeviceId();
}
else{
Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);
// return Settings.Secure.ANDROID_ID;
return android.os.Build.SERIAL;
}
}
public static String getCleartextID_HARDCHECK (Context mContext){
String ret = "";
TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if(telMgr != null && hasTelephony(mContext)){
Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId() + "");
return telMgr.getDeviceId();
}
else{
Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);
// return Settings.Secure.ANDROID_ID;
return android.os.Build.SERIAL;
}
}
public static boolean isSIMAvailable(Context mContext,
TelephonyManager telMgr){
int simState = telMgr.getSimState();
switch (simState) {
case TelephonyManager.SIM_STATE_ABSENT:
return false;
case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
return false;
case TelephonyManager.SIM_STATE_PIN_REQUIRED:
return false;
case TelephonyManager.SIM_STATE_PUK_REQUIRED:
return false;
case TelephonyManager.SIM_STATE_READY:
return true;
case TelephonyManager.SIM_STATE_UNKNOWN:
return false;
default:
return false;
}
}
static public boolean hasTelephony(Context mContext)
{
TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null)
return false;
//devices below are phones only
if (Build.VERSION.SDK_INT < 5)
return true;
PackageManager pm = mContext.getPackageManager();
if (pm == null)
return false;
boolean retval = false;
try
{
Class<?> [] parameters = new Class[1];
parameters[0] = String.class;
Method method = pm.getClass().getMethod("hasSystemFeature", parameters);
Object [] parm = new Object[1];
parm[0] = "android.hardware.telephony";
Object retValue = method.invoke(pm, parm);
if (retValue instanceof Boolean)
retval = ((Boolean) retValue).booleanValue();
else
retval = false;
}
catch (Exception e)
{
retval = false;
}
return retval;
}
}
Run Code Online (Sandbox Code Playgroud)
我会建议使用getCleartextID_HARDCHECK.如果反射不会粘在您的环境中,请改用该getCleartextID_SIMCHECK方法,但要考虑到它应该适应您特定的SIM存在需求.
PS:请注意,OEM已经成功地违反了SERIAL违反Google政策(多个设备使用相同的SERIAL),谷歌表示至少有一个已知的大型OEM案例(未透露,我不知道哪个品牌)它要么是,我猜三星).
免责声明:这回答了获取唯一设备ID的原始问题,但OP通过声明他需要APP的唯一ID来引入歧义.即使对于这样的场景,Android_ID会更好,但是,通过2个不同的ROM安装(甚至可以是相同的ROM),应用程序的Titanium备份后,它将无法工作.我的解决方案保持独立于闪存或恢复出厂设置的持久性,并且只有在通过hacks/hardware mods发生IMEI或SERIAL篡改时才会失败.
所有上述方法都存在问题.在Google i/o上,Reto Meier发布了一个强有力的解决方案,解决了如何解决这个问题,以满足大多数开发人员在跨安装时跟踪用户的需求.
这种方法会为您提供一个匿名的,安全的用户ID,该ID对于不同设备(包括平板电脑,基于主要Google帐户)的用户以及同一设备上的安装都是持久的.基本方法是生成随机用户ID并将其存储在apps共享首选项中.然后,您可以使用Google的备用代理存储与云中Google帐户关联的共享偏好设置.
让我们完整的方法.首先,我们需要使用Android备份服务为SharedPreferences创建备份.首先通过以下链接注册您的应用:http://developer.android.com/google/backup/signup.html
Google会为您提供备份服务密钥,您需要将其添加到清单中.您还需要告诉应用程序使用BackupAgent,如下所示:
<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="your_backup_service_key" />
</application>
Run Code Online (Sandbox Code Playgroud)
然后,您需要创建备份代理并告诉它使用帮助代理进行共享优先:
public class MyBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String PREFS = "user_preferences";
// A key to uniquely identify the set of backup data
static final String PREFS_BACKUP_KEY = "prefs";
// Allocate a helper and add it to the backup agent
@Override
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
addHelper(PREFS_BACKUP_KEY, helper);
}
}
Run Code Online (Sandbox Code Playgroud)
要完成备份,您需要在主Activity中创建一个BackupManager实例:
BackupManager backupManager = new BackupManager(context);
Run Code Online (Sandbox Code Playgroud)
最后创建一个用户ID(如果尚不存在),并将其存储在SharedPreferences中:
public static String getUserID(Context context) {
private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
if (uniqueID == null) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
MyBackupAgent.PREFS, 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();
//backup the changes
BackupManager mBackupManager = new BackupManager(context);
mBackupManager.dataChanged();
}
}
return uniqueID;
}
Run Code Online (Sandbox Code Playgroud)
即使用户切换设备,此User_ID现在也将在安装期间保持不变.
有关此方法的详细信息,请参阅Reto在此处的讨论http://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html
有关如何实施备份代理的完整详细信息,请参阅此处的开发者网站:http://developer.android.com/guide/topics/data/backup.html 我特别推荐测试底部的部分作为备份不是偶然发生的,所以要测试你必须强制备份.
| 归档时间: |
|
| 查看次数: |
231120 次 |
| 最近记录: |