Android获取手机制作商,系统版本等
获取Android 的Rom信息,以及判断是否为MIUI及获取MIUI版本
在开发中 我们有时候会需要获取当前手机的系统版本来进行判断,或者需要获取一些当前手机的硬件信息。
android.os.Build类中。包括了这样的一些信息。我们可以直接调用 而不需要添加任何的权限和方法。
android.os.Build.BOARD:获取设备基板名称
android.os.Build.BOOTLOADER:获取设备引导程序版本号
android.os.Build.BRAND:获取设备品牌
android.os.Build.CPU_ABI:获取设备指令集名称(CPU的类型)
android.os.Build.CPU_ABI2:获取第二个指令集名称
android.os.Build.DEVICE:获取设备驱动名称
android.os.Build.DISPLAY:获取设备显示的版本包(在系统设置中显示为版本号)和ID一样
android.os.Build.FINGERPRINT:设备的唯一标识。由设备的多个信息拼接合成。
android.os.Build.HARDWARE:设备硬件名称,一般和基板名称一样(BOARD)
android.os.Build.HOST:设备主机地址
android.os.Build.ID:设备版本号。
android.os.Build.MODEL :获取手机的型号 设备名称。
android.os.Build.MANUFACTURER:获取设备制造商
android:os.Build.PRODUCT:整个产品的名称
android:os.Build.RADIO:无线电固件版本号,通常是不可用的 显示unknown
android.os.Build.TAGS:设备标签。如release-keys 或测试的 test-keys
android.os.Build.TIME:时间
android.os.Build.TYPE:设备版本类型 主要为”user” 或”eng”.
android.os.Build.USER:设备用户名 基本上都为android-build
android.os.Build.VERSION.RELEASE:获取系统版本字符串。如4.1.2 或2.2 或2.3等
android.os.Build.VERSION.CODENAME:设备当前的系统开发代号,一般使用REL代替
android.os.Build.VERSION.INCREMENTAL:系统源代码控制值,一个数字或者git hash值
android.os.Build.VERSION.SDK:系统的API级别 一般使用下面大的SDK_INT 来查看
android.os.Build.VERSION.SDK_INT:系统的API级别 数字表示
android.os.Build.VERSION_CODES类 中有所有的已公布的Android版本号。全部是Int常亮。可用于与SDK_INT进行比较来判断当前的系统版本
adb shell getprop | grep "sn\|serial"
adb shell getprop | findstr "sn"
系统中有3个sn 号
PROD_SN 整机SN factory_phone_sn
PCB_SN 主板SN factory_sn
sn android原生api获取 android.os.build.SERIAL (ro.serialno)
DeviceID
android.telephony.TelephonyManager tm = (android.telephony.TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String deviceId = tm.getDeviceId();
Sim 序列号(Sim Serial Number)
android.telephony.TelephonyManager tm = (android.telephony.TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String simSerialNum = tm.getSimSerialNumber();
设备序列号(Serial Number, SN)
android.os.Build.SERIAL;
ANDROID_ID
//在设备第一次启动的时候生成并保存,并且可能会在恢复出厂设置后重置该值。理论上是大部分是重置的。(API 中原话是:The value may change if a factory reset is performed on the device.)
android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
谈谈 Android 中的各种设备标识符 https://www.jianshu.com/p/b6f4b0aca6b0
首先,我们先要弄清自己跟踪设备的具体需求。目前看来,需求无非两种:
跟踪用户设备使用周期层次上的设备。
意思是将每次用户的擦除设备、恢复出厂设置动作后将设备视为一台新的设备。
跟踪硬件层次上的设备。
意思是无论设备擦除数据或者恢复出厂设置后都需要将该设备视为同一台设备。
方案 1:
这个层次上的设备跟踪,我比较推荐使用谷歌官方推荐的办法来跟踪, App 首次启动时生成一个 Random UUID 并保存在本地存储,
以后每次启动时检查该 UUID 文件。具体可以查看我的上一篇翻译文章),其中有具体的代码实现。
方案 2:
如果你不喜欢谷歌推荐的这种方式,或者觉得这种方式涉及到文件读写太过繁琐等。我们也可以通过以上介绍的这些标识符来跟踪设备。因为需要将设备擦除数据或恢复出厂设置后将其视为一台新的设备,所以需要使用一些与当前用户设备使用周期有关的值。
理论上,Android_ID 这一个值就已经足够我们实现这样的需求,不过正是因为 Android_ID 存在缺陷,所以我们无法直接拿来识别设备。这里我们使用多个值拼凑来规避这些缺点。
与用户设备使用周期有关的标识符我推荐使用Android_ID和Sim Serial Number。另外可以加上Device_ID,通过 UUID 或者 MD5 等来计算生成设备的标识符。
以下是一个简单的实现,参考了 Stack Overflow 上的这个问题下面的回答。
UUID 实现:
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)deviceId.hashCode() << 32) | simSerialNum.hashCode());
String deviceId = deviceUuid.toString();
结果类似:00000000-54b3-e7c7-0000-000046bffd97
或者你也可以使用 MD5 实现(MD5 算法见下文):
String md5ID = md5(androidId + deviceId + simSerialNum);
结果类似:f87b20b3c359c4af608b3eb26b26a1b8
跟踪硬件层次上的设备
跟踪硬件层次上的设备建议使用硬件的标识符,比如设备ID(DeviceId)、Mac 地址、设备序列号(SN)或者设备的品牌,型号名等,这些值在用户擦除数据或者恢复出厂设置后也不会改变。同样的,为了提升稳定性及排除单一标识符所存在的缺陷,我们使用多个标识符拼接,然后通过 UUID 或者 MD5 算法计算得出我们需要的设备标识符。
以下是一个简单的实现,使用了设备序列号(SN)、设备ID(DeviceId)和 Mac 地址。
拼接后的字符串类似于:01b4549262d6a4a235513602180805610:68:3f:81:ed:ff
同时为了不暴露用户的设备具体信息,这里我们同样采用 MD5 对拼接后的字符串进行Hash操作:
String md5ID = md5("01b4549262d6a4a235513602180805610:68:3f:81:ed:ff");
拼凑的标识符选择,拼接的顺序,MD5或者UUID的选择并无绝对,重要的是思想。
其他
以上这些值在使用前都建议判空。
因为硬件缺失或者不可用,获取标识符过程中也可能返回 null 对象。为了避免 NullPointerException,建议获取标识符操作全部在 try...catch 中操作。
安卓设备的用户不乏极客,修改 Android_ID 或者 Build 文件对他们来说并非难题。所以一定程度上说,没有绝对准确的跟踪设备的标识符。
*以下是一个Demo,项目建立后添加权限后即可使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String deviceId = "";
String macAddress = "";
String androidId = "";
String serialNum = "";
String simSerialNum = "";
//需要READ_PHONE_STATE权限
android.telephony.TelephonyManager tm = (android.telephony.TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);
if(checkPermission(this, Manifest.permission.READ_PHONE_STATE)){
deviceId = tm.getDeviceId();
simSerialNum = tm.getSimSerialNumber();
}
//需要ACCESS_WIFI_STATE权限
android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) this
.getSystemService(Context.WIFI_SERVICE);
macAddress = wifi.getConnectionInfo().getMacAddress();
androidId = android.provider.Settings.Secure.getString(this.getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
serialNum = Build.SERIAL;
String deviceManufacturer = Build.MANUFACTURER;
String deviceModel = Build.MODEL;
String deviceBrand = Build.BRAND;
String device = Build.DEVICE;
//==============
Log.e("Identifier_Device_ID", validate(deviceId));
Log.e("Identifier_Mac_Address", validate(macAddress));
Log.e("Identifier_Android_ID", validate(androidId));
Log.e("Identifier_Serial_Num", validate(serialNum));
Log.e("Identifier_Sim_SN", validate(simSerialNum));
Log.e("Identifier_Manufacturer", validate(deviceManufacturer));
Log.e("Identifier_Model", validate(deviceModel));
Log.e("Identifier_Brand", validate(deviceBrand));
Log.e("Identifier_Device", validate(device));
UUID deviceUserLifetimeUUID = new UUID(validate(androidId).hashCode(), ((long)validate(deviceId).hashCode() << 32) | validate(simSerialNum).hashCode());
String deviceUserLifetimeId = deviceUserLifetimeUUID.toString();
String deviceHardwareId = md5(validate(serialNum) + validate(deviceId) + validate(macAddress));;
Log.e("deviceUserLifetimeId", deviceUserLifetimeId);
Log.e("deviceHardwareId", deviceHardwareId);
}
// MD5加密,32位小写
public static String md5(String str) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
e.printStackTrace();
return "";
}
md5.update(str.getBytes());
byte[] md5Bytes = md5.digest();
StringBuilder hexValue = new StringBuilder();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
//检查权限,READ_PHONE_STATE在API>=23需要用户手动赋予权限
public static boolean checkPermission(Context context, String permission) {
boolean result = false;
if (Build.VERSION.SDK_INT >= 23) {
if (context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
result = true;
}
} else {
PackageManager pm = context.getPackageManager();
if (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
result = true;
}
}
return result;
}
//判空
private String validate(String value) {
if(value == null) {
return "";
}
return value;
}
}