提交 632a5a92 编写于 作者: B Blankj

see 07/29 log

上级 253bebfa
* `19/07/31` [add] DeviceUtils#getUniqueDeviceId, DeviceUtils#isSameDevice. Publish v1.25.5.
* `19/07/30` [fix] ThreadUtils's task can only be executed once. PhoneUtils#getIMEI wrong.
* `19/07/29` [fix] BusUtils post father class useless. KeyboardUtils#hideSoft bug. Publish v1.25.4.
* `19/07/28` [add] NetworkUtils#(un)registerNetworkStatusChangedListener. Publish v1.25.3.
* `19/07/27` [fix] ThreadUtils memory leak.
......
......@@ -45,7 +45,7 @@
[frame]: https://raw.githubusercontent.com/Blankj/AndroidUtilCode/master/art/auc_frame.png
[aucSvg]: https://img.shields.io/badge/AndroidUtilCode-v1.25.4-brightgreen.svg
[aucSvg]: https://img.shields.io/badge/AndroidUtilCode-v1.25.5-brightgreen.svg
[auc]: https://github.com/Blankj/AndroidUtilCode
[apiSvg]: https://img.shields.io/badge/API-14+-brightgreen.svg
......
......@@ -45,7 +45,7 @@ If this project helps you a lot and you want to support the project's developmen
[frame]: https://raw.githubusercontent.com/Blankj/AndroidUtilCode/master/art/auc_frame.png
[aucSvg]: https://img.shields.io/badge/AndroidUtilCode-v1.25.4-brightgreen.svg
[aucSvg]: https://img.shields.io/badge/AndroidUtilCode-v1.25.5-brightgreen.svg
[auc]: https://github.com/Blankj/AndroidUtilCode
[apiSvg]: https://img.shields.io/badge/API-14+-brightgreen.svg
......
......@@ -14,8 +14,8 @@ class Config {
static compileSdkVersion = 28
static minSdkVersion = 14
static targetSdkVersion = 28
static versionCode = 1_025_004
static versionName = '1.25.4'// E.g. 1.9.72 => 1,009,072
static versionCode = 1_025_005
static versionName = '1.25.5'// E.g. 1.9.72 => 1,009,072
// lib version
static kotlin_version = '1.3.10'
......
......@@ -57,7 +57,9 @@ class DeviceActivity : CommonTitleActivity() {
.appendLine("getModel: " + DeviceUtils.getModel())
.appendLine("getABIs: " + Arrays.asList(*DeviceUtils.getABIs()))
.appendLine("isTablet: " + DeviceUtils.isTablet())
.append("isEmulator: " + DeviceUtils.isEmulator())
.appendLine("isEmulator: " + DeviceUtils.isEmulator())
.appendLine("getUniqueDeviceId: " + DeviceUtils.getUniqueDeviceId("util"))
.appendLine("isSameDevice: " + DeviceUtils.isSameDevice(DeviceUtils.getUniqueDeviceId()))
.create()
}
......
......@@ -128,7 +128,7 @@ class NetworkActivity : CommonTitleActivity(), NetworkUtils.OnNetworkStatusChang
override fun onDestroy() {
task.cancel()
NetworkUtils.unregisterOnNetworkChangedListener(this)
NetworkUtils.unregisterNetworkStatusChangedListener(this)
super.onDestroy()
}
}
......@@ -50,6 +50,7 @@ class PhoneActivity : CommonTitleActivity() {
SpanUtils.with(phoneAboutTv)
.appendLine("isPhone: " + PhoneUtils.isPhone())
.appendLine("getDeviceId: " + PhoneUtils.getDeviceId())
.appendLine("getSerial: " + PhoneUtils.getSerial())
.appendLine("getIMEI: " + PhoneUtils.getIMEI())
.appendLine("getMEID: " + PhoneUtils.getMEID())
.appendLine("getIMSI: " + PhoneUtils.getIMSI())
......
......@@ -2,10 +2,10 @@
Gradle:
```groovy
implementation 'com.blankj:utilcode:1.25.4'
implementation 'com.blankj:utilcode:1.25.5'
// if u use AndroidX, use the following
implementation 'com.blankj:utilcodex:1.25.4'
implementation 'com.blankj:utilcodex:1.25.5'
```
......@@ -295,6 +295,8 @@ getModel : 获取设备型号
getABIs : 获取设备 ABIs
isTablet : 判断是否是平板
isEmulator : 判断是否是模拟器
getUniqueDeviceId: 获取唯一设备 ID
isSameDevice : 判断是否同一设备
```
* ### 闪光灯相关 -> [FlashlightUtils.java][flashlight.java] -> [Demo][flashlight.demo]
......@@ -546,26 +548,28 @@ getMetaDataInReceiver: 获取 receiver 的 meta-data 值
* ### 网络相关 -> [NetworkUtils.java][network.java] -> [Demo][network.demo]
```
openWirelessSettings : 打开网络设置界面
isConnected : 判断网络是否连接
isAvailable[Async] : 判断网络是否可用
isAvailableByPing[Async]: 用 ping 判断网络是否可用
isAvailableByDns[Async] : 用 DNS 判断网络是否可用
getMobileDataEnabled : 判断移动数据是否打开
isMobileData : 判断网络是否是移动数据
is4G : 判断网络是否是 4G
getWifiEnabled : 判断 wifi 是否打开
setWifiEnabled : 打开或关闭 wifi
isWifiConnected : 判断 wifi 是否连接状态
isWifiAvailable[Async] : 判断 wifi 数据是否可用
getNetworkOperatorName : 获取移动网络运营商名称
getNetworkType : 获取当前网络类型
getIPAddress[Async] : 获取 IP 地址
getDomainAddress[Async] : 获取域名 IP 地址
getIpAddressByWifi : 根据 WiFi 获取网络 IP 地址
getGatewayByWifi : 根据 WiFi 获取网关 IP 地址
getNetMaskByWifi : 根据 WiFi 获取子网掩码 IP 地址
getServerAddressByWifi : 根据 WiFi 获取服务端 IP 地址
openWirelessSettings : 打开网络设置界面
isConnected : 判断网络是否连接
isAvailable[Async] : 判断网络是否可用
isAvailableByPing[Async] : 用 ping 判断网络是否可用
isAvailableByDns[Async] : 用 DNS 判断网络是否可用
getMobileDataEnabled : 判断移动数据是否打开
isMobileData : 判断网络是否是移动数据
is4G : 判断网络是否是 4G
getWifiEnabled : 判断 wifi 是否打开
setWifiEnabled : 打开或关闭 wifi
isWifiConnected : 判断 wifi 是否连接状态
isWifiAvailable[Async] : 判断 wifi 数据是否可用
getNetworkOperatorName : 获取移动网络运营商名称
getNetworkType : 获取当前网络类型
getIPAddress[Async] : 获取 IP 地址
getDomainAddress[Async] : 获取域名 IP 地址
getIpAddressByWifi : 根据 WiFi 获取网络 IP 地址
getGatewayByWifi : 根据 WiFi 获取网关 IP 地址
getNetMaskByWifi : 根据 WiFi 获取子网掩码 IP 地址
getServerAddressByWifi : 根据 WiFi 获取服务端 IP 地址
registerNetworkStatusChangedListener : 注册网络状态改变监听器
unregisterNetworkStatusChangedListener: 注销网络状态改变监听器
```
* ### 对象相关 -> [ObjectUtils.java][object.java] -> [Test][object.test]
......
......@@ -2,10 +2,10 @@
Gradle:
```groovy
implementation 'com.blankj:utilcode:1.25.4'
implementation 'com.blankj:utilcode:1.25.5'
// if u use AndroidX, use the following
implementation 'com.blankj:utilcodex:1.25.4'
implementation 'com.blankj:utilcodex:1.25.5'
```
......@@ -295,6 +295,8 @@ getModel
getABIs
isTablet
isEmulator
getUniqueDeviceId
isSameDevice
```
* ### About Flashlight -> [FlashlightUtils.java][flashlight.java] -> [Demo][flashlight.demo]
......@@ -548,24 +550,26 @@ getMetaDataInReceiver
```
openWirelessSettings
isConnected
isAvailable[Async] : 判断网络是否可用
isAvailableByPing[Async]: 用 ping 判断网络是否可用
isAvailableByDns[Async] : 用 DNS 判断网络是否可用
isAvailable[Async] : 判断网络是否可用
isAvailableByPing[Async] : 用 ping 判断网络是否可用
isAvailableByDns[Async] : 用 DNS 判断网络是否可用
getMobileDataEnabled
isMobileData
is4G
getWifiEnabled
setWifiEnabled
isWifiConnected
isWifiAvailable[Async] : 判断 wifi 数据是否可用
isWifiAvailable[Async] : 判断 wifi 数据是否可用
getNetworkOperatorName
getNetworkType
getIPAddress[Async] : 获取 IP 地址
getDomainAddress[Async] : 获取域名 IP 地址
getIPAddress[Async] : 获取 IP 地址
getDomainAddress[Async] : 获取域名 IP 地址
getIpAddressByWifi
getGatewayByWifi
getNetMaskByWifi
getServerAddressByWifi
registerNetworkStatusChangedListener
unregisterNetworkStatusChangedListener
```
* ### About Object -> [ObjectUtils.java][object.java] -> [Test][object.test]
......
......@@ -8,7 +8,6 @@ import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Debug;
import android.provider.Settings;
import android.support.annotation.RequiresApi;
import android.support.annotation.RequiresPermission;
......@@ -20,9 +19,11 @@ import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.UUID;
import static android.Manifest.permission.ACCESS_WIFI_STATE;
import static android.Manifest.permission.INTERNET;
import static android.content.Context.WIFI_SERVICE;
/**
* <pre>
......@@ -98,6 +99,7 @@ public final class DeviceUtils {
Utils.getApp().getContentResolver(),
Settings.Secure.ANDROID_ID
);
if ("9774d56d682e549c".equals(id)) return "";
return id == null ? "" : id;
}
......@@ -110,9 +112,27 @@ public final class DeviceUtils {
*/
@RequiresPermission(allOf = {ACCESS_WIFI_STATE, INTERNET})
public static String getMacAddress() {
String macAddress = getMacAddress((String[]) null);
if (!macAddress.equals("") || getWifiEnabled()) return macAddress;
setWifiEnabled(true);
setWifiEnabled(false);
return getMacAddress((String[]) null);
}
private static boolean getWifiEnabled() {
@SuppressLint("WifiManagerLeak")
WifiManager manager = (WifiManager) Utils.getApp().getSystemService(WIFI_SERVICE);
if (manager == null) return false;
return manager.isWifiEnabled();
}
private static void setWifiEnabled(final boolean enabled) {
@SuppressLint("WifiManagerLeak")
WifiManager manager = (WifiManager) Utils.getApp().getSystemService(WIFI_SERVICE);
if (manager == null) return;
manager.setWifiEnabled(enabled);
}
/**
* Return the MAC address.
* <p>Must hold {@code <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />},
......@@ -157,7 +177,7 @@ public final class DeviceUtils {
private static String getMacAddressByWifiInfo() {
try {
final WifiManager wifi = (WifiManager) Utils.getApp()
.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
.getApplicationContext().getSystemService(WIFI_SERVICE);
if (wifi != null) {
final WifiInfo info = wifi.getConnectionInfo();
if (info != null) return info.getMacAddress();
......@@ -315,17 +335,12 @@ public final class DeviceUtils {
|| Build.FINGERPRINT.toLowerCase().contains("test-keys")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.SERIAL.equalsIgnoreCase("unknown")
|| Build.SERIAL.equalsIgnoreCase("android")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| "google_sdk".equals(Build.PRODUCT);
if (checkProperty) return true;
boolean checkDebuggerConnected = Debug.isDebuggerConnected();
if (checkDebuggerConnected) return true;
String operatorName = "";
TelephonyManager tm = (TelephonyManager) Utils.getApp().getSystemService(Context.TELEPHONY_SERVICE);
if (tm != null) {
......@@ -341,46 +356,118 @@ public final class DeviceUtils {
Intent intent = new Intent();
intent.setData(Uri.parse(url));
intent.setAction(Intent.ACTION_DIAL);
boolean checkDial = intent.resolveActivity(Utils.getApp().getPackageManager()) != null;
boolean checkDial = intent.resolveActivity(Utils.getApp().getPackageManager()) == null;
if (checkDial) return true;
// boolean checkDebuggerConnected = Debug.isDebuggerConnected();
// if (checkDebuggerConnected) return true;
return false;
}
// protected static final String PREFS_FILE = "device_id.xml";
// protected static final String PREFS_DEVICE_ID = "device_id";
//
// protected static UUID uuid;
//
// public static String getDeviceId() {
// if (uuid == null) {
// synchronized (DeviceUtils.class) {
// if (uuid == null) {
// final SharedPreferences prefs = Utils.getApp().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 = Settings.Secure.getString(Utils.getApp().getContentResolver(), Settings.Secure.ANDROID_ID);
// try {
// if (!"9774d56d682e549c".equals(androidId)) {
// uuid = UUID.nameUUIDFromBytes(androidId.getBytes());
// } else {
// final String deviceId = ((TelephonyManager) Utils.getApp().getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
// uuid = deviceId != null ? UUID.nameUUIDFromBytes(deviceId.getBytes()) : 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();
// }
//
// }
// }
// }
// }
private static final String KEY_UDID = "KEY_UDID";
private volatile static String udid;
/**
* Return the unique device id.
* <pre>{1}{UUID(macAddress)}</pre>
* <pre>{2}{UUID(deviceId )}</pre>
* <pre>{3}{UUID(androidId )}</pre>
* <pre>{4}{UUID(random )}</pre>
*
* @return the unique device id
*/
@SuppressLint({"MissingPermission", "HardwareIds"})
public static String getUniqueDeviceId() {
return getUniqueDeviceId("");
}
/**
* Return the unique device id.
* <pre>{prefix}{1}{UUID(macAddress)}</pre>
* <pre>{prefix}{2}{UUID(deviceId )}</pre>
* <pre>{prefix}{3}{UUID(androidId )}</pre>
* <pre>{prefix}{4}{UUID(random )}</pre>
*
* @param prefix The prefix of the unique device id.
* @return the unique device id
*/
@SuppressLint({"MissingPermission", "HardwareIds"})
public static String getUniqueDeviceId(String prefix) {
if (udid == null) {
synchronized (DeviceUtils.class) {
if (udid == null) {
final String id = Utils.getSpUtils4Utils().getString(KEY_UDID, null);
if (id != null) {
udid = id;
return udid;
}
try {
String macAddress = getMacAddress();
if (!macAddress.equals("")) {
return saveUdid(prefix + 1, macAddress);
}
final String androidId = getAndroidID();
if (!TextUtils.isEmpty(androidId)) {
return saveUdid(prefix + 2, androidId);
}
final String deviceId = ((TelephonyManager) Utils.getApp().getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
if (!TextUtils.isEmpty(deviceId)) {
return saveUdid(prefix + 3, deviceId);
}
} catch (Exception ignore) {/**/}
return saveUdid(prefix + 4, "");
}
}
}
return udid;
}
@SuppressLint({"MissingPermission", "HardwareIds"})
public static boolean isSameDevice(final String uniqueDeviceId) {
// {prefix}{type}{32id}
if (TextUtils.isEmpty(uniqueDeviceId) && uniqueDeviceId.length() < 33) return false;
if (uniqueDeviceId.equals(udid)) return true;
final String cachedId = Utils.getSpUtils4Utils().getString(KEY_UDID, null);
if (uniqueDeviceId.equals(cachedId)) return true;
int st = uniqueDeviceId.length() - 33;
String type = uniqueDeviceId.substring(st, st + 1);
if (type.startsWith("1")) {
String macAddress = getMacAddress();
if (macAddress.equals("")) {
return false;
}
return uniqueDeviceId.substring(st + 1).equals(getUdid("", macAddress));
} else if (type.startsWith("2")) {
final String androidId = getAndroidID();
if (TextUtils.isEmpty(androidId)) {
return false;
}
return uniqueDeviceId.substring(st + 1).equals(getUdid("", androidId));
} else if (type.startsWith("3")) {
final String deviceId = ((TelephonyManager) Utils.getApp().getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
if (TextUtils.isEmpty(deviceId)) {
return false;
}
return uniqueDeviceId.substring(st + 1).equals(getUdid("", deviceId));
}
return false;
}
private static String saveUdid(String prefix, String id) {
udid = getUdid(prefix, id);
SPUtils.getInstance().put(KEY_UDID, udid);
return udid;
}
private static String getUdid(String prefix, String id) {
if (id.equals("")) {
return prefix + UUID.randomUUID().toString().replace("-", "");
}
return prefix + UUID.nameUUIDFromBytes(id.getBytes()).toString().replace("-", "");
}
}
......@@ -1519,7 +1519,7 @@ public final class FragmentUtils {
* @return the top fragment
*/
public static Fragment getTop(@NonNull final FragmentManager fm) {
return getTopIsInStack(fm, false);
return getTopIsInStack(fm, null, false);
}
/**
......@@ -1529,10 +1529,11 @@ public final class FragmentUtils {
* @return the top fragment in stack
*/
public static Fragment getTopInStack(@NonNull final FragmentManager fm) {
return getTopIsInStack(fm, true);
return getTopIsInStack(fm, null, true);
}
private static Fragment getTopIsInStack(@NonNull final FragmentManager fm,
Fragment parentFragment,
final boolean isInStack) {
List<Fragment> fragments = getFragments(fm);
for (int i = fragments.size() - 1; i >= 0; --i) {
......@@ -1541,10 +1542,10 @@ public final class FragmentUtils {
if (isInStack) {
Bundle args = fragment.getArguments();
if (args != null && args.getBoolean(ARGS_IS_ADD_STACK)) {
return fragment;
return getTopIsInStack(fragment.getChildFragmentManager(), parentFragment, true);
}
} else {
return fragment;
return getTopIsInStack(fragment.getChildFragmentManager(), parentFragment, false);
}
}
}
......@@ -1558,7 +1559,7 @@ public final class FragmentUtils {
* @return the top fragment which is shown
*/
public static Fragment getTopShow(@NonNull final FragmentManager fm) {
return getTopShowIsInStack(fm, false);
return getTopShowIsInStack(fm, null, false);
}
/**
......@@ -1568,10 +1569,11 @@ public final class FragmentUtils {
* @return the top fragment which is shown in stack
*/
public static Fragment getTopShowInStack(@NonNull final FragmentManager fm) {
return getTopShowIsInStack(fm, true);
return getTopShowIsInStack(fm, null, true);
}
private static Fragment getTopShowIsInStack(@NonNull final FragmentManager fm,
Fragment parentFragment,
final boolean isInStack) {
List<Fragment> fragments = getFragments(fm);
for (int i = fragments.size() - 1; i >= 0; --i) {
......@@ -1583,14 +1585,14 @@ public final class FragmentUtils {
if (isInStack) {
Bundle args = fragment.getArguments();
if (args != null && args.getBoolean(ARGS_IS_ADD_STACK)) {
return fragment;
return getTopShowIsInStack(fragment.getChildFragmentManager(), fragment, true);
}
} else {
return fragment;
return getTopShowIsInStack(fragment.getChildFragmentManager(), fragment, false);
}
}
}
return null;
return parentFragment;
}
/**
......
......@@ -90,11 +90,11 @@ public class LanguageUtils {
final String activityClassName,
final boolean isFollowSystem) {
if (isFollowSystem) {
SPUtils.getInstance().put(KEY_LOCALE, VALUE_FOLLOW_SYSTEM);
Utils.getSpUtils4Utils().put(KEY_LOCALE, VALUE_FOLLOW_SYSTEM);
} else {
String localLanguage = locale.getLanguage();
String localCountry = locale.getCountry();
SPUtils.getInstance().put(KEY_LOCALE, localLanguage + "$" + localCountry);
Utils.getSpUtils4Utils().put(KEY_LOCALE, localLanguage + "$" + localCountry);
}
updateLanguage(Utils.getApp(), locale);
......@@ -111,7 +111,7 @@ public class LanguageUtils {
}
static void applyLanguage(@NonNull final Activity activity) {
final String spLocale = SPUtils.getInstance().getString(KEY_LOCALE);
final String spLocale = Utils.getSpUtils4Utils().getString(KEY_LOCALE);
if (TextUtils.isEmpty(spLocale)) {
return;
}
......
......@@ -657,7 +657,7 @@ public final class NetworkUtils {
*
* @param listener The status of network changed listener
*/
public static void unregisterOnNetworkChangedListener(OnNetworkStatusChangedListener listener) {
public static void unregisterNetworkStatusChangedListener(OnNetworkStatusChangedListener listener) {
NetworkChangedReceiver.getInstance().unregisterListener(listener);
}
......
......@@ -11,8 +11,8 @@ import android.support.annotation.RequiresPermission;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
......@@ -82,89 +82,111 @@ public final class PhoneUtils {
*
* @return the IMEI
*/
@SuppressLint("HardwareIds")
@RequiresPermission(READ_PHONE_STATE)
public static String getIMEI() {
TelephonyManager tm = getTelephonyManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return tm.getImei();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Class clazz = tm.getClass();
//noinspection unchecked
Method getImeiMethod = clazz.getDeclaredMethod("getImei");
getImeiMethod.setAccessible(true);
String imei = (String) getImeiMethod.invoke(tm);
if (imei != null) return imei;
} catch (Exception e) {
Log.e("PhoneUtils", "getIMEI: ", e);
}
}
String imei = tm.getDeviceId();
if (imei != null && imei.length() == 15) {
return imei;
}
return "";
return getImeiOrMeid(true);
}
/**
* Return the IMEI.
* Return the MEID.
* <p>Must hold {@code <uses-permission android:name="android.permission.READ_PHONE_STATE" />}</p>
*
* @param slotId of which deviceID is returned
* @return the IMEI
* @return the MEID
*/
@RequiresPermission(READ_PHONE_STATE)
public static String getMEID() {
return getImeiOrMeid(false);
}
@SuppressLint("HardwareIds")
@RequiresPermission(READ_PHONE_STATE)
public static String getIMEI(int slotId) {
public static String getImeiOrMeid(boolean isImei) {
TelephonyManager tm = getTelephonyManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return tm.getImei(slotId);
if (isImei) {
return getMinOne(tm.getImei(0), tm.getImei(1));
} else {
return getMinOne(tm.getMeid(0), tm.getMeid(1));
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String ids = getSystemPropertyByReflect(isImei ? "ril.gsm.imei" : "ril.cdma.meid");
if (!TextUtils.isEmpty(ids)) {
String[] idArr = ids.split(",");
if (idArr.length == 2) {
return getMinOne(idArr[0], idArr[1]);
} else {
return idArr[0];
}
}
String id0 = tm.getDeviceId();
String id1 = "";
try {
Class clazz = tm.getClass();
//noinspection unchecked
Method getImeiMethod = clazz.getDeclaredMethod("getImei", int.class);
getImeiMethod.setAccessible(true);
String imei = (String) getImeiMethod.invoke(tm, slotId);
if (imei != null) return imei;
} catch (Exception e) {
Log.e("PhoneUtils", "getIMEI: ", e);
Method method = tm.getClass().getMethod("getDeviceId", int.class);
id1 = (String) method.invoke(tm,
isImei ? TelephonyManager.PHONE_TYPE_GSM
: TelephonyManager.PHONE_TYPE_CDMA);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
if (isImei) {
if (id0 != null && id0.length() < 15) {
id0 = "";
}
if (id1 != null && id1.length() < 15) {
id1 = "";
}
} else {
if (id0 != null && id0.length() == 14) {
id0 = "";
}
if (id1 != null && id1.length() == 14) {
id1 = "";
}
}
return getMinOne(id0, id1);
} else {
String deviceId = tm.getDeviceId();
if (isImei) {
if (deviceId != null && deviceId.length() >= 15) {
return deviceId;
}
} else {
if (deviceId != null && deviceId.length() == 14) {
return deviceId;
}
}
}
return getIMEI();
return "";
}
/**
* Return the MEID.
* <p>Must hold {@code <uses-permission android:name="android.permission.READ_PHONE_STATE" />}</p>
*
* @return the MEID
*/
@SuppressLint("HardwareIds")
@RequiresPermission(READ_PHONE_STATE)
public static String getMEID() {
TelephonyManager tm = getTelephonyManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return tm.getMeid();
private static String getMinOne(String s0, String s1) {
boolean empty0 = TextUtils.isEmpty(s0);
boolean empty1 = TextUtils.isEmpty(s1);
if (empty0 && empty1) return "";
if (!empty0 && !empty1) {
if (s0.compareTo(s1) <= 0) {
return s0;
} else {
return s1;
}
}
return tm.getDeviceId();
if (!empty0) return s0;
return s1;
}
/**
* Return the MEID.
* <p>Must hold {@code <uses-permission android:name="android.permission.READ_PHONE_STATE" />}</p>
*
* @return the MEID
*/
@SuppressLint("HardwareIds")
@RequiresPermission(READ_PHONE_STATE)
public static String getMEID(final int slotId) {
TelephonyManager tm = getTelephonyManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return tm.getMeid(slotId);
}
return getMEID();
private static String getSystemPropertyByReflect(String key) {
try {
@SuppressLint("PrivateApi")
Class<?> clz = Class.forName("android.os.SystemProperties");
Method getMethod = clz.getMethod("get", String.class, String.class);
return (String) getMethod.invoke(clz, key, "");
} catch (Exception e) {/**/}
return "";
}
/**
......@@ -176,8 +198,7 @@ public final class PhoneUtils {
@SuppressLint("HardwareIds")
@RequiresPermission(READ_PHONE_STATE)
public static String getIMSI() {
TelephonyManager tm = getTelephonyManager();
return tm.getSubscriberId();
return getTelephonyManager().getSubscriberId();
}
/**
......@@ -270,7 +291,7 @@ public final class PhoneUtils {
TelephonyManager tm = getTelephonyManager();
String str = "";
//noinspection ConstantConditions
str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n";
str += "DeviceId = " + tm.getDeviceId() + "\n";
str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
str += "Line1Number = " + tm.getLine1Number() + "\n";
str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
......
......@@ -309,7 +309,7 @@ public final class ThreadUtils {
* @param <T> The type of the task's result.
*/
public static <T> void executeBySingle(final Task<T> task) {
getPoolByTypeAndPriority(TYPE_SINGLE).execute(task);
execute(getPoolByTypeAndPriority(TYPE_SINGLE), task);
}
/**
......@@ -897,42 +897,60 @@ public final class ThreadUtils {
sDeliver = deliver;
}
private static <T> void execute(final ExecutorService pool, final Task<T> task) {
execute(pool, task, 0, 0, null);
}
private static <T> void executeWithDelay(final ExecutorService pool,
final Task<T> task,
final long delay,
final TimeUnit unit) {
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
execute(pool, task, this);
}
};
TIMER.schedule(timerTask, unit.toMillis(delay));
execute(pool, task, delay, 0, unit);
}
private static <T> void executeAtFixedRate(final ExecutorService pool,
final Task<T> task,
long initialDelay,
long delay,
final long period,
final TimeUnit unit) {
task.setSchedule(true);
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
execute(pool, task, this);
}
};
TIMER.scheduleAtFixedRate(timerTask, unit.toMillis(initialDelay), unit.toMillis(period));
}
private static <T> void execute(final ExecutorService pool, final Task<T> task) {
execute(pool, task, null);
execute(pool, task, delay, period, unit);
}
private static <T> void execute(final ExecutorService pool, final Task<T> task,
final TimerTask timerTask) {
pool.execute(task);
TASK_TASKINFO_MAP.put(task, new TaskInfo(timerTask, pool));
long delay, final long period, final TimeUnit unit) {
TaskInfo taskInfo;
synchronized (TASK_TASKINFO_MAP) {
if (TASK_TASKINFO_MAP.get(task) != null) {
Log.e("ThreadUtils", "Task can only be executed once.");
return;
}
taskInfo = new TaskInfo(pool);
TASK_TASKINFO_MAP.put(task, taskInfo);
}
if (period == 0) {
if (delay == 0) {
pool.execute(task);
} else {
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
pool.execute(task);
}
};
taskInfo.mTimerTask = timerTask;
TIMER.schedule(timerTask, unit.toMillis(delay));
}
} else {
task.setSchedule(true);
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
pool.execute(task);
}
};
taskInfo.mTimerTask = timerTask;
TIMER.scheduleAtFixedRate(timerTask, unit.toMillis(delay), unit.toMillis(period));
}
}
private static ExecutorService getPoolByTypeAndPriority(final int type) {
......@@ -1132,19 +1150,19 @@ public final class ThreadUtils {
public abstract static class Task<T> implements Runnable {
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int CANCELLED = 2;
private static final int EXCEPTIONAL = 3;
private static final int RUNNING = 1;
private static final int EXCEPTIONAL = 2;
private static final int COMPLETING = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTED = 5;
private static final Object LOCK = "";
private final AtomicInteger state = new AtomicInteger(NEW);
private volatile int state = NEW;
private volatile boolean isSchedule;
private volatile Thread runner;
private Executor deliver;
public abstract T doInBackground() throws Throwable;
public abstract void onSuccess(T result);
......@@ -1153,19 +1171,23 @@ public final class ThreadUtils {
public abstract void onFail(Throwable t);
@Override
public void run() {
if (state != NEW) return;
synchronized (LOCK) {
if (isSchedule) {
if (runner == null) {
if (!state.compareAndSet(NEW, RUNNING)) return;
runner = Thread.currentThread();
} else {
if (state.get() != RUNNING) return;
}
} else {
if (!state.compareAndSet(NEW, RUNNING)) return;
runner = Thread.currentThread();
}
try {
final T result = doInBackground();
if (state != NEW) return;
if (isSchedule) {
if (state.get() != RUNNING) return;
getDeliver().execute(new Runnable() {
@Override
public void run() {
......@@ -1173,7 +1195,7 @@ public final class ThreadUtils {
}
});
} else {
state = COMPLETING;
if (!state.compareAndSet(RUNNING, COMPLETING)) return;
getDeliver().execute(new Runnable() {
@Override
public void run() {
......@@ -1183,11 +1205,9 @@ public final class ThreadUtils {
});
}
} catch (InterruptedException ignore) {
state.set(INTERRUPTED);
} catch (final Throwable throwable) {
if (state != NEW) return;
state = EXCEPTIONAL;
if (!state.compareAndSet(RUNNING, EXCEPTIONAL)) return;
getDeliver().execute(new Runnable() {
@Override
public void run() {
......@@ -1203,17 +1223,16 @@ public final class ThreadUtils {
}
public void cancel(boolean mayInterruptIfRunning) {
if (state != NEW) return;
synchronized (state) {
if (state.get() > RUNNING) return;
state.set(CANCELLED);
}
if (mayInterruptIfRunning) {
synchronized (LOCK) {
if (runner != null) {
runner.interrupt();
}
if (runner != null) {
runner.interrupt();
}
}
state = CANCELLED;
getDeliver().execute(new Runnable() {
@Override
public void run() {
......@@ -1224,11 +1243,11 @@ public final class ThreadUtils {
}
public boolean isCanceled() {
return state == CANCELLED;
return state.get() >= CANCELLED;
}
public boolean isDone() {
return state != NEW;
return state.get() > RUNNING;
}
public Task<T> setDeliver(Executor deliver) {
......@@ -1270,8 +1289,7 @@ public final class ThreadUtils {
private TimerTask mTimerTask;
private ExecutorService mService;
private TaskInfo(TimerTask timerTask, ExecutorService service) {
mTimerTask = timerTask;
private TaskInfo(ExecutorService service) {
mService = service;
}
}
......
......@@ -201,6 +201,10 @@ public final class Utils {
}
}
static SPUtils getSpUtils4Utils() {
return SPUtils.getInstance("Utils");
}
///////////////////////////////////////////////////////////////////////////
// private method
///////////////////////////////////////////////////////////////////////////
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册