我需要在Android应用程序中使用唯一标识符,而我认为设备的序列号是一个好的选择。如何在我的应用程序中检索Android设备的序列号?
我需要在Android应用程序中使用唯一标识符,而我认为设备的序列号是一个好的选择。如何在我的应用程序中检索Android设备的序列号?
正如 @haserman 所说:
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();
但是在清单文件中包含权限是必要的:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Build.SERIAL
是最简单的方法,但并不完全可靠,因为它可能为空,有时会返回与您设备设置中看到的不同的值(证明 1, 证明 2)。
根据设备制造商和Android版本,有几种获取该号码的方法,因此我决定将我能找到的每个可能的解决方案编译成一个单一的gist。以下是其简化版:
public static String getSerialNumber() {
String serialNumber;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serialNumber = (String) get.invoke(c, "gsm.sn1");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "ril.serialnumber");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "ro.serialno");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "sys.serialnumber");
if (serialNumber.equals(""))
serialNumber = Build.SERIAL;
// If none of the methods above worked
if (serialNumber.equals(""))
serialNumber = null;
} catch (Exception e) {
e.printStackTrace();
serialNumber = null;
}
return serialNumber;
}
Android操作系统设备的唯一设备ID,以字符串形式表示。
String deviceId;
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null){
deviceId = mTelephony.getDeviceId();
}
else{
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
}
但我强烈建议使用谷歌推荐的这种方法:
public static String getManufacturerSerialNumber() {
String serial = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class, String.class);
serial = (String) get.invoke(c, "ril.serialnumber", "unknown");
} catch (Exception ignored) {}
return serial;
}
适用于API 29和30,在三星Galaxy S7、S9 Xcover上进行了测试
我知道这个问题很久了,但是它可以在一行代码中完成
String deviceID = Build.SERIAL;
从Android 10开始,应用程序必须具有READ_PRIVILEGED_PHONE_STATE特权权限才能访问设备的不可重置标识符,包括IMEI和序列号。
受影响的方法包括以下内容:
Build getSerial() TelephonyManager getImei() getDeviceId() getMeid() getSimSerialNumber() getSubscriberId()
READ_PRIVILEGED_PHONE_STATE仅适用于平台
我发现@emmby上面发布的示例类是一个很好的起点。但是它有一些缺陷,正如其他帖子中提到的那样。最主要的问题是它不必要地将UUID持久化到XML文件中,然后总是从该文件中检索它。这使得该类容易被黑客攻击:任何拥有root手机的人都可以编辑XML文件以获得新的UUID。
我已经更新了代码,只有在绝对必要时(即使用随机生成的UUID时)才将其持久化到XML,并按照@Brill Pappin的答案重新设计了逻辑:
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 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) || (androidId == null) ) {
final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();
if (deviceId != null)
{
uuid = UUID.nameUUIDFromBytes(deviceId.getBytes("utf8"));
}
else
{
uuid = UUID.randomUUID();
// Write the value out to the prefs file so it persists
prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString() ).commit();
}
}
else
{
uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
/**
* 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;
}
是的。它是设备硬件序列号,而且是唯一的。因此,在API级别2.3及以上,您可以使用android.os.Build.ANDROID_ID来获取它。对于低于2.3 API级别的设备,请使用TelephonyManager.getDeviceID()。
您可以阅读此http://android-developers.blogspot.in/2011/03/identifying-app-installations.html。