package cm.android.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import cm.java.cmd.Shell;
import cm.java.util.IoUtil;
import cm.java.util.Reflect;
import cm.java.util.ReflectUtil;
import cm.java.util.Utils;
public class DeviceUtil {
private static final Logger logger = LoggerFactory.getLogger(DeviceUtil.class);
private DeviceUtil() {
}
public static String getDeviceFeatures(Context ctx) {
return getIdentifiers(ctx) + getSystemFeatures()
+ getScreenFeatures(ctx) + getTele(ctx);
}
public static String getIdentifiers(Context ctx) {
StringBuilder sb = new StringBuilder();
sb.append(getPair("\nserial", Build.SERIAL));
sb.append(getPair("\nandroid_id", getAndroidId(ctx)));
TelephonyManager tel = (TelephonyManager) ctx
.getSystemService(Context.TELEPHONY_SERVICE);
sb.append(getPair("\nsim_country_iso", tel.getSimCountryIso()));
sb.append(getPair("\nnetwork_operator_name", tel.getNetworkOperatorName()));
// sb.append(getPair("unique_id", Crypto.md5(sb.toString())));
return sb.toString();
}
public static String getTele(Context context) {
StringBuilder sb = new StringBuilder();
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
sb.append(getPair("getPhoneType", tm.getPhoneType() + ""));
sb.append(getPair("getDeviceSoftwareVersion", tm.getDeviceSoftwareVersion() + ""));
sb.append(getPair("getSimOperator", tm.getSimOperator() + ""));
sb.append(getPair("getSimOperatorName", tm.getSimOperatorName() + ""));
sb.append(getPair("getSimSerialNumber", tm.getSimSerialNumber() + ""));
sb.append(getPair("getVoiceMailNumber", tm.getVoiceMailNumber() + ""));
return sb.toString();
}
public static String getSystemFeatures() {
StringBuilder sb = new StringBuilder();
sb.append(getPair("\nMODEL", Build.MODEL));
sb.append(getPair("\nMANUFACTURER", Build.MANUFACTURER));//api:4
sb.append(getPair("\nBOARD", Build.BOARD));
sb.append(getPair("\nFINGERPRINT", Build.FINGERPRINT));
sb.append(getPair("\nBOOTLOADER", Build.BOOTLOADER));//api:8
sb.append(getPair("\nBRAND", Build.BRAND));
sb.append(getPair("\nCPU_ABI", Build.CPU_ABI));//api:4
sb.append(getPair("\nCPU_ABI2", Build.CPU_ABI2));//api:8
sb.append(getPair("\nDEVICE", Build.DEVICE));
sb.append(getPair("\nDISPLAY", Build.DISPLAY));//api:3
//sb.append(getPair("\ndevice_cpu_feature", Build.getRadioVersion()));//API:14
sb.append(getPair("\nHARDWARE", Build.HARDWARE));//API:8
sb.append(getPair("\nHOST", Build.HOST));
sb.append(getPair("\nID", Build.ID));
sb.append(getPair("\nPRODUCT", Build.PRODUCT));
sb.append(getPair("\nSERIAL", Build.SERIAL));//api:9
sb.append(getPair("\nTAGS", Build.TAGS));
sb.append(getPair("\nTYPE", Build.TYPE));
sb.append(getPair("\nUSER", Build.USER));
sb.append(getPair("\nTIME", Build.TIME + ""));
sb.append(getPair("\nVERSION.SDK_INT", "" + Build.VERSION.SDK_INT));//api:4
sb.append(getPair("\nVERSION.CODENAME", Build.VERSION.CODENAME));//api:4
sb.append(getPair("\nVERSION.RELEASE", Build.VERSION.RELEASE));
sb.append(getPair("\nVERSION.INCREMENTAL", Build.VERSION.INCREMENTAL));
return sb.toString();
}
public static String getScreenFeatures(Context ctx) {
StringBuilder sb = new StringBuilder();
DisplayMetrics disp = ctx.getResources().getDisplayMetrics();
sb.append(getPair("\nscreen_density", "" + disp.density));
sb.append(getPair("\nscreen_density_dpi", "" + disp.densityDpi));
sb.append(getPair("\nscreen_height_pixels", "" + disp.heightPixels));
sb.append(getPair("\nscreen_width_pixels", "" + disp.widthPixels));
sb.append(getPair("\nscreen_scaled_density", "" + disp.scaledDensity));
sb.append(getPair("\nscreen_xdpi", "" + disp.xdpi));
sb.append(getPair("\nscreen_ydpi", "" + disp.ydpi));
return sb.toString();
}
private static String getPair(String key, String value) {
key = key == null ? "" : key.trim();
value = value == null ? "" : value.trim();
return "\n" + key + "=" + value;
}
public static int getSdkInt() {
return Build.VERSION.SDK_INT;
}
@TargetApi(8)
public static String getBootloader() {
if (EnvironmentUtil.SdkUtil.hasFroyo()) {
return Build.BOOTLOADER;
}
return "";
}
@TargetApi(8)
public static String getCpuAbi2() {
try {
String cpuAbi2 = ReflectUtil.getStaticFieldValue(Build.class, "CPU_ABI2");
return cpuAbi2;
} catch (Exception e1) {
return "";
}
}
@TargetApi(8)
public static String getHardware() {
try {
String hardware = ReflectUtil.getStaticFieldValue(Build.class, "HARDWARE");
return hardware;
} catch (Exception e) {
return "";
}
}
/**
* 目前已知中兴手机相同机型返回值一样
*/
public static String getSerial() {
try {
// TODO: ggg 2017/3/22 : Android O上改为Build.getSerial(),需READ_PHONE_STATE权限
String serial = Reflect.load(Build.class).field("SERIAL");
// String serial = ReflectUtil.getStaticFieldValue(Build.class, "SERIAL");
if (Utils.isEmpty(serial) || "unknown".equalsIgnoreCase(serial)) {
logger.error("serial = {}", serial);
return "";
}
return serial;
} catch (Reflect.ReflectException e) {
return "";
}
}
/**
* 获取设备号
*/
@TargetApi(3)
public static String getAndroidId(Context context) {
// InstanceId.getId
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
/**
* 获取唯一识别码
*/
public static String getDeviceId(Context context) {
// String serial = getSerial();
// if (!Utils.isEmpty(serial)) {
// return serial;
// }
//1. 部分机型androidId一样
//2. 恢复出厂设置后androidId会变
String androidId = getAndroidId(context);
if (!Utils.isEmpty(androidId)) {
return androidId;
}
logger.error("getDeviceId() = null");
return "";
}
// public static UUID getUUID(Context context) {
// String appTag = "cm";
// return getUUID(context, appTag);
// }
// public static UUID getUUID(Context context, String appTag) {
//// ro.boot.serialno
//// String serialno = SystemPropertiesProxy.get("ro.serialno", "ro.serialno");
//
// String board = Build.BOARD;
//
// String model = Build.MODEL;
//
// //可能相同或为null
// String serial = getSerial();
//
// int appTagHashCode = appTag.hashCode();
// int serialHashCode = serial.hashCode();
//
// int boardHashCode = board.hashCode();
// int modelHashCode = model.hashCode();
//
// long mostSigBits = ((long) appTagHashCode) << 32 | serialHashCode;
// long leastSigBits = ((long) boardHashCode) << 32 | modelHashCode;
// UUID deviceUuid = new UUID(mostSigBits, leastSigBits);
// return deviceUuid;
// }
// public static UUID getUUID(Context context, String appTag) {
// //需要通信模块
//// String imei = getIMEI(context);
//
// //可能相同或为null
// String serial = getSerial();
//
// int appTagHashCode = Math.abs(appTag.hashCode());
//// int imeiHashCode = Math.abs(imei.hashCode());
// int serialHashCode = Math.abs(serial.hashCode());
//
//// long mostSigBits = ((long) appTagHashCode) << 32 | imeiHashCode;
//// long leastSigBits = ((long) macAddressHashCode) << 32 | serialHashCode;
//
// long mostSigBits = ((long) appTagHashCode) << 32 | serialHashCode;
// long leastSigBits = ((long) macAddressHashCode) << 32 | serialHashCode;
// UUID deviceUuid = new UUID(mostSigBits, leastSigBits);
// return deviceUuid;
// }
/**
* 获取设备MAC地址
* <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>}</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
*
* @param context 上下文
* @return MAC地址
*/
public static String getMacAddress(Context context) {
String macAddress = getMacAddressByWifiInfo(context);
if (!Utils.isEmpty(macAddress)) {
return macAddress;
}
macAddress = getMacAddressByNetworkInterface();
if (!Utils.isEmpty(macAddress)) {
return macAddress;
}
macAddress = getMacAddressByFile();
if (!Utils.isEmpty(macAddress)) {
return macAddress;
}
return "";
}
/**
* 获取Mac地址
* <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
*/
public static String getMacAddressByWifiInfo(Context context) {
try {
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
// if (!wifi.isWifiEnabled()) {
// wifi.setWifiEnabled(true);
// wifi.setWifiEnabled(false);
// }
WifiInfo info = wifi.getConnectionInfo();
if (info != null) {
String mac = info.getMacAddress();
if (!Utils.isEmpty(mac)) {
return mac;
}
}
} catch (Exception e) {
logger.error("", e);
}
return "";
}
/**
* 获取设备MAC地址
* <p>需添加权限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
*
* @return MAC地址
*/
private static String getMacAddressByNetworkInterface() {
try {
List<NetworkInterface> nis = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface ni : nis) {
if (!ni.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = ni.getHardwareAddress();
if (macBytes != null && macBytes.length > 0) {
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(String.format("%02x:", b));
}
return res1.deleteCharAt(res1.length() - 1).toString();
}
}
} catch (Exception e) {
logger.error("", e);
}
return "";
}
/**
* 获取设备MAC地址
*
* @return MAC地址
*/
private static String getMacAddressByFile() {
// String result = CmdExecute.exec(new String[]{
// "getprop", "wifi.interface"
// });
String result = Shell.exec("getprop wifi.interface");
if (!Utils.isEmpty(result)) {
// result = CmdExecute.exec(new String[]{
// "cat", "/sys/class/net/" + result.trim() + "/address"
// });
result = Shell.exec("cat /sys/class/net/" + result.trim() + "/address");
}
return result;
}
/**
* 获取IP地址
*/
public static String getIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException ex) {
logger.error("", ex);
}
return null;
}
/**
* 获取IMEI
*/
public static String getIMEI(Context context) {
try {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId();
if (Utils.isEmpty(imei)) {
logger.error("imei = " + imei);
return "";
}
return imei;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return "";
}
}
/**
* 获取IMSI
*/
public static String getIMSI(Context context) {
try {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
String imsi = tm.getSubscriberId();
if (Utils.isEmpty(imsi)) {
logger.error("imsi = " + imsi);
return "";
}
return imsi;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return "";
}
}
public static String getHostName() {
try {
return Reflect.load(Build.class)
.method("getString", String.class)
.call("net.hostname");
} catch (Reflect.ReflectException e) {
StringBuilder sb = new StringBuilder();
sb.append(Build.MANUFACTURER).append("_").append(Build.MODEL);
return sb.toString();
}
// try {
// Method getString = Build.class.getDeclaredMethod("getString", String.class);
// getString.setAccessible(true);
// return getString.invoke(null, "net.hostname").toString();
// } catch (NoSuchMethodException e) {
// logger.debug(e.getMessage(), e);
// } catch (IllegalAccessException e) {
// logger.debug(e.getMessage(), e);
// } catch (InvocationTargetException e) {
// logger.debug(e.getMessage(), e);
// }
}
// TODO: ggg 2017/3/22 : 8.0上不在支持SystemProperties.get("net.hostname")
public static String getHostName2() {
try {
return Reflect.load("android.os.SystemProperties")
.method("get", String.class, String.class)
.call("net.hostname", Build.UNKNOWN);
} catch (Reflect.ReflectException e) {
StringBuilder sb = new StringBuilder();
sb.append(Build.MANUFACTURER).append("_").append(Build.MODEL);
return sb.toString();
}
// try {
// // TODO: ggg 2017/3/22 : 8.0上不在支持SystemProperties.get("net.hostname")
// Class clazz = Class.forName("android.os.SystemProperties");
// Method get = clazz.getDeclaredMethod("get", String.class);
// get.setAccessible(true);
// return get.invoke(null, "net.hostname").toString();
// } catch (ClassNotFoundException e) {
// logger.debug(e.getMessage(), e);
// } catch (NoSuchMethodException e) {
// logger.debug(e.getMessage(), e);
// } catch (IllegalAccessException e) {
// logger.debug(e.getMessage(), e);
// } catch (InvocationTargetException e) {
// logger.debug(e.getMessage(), e);
// }
//
// StringBuilder sb = new StringBuilder();
// sb.append(Build.MANUFACTURER).append("_").append(Build.MODEL);
// return sb.toString();
}
public static int getAdbEnabled(Context context) {
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Global.ADB_ENABLED, 0);
}
private static String getDeviceCid(String block) {
BufferedReader cidFile = null;
try {
File input = new File("/sys/block/" + block + "/device");
FileInputStream fis = new FileInputStream(new File(input, "cid"));
cidFile = new BufferedReader(new InputStreamReader(fis, Charset.defaultCharset()));
// cidFile = new BufferedReader(new FileReader(fis,""));
String sd_cid = cidFile.readLine();
logger.info("CID of the MMC = {}", sd_cid);
return sd_cid;
} catch (FileNotFoundException e) {
return "";
} catch (IOException e) {
logger.error(e.getMessage(), e);
return "";
} finally {
IoUtil.closeQuietly(cidFile);
}
}
public static String getSdcardId() {
if (!EnvironmentUtil.isExternalStorageWritable()) {
return "";
}
return getDeviceCid("mmcblk0");
}
public static String getExtSdcardId() {
// if (!EnvironmentUtil.hasExtSdcard()) {
// return "";
// }
return getDeviceCid("mmcblk1");
}
// sim卡是否可读
public static boolean isSimReady(Context context) {
try {
TelephonyManager mgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
return TelephonyManager.SIM_STATE_READY == mgr.getSimState();
} catch (Exception e) {
logger.error(e.getMessage(), e);
return false;
}
}
/**
* 精确获取屏幕尺寸(例如:3.5、4.0、5.0寸屏幕)
*/
public static double getScreenPhysicalSize(Activity ctx) {
DisplayMetrics dm = new DisplayMetrics();
ctx.getWindowManager().getDefaultDisplay().getMetrics(dm);
double diagonalPixels = Math.sqrt(Math.pow(dm.widthPixels, 2)
+ Math.pow(dm.heightPixels, 2));
return diagonalPixels / (160 * dm.density);
}
}