diff --git a/md/about_app.md b/md/about_app.md index 3b634a1a6ed61df57635e7d58e4b8a24fa874ab6..1a5c570ed0e0e776ef82d6a6dd66040912f92793 100644 --- a/md/about_app.md +++ b/md/about_app.md @@ -1,138 +1,159 @@ # App相关 -### 安装指定路径下的Apk ``` java +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.net.Uri; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + /** - * 安装指定路径下的Apk - *

根据路径名是否符合和文件是否存在判断是否安装成功 - *

更好的做法应该是startActivityForResult回调判断是否安装成功比较妥当 - *

这里做不了回调,后续自己做处理 + *

+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : App相关的工具类
+ * 
*/ -public static boolean installApp(Context context, String filePath) { - if (filePath != null && filePath.length() > 4 - && filePath.toLowerCase().substring(filePath.length() - 4).equals(".apk")) { +public class AppUtils { + + private AppUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } + + /** + * 安装App + *

根据路径安装App

+ * + * @param context 上下文 + * @param filePath 文件路径 + */ + public static void installApp(Context context, String filePath) { + installApp(context, new File(filePath)); + } + + /** + * 安装App + *

根据文件安装App

+ * + * @param context 上下文 + * @param file 文件 + */ + public static void installApp(Context context, File file) { Intent intent = new Intent(Intent.ACTION_VIEW); - File file = new File(filePath); - if (file.exists() && file.isFile() && file.length() > 0) { - intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - return true; - } + intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); } - return false; -} -``` -### 卸载指定包名的App -``` java -/** - * 卸载指定包名的App - *

这里卸载成不成功只判断了packageName是否为空 - *

如果要根据是否卸载成功应该用startActivityForResult回调判断是否还存在比较妥当 - *

这里做不了回调,后续自己做处理 - */ -public boolean uninstallApp(Context context, String packageName) { - if (!TextUtils.isEmpty(packageName)) { + /** + * 卸载指定包名的App + * + * @param context 上下文 + * @param packageName 包名 + */ + public void uninstallApp(Context context, String packageName) { Intent intent = new Intent(Intent.ACTION_DELETE); intent.setData(Uri.parse("package:" + packageName)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); - return true; } - return false; -} -``` -### 获取当前App信息 -``` java -/** - * 封装App信息的Bean类 - */ -public static class AppInfo { - - private String name; - private Drawable icon; - private String packagName; - private String versionName; - private int versionCode; - private boolean isSD; - private boolean isUser; - - public Drawable getIcon() { - return icon; - } + /** + * 封装App信息的Bean类 + */ + public static class AppInfo { - public void setIcon(Drawable icon) { - this.icon = icon; - } + private String name; + private Drawable icon; + private String packageName; + private String versionName; + private int versionCode; + private boolean isSD; + private boolean isUser; - public boolean isSD() { - return isSD; - } + public Drawable getIcon() { + return icon; + } - public void setSD(boolean SD) { - isSD = SD; - } + public void setIcon(Drawable icon) { + this.icon = icon; + } - public boolean isUser() { - return isUser; - } + public boolean isSD() { + return isSD; + } - public void setUser(boolean user) { - isUser = user; - } + public void setSD(boolean SD) { + isSD = SD; + } - public String getName() { - return name; - } + public boolean isUser() { + return isUser; + } - public void setName(String name) { - this.name = name; - } + public void setUser(boolean user) { + isUser = user; + } - public String getPackagName() { - return packagName; - } + public String getName() { + return name; + } - public void setPackagName(String packagName) { - this.packagName = packagName; - } + public void setName(String name) { + this.name = name; + } - public int getVersionCode() { - return versionCode; - } + public String getPackageName() { + return packageName; + } - public void setVersionCode(int versionCode) { - this.versionCode = versionCode; - } + public void setPackageName(String packagName) { + this.packageName = packagName; + } - public String getVersionName() { - return versionName; - } + public int getVersionCode() { + return versionCode; + } - public void setVersionName(String versionName) { - this.versionName = versionName; - } + public void setVersionCode(int versionCode) { + this.versionCode = versionCode; + } - /** - * @param name 名称 - * @param icon 图标 - * @param packagName 包名 - * @param versionName 版本号 - * @param versionCode 版本Code - * @param isSD 是否安装在SD卡 - * @param isUser 是否是用户程序 - */ - public AppInfo(String name, Drawable icon, String packagName, - String versionName, int versionCode, boolean isSD, boolean isUser) { - this.setName(name); - this.setIcon(icon); - this.setPackagName(packagName); - this.setVersionName(versionName); - this.setVersionCode(versionCode); - this.setSD(isSD); - this.setUser(isUser); - } + public String getVersionName() { + return versionName; + } + + public void setVersionName(String versionName) { + this.versionName = versionName; + } + + /** + * @param name 名称 + * @param icon 图标 + * @param packageName 包名 + * @param versionName 版本号 + * @param versionCode 版本Code + * @param isSD 是否安装在SD卡 + * @param isUser 是否是用户程序 + */ + public AppInfo(String name, Drawable icon, String packageName, + String versionName, int versionCode, boolean isSD, boolean isUser) { + this.setName(name); + this.setIcon(icon); + this.setPackageName(packageName); + this.setVersionName(versionName); + this.setVersionCode(versionCode); + this.setSD(isSD); + this.setUser(isUser); + } /*@Override public String toString() { @@ -144,127 +165,149 @@ public static class AppInfo { + isSD() + "\n" + isUser() + "\n"; }*/ -} + } -/** - * 获取当前App信息 - *

AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序) - */ -public static AppInfo getAppInfo(Context context) { - PackageManager pm = context.getPackageManager(); - PackageInfo pi = null; - try { - pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); + /** + * 获取当前App信息 + *

AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序)

+ * + * @param context 上下文 + * @return 当前应用的AppInfo + */ + public static AppInfo getAppInfo(Context context) { + PackageManager pm = context.getPackageManager(); + PackageInfo pi = null; + try { + pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return pi != null ? getBean(pm, pi) : null; } - return pi != null ? getBean(pm, pi) : null; -} -/** - * 得到AppInfo的Bean - */ -private static AppInfo getBean(PackageManager pm, PackageInfo pi) { - ApplicationInfo ai = pi.applicationInfo; - String name = ai.loadLabel(pm).toString(); - Drawable icon = ai.loadIcon(pm); - String packageName = pi.packageName; - String versionName = pi.versionName; - int versionCode = pi.versionCode; - boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; - boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; - return new AppInfo(name, icon, packageName, versionName, versionCode, isSD, isUser); -} -``` + /** + * 得到AppInfo的Bean + * + * @param pm 包的管理 + * @param pi 包的信息 + * @return AppInfo类 + */ + private static AppInfo getBean(PackageManager pm, PackageInfo pi) { + ApplicationInfo ai = pi.applicationInfo; + String name = ai.loadLabel(pm).toString(); + Drawable icon = ai.loadIcon(pm); + String packageName = pi.packageName; + String versionName = pi.versionName; + int versionCode = pi.versionCode; + boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; + boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; + return new AppInfo(name, icon, packageName, versionName, versionCode, isSD, isUser); + } -### 获取所有已安装App信息 -``` -/** - * 获取所有已安装App信息 - *

AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序) - *

依赖上面的getBean方法 - */ -public static List getAllAppsInfo(Context context) { - List list = new ArrayList<>(); - PackageManager pm = context.getPackageManager(); - // 获取系统中安装的所有软件信息 - List installedPackages = pm.getInstalledPackages(0); - for (PackageInfo pi : installedPackages) { - if (pi != null) { - list.add(getBean(pm, pi)); + /** + * 获取所有已安装App信息 + *

AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序)

+ *

依赖上面的getBean方法

+ * + * @param context 上下文 + * @return 所有已安装的AppInfo列表 + */ + public static List getAllAppsInfo(Context context) { + List list = new ArrayList<>(); + PackageManager pm = context.getPackageManager(); + // 获取系统中安装的所有软件信息 + List installedPackages = pm.getInstalledPackages(0); + for (PackageInfo pi : installedPackages) { + if (pi != null) { + list.add(getBean(pm, pi)); + } } + return list; } - return list; -} -``` -### 打开指定包名的App -``` -/** - * 打开指定包名的App - */ -public static boolean openAppByPackageName(Context context, String packageName) { - if (!TextUtils.isEmpty(packageName)) { - PackageManager pm = context.getPackageManager(); - Intent launchIntentForPackage = pm.getLaunchIntentForPackage(packageName); - if (launchIntentForPackage != null) { - context.startActivity(launchIntentForPackage); + /** + * 根据包名获取意图 + * + * @param context 上下文 + * @param packageName 包名 + * @return 意图 + */ + private static Intent getIntentByPackageName(Context context, String packageName) { + return context.getPackageManager().getLaunchIntentForPackage(packageName); + } + + /** + * 根据包名判断App是否安装 + * + * @param context 上下文 + * @param packageName 包名 + * @return true: 已安装
false: 未安装 + */ + public static boolean isInstallApp(Context context, String packageName) { + return getIntentByPackageName(context, packageName) != null; + } + + /** + * 打开指定包名的App + * + * @param context 上下文 + * @param packageName 包名 + * @return true: 打开成功
false: 打开失败 + */ + public static boolean openAppByPackageName(Context context, String packageName) { + Intent intent = getIntentByPackageName(context, packageName); + if (intent != null) { + context.startActivity(intent); return true; } + return false; } - return false; -} -``` -### 打开指定包名的App应用信息界面 -``` java -/** - * 打开指定包名的App应用信息界面 - */ -public static boolean openAppInfo(Context context, String packageName) { - if (!TextUtils.isEmpty(packageName)) { + /** + * 打开指定包名的App应用信息界面 + * + * @param context 上下文 + * @param packageName 包名 + */ + public static void openAppInfo(Context context, String packageName) { Intent intent = new Intent(); intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); intent.setData(Uri.parse("package:" + packageName)); context.startActivity(intent); - return true; } - return false; -} -``` -### 可用来做App信息分享 -``` java -/** - * 可用来做App信息分享 - */ -public static void shareAppInfo(Context context, String info) { - if (!TextUtils.isEmpty(info)) { + /** + * 可用来做App信息分享 + * + * @param context 上下文 + * @param info 分享信息 + */ + public static void shareAppInfo(Context context, String info) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, info); context.startActivity(intent); } -} -``` -### 判断当前App处于前台还是后台 -``` java -/** - * 判断当前App处于前台还是后台 - *

需添加权限 android.permission.GET_TASKS - *

并且必须是系统应用该方法才有效 - */ -public static boolean isAppBackground(Context context) { - ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - @SuppressWarnings("deprecation") - List tasks = am.getRunningTasks(1); - if (!tasks.isEmpty()) { - ComponentName topActivity = tasks.get(0).topActivity; - if (!topActivity.getPackageName().equals(context.getPackageName())) { - return true; + /** + * 判断当前App处于前台还是后台 + *

需添加权限 android.permission.GET_TASKS

+ *

并且必须是系统应用该方法才有效

+ * + * @param context 上下文 + * @return true: 后台
false: 前台 + */ + public static boolean isAppBackground(Context context) { + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + @SuppressWarnings("deprecation") + List tasks = am.getRunningTasks(1); + if (!tasks.isEmpty()) { + ComponentName topActivity = tasks.get(0).topActivity; + if (!topActivity.getPackageName().equals(context.getPackageName())) { + return true; + } } + return false; } - return false; } -``` +``` \ No newline at end of file diff --git a/md/about_device.md b/md/about_device.md index 990e0a5e918d54c396c39759ce806fd382d92869..908b3d42f2b984dc433cbd889a9a48148179803c 100644 --- a/md/about_device.md +++ b/md/about_device.md @@ -1,68 +1,106 @@ # 设备相关 -### 获取设备MAC地址 ``` java +import android.content.Context; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; + /** - * 获取设备MAC地址 - *

需添加权限 android.permission.ACCESS_WIFI_STATE + *

+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/1
+ *     desc  : 设备相关的工具类
+ * 
*/ -public static String getMacAddress(Context context) { - String macAddress; - WifiManager wifi = (WifiManager) context - .getSystemService(Context.WIFI_SERVICE); - WifiInfo info = wifi.getConnectionInfo(); - macAddress = info.getMacAddress(); - if (null == macAddress) { - return ""; +public class DeviceUtils { + + private DeviceUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); } - macAddress = macAddress.replace(":", ""); - return macAddress; -} -``` -### 获取设备厂商,如Xiaomi -``` java -/** -* 获取设备厂商,如Xiaomi -*/ -public static String getManufacturer() { - String MANUFACTURER = Build.MANUFACTURER; - return MANUFACTURER; -} -``` + /** + * 获取设备MAC地址 + *

需添加权限 android.permission.ACCESS_WIFI_STATE

+ * + * @param context 上下文 + * @return MAC地址 + */ + public static String getMacAddress(Context context) { + WifiManager wifi = (WifiManager) context + .getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + String macAddress = info.getMacAddress().replace(":", ""); + return macAddress == null ? "" : macAddress; + } -### 获取设备型号,如MI2SC -``` java -/** - * 获取设备型号,如MI2SC - */ -public static String getModel() { - String model = Build.MODEL; - if (model != null) { - model = model.trim().replaceAll("\\s*", ""); - } else { - model = ""; + /** + * 获取设备MAC地址 + *

需添加权限 android.permission.ACCESS_WIFI_STATE

+ * + * @return MAC地址 + */ + public static String getMacAddress() { + String macAddress = null; + try { + Process pp = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address"); + InputStreamReader ir = new InputStreamReader(pp.getInputStream()); + LineNumberReader reader = new LineNumberReader(ir); + macAddress = reader.readLine().replace(":", ""); + } catch (IOException ex) { + ex.printStackTrace(); + } + return macAddress == null ? "" : macAddress; } - return model; -} -``` -### 获取设备SD卡是否可用 -``` java -/** - * 获取设备SD卡是否可用 - */ -public static boolean isSDCardEnable() { - return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); -} -``` + /** + * 获取设备厂商,如Xiaomi + * + * @return 设备厂商 + */ + public static String getManufacturer() { + String MANUFACTURER = Build.MANUFACTURER; + return MANUFACTURER; + } -### 获取设备SD卡路径 -``` -/** - * 获取设备SD卡路径 - *

一般是/storage/emulated/0/ - */ -public static String getSDCardPath() { - return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator; + /** + * 获取设备型号,如MI2SC + * + * @return 设备型号 + */ + public static String getModel() { + String model = Build.MODEL; + if (model != null) { + model = model.trim().replaceAll("\\s*", ""); + } else { + model = ""; + } + return model; + } + + /** + * 获取设备SD卡是否可用 + * + * @return true : 可用
false : 不可用 + */ + public static boolean isSDCardEnable() { + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); + } + + /** + * 获取设备SD卡路径 + *

一般是/storage/emulated/0/

+ * + * @return SD卡路径 + */ + public static String getSDCardPath() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator; + } } ``` diff --git a/md/about_encode.md b/md/about_encode.md index ab1d1cb37a7e61a6672260ff4310dc3bfecea0e2..abdb2d2cc570b5fd9801cd5e3da1013ee1114e51 100644 --- a/md/about_encode.md +++ b/md/about_encode.md @@ -1,148 +1,75 @@ -# 加解密相关 -### MD5加密 +# 编码解码相关 ``` java -/** - * MD5加密 - * - * @param data 明文字符串 - * @return 密文 - */ -public static String getMD5(String data) { - return getMD5(data.getBytes()); -} +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; /** - * MD5加密 - * - * @param data 明文字符串 - * @param salt 盐 - * @return 密文 + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/7
+ *     desc  : 编码解码相关工具类
+ * 
*/ -public static String getMD5(String data, String salt) { - return bytes2Hex(encryptMD5((data + salt).getBytes())); -} +public class EncodeUtils { -/** - * MD5加密 - * - * @param data 明文字节数组 - * @return 密文 - */ -public static String getMD5(byte[] data) { - return bytes2Hex(encryptMD5(data)); -} - -/** - * MD5加密 - * - * @param data 明文字节数组 - * @param salt 盐字节数组 - * @return 密文 - */ -public static String getMD5(byte[] data, byte[] salt) { - byte[] dataSalt = new byte[data.length + salt.length]; - System.arraycopy(data, 0, dataSalt, 0, data.length); - System.arraycopy(salt, 0, dataSalt, data.length, salt.length); - return bytes2Hex(encryptMD5(dataSalt)); -} + private EncodeUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } -/** - * MD5加密 - * - * @param data 明文字节数组 - * @return 密文字节数组 - */ -public static byte[] encryptMD5(byte[] data) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(data); - return md.digest(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); + /** + * 以UTF-8编码字符串 + *

若想自己指定字符集,可以使用encode(String string, String charset)方法

+ * + * @param string 要编码的字符 + * @return 编码为UTF-8的字符串 + */ + public static String encodeUTF8(String string) { + return encode(string, "UTF-8"); } - return new byte[0]; -} -/** - * 获取文件的MD5校验码 - * - * @param filePath 文件路径 - * @return 文件的MD5校验码 - */ -public static String getMD5File(String filePath) { - FileInputStream in = null; - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - in = new FileInputStream(filePath); - int len; - byte[] buffer = new byte[1024]; - while ((len = in.read(buffer)) != -1) { - md.update(buffer, 0, len); - } - return bytes2Hex(md.digest()); - } catch (NoSuchAlgorithmException | IOException e) { - e.printStackTrace(); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ignored) { - } + /** + * 字符编码 + *

若系统不支持指定的编码字符集,则直接将string原样返回

+ * + * @param string 要编码的字符 + * @param charset 字符集 + * @return 编码为字符集的字符串 + */ + public static String encode(String string, String charset) { + try { + return URLEncoder.encode(string, charset); + } catch (UnsupportedEncodingException e) { + return string; } } - return ""; -} -``` -### SHA加密 -``` -/** - * SHA加密 - * - * @param data 明文字符串 - * @return 密文 - */ -public static String getSHA(String data) { - return getSHA(data.getBytes()); -} - -/** - * SHA加密 - * - * @param data 明文字节数组 - * @return 密文 - */ -public static String getSHA(byte[] data) { - return bytes2Hex(encryptSHA(data)); -} - -/** - * SHA加密 - * - * @param data 明文字节数组 - * @return 密文字节数组 - */ -public static byte[] encryptSHA(byte[] data) { - try { - MessageDigest md = MessageDigest.getInstance("SHA"); - md.update(data); - return md.digest(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); + /** + * 以UTF-8解码字符串 + *

若想自己指定字符集,可以使用# {decode(String string, String charset)}方法

+ * + * @param string 要解码的字符 + * @return 解码为UTF-8的字符串 + */ + public static String decodeUTF8(String string) { + return decode(string, "UTF-8"); } - return new byte[0]; -} -/** - * 一个byte转为2个hex字符 - */ -public static String bytes2Hex(byte[] src) { - char[] res = new char[src.length * 2]; - final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - for (int i = 0, j = 0; i < src.length; i++) { - res[j++] = hexDigits[src[i] >>> 4 & 0x0f]; - res[j++] = hexDigits[src[i] & 0x0f]; + /** + * 字符解码 + *

若系统不支持指定的解码字符集,则直接将string原样返回

+ * + * @param string 要解码的字符 + * @param charset 字符集 + * @return 解码为字符集的字符串 + */ + public static String decode(String string, String charset) { + try { + return URLDecoder.decode(string, charset); + } catch (UnsupportedEncodingException e) { + return string; + } } - return new String(res); } ``` diff --git a/md/about_encrypt.md b/md/about_encrypt.md index ab1d1cb37a7e61a6672260ff4310dc3bfecea0e2..4f20c9716b845552adabc5a32cab3f8b5d8a7e39 100644 --- a/md/about_encrypt.md +++ b/md/about_encrypt.md @@ -1,148 +1,178 @@ # 加解密相关 -### MD5加密 ``` java -/** - * MD5加密 - * - * @param data 明文字符串 - * @return 密文 - */ -public static String getMD5(String data) { - return getMD5(data.getBytes()); -} +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; /** - * MD5加密 - * - * @param data 明文字符串 - * @param salt 盐 - * @return 密文 + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 加密相关的工具类
+ * 
*/ -public static String getMD5(String data, String salt) { - return bytes2Hex(encryptMD5((data + salt).getBytes())); -} +public class EncryptUtils { -/** - * MD5加密 - * - * @param data 明文字节数组 - * @return 密文 - */ -public static String getMD5(byte[] data) { - return bytes2Hex(encryptMD5(data)); -} + private EncryptUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } -/** - * MD5加密 - * - * @param data 明文字节数组 - * @param salt 盐字节数组 - * @return 密文 - */ -public static String getMD5(byte[] data, byte[] salt) { - byte[] dataSalt = new byte[data.length + salt.length]; - System.arraycopy(data, 0, dataSalt, 0, data.length); - System.arraycopy(salt, 0, dataSalt, data.length, salt.length); - return bytes2Hex(encryptMD5(dataSalt)); -} + /** + * MD5加密 + * + * @param data 明文字符串 + * @return 密文 + */ + public static String getMD5(String data) { + return getMD5(data.getBytes()); + } -/** - * MD5加密 - * - * @param data 明文字节数组 - * @return 密文字节数组 - */ -public static byte[] encryptMD5(byte[] data) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(data); - return md.digest(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); + /** + * MD5加密 + * + * @param data 明文字符串 + * @param salt 盐 + * @return 密文 + */ + public static String getMD5(String data, String salt) { + return bytes2Hex(encryptMD5((data + salt).getBytes())); } - return new byte[0]; -} -/** - * 获取文件的MD5校验码 - * - * @param filePath 文件路径 - * @return 文件的MD5校验码 - */ -public static String getMD5File(String filePath) { - FileInputStream in = null; - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - in = new FileInputStream(filePath); - int len; - byte[] buffer = new byte[1024]; - while ((len = in.read(buffer)) != -1) { - md.update(buffer, 0, len); + /** + * MD5加密 + * + * @param data 明文字节数组 + * @return 密文 + */ + public static String getMD5(byte[] data) { + return bytes2Hex(encryptMD5(data)); + } + + /** + * MD5加密 + * + * @param data 明文字节数组 + * @param salt 盐字节数组 + * @return 密文 + */ + public static String getMD5(byte[] data, byte[] salt) { + byte[] dataSalt = new byte[data.length + salt.length]; + System.arraycopy(data, 0, dataSalt, 0, data.length); + System.arraycopy(salt, 0, dataSalt, data.length, salt.length); + return bytes2Hex(encryptMD5(dataSalt)); + } + + /** + * MD5加密 + * + * @param data 明文字节数组 + * @return 密文字节数组 + */ + public static byte[] encryptMD5(byte[] data) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(data); + return md.digest(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); } - return bytes2Hex(md.digest()); - } catch (NoSuchAlgorithmException | IOException e) { - e.printStackTrace(); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ignored) { + return new byte[0]; + } + + /** + * 获取文件的MD5校验码 + * + * @param filePath 文件路径 + * @return 文件的MD5校验码 + */ + public static String getMD5File(String filePath) { + return getMD5File(new File(filePath)); + } + + /** + * 获取文件的MD5校验码 + * + * @param file 文件 + * @return 文件的MD5校验码 + */ + public static String getMD5File(File file) { + FileInputStream in = null; + try { + in = new FileInputStream(file); + FileChannel channel = in.getChannel(); + MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(buffer); + return bytes2Hex(md.digest()); + } catch (NoSuchAlgorithmException | IOException e) { + e.printStackTrace(); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) { + } } } + return ""; } - return ""; -} -``` -### SHA加密 -``` -/** - * SHA加密 - * - * @param data 明文字符串 - * @return 密文 - */ -public static String getSHA(String data) { - return getSHA(data.getBytes()); -} + /** + * SHA加密 + * + * @param data 明文字符串 + * @return 密文 + */ + public static String getSHA(String data) { + return getSHA(data.getBytes()); + } -/** - * SHA加密 - * - * @param data 明文字节数组 - * @return 密文 - */ -public static String getSHA(byte[] data) { - return bytes2Hex(encryptSHA(data)); -} + /** + * SHA加密 + * + * @param data 明文字节数组 + * @return 密文 + */ + public static String getSHA(byte[] data) { + return bytes2Hex(encryptSHA(data)); + } -/** - * SHA加密 - * - * @param data 明文字节数组 - * @return 密文字节数组 - */ -public static byte[] encryptSHA(byte[] data) { - try { - MessageDigest md = MessageDigest.getInstance("SHA"); - md.update(data); - return md.digest(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); + /** + * SHA加密 + * + * @param data 明文字节数组 + * @return 密文字节数组 + */ + public static byte[] encryptSHA(byte[] data) { + try { + MessageDigest md = MessageDigest.getInstance("SHA"); + md.update(data); + return md.digest(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return new byte[0]; } - return new byte[0]; -} -/** - * 一个byte转为2个hex字符 - */ -public static String bytes2Hex(byte[] src) { - char[] res = new char[src.length * 2]; - final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - for (int i = 0, j = 0; i < src.length; i++) { - res[j++] = hexDigits[src[i] >>> 4 & 0x0f]; - res[j++] = hexDigits[src[i] & 0x0f]; + /** + * 一个byte转为2个hex字符 + * + * @param src byte数组 + * @return 16进制大写字符串 + */ + public static String bytes2Hex(byte[] src) { + char[] res = new char[src.length << 1]; + final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + for (int i = 0, j = 0; i < src.length; i++) { + res[j++] = hexDigits[src[i] >>> 4 & 0x0f]; + res[j++] = hexDigits[src[i] & 0x0f]; + } + return new String(res); } - return new String(res); } ``` diff --git a/md/about_keyboard.md b/md/about_keyboard.md index 5cadb8fdd5dcf045f49b942e2886875587b51408..4f15fd9b0973d125fee550abc1bf5bbabb6702e9 100644 --- a/md/about_keyboard.md +++ b/md/about_keyboard.md @@ -1,126 +1,145 @@ # 键盘相关 -### 避免输入法面板遮挡 ``` java -// 在manifest.xml中activity中设置 -android:windowSoftInputMode="stateVisible|adjustResize" -``` +import android.app.Activity; +import android.content.Context; +import android.util.Log; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; -### 动态隐藏软键盘 -``` java /** -* 动态隐藏软键盘 -*/ -public static void hideSoftInput(Activity activity) { - View view = activity.getWindow().peekDecorView(); - if (view != null) { - InputMethodManager inputmanger = (InputMethodManager) activity - .getSystemService(Context.INPUT_METHOD_SERVICE); - inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0); - } -} + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 键盘相关的工具类
+ * 
+ */ +public class KeyboardUtils { -/** -* 动态隐藏软键盘 -*/ -public static void hideSoftInput(Context context, EditText edit) { - edit.clearFocus(); - InputMethodManager inputmanger = (InputMethodManager) context - .getSystemService(Context.INPUT_METHOD_SERVICE); - inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0); -} -``` + private KeyboardUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } -### 点击屏幕空白区域隐藏软键盘 -``` java -/** - * 点击屏幕空白区域隐藏软键盘(方法0) - *

在onTouch中处理,未获焦点则隐藏 - *

参照以下注释代码 - */ -public static void clickBlankArea2HideSoftInput0() { - Log.i("tips", "U should copy the following code."); - /* - @Override - public boolean onTouchEvent (MotionEvent event){ - if (null != this.getCurrentFocus()) { - InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); - return mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); + /** + * 动态隐藏软键盘 + * + * @param activity activity + */ + public static void hideSoftInput(Activity activity) { + View view = activity.getWindow().peekDecorView(); + if (view != null) { + InputMethodManager inputmanger = (InputMethodManager) activity + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0); } - return super.onTouchEvent(event); } - */ -} -/** - * 点击屏幕空白区域隐藏软键盘(方法1) - *

根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 - *

需重写dispatchTouchEvent - *

参照以下注释代码 - */ -public static void clickBlankArea2HideSoftInput1() { - Log.i("tips", "U should copy the following code."); - /* - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - View v = getCurrentFocus(); - if (isShouldHideKeyboard(v, ev)) { - hideKeyboard(v.getWindowToken()); + /** + * 动态隐藏软键盘 + * + * @param context 上下文 + * @param edit 输入框 + */ + public static void hideSoftInput(Context context, EditText edit) { + edit.clearFocus(); + InputMethodManager inputmanger = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0); + } + + /** + * 点击屏幕空白区域隐藏软键盘(方法1) + *

在onTouch中处理,未获焦点则隐藏

+ *

参照以下注释代码

+ */ + public static void clickBlankArea2HideSoftInput0() { + Log.i("tips", "U should copy the following code."); + /* + @Override + public boolean onTouchEvent (MotionEvent event){ + if (null != this.getCurrentFocus()) { + InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + return mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); } + return super.onTouchEvent(event); } - return super.dispatchTouchEvent(ev); + */ } - // 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 - private boolean isShouldHideKeyboard(View v, MotionEvent event) { - if (v != null && (v instanceof EditText)) { - int[] l = {0, 0}; - v.getLocationInWindow(l); - int left = l[0], - top = l[1], - bottom = top + v.getHeight(), - right = left + v.getWidth(); - return !(event.getX() > left && event.getX() < right - && event.getY() > top && event.getY() < bottom); + + /** + * 点击屏幕空白区域隐藏软键盘(方法2) + *

根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘

+ *

需重写dispatchTouchEvent

+ *

参照以下注释代码

+ */ + public static void clickBlankArea2HideSoftInput1() { + Log.i("tips", "U should copy the following code."); + /* + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + View v = getCurrentFocus(); + if (isShouldHideKeyboard(v, ev)) { + hideKeyboard(v.getWindowToken()); + } + } + return super.dispatchTouchEvent(ev); } - return false; - } - // 获取InputMethodManager,隐藏软键盘 - private void hideKeyboard(IBinder token) { - if (token != null) { - InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); + + // 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 + private boolean isShouldHideKeyboard(View v, MotionEvent event) { + if (v != null && (v instanceof EditText)) { + int[] l = {0, 0}; + v.getLocationInWindow(l); + int left = l[0], + top = l[1], + bottom = top + v.getHeight(), + right = left + v.getWidth(); + return !(event.getX() > left && event.getX() < right + && event.getY() > top && event.getY() < bottom); + } + return false; + } + + // 获取InputMethodManager,隐藏软键盘 + private void hideKeyboard(IBinder token) { + if (token != null) { + InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); + } } + */ } - */ -} -``` -### 动态显示软键盘 -``` java -/** -* 动态显示软键盘 -*/ -public static void showSoftInput(Context context, EditText edit) { - edit.setFocusable(true); - edit.setFocusableInTouchMode(true); - edit.requestFocus(); - InputMethodManager inputManager = (InputMethodManager) context - .getSystemService(Context.INPUT_METHOD_SERVICE); - inputManager.showSoftInput(edit, 0); -} -``` + /** + * 动态显示软键盘 + * + * @param context 上下文 + * @param edit 输入框 + */ + public static void showSoftInput(Context context, EditText edit) { + edit.setFocusable(true); + edit.setFocusableInTouchMode(true); + edit.requestFocus(); + InputMethodManager inputManager = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.showSoftInput(edit, 0); + } -### 切换键盘显示与否状态 -``` java -/** -* 切换键盘显示与否状态 -*/ -public static void toggleSoftInput(Context context, EditText edit) { - edit.setFocusable(true); - edit.setFocusableInTouchMode(true); - edit.requestFocus(); - InputMethodManager inputManager = (InputMethodManager) context - .getSystemService(Context.INPUT_METHOD_SERVICE); - inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + /** + * 切换键盘显示与否状态 + * + * @param context 上下文 + * @param edit 输入框 + */ + public static void toggleSoftInput(Context context, EditText edit) { + edit.setFocusable(true); + edit.setFocusableInTouchMode(true); + edit.requestFocus(); + InputMethodManager inputManager = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } } ``` diff --git a/md/about_network.md b/md/about_network.md index 272dde0abcc1d2a0ec9973c4d3c346fc6471fab1..08c907e789b8240b416e170d3412ca967d18b9ff 100644 --- a/md/about_network.md +++ b/md/about_network.md @@ -1,210 +1,240 @@ # 网络相关 -### 打开网络设置界面 ``` java +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.telephony.TelephonyManager; + /** - * 打开网络设置界面 - *

3.0以下打开设置界面 + *

+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 网络相关的工具类
+ * 
*/ -public static void openWirelessSettings(Context context) { - if (android.os.Build.VERSION.SDK_INT > 10) { - context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS)); - } else { - context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS)); +public class NetworkUtils { + + private NetworkUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); } -} -``` -### 判断网络是否可用 -``` java -/** - * 获取活动网路信息 - */ -private static NetworkInfo getActiveNetworkInfo(Context context) { - ConnectivityManager cm = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - return cm.getActiveNetworkInfo(); -} + public static final int NETWORK_WIFI = 1; // wifi network + public static final int NETWORK_4G = 4; // "4G" networks + public static final int NETWORK_3G = 3; // "3G" networks + public static final int NETWORK_2G = 2; // "2G" networks + public static final int NETWORK_UNKNOWN = 5; // unknown network + public static final int NETWORK_NO = -1; // no network -/** - * 判断网络是否可用 - *

需添加权限 android.permission.ACCESS_NETWORK_STATE - */ -public static boolean isAvailable(Context context) { - NetworkInfo info = getActiveNetworkInfo(context); - return info != null && info.isAvailable(); -} -``` + private static final int NETWORK_TYPE_GSM = 16; + private static final int NETWORK_TYPE_TD_SCDMA = 17; + private static final int NETWORK_TYPE_IWLAN = 18; -### 判断网络是否连接 -``` java -/** - * 判断网络是否连接 - *

需添加权限 android.permission.ACCESS_NETWORK_STATE - */ -public static boolean isConnected(Context context) { - NetworkInfo info = getActiveNetworkInfo(context); - return info != null && info.isConnected(); -} -``` + /** + * 打开网络设置界面 + *

3.0以下打开设置界面

+ * + * @param context 上下文 + */ + public static void openWirelessSettings(Context context) { + if (android.os.Build.VERSION.SDK_INT > 10) { + context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS)); + } else { + context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS)); + } + } -### 判断网络是否是4G -``` java -/** - * 判断网络是否是4G - *

需添加权限 android.permission.ACCESS_NETWORK_STATE - */ -public static boolean is4G(Context context) { - NetworkInfo info = getActiveNetworkInfo(context); - return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE; -} -``` + /** + * 获取活动网路信息 + * + * @param context 上下文 + * @return NetworkInfo + */ + private static NetworkInfo getActiveNetworkInfo(Context context) { + ConnectivityManager cm = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + return cm.getActiveNetworkInfo(); + } -### 判断wifi是否连接状态 -``` java -/** - * 判断wifi是否连接状态 - *

需添加权限 android.permission.ACCESS_NETWORK_STATE - */ -public static boolean isWifiConnected(Context context) { - ConnectivityManager cm = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; -} -``` + /** + * 判断网络是否可用 + *

需添加权限 android.permission.ACCESS_NETWORK_STATE

+ */ + public static boolean isAvailable(Context context) { + NetworkInfo info = getActiveNetworkInfo(context); + return info != null && info.isAvailable(); + } -### 获取移动网络运营商名称 -``` java -/** - * 获取移动网络运营商名称 - *

如中国联通、中国移动、中国电信 - */ -public static String getNetworkOperatorName(Context context) { - TelephonyManager tm = (TelephonyManager) context - .getSystemService(Context.TELEPHONY_SERVICE); - return tm != null ? tm.getNetworkOperatorName() : null; -} -``` + /** + * 判断网络是否连接 + *

需添加权限 android.permission.ACCESS_NETWORK_STATE

+ * + * @param context 上下文 + * @return true: 是
false: 否 + */ + public static boolean isConnected(Context context) { + NetworkInfo info = getActiveNetworkInfo(context); + return info != null && info.isConnected(); + } -### 获取移动终端类型 -``` java -/** - * 获取移动终端类型 - * - * @return 手机制式 - *
    - *
  • PHONE_TYPE_NONE : 0 手机制式未知
  • - *
  • PHONE_TYPE_GSM : 1 手机制式为GSM,移动和联通
  • - *
  • PHONE_TYPE_CDMA : 2 手机制式为CDMA,电信
  • - *
  • PHONE_TYPE_SIP : 3
  • - *
- */ -public static int getPhoneType(Context context) { - TelephonyManager tm = (TelephonyManager) context - .getSystemService(Context.TELEPHONY_SERVICE); - return tm != null ? tm.getPhoneType() : -1; -} -``` + /** + * 判断网络是否是4G + *

需添加权限 android.permission.ACCESS_NETWORK_STATE

+ * + * @param context 上下文 + * @return true: 是
false: 不是 + */ + public static boolean is4G(Context context) { + NetworkInfo info = getActiveNetworkInfo(context); + return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE; + } -### 获取当前的网络类型(WIFI,2G,3G,4G) -``` java -/** - * 获取当前的网络类型(WIFI,2G,3G,4G) - *

需添加权限 android.permission.ACCESS_NETWORK_STATE - * - * @return 网络类型 - *

    - *
  • NETWORK_WIFI = 1;
  • - *
  • NETWORK_4G = 4;
  • - *
  • NETWORK_3G = 3;
  • - *
  • NETWORK_2G = 2;
  • - *
  • NETWORK_UNKNOWN = 5;
  • - *
  • NETWORK_NO = -1;
  • - *
- */ -public static int getNetWorkType(Context context) { - int netType = NETWORK_NO; - NetworkInfo info = getActiveNetworkInfo(context); - if (info != null && info.isAvailable()) { - - if (info.getType() == ConnectivityManager.TYPE_WIFI) { - netType = NETWORK_WIFI; - } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { - switch (info.getSubtype()) { - - case NETWORK_TYPE_GSM: - case TelephonyManager.NETWORK_TYPE_GPRS: - case TelephonyManager.NETWORK_TYPE_CDMA: - case TelephonyManager.NETWORK_TYPE_EDGE: - case TelephonyManager.NETWORK_TYPE_1xRTT: - case TelephonyManager.NETWORK_TYPE_IDEN: - netType = NETWORK_2G; - break; - - case NETWORK_TYPE_TD_SCDMA: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_UMTS: - case TelephonyManager.NETWORK_TYPE_EVDO_0: - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_EHRPD: - case TelephonyManager.NETWORK_TYPE_HSPAP: - netType = NETWORK_3G; - break; - - case NETWORK_TYPE_IWLAN: - case TelephonyManager.NETWORK_TYPE_LTE: - netType = NETWORK_4G; - break; - default: - - String subtypeName = info.getSubtypeName(); - if (subtypeName.equalsIgnoreCase("TD-SCDMA") - || subtypeName.equalsIgnoreCase("WCDMA") - || subtypeName.equalsIgnoreCase("CDMA2000")) { + /** + * 判断wifi是否连接状态 + *

需添加权限 android.permission.ACCESS_NETWORK_STATE

+ * + * @param context 上下文 + * @return true: 连接
false: 未连接 + */ + public static boolean isWifiConnected(Context context) { + ConnectivityManager cm = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; + } + + /** + * 获取移动网络运营商名称 + *

如中国联通、中国移动、中国电信

+ * + * @param context 上下文 + * @return 移动网络运营商名称 + */ + public static String getNetworkOperatorName(Context context) { + TelephonyManager tm = (TelephonyManager) context + .getSystemService(Context.TELEPHONY_SERVICE); + return tm != null ? tm.getNetworkOperatorName() : null; + } + + /** + * 获取移动终端类型 + * + * @param context 上下文 + * @return 手机制式 + *
    + *
  • PHONE_TYPE_NONE : 0 手机制式未知
  • + *
  • PHONE_TYPE_GSM : 1 手机制式为GSM,移动和联通
  • + *
  • PHONE_TYPE_CDMA : 2 手机制式为CDMA,电信
  • + *
  • PHONE_TYPE_SIP : 3
  • + *
+ */ + public static int getPhoneType(Context context) { + TelephonyManager tm = (TelephonyManager) context + .getSystemService(Context.TELEPHONY_SERVICE); + return tm != null ? tm.getPhoneType() : -1; + } + + + /** + * 获取当前的网络类型(WIFI,2G,3G,4G) + *

需添加权限 android.permission.ACCESS_NETWORK_STATE

+ * + * @param context 上下文 + * @return 网络类型 + *
    + *
  • NETWORK_WIFI = 1;
  • + *
  • NETWORK_4G = 4;
  • + *
  • NETWORK_3G = 3;
  • + *
  • NETWORK_2G = 2;
  • + *
  • NETWORK_UNKNOWN = 5;
  • + *
  • NETWORK_NO = -1;
  • + *
+ */ + public static int getNetWorkType(Context context) { + int netType = NETWORK_NO; + NetworkInfo info = getActiveNetworkInfo(context); + if (info != null && info.isAvailable()) { + + if (info.getType() == ConnectivityManager.TYPE_WIFI) { + netType = NETWORK_WIFI; + } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { + switch (info.getSubtype()) { + + case NETWORK_TYPE_GSM: + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_1xRTT: + case TelephonyManager.NETWORK_TYPE_IDEN: + netType = NETWORK_2G; + break; + + case NETWORK_TYPE_TD_SCDMA: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + case TelephonyManager.NETWORK_TYPE_HSPAP: netType = NETWORK_3G; - } else { - netType = NETWORK_UNKNOWN; - } - break; + break; + + case NETWORK_TYPE_IWLAN: + case TelephonyManager.NETWORK_TYPE_LTE: + netType = NETWORK_4G; + break; + default: + + String subtypeName = info.getSubtypeName(); + if (subtypeName.equalsIgnoreCase("TD-SCDMA") + || subtypeName.equalsIgnoreCase("WCDMA") + || subtypeName.equalsIgnoreCase("CDMA2000")) { + netType = NETWORK_3G; + } else { + netType = NETWORK_UNKNOWN; + } + break; + } + } else { + netType = NETWORK_UNKNOWN; } - } else { - netType = NETWORK_UNKNOWN; } + return netType; } - return netType; -} -/** - * 获取当前的网络类型(WIFI,2G,3G,4G) - * 依赖上面的方法 - * - * @param context - * @return 网络类型名称 - *
    - *
  • NETWORK_WIFI
  • - *
  • NETWORK_4G
  • - *
  • NETWORK_3G
  • - *
  • NETWORK_2G
  • - *
  • NETWORK_UNKNOWN
  • - *
  • NETWORK_NO
  • - *
- */ -public static String getNetWorkTypeName(Context context) { - switch (getNetWorkType(context)) { - case NETWORK_WIFI: - return "NETWORK_WIFI"; - case NETWORK_4G: - return "NETWORK_4G"; - case NETWORK_3G: - return "NETWORK_3G"; - case NETWORK_2G: - return "NETWORK_2G"; - case NETWORK_NO: - return "NETWORK_NO"; - default: - return "NETWORK_UNKNOWN"; + /** + * 获取当前的网络类型(WIFI,2G,3G,4G) + *

依赖上面的方法

+ * + * @param context 上下文 + * @return 网络类型名称 + *
    + *
  • NETWORK_WIFI
  • + *
  • NETWORK_4G
  • + *
  • NETWORK_3G
  • + *
  • NETWORK_2G
  • + *
  • NETWORK_UNKNOWN
  • + *
  • NETWORK_NO
  • + *
+ */ + public static String getNetWorkTypeName(Context context) { + switch (getNetWorkType(context)) { + case NETWORK_WIFI: + return "NETWORK_WIFI"; + case NETWORK_4G: + return "NETWORK_4G"; + case NETWORK_3G: + return "NETWORK_3G"; + case NETWORK_2G: + return "NETWORK_2G"; + case NETWORK_NO: + return "NETWORK_NO"; + default: + return "NETWORK_UNKNOWN"; + } } } ``` diff --git a/md/about_phone.md b/md/about_phone.md index 90f0de0b88e9f356146cc1d58652d887e37f4c88..e7bb09a00673e11ea4a54e6808f5124c7a2171da 100644 --- a/md/about_phone.md +++ b/md/about_phone.md @@ -1,282 +1,312 @@ # 手机相关 -### 判断设备是否是手机 ``` java -/** - * 判断设备是否是手机 - */ -public static boolean isPhone(Context context) { - TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; -} -``` +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.SystemClock; +import android.provider.Settings; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; +import android.util.Xml; + +import org.xmlpull.v1.XmlSerializer; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; -### 获取手机的IMIE -``` java /** - * 获取当前设备的IMIE - *

需与上面的isPhone一起使用 - *

需添加权限 android.permission.READ_PHONE_STATE + *

+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 手机相关的工具类
+ * 
*/ -public static String getPhoneIMEI(Context context) { - String deviceId; - if (isPhone(context)) { +public class PhoneUtils { + + private PhoneUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } + + /** + * 判断设备是否是手机 + * + * @param context 上下文 + * @return true: 是
false: 否 + */ + public static boolean isPhone(Context context) { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - deviceId = tm.getDeviceId(); - } else { - deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); + return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; } - return deviceId; -} -``` -### 获取手机状态信息 -``` java -/** - * 获取手机状态信息 - *

需添加权限 android.permission.READ_PHONE_STATE - *

返回如下 - *

- * DeviceId(IMEI) = 99000311726612
- * DeviceSoftwareVersion = 00
- * Line1Number =
- * NetworkCountryIso = cn
- * NetworkOperator = 46003
- * NetworkOperatorName = 中国电信
- * NetworkType = 6
- * honeType = 2
- * SimCountryIso = cn
- * SimOperator = 46003
- * SimOperatorName = 中国电信
- * SimSerialNumber = 89860315045710604022
- * SimState = 5
- * SubscriberId(IMSI) = 460030419724900
- * VoiceMailNumber = *86
- * 
- */
-public static String getPhoneStatus(Context context) {
-    TelephonyManager tm = (TelephonyManager) context
-            .getSystemService(Context.TELEPHONY_SERVICE);
-    String str = "";
-    str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n";
-    str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
-    str += "Line1Number = " + tm.getLine1Number() + "\n";
-    str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
-    str += "NetworkOperator = " + tm.getNetworkOperator() + "\n";
-    str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n";
-    str += "NetworkType = " + tm.getNetworkType() + "\n";
-    str += "honeType = " + tm.getPhoneType() + "\n";
-    str += "SimCountryIso = " + tm.getSimCountryIso() + "\n";
-    str += "SimOperator = " + tm.getSimOperator() + "\n";
-    str += "SimOperatorName = " + tm.getSimOperatorName() + "\n";
-    str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n";
-    str += "SimState = " + tm.getSimState() + "\n";
-    str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n";
-    str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n";
-    return str;
-}
-```
+    /**
+     * 获取当前设备的IMIE
+     * 

需与上面的isPhone一起使用

+ *

需添加权限 android.permission.READ_PHONE_STATE

+ * + * @param context 上下文 + * @return IMIE码 + */ + public static String getDeviceIMEI(Context context) { + String deviceId; + if (isPhone(context)) { + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + deviceId = tm.getDeviceId(); + } else { + deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); + } + return deviceId; + } -### 跳至填充好phoneNumber的拨号界面 -``` java -/** - * 跳至填充好phoneNumber的拨号界面 - */ -public static void dial(Context context, String phoneNumber) { - context.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber))); -} -``` + /** + * 获取手机状态信息 + *

需添加权限 android.permission.READ_PHONE_STATE

+ * + * @param context 上下文 + * @return DeviceId(IMEI) = 99000311726612
+ * DeviceSoftwareVersion = 00
+ * Line1Number =
+ * NetworkCountryIso = cn
+ * NetworkOperator = 46003
+ * NetworkOperatorName = 中国电信
+ * NetworkType = 6
+ * honeType = 2
+ * SimCountryIso = cn
+ * SimOperator = 46003
+ * SimOperatorName = 中国电信
+ * SimSerialNumber = 89860315045710604022
+ * SimState = 5
+ * SubscriberId(IMSI) = 460030419724900
+ * VoiceMailNumber = *86
+ */ + public static String getPhoneStatus(Context context) { + TelephonyManager tm = (TelephonyManager) context + .getSystemService(Context.TELEPHONY_SERVICE); + String str = ""; + str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n"; + str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n"; + str += "Line1Number = " + tm.getLine1Number() + "\n"; + str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n"; + str += "NetworkOperator = " + tm.getNetworkOperator() + "\n"; + str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n"; + str += "NetworkType = " + tm.getNetworkType() + "\n"; + str += "honeType = " + tm.getPhoneType() + "\n"; + str += "SimCountryIso = " + tm.getSimCountryIso() + "\n"; + str += "SimOperator = " + tm.getSimOperator() + "\n"; + str += "SimOperatorName = " + tm.getSimOperatorName() + "\n"; + str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n"; + str += "SimState = " + tm.getSimState() + "\n"; + str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n"; + str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n"; + return str; + } -### 拨打phoneNumber -``` java -/** - * 拨打phoneNumber - *

需添加权限 android.permission.CALL_PHONE - */ -public static void call(Context context, String phoneNumber) { - context.startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber))); -} -``` + /** + * 跳至填充好phoneNumber的拨号界面 + * + * @param context 上下文 + * @param phoneNumber 电话号码 + */ + public static void dial(Context context, String phoneNumber) { + context.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber))); + } -### 发送短信 -``` java -/** -* 发送短信 -*/ -public static void sendSms(Context context, String phoneNumber, String content) { - Uri uri = Uri.parse("smsto:" + (TextUtils.isEmpty(phoneNumber) ? "" : phoneNumber)); - Intent intent = new Intent(Intent.ACTION_SENDTO, uri); - intent.putExtra("sms_body", TextUtils.isEmpty(content) ? "" : content); - context.startActivity(intent); -} -``` + /** + * 拨打phoneNumber + *

需添加权限 android.permission.CALL_PHONE

+ * + * @param context 上下文 + * @param phoneNumber 电话号码 + */ + public static void call(Context context, String phoneNumber) { + context.startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber))); + } -### 获取手机联系人 -``` java -/** - * 获取手机联系人 - *

需添加权限 android.permission.READ_EXTERNAL_STORAGE - *

需添加权限 android.permission.READ_CONTACTS - */ -public static List> getAllContactInfo(Context context) { - SystemClock.sleep(3000); - ArrayList> list = new ArrayList>(); - // 1.获取内容解析者 - ContentResolver resolver = context.getContentResolver(); - // 2.获取内容提供者的地址:com.android.contacts - // raw_contacts表的地址 :raw_contacts - // view_data表的地址 : data - // 3.生成查询地址 - Uri raw_uri = Uri.parse("content://com.android.contacts/raw_contacts"); - Uri date_uri = Uri.parse("content://com.android.contacts/data"); - // 4.查询操作,先查询raw_contacts,查询contact_id - // projection : 查询的字段 - Cursor cursor = resolver.query(raw_uri, new String[] { "contact_id" }, - null, null, null); - // 5.解析cursor - while (cursor.moveToNext()) { - // 6.获取查询的数据 - String contact_id = cursor.getString(0); - // cursor.getString(cursor.getColumnIndex("contact_id"));//getColumnIndex - // : 查询字段在cursor中索引值,一般都是用在查询字段比较多的时候 - // 判断contact_id是否为空 - if (!TextUtils.isEmpty(contact_id)) {//null "" - // 7.根据contact_id查询view_data表中的数据 - // selection : 查询条件 - // selectionArgs :查询条件的参数 - // sortOrder : 排序 - // 空指针: 1.null.方法 2.参数为null - Cursor c = resolver.query(date_uri, new String[] { "data1", - "mimetype" }, "raw_contact_id=?", - new String[] { contact_id }, null); - HashMap map = new HashMap(); - // 8.解析c - while (c.moveToNext()) { - // 9.获取数据 - String data1 = c.getString(0); - String mimetype = c.getString(1); - // 10.根据类型去判断获取的data1数据并保存 - if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { - // 电话 - map.put("phone", data1); - } else if (mimetype.equals("vnd.android.cursor.item/name")) { - // 姓名 - map.put("name", data1); + /** + * 发送短信 + * + * @param context 上下文 + * @param phoneNumber 电话号码 + * @param content 内容 + */ + public static void sendSms(Context context, String phoneNumber, String content) { + Uri uri = Uri.parse("smsto:" + (TextUtils.isEmpty(phoneNumber) ? "" : phoneNumber)); + Intent intent = new Intent(Intent.ACTION_SENDTO, uri); + intent.putExtra("sms_body", TextUtils.isEmpty(content) ? "" : content); + context.startActivity(intent); + } + + /** + * 获取手机联系人 + *

需添加权限 android.permission.READ_EXTERNAL_STORAGE

+ *

需添加权限 android.permission.READ_CONTACTS

+ * + * @param context 上下文; + * @return 联系人链表 + */ + public static List> getAllContactInfo(Context context) { + SystemClock.sleep(3000); + ArrayList> list = new ArrayList>(); + // 1.获取内容解析者 + ContentResolver resolver = context.getContentResolver(); + // 2.获取内容提供者的地址:com.android.contacts + // raw_contacts表的地址 :raw_contacts + // view_data表的地址 : data + // 3.生成查询地址 + Uri raw_uri = Uri.parse("content://com.android.contacts/raw_contacts"); + Uri date_uri = Uri.parse("content://com.android.contacts/data"); + // 4.查询操作,先查询raw_contacts,查询contact_id + // projection : 查询的字段 + Cursor cursor = resolver.query(raw_uri, new String[]{"contact_id"}, + null, null, null); + // 5.解析cursor + while (cursor.moveToNext()) { + // 6.获取查询的数据 + String contact_id = cursor.getString(0); + // cursor.getString(cursor.getColumnIndex("contact_id"));//getColumnIndex + // : 查询字段在cursor中索引值,一般都是用在查询字段比较多的时候 + // 判断contact_id是否为空 + if (!TextUtils.isEmpty(contact_id)) {//null "" + // 7.根据contact_id查询view_data表中的数据 + // selection : 查询条件 + // selectionArgs :查询条件的参数 + // sortOrder : 排序 + // 空指针: 1.null.方法 2.参数为null + Cursor c = resolver.query(date_uri, new String[]{"data1", + "mimetype"}, "raw_contact_id=?", + new String[]{contact_id}, null); + HashMap map = new HashMap(); + // 8.解析c + while (c.moveToNext()) { + // 9.获取数据 + String data1 = c.getString(0); + String mimetype = c.getString(1); + // 10.根据类型去判断获取的data1数据并保存 + if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { + // 电话 + map.put("phone", data1); + } else if (mimetype.equals("vnd.android.cursor.item/name")) { + // 姓名 + map.put("name", data1); + } } + // 11.添加到集合中数据 + list.add(map); + // 12.关闭cursor + c.close(); } - // 11.添加到集合中数据 - list.add(map); - // 12.关闭cursor - c.close(); } + // 12.关闭cursor + cursor.close(); + return list; } - // 12.关闭cursor - cursor.close(); - return list; -} -``` -### 打开手机联系人界面点击联系人后便获取该号码 -``` java -/** - * 打开手机联系人界面点击联系人后便获取该号码 - *

参照以下注释代码 - */ -public static void getContantNum() { - Log.i("tips", "U should copy the follow code."); - /* - Intent intent = new Intent(); - intent.setAction("android.intent.action.PICK"); - intent.setType("vnd.android.cursor.dir/phone_v2"); - startActivityForResult(intent, 0); - @Override - protected void onActivityResult ( int requestCode, int resultCode, Intent data){ - super.onActivityResult(requestCode, resultCode, data); - if (data != null) { - Uri uri = data.getData(); - String num = null; - // 创建内容解析者 - ContentResolver contentResolver = getContentResolver(); - Cursor cursor = contentResolver.query(uri, - null, null, null, null); - while (cursor.moveToNext()) { - num = cursor.getString(cursor.getColumnIndex("data1")); + /** + * 打开手机联系人界面点击联系人后便获取该号码 + *

参照以下注释代码

+ */ + public static void getContantNum() { + Log.i("tips", "U should copy the following code."); + /* + Intent intent = new Intent(); + intent.setAction("android.intent.action.PICK"); + intent.setType("vnd.android.cursor.dir/phone_v2"); + startActivityForResult(intent, 0); + + @Override + protected void onActivityResult ( int requestCode, int resultCode, Intent data){ + super.onActivityResult(requestCode, resultCode, data); + if (data != null) { + Uri uri = data.getData(); + String num = null; + // 创建内容解析者 + ContentResolver contentResolver = getContentResolver(); + Cursor cursor = contentResolver.query(uri, + null, null, null, null); + while (cursor.moveToNext()) { + num = cursor.getString(cursor.getColumnIndex("data1")); + } + cursor.close(); + num = num.replaceAll("-", "");//替换的操作,555-6 -> 5556 } - cursor.close(); - num = num.replaceAll("-", "");//替换的操作,555-6 -> 5556 } + */ } - */ -} -``` -### 获取手机短信并保存到xml中 -``` java -/** - * 获取手机短信并保存到xml中 - *

需添加权限 android.permission.READ_SMS - *

需添加权限 android.permission.WRITE_EXTERNAL_STORAGE - */ -public static void getAllSMS(Context context) { - //1.获取短信 - //1.1获取内容解析者 - ContentResolver resolver = context.getContentResolver(); - //1.2获取内容提供者地址 sms,sms表的地址:null 不写 - //1.3获取查询路径 - Uri uri = Uri.parse("content://sms"); - //1.4.查询操作 - //projection : 查询的字段 - //selection : 查询的条件 - //selectionArgs : 查询条件的参数 - //sortOrder : 排序 - Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null); - //设置最大进度 - int count = cursor.getCount();//获取短信的个数 - //2.备份短信 - //2.1获取xml序列器 - XmlSerializer xmlSerializer = Xml.newSerializer(); - try { - //2.2设置xml文件保存的路径 - //os : 保存的位置 - //encoding : 编码格式 - xmlSerializer.setOutput(new FileOutputStream(new File("/mnt/sdcard/backupsms.xml")), "utf-8"); - //2.3设置头信息 - //standalone : 是否独立保存 - xmlSerializer.startDocument("utf-8", true); - //2.4设置根标签 - xmlSerializer.startTag(null, "smss"); - //1.5.解析cursor - while (cursor.moveToNext()) { - SystemClock.sleep(1000); - //2.5设置短信的标签 - xmlSerializer.startTag(null, "sms"); - //2.6设置文本内容的标签 - xmlSerializer.startTag(null, "address"); - String address = cursor.getString(0); - //2.7设置文本内容 - xmlSerializer.text(address); - xmlSerializer.endTag(null, "address"); - xmlSerializer.startTag(null, "date"); - String date = cursor.getString(1); - xmlSerializer.text(date); - xmlSerializer.endTag(null, "date"); - xmlSerializer.startTag(null, "type"); - String type = cursor.getString(2); - xmlSerializer.text(type); - xmlSerializer.endTag(null, "type"); - xmlSerializer.startTag(null, "body"); - String body = cursor.getString(3); - xmlSerializer.text(body); - xmlSerializer.endTag(null, "body"); - xmlSerializer.endTag(null, "sms"); - System.out.println("address:" + address + " date:" + date + " type:" + type + " body:" + body); + /** + * 获取手机短信并保存到xml中 + *

需添加权限 android.permission.READ_SMS

+ *

需添加权限 android.permission.WRITE_EXTERNAL_STORAGE

+ * + * @param context 上下文 + */ + public static void getAllSMS(Context context) { + // 1.获取短信 + // 1.1获取内容解析者 + ContentResolver resolver = context.getContentResolver(); + // 1.2获取内容提供者地址 sms,sms表的地址:null 不写 + // 1.3获取查询路径 + Uri uri = Uri.parse("content://sms"); + // 1.4.查询操作 + // projection : 查询的字段 + // selection : 查询的条件 + // selectionArgs : 查询条件的参数 + // sortOrder : 排序 + Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null); + // 设置最大进度 + int count = cursor.getCount();//获取短信的个数 + // 2.备份短信 + // 2.1获取xml序列器 + XmlSerializer xmlSerializer = Xml.newSerializer(); + try { + // 2.2设置xml文件保存的路径 + // os : 保存的位置 + // encoding : 编码格式 + xmlSerializer.setOutput(new FileOutputStream(new File("/mnt/sdcard/backupsms.xml")), "utf-8"); + // 2.3设置头信息 + // standalone : 是否独立保存 + xmlSerializer.startDocument("utf-8", true); + // 2.4设置根标签 + xmlSerializer.startTag(null, "smss"); + // 1.5.解析cursor + while (cursor.moveToNext()) { + SystemClock.sleep(1000); + // 2.5设置短信的标签 + xmlSerializer.startTag(null, "sms"); + // 2.6设置文本内容的标签 + xmlSerializer.startTag(null, "address"); + String address = cursor.getString(0); + // 2.7设置文本内容 + xmlSerializer.text(address); + xmlSerializer.endTag(null, "address"); + xmlSerializer.startTag(null, "date"); + String date = cursor.getString(1); + xmlSerializer.text(date); + xmlSerializer.endTag(null, "date"); + xmlSerializer.startTag(null, "type"); + String type = cursor.getString(2); + xmlSerializer.text(type); + xmlSerializer.endTag(null, "type"); + xmlSerializer.startTag(null, "body"); + String body = cursor.getString(3); + xmlSerializer.text(body); + xmlSerializer.endTag(null, "body"); + xmlSerializer.endTag(null, "sms"); + System.out.println("address:" + address + " date:" + date + " type:" + type + " body:" + body); + } + xmlSerializer.endTag(null, "smss"); + xmlSerializer.endDocument(); + // 2.8将数据刷新到文件中 + xmlSerializer.flush(); + } catch (Exception e) { + e.printStackTrace(); } - xmlSerializer.endTag(null, "smss"); - xmlSerializer.endDocument(); - //2.8将数据刷新到文件中 - xmlSerializer.flush(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); } } ``` diff --git a/md/about_regular.md b/md/about_regular.md index 9a5d0dbe3ecf75303787033182a5c285a001bf3d..2e9bea529aa61349966219d61e399ad3a303d649 100644 --- a/md/about_regular.md +++ b/md/about_regular.md @@ -1,15 +1,17 @@ # 正则相关 -### 正则工具类 ``` java import android.text.TextUtils; import java.util.regex.Pattern; -/********************************************* - * author: Blankj on 2016/8/2 21:19 - * blog: http://blankj.com - * e-mail: blankj@qq.com - *********************************************/ +/** + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 正则相关的工具类
+ * 
+ */ public class RegularUtils { private RegularUtils() { @@ -22,7 +24,7 @@ public class RegularUtils { private static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$"; /** * 验证手机号(精确) - *

+ *

*

移动:134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188 *

联通:130、131、132、145、155、156、175、176、185、186 *

电信:133、153、173、177、180、181、189 diff --git a/md/about_screen.md b/md/about_screen.md index 2b97a76ec78e7cbe0e229df6a2dacbfaceeec0ca..da88681fee985ee9419f836f98270733592ec166 100644 --- a/md/about_screen.md +++ b/md/about_screen.md @@ -1,217 +1,238 @@ # 屏幕相关 -### 获取手机分辨率 ``` java -/** -* 获取屏幕的宽度px -*/ -public static int getDeviceWidth(Context context) { - WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 - windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 - return outMetrics.widthPixels; -} +import android.app.Activity; +import android.app.KeyguardManager; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.graphics.Bitmap; +import android.os.Build; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; -/** -* 获取屏幕的高度px -*/ -public static int getDeviceHeight(Context context) { - WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 - windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 - return outMetrics.heightPixels; -} -``` +import java.lang.reflect.Method; -### 设置透明状态栏(api >= 19方可使用) -``` java /** - * 设置透明状态栏(api >= 19方可使用) - *

可在Activity的onCreat()中调用 - *

需在顶部控件布局中加入以下属性让内容出现在状态栏之下 - *

android:clipToPadding="true" - *

android:fitsSystemWindows="true" + *

+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 屏幕相关的工具类
+ * 
*/ -public static void setTransparentStatusBar(Activity activity) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - //透明状态栏 - activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS); - //透明导航栏 - activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); +public class ScreenUtils { + + private ScreenUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); } -} -``` -### 隐藏状态栏 -``` java -/** - * 隐藏状态栏 - *

也就是设置全屏,一定要在setContentView之前调用,否则报错 - *

此方法Activity可以继承AppCompatActivity - *

启动的时候状态栏会显示一下再隐藏,比如QQ的欢迎界面 - *

在配置文件中Activity加属性android:theme="@android:style/Theme.NoTitleBar.Fullscreen" - *

如加了以上配置Activity不能继承AppCompatActivity,会报错 - */ -public static void hideStatusBar(Activity activity) { - activity.requestWindowFeature(Window.FEATURE_NO_TITLE); - activity.getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, - LayoutParams.FLAG_FULLSCREEN); -} -``` + /** + * 获取屏幕的宽度px + * + * @param context 上下文 + * @return 屏幕宽px + */ + public static int getScreenWidth(Context context) { + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 + windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 + return outMetrics.widthPixels; + } -### 获取状态栏高度 -``` java -/** - * 获取状态栏高度 - */ -public static int getStatusBarHeight(Context context) { - int result = 0; - int resourceId = context.getResources() - .getIdentifier("status_bar_height", "dimen", "android"); - if (resourceId > 0) { - result = context.getResources().getDimensionPixelSize(resourceId); + /** + * 获取屏幕的高度px + * + * @param context 上下文 + * @return 屏幕高px + */ + public static int getScreenHeight(Context context) { + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 + windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 + return outMetrics.heightPixels; } - return result; -} -``` -### 判断状态栏是否存在 -``` java -/** -* 判断状态栏是否存在 -* -* @param activity -* @return

    -*
  • true: 存在
  • -*
  • false: 不存在
  • -*
-*/ -public static boolean isStatusBarExists(Activity activity) { - WindowManager.LayoutParams params = activity.getWindow().getAttributes(); - return (params.flags & LayoutParams.FLAG_FULLSCREEN) != LayoutParams.FLAG_FULLSCREEN; -} -``` + /** + * 设置透明状态栏(api大于19方可使用) + *

可在Activity的onCreat()中调用

+ *

需在顶部控件布局中加入以下属性让内容出现在状态栏之下

+ *

android:clipToPadding="true"

+ *

android:fitsSystemWindows="true"

+ * + * @param activity activity + */ + public static void setTransparentStatusBar(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + //透明状态栏 + activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS); + //透明导航栏 + activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); + } + } -### 获取ActionBar高度 -``` java -/** - * 获取ActionBar高度 - */ -public static int getActionBarHeight(Activity activity) { - TypedValue tv = new TypedValue(); - if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { - return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics()); + /** + * 隐藏状态栏 + *

也就是设置全屏,一定要在setContentView之前调用,否则报错

+ *

此方法Activity可以继承AppCompatActivity

+ *

启动的时候状态栏会显示一下再隐藏,比如QQ的欢迎界面

+ *

在配置文件中Activity加属性android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

+ *

如加了以上配置Activity不能继承AppCompatActivity,会报错

+ * + * @param activity activity + */ + public static void hideStatusBar(Activity activity) { + activity.requestWindowFeature(Window.FEATURE_NO_TITLE); + activity.getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, + LayoutParams.FLAG_FULLSCREEN); } - return 0; -} -``` -### 显示通知栏 -``` java -/** - * 显示通知栏 - * 需添加权限 android.permission.EXPAND_STATUS_BAR - * - * @param isSettingPanel true,打开设置,false 打开通知 - */ -public static void showNotificationBar(Context context, boolean isSettingPanel) { - String methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" - : (isSettingPanel ? "expandSettingsPanel" : "expandNotificationsPanel"); - invokePanels(context, methodName); -} -``` + /** + * 获取状态栏高度 + * + * @param context 上下文 + * @return 状态栏高度 + */ + public static int getStatusBarHeight(Context context) { + int result = 0; + int resourceId = context.getResources() + .getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + result = context.getResources().getDimensionPixelSize(resourceId); + } + return result; + } -### 隐藏通知栏 -``` java -/** - * 隐藏通知栏 - * 需添加权限 android.permission.EXPAND_STATUS_BAR - */ -public static void hideNotificationBar(Context context) { - String methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels"; - invokePanels(context, methodName); -} -``` + /** + * 判断状态栏是否存在 + * + * @param activity activity + * @return true: 存在
false: 不存在 + */ + public static boolean isStatusBarExists(Activity activity) { + LayoutParams params = activity.getWindow().getAttributes(); + return (params.flags & LayoutParams.FLAG_FULLSCREEN) != LayoutParams.FLAG_FULLSCREEN; + } -### 设置屏幕为横屏 -``` -/** - * 设置屏幕为横屏 - *

还有一种就是在Activity中加属性android:screenOrientation="landscape" - *

不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次 - *

设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次 - *

设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时 - * 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法 - */ -public static void setLandscape(Activity activity) { - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); -} -``` + /** + * 获取ActionBar高度 + * + * @param activity activity + * @return ActionBar高度 + */ + public static int getActionBarHeight(Activity activity) { + TypedValue tv = new TypedValue(); + if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { + return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics()); + } + return 0; + } -### 获取当前屏幕截图 -``` java -/** - * 获取当前屏幕截图,包含状态栏 - */ -public static Bitmap captureWithStatusBar(Activity activity) { - View view = activity.getWindow().getDecorView(); - view.setDrawingCacheEnabled(true); - view.buildDrawingCache(); - Bitmap bmp = view.getDrawingCache(); - int width = getScreenWidth(activity); - int height = getScreenHeight(activity); - Bitmap bp = Bitmap.createBitmap(bmp, 0, 0, width, height); - view.destroyDrawingCache(); - return bp; -} + /** + * 显示通知栏 + *

需添加权限 android.permission.EXPAND_STATUS_BAR

+ * + * @param context 上下文 + * @param isSettingPanel true: 打开设置
false: 打开通知 + */ + public static void showNotificationBar(Context context, boolean isSettingPanel) { + String methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" + : (isSettingPanel ? "expandSettingsPanel" : "expandNotificationsPanel"); + invokePanels(context, methodName); + } -/** - * 获取当前屏幕截图,不包含状态栏 - *

需要用到上面获取状态栏高度的方法 - */ -public static Bitmap captureWithoutStatusBar(Activity activity) { - View view = activity.getWindow().getDecorView(); - view.setDrawingCacheEnabled(true); - view.buildDrawingCache(); - Bitmap bmp = view.getDrawingCache(); - int statusBarHeight = getStatusBarHeight(activity); - int width = getScreenWidth(activity); - int height = getScreenHeight(activity); - Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); - view.destroyDrawingCache(); - return bp; -} -``` + /** + * 隐藏通知栏 + *

需添加权限 android.permission.EXPAND_STATUS_BAR

+ * + * @param context 上下文 + */ + public static void hideNotificationBar(Context context) { + String methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels"; + invokePanels(context, methodName); + } -### 判断是否锁屏 -``` java -/** - * 判断是否锁屏 - */ -public static boolean isScreenLock(Context context) { - KeyguardManager km = (KeyguardManager) context - .getSystemService(Context.KEYGUARD_SERVICE); - return km.inKeyguardRestrictedInputMode(); -} -``` + /** + * 反射唤醒通知栏 + * + * @param context 上下文 + * @param methodName 方法名 + */ + private static void invokePanels(Context context, String methodName) { + try { + Object service = context.getSystemService("statusbar"); + Class statusBarManager = Class.forName("android.app.StatusBarManager"); + Method expand = statusBarManager.getMethod(methodName); + expand.invoke(service); + } catch (Exception e) { + e.printStackTrace(); + } + } -*** -# 尺寸相关 -### dp与px转换 -``` java -/** -* dp转px -*/ -public static int dp2px(Context context, float dpValue) { - final float scale = context.getResources().getDisplayMetrics().density; - return (int) (dpValue * scale + 0.5f); -} + /** + * 设置屏幕为横屏 + *

还有一种就是在Activity中加属性android:screenOrientation="landscape"

+ *

不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

+ *

设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

+ *

设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时 + * 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

+ * + * @param activity activity + */ + public static void setLandscape(Activity activity) { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } -/** -* px转dp -*/ -public static int px2dp(Context context, float pxValue) { - final float scale = context.getResources().getDisplayMetrics().density; - return (int) (pxValue / scale + 0.5f); + /** + * 获取当前屏幕截图,包含状态栏 + * + * @param activity activity + * @return Bitmap + */ + public static Bitmap captureWithStatusBar(Activity activity) { + View view = activity.getWindow().getDecorView(); + view.setDrawingCacheEnabled(true); + view.buildDrawingCache(); + Bitmap bmp = view.getDrawingCache(); + int width = getScreenWidth(activity); + int height = getScreenHeight(activity); + Bitmap bp = Bitmap.createBitmap(bmp, 0, 0, width, height); + view.destroyDrawingCache(); + return bp; + } + + /** + * 获取当前屏幕截图,不包含状态栏 + *

需要用到上面获取状态栏高度getStatusBarHeight的方法

+ * + * @param activity activity + * @return Bitmap + */ + public static Bitmap captureWithoutStatusBar(Activity activity) { + View view = activity.getWindow().getDecorView(); + view.setDrawingCacheEnabled(true); + view.buildDrawingCache(); + Bitmap bmp = view.getDrawingCache(); + int statusBarHeight = getStatusBarHeight(activity); + int width = getScreenWidth(activity); + int height = getScreenHeight(activity); + Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); + view.destroyDrawingCache(); + return bp; + } + + /** + * 判断是否锁屏 + * + * @param context 上下文 + * @return true: 是
false: 否 + */ + public static boolean isScreenLock(Context context) { + KeyguardManager km = (KeyguardManager) context + .getSystemService(Context.KEYGUARD_SERVICE); + return km.inKeyguardRestrictedInputMode(); + } } -``` - \ No newline at end of file +``` \ No newline at end of file diff --git a/md/about_shell.md b/md/about_shell.md new file mode 100644 index 0000000000000000000000000000000000000000..c0e22cf2ac27f4edeaf24c98b725bb6245e69b26 --- /dev/null +++ b/md/about_shell.md @@ -0,0 +1,193 @@ +# Shell相关 +``` java +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; + +/** + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/7
+ *     desc  : Shell操作工具类
+ * 
+ */ +public class ShellUtils { + + private ShellUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } + + public static final String COMMAND_SU = "su"; + public static final String COMMAND_SH = "sh"; + public static final String COMMAND_EXIT = "exit\n"; + public static final String COMMAND_LINE_END = "\n"; + + /** + * 判断设备是否root + */ + public static boolean isRoot() { + return execCmd("echo root", true, false).result == 0; + } + + /** + * 是否是在root下执行命令 + * + * @param command 命令 + * @param isRoot 是否root + * @return CommandResult + */ + public static CommandResult execCmd(String command, boolean isRoot) { + return execCmd(new String[]{command}, isRoot, true); + } + + /** + * 是否是在root下执行命令 + * + * @param commands 多条命令链表 + * @param isRoot 是否root + * @return CommandResult + */ + public static CommandResult execCmd(List commands, boolean isRoot) { + return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, true); + } + + /** + * 是否是在root下执行命令 + * + * @param commands 多条命令数组 + * @param isRoot 是否root + * @return CommandResult + */ + public static CommandResult execCmd(String[] commands, boolean isRoot) { + return execCmd(commands, isRoot, true); + } + + /** + * 是否是在root下执行命令 + * + * @param command 命令 + * @param isRoot 是否root + * @param isNeedResultMsg 是否需要结果消息 + * @return CommandResult + */ + public static CommandResult execCmd(String command, boolean isRoot, boolean isNeedResultMsg) { + return execCmd(new String[]{command}, isRoot, isNeedResultMsg); + } + + /** + * 是否是在root下执行命令 + * + * @param commands 命令链表 + * @param isRoot 是否root + * @param isNeedResultMsg 是否需要结果消息 + * @return CommandResult + */ + public static CommandResult execCmd(List commands, boolean isRoot, boolean isNeedResultMsg) { + return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg); + } + + /** + * 是否是在root下执行命令 + * + * @param commands 命令数组 + * @param isRoot 是否root + * @param isNeedResultMsg 是否需要结果消息 + * @return CommandResult + */ + public static CommandResult execCmd(String[] commands, boolean isRoot, boolean isNeedResultMsg) { + int result = -1; + if (commands == null || commands.length == 0) { + return new CommandResult(result, null, null); + } + Process process = null; + BufferedReader successResult = null; + BufferedReader errorResult = null; + StringBuilder successMsg = null; + StringBuilder errorMsg = null; + DataOutputStream os = null; + try { + process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); + os = new DataOutputStream(process.getOutputStream()); + for (String command : commands) { + if (command == null) { + continue; + } + os.write(command.getBytes()); + os.writeBytes(COMMAND_LINE_END); + os.flush(); + } + os.writeBytes(COMMAND_EXIT); + os.flush(); + + result = process.waitFor(); + if (isNeedResultMsg) { + successMsg = new StringBuilder(); + errorMsg = new StringBuilder(); + successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String s; + while ((s = successResult.readLine()) != null) { + successMsg.append(s); + } + while ((s = errorResult.readLine()) != null) { + errorMsg.append(s); + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (os != null) { + os.close(); + } + if (successResult != null) { + successResult.close(); + } + if (errorResult != null) { + errorResult.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + if (process != null) { + process.destroy(); + } + } + return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null + : errorMsg.toString()); + } + + /** + * 返回的命令结果 + */ + public static class CommandResult { + + /** + * 结果码 + **/ + public int result; + /** + * 成功的信息 + **/ + public String successMsg; + /** + * 错误信息 + **/ + public String errorMsg; + + public CommandResult(int result) { + this.result = result; + } + + public CommandResult(int result, String successMsg, String errorMsg) { + this.result = result; + this.successMsg = successMsg; + this.errorMsg = errorMsg; + } + } +} +``` \ No newline at end of file diff --git a/md/about_size.md b/md/about_size.md index 17d3fc0400e7d9f25a79954199a4d62e0f8c5d76..246c71e5158f45a6754dce80a30924bdcb383abb 100644 --- a/md/about_size.md +++ b/md/about_size.md @@ -1,131 +1,166 @@ # 尺寸相关 -### dp与px转换 ``` java -/** -* dp转px -*/ -public static int dp2px(Context context, float dpValue) { - final float scale = context.getResources().getDisplayMetrics().density; - return (int) (dpValue * scale + 0.5f); -} +import android.content.Context; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; /** -* px转dp -*/ -public static int px2dp(Context context, float pxValue) { - final float scale = context.getResources().getDisplayMetrics().density; - return (int) (pxValue / scale + 0.5f); -} -``` - -### sp与px转换 -``` java -/** -* sp转px -*/ -public static int sp2px(Context context, float spValue) { - final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; - return (int) (spValue * fontScale + 0.5f); -} + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 尺寸相关的工具类
+ * 
+ */ +public class SizeUtils { -/** -* px转sp -*/ -public static int px2sp(Context context, float pxValue) { - final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; - return (int) (pxValue / fontScale + 0.5f); -} -``` + private SizeUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } -### 各种单位转换 -``` java -/** - * 各种单位转换 - *

该方法存在于TypedValue - */ -public static float applyDimension(int unit, float value, DisplayMetrics metrics) { - switch (unit) { - case TypedValue.COMPLEX_UNIT_PX: - return value; - case TypedValue.COMPLEX_UNIT_DIP: - return value * metrics.density; - case TypedValue.COMPLEX_UNIT_SP: - return value * metrics.scaledDensity; - case TypedValue.COMPLEX_UNIT_PT: - return value * metrics.xdpi * (1.0f / 72); - case TypedValue.COMPLEX_UNIT_IN: - return value * metrics.xdpi; - case TypedValue.COMPLEX_UNIT_MM: - return value * metrics.xdpi * (1.0f / 25.4f); + /** + * dp转px + * + * @param context 上下文 + * @param dpValue dp值 + * @return px值 + */ + public static int dp2px(Context context, float dpValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); } - return 0; -} -``` -### 在onCreate()即可强行获取View的尺寸 -``` java -/** -* 在onCreate()即可强行获取View的尺寸 -*

需回调onGetSizeListener接口,在onGetSize中获取view宽高 -* 用法示例如下所示 -* SizeUtils.forceGetViewSize(view); -* SizeUtils.setListener(new SizeUtils.onGetSizeListener() { - * @Override - * public void onGetSize(View view) { - * Log.d("tag", view.getWidth() + " " + view.getHeight()); - * } -* }); -*/ -public static void forceGetViewSize(final View view) { - view.post(new Runnable() { - @Override - public void run() { - if (mListener != null) { - mListener.onGetSize(view); - } - } - }); -} + /** + * px转dp + * + * @param context 上下文 + * @param pxValue px值 + * @return dp值 + */ + public static int px2dp(Context context, float pxValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (pxValue / scale + 0.5f); + } -/** -* 获取到View尺寸的监听 -*/ -public interface onGetSizeListener { - void onGetSize(View view); -} + /** + * sp转px + * + * @param context 上下文 + * @param spValue sp值 + * @return px值 + */ + public static int sp2px(Context context, float spValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } -public static void setListener(onGetSizeListener listener) { - mListener = listener; -} + /** + * px转sp + * + * @param context 上下文 + * @param pxValue px值 + * @return sp值 + */ + public static int px2sp(Context context, float pxValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (pxValue / fontScale + 0.5f); + } -private static onGetSizeListener mListener; -``` + /** + * 各种单位转换 + *

该方法存在于TypedValue

+ * + * @param unit 单位 + * @param value 值 + * @param metrics DisplayMetrics + * @return 转换结果 + */ + public static float applyDimension(int unit, float value, DisplayMetrics metrics) { + switch (unit) { + case TypedValue.COMPLEX_UNIT_PX: + return value; + case TypedValue.COMPLEX_UNIT_DIP: + return value * metrics.density; + case TypedValue.COMPLEX_UNIT_SP: + return value * metrics.scaledDensity; + case TypedValue.COMPLEX_UNIT_PT: + return value * metrics.xdpi * (1.0f / 72); + case TypedValue.COMPLEX_UNIT_IN: + return value * metrics.xdpi; + case TypedValue.COMPLEX_UNIT_MM: + return value * metrics.xdpi * (1.0f / 25.4f); + } + return 0; + } -### ListView中提前测量View尺寸 -``` java -/** - * ListView中提前测量View尺寸,如headerView - *

用的时候去掉注释拷贝到ListView中即可 - *

参照以下注释代码 - */ -public static void measureViewInLV(View view) { - Log.i("tips", "U should copy the follow code."); - /* - ViewGroup.LayoutParams p = view.getLayoutParams(); - if (p == null) { - p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); + /** + * 在onCreate()即可强行获取View的尺寸 + *

需回调onGetSizeListener接口,在onGetSize中获取view宽高

+ *

用法示例如下所示

+ *
+     * SizeUtils.forceGetViewSize(view);
+     * SizeUtils.setListener(new SizeUtils.onGetSizeListener() {
+     *     
@Override + * public void onGetSize(View view) { + * Log.d("tag", view.getWidth() + " " + view.getHeight()); + * } + * }); + *
+ * + * @param view 视图 + */ + public static void forceGetViewSize(final View view) { + view.post(new Runnable() { + @Override + public void run() { + if (mListener != null) { + mListener.onGetSize(view); + } + } + }); + } + + /** + * 获取到View尺寸的监听 + */ + public interface onGetSizeListener { + void onGetSize(View view); + } + + public static void setListener(onGetSizeListener listener) { + mListener = listener; } - int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); - int height; - int tempHeight = p.height; - if (tempHeight > 0) { - height = MeasureSpec.makeMeasureSpec(tempHeight, - MeasureSpec.EXACTLY); - } else { - height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + + private static onGetSizeListener mListener; + + /** + * ListView中提前测量View尺寸,如headerView + *

用的时候去掉注释拷贝到ListView中即可

+ *

参照以下注释代码

+ * + * @param view 视图 + */ + public static void measureViewInLV(View view) { + Log.i("tips", "U should copy the following code."); + /* + ViewGroup.LayoutParams p = view.getLayoutParams(); + if (p == null) { + p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + } + int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); + int height; + int tempHeight = p.height; + if (tempHeight > 0) { + height = MeasureSpec.makeMeasureSpec(tempHeight, + MeasureSpec.EXACTLY); + } else { + height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + } + view.measure(width, height); + */ } - view.measure(width, height); - */ } -``` +``` \ No newline at end of file diff --git a/md/about_sp.md b/md/about_sp.md new file mode 100644 index 0000000000000000000000000000000000000000..7ebbc4987f7fa1babcac69c611baef53963ed290 --- /dev/null +++ b/md/about_sp.md @@ -0,0 +1,211 @@ +# SP相关 +``` java +import android.content.Context; +import android.content.SharedPreferences; + +/** + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : SP读写工具类
+ * 
+ */ +public class SPUtils { + + private SPUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } + + /** + * SP的name值 + *

可通过修改PREFERENCE_NAME变量修改SP的name值

+ */ + public static String PREFERENCE_NAME = "ANCROID_UTIL_CODE"; + + /** + * SP中写入String类型value + * + * @param context 上下文 + * @param key 键 + * @param value 值 + * @return true: 写入成功
false: 写入失败 + */ + public static boolean putString(Context context, String key, String value) { + return getSP(context).edit().putString(key, value).commit(); + } + + /** + * SP中读取String + * + * @param context 上下文 + * @param key 键 + * @return 存在返回对应值,不存在返回默认值null + */ + public static String getString(Context context, String key) { + return getString(context, key, null); + } + + /** + * SP中读取String + * + * @param context 上下文 + * @param key 键 + * @param defaultValue 默认值 + * @return 存在返回对应值,不存在返回默认值defaultValue + */ + public static String getString(Context context, String key, String defaultValue) { + return getSP(context).getString(key, defaultValue); + } + + /** + * SP中写入int类型value + * + * @param context 上下文 + * @param key 键 + * @param value 值 + * @return true: 写入成功
false: 写入失败 + */ + public static boolean putInt(Context context, String key, int value) { + return getSP(context).edit().putInt(key, value).commit(); + } + + /** + * SP中读取int + * + * @param context 上下文 + * @param key 键 + * @return 存在返回对应值,不存在返回默认值-1 + */ + public static int getInt(Context context, String key) { + return getInt(context, key, -1); + } + + /** + * SP中读取int + * + * @param context 上下文 + * @param key 键 + * @param defaultValue 默认值 + * @return 存在返回对应值,不存在返回默认值defaultValue + */ + public static int getInt(Context context, String key, int defaultValue) { + return getSP(context).getInt(key, defaultValue); + } + + /** + * SP中写入long类型value + * + * @param context 上下文 + * @param key 键 + * @param value 值 + * @return true: 写入成功
false: 写入失败 + */ + public static boolean putLong(Context context, String key, long value) { + return getSP(context).edit().putLong(key, value).commit(); + } + + /** + * SP中读取long + * + * @param context 上下文 + * @param key 键 + * @return 存在返回对应值,不存在返回默认值-1 + */ + public static long getLong(Context context, String key) { + return getLong(context, key, -1); + } + + /** + * SP中读取long + * + * @param context 上下文 + * @param key 键 + * @param defaultValue 默认值 + * @return 存在返回对应值,不存在返回默认值defaultValue + */ + public static long getLong(Context context, String key, long defaultValue) { + return getSP(context).getLong(key, defaultValue); + } + + /** + * SP中写入float类型value + * + * @param context 上下文 + * @param key 键 + * @param value 值 + * @return true: 写入成功
false: 写入失败 + */ + public static boolean putFloat(Context context, String key, float value) { + return getSP(context).edit().putFloat(key, value).commit(); + } + + /** + * SP中读取float + * + * @param context 上下文 + * @param key 键 + * @return 存在返回对应值,不存在返回默认值-1 + */ + public static float getFloat(Context context, String key) { + return getFloat(context, key, -1); + } + + /** + * SP中读取float + * + * @param context 上下文 + * @param key 键 + * @param defaultValue 默认值 + * @return 存在返回对应值,不存在返回默认值defaultValue + */ + public static float getFloat(Context context, String key, float defaultValue) { + return getSP(context).getFloat(key, defaultValue); + } + + /** + * SP中写入boolean类型value + * + * @param context 上下文 + * @param key 键 + * @param value 值 + * @return true: 写入成功
false: 写入失败 + */ + public static boolean putBoolean(Context context, String key, boolean value) { + return getSP(context).edit().putBoolean(key, value).commit(); + } + + /** + * SP中读取boolean + * + * @param context 上下文 + * @param key 键 + * @return 存在返回对应值,不存在返回默认值false + */ + public static boolean getBoolean(Context context, String key) { + return getBoolean(context, key, false); + } + + /** + * SP中读取boolean + * + * @param context 上下文 + * @param key 键 + * @param defaultValue 默认值 + * @return 存在返回对应值,不存在返回默认值defaultValue + */ + public static boolean getBoolean(Context context, String key, boolean defaultValue) { + return getSP(context).getBoolean(key, defaultValue); + } + + /** + * 获取name为PREFERENCE_NAME的SP对象 + * + * @param context 上下文 + * @return SP + */ + private static SharedPreferences getSP(Context context) { + return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); + } +} +``` \ No newline at end of file diff --git a/md/about_time.md b/md/about_time.md index e1d7c95253414d007938d2459875b94bc1874467..ce287b35eacedbaec4351d5c65ff1ba3ca64e7d1 100644 --- a/md/about_time.md +++ b/md/about_time.md @@ -1,265 +1,481 @@ # 时间相关 -### 将时间戳转为时间字符串 ``` java -/** - * 将时间戳转为时间字符串 - *

格式为yyyy-MM-dd HH:mm:ss - */ -public static String milliseconds2String(long milliseconds) { - return milliseconds2String(milliseconds, DEFAULT_SDF); -} +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; /** - * 将时间戳转为时间字符串 - *

格式为用户自定义 - */ -public static String milliseconds2String(long milliseconds, SimpleDateFormat format) { - return format.format(new Date(milliseconds)); -} -``` - -### 将时间字符串转为时间戳 -``` java -/** - * 将时间字符串转为时间戳 - *

格式为yyyy-MM-dd HH:mm:ss + *

+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 时间相关的工具类
+ * 
*/ -public static long string2Milliseconds(String time) { - return string2Milliseconds(time, DEFAULT_SDF); -} +public class TimeUtils { -/** - * 将时间字符串转为时间戳 - *

格式为用户自定义 - */ -public static long string2Milliseconds(String time, SimpleDateFormat format) { - try { - return format.parse(time).getTime(); - } catch (ParseException e) { - e.printStackTrace(); + private TimeUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); } - return -1; -} -``` -### 将时间字符串转为Date类型 -``` java -/** - * 将时间字符串转为Date类型 - *

格式为yyyy-MM-dd HH:mm:ss - */ -public static Date string2Date(String formatDate) { - return string2Date(formatDate, DEFAULT_SDF); -} + /** + *

在工具类中经常使用到工具类的格式化描述,这个主要是一个日期的操作类,所以日志格式主要使用 SimpleDateFormat的定义格式.

+ * 格式的意义如下: 日期和时间模式
+ *

日期和时间格式由日期和时间模式字符串指定。在日期和时间模式字符串中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z' + * 被解释为模式字母,用来表示日期或时间字符串元素。文本可以使用单引号 (') 引起来,以免进行解释。"''" + * 表示单引号。所有其他字符均不解释;只是在格式化时将它们简单复制到输出字符串,或者在分析时与输入字符串进行匹配。 + *

+ * 定义了以下模式字母(所有其他字符 'A' 到 'Z' 和 'a' 到 'z' 都被保留):
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
字母日期或时间元素表示示例
GEra 标志符TextAD
y Year 1996; 96
M 年中的月份 Month July; Jul; 07
w 年中的周数 Number 27
W 月份中的周数 Number 2
D 年中的天数 Number 189
d 月份中的天数 Number 10
F 月份中的星期 Number 2
E 星期中的天数 Text Tuesday; Tue
a Am/pm 标记 Text PM
H 一天中的小时数(0-23) Number 0
k 一天中的小时数(1-24) Number 24
K am/pm 中的小时数(0-11) Number 0
h am/pm 中的小时数(1-12) Number 12
m 小时中的分钟数 Number 30
s 分钟中的秒数 Number 55
S 毫秒数 Number 978
z 时区 General time zone Pacific Standard Time; PST; GMT-08:00
Z 时区 RFC 822 time zone -0800
+ *
+     *                     yyyy-MM-dd 1969-12-31
+     *                     yyyy-MM-dd 1970-01-01
+     *               yyyy-MM-dd HH:mm 1969-12-31 16:00
+     *               yyyy-MM-dd HH:mm 1970-01-01 00:00
+     *              yyyy-MM-dd HH:mmZ 1969-12-31 16:00-0800
+     *              yyyy-MM-dd HH:mmZ 1970-01-01 00:00+0000
+     *       yyyy-MM-dd HH:mm:ss.SSSZ 1969-12-31 16:00:00.000-0800
+     *       yyyy-MM-dd HH:mm:ss.SSSZ 1970-01-01 00:00:00.000+0000
+     *     yyyy-MM-dd'T'HH:mm:ss.SSSZ 1969-12-31T16:00:00.000-0800
+     *     yyyy-MM-dd'T'HH:mm:ss.SSSZ 1970-01-01T00:00:00.000+0000
+     * 
+ */ + public static final SimpleDateFormat DEFAULT_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + /** + * 各时间单位与毫秒的倍数 + */ + public static final int UNIT_MSEC = 1; + public static final int UNIT_SEC = 1000; + public static final int UNIT_MIN = 60000; + public static final int UNIT_HOUR = 3600000; + public static final int UNIT_DAY = 86400000; -/** - * 将时间字符串转为Date类型 - *

格式为用户自定义 - */ -public static Date string2Date(String formatDate, SimpleDateFormat format) { - return new Date(string2Milliseconds(formatDate, format)); -} -``` + /** + * 将时间戳转为时间字符串 + *

格式为yyyy-MM-dd HH:mm:ss

+ * + * @param milliseconds 毫秒时间戳 + * @return 时间字符串 + */ + public static String milliseconds2String(long milliseconds) { + return milliseconds2String(milliseconds, DEFAULT_SDF); + } -### 将Date类型转为时间字符串 -``` java -/** - * 将Date类型转为时间字符串 - *

格式为yyyy-MM-dd HH:mm:ss - */ -public static String date2String(Date date) { - return date2String(date, DEFAULT_SDF); -} + /** + * 将时间戳转为时间字符串 + *

格式为用户自定义

+ * + * @param milliseconds 毫秒时间戳 + * @param format 时间格式 + * @return 时间字符串 + */ + public static String milliseconds2String(long milliseconds, SimpleDateFormat format) { + return format.format(new Date(milliseconds)); + } -/** - * 将Date类型转为时间字符串 - *

格式为用户自定义 - */ -public static String date2String(Date date, SimpleDateFormat format) { - return format.format(date); -} -``` + /** + * 将时间字符串转为时间戳 + *

格式为yyyy-MM-dd HH:mm:ss

+ * + * @param time 时间字符串 + * @return 毫秒时间戳 + */ + public static long string2Milliseconds(String time) { + return string2Milliseconds(time, DEFAULT_SDF); + } -### 将Date类型转为时间戳 -``` java -/** - * 将Date类型转为时间戳 - */ -public static long date2Milliseconds(Date date) { - return date.getTime(); -} -``` + /** + * 将时间字符串转为时间戳 + *

格式为用户自定义

+ * + * @param time 时间字符串 + * @param format 时间格式 + * @return 毫秒时间戳 + */ + public static long string2Milliseconds(String time, SimpleDateFormat format) { + try { + return format.parse(time).getTime(); + } catch (ParseException e) { + e.printStackTrace(); + } + return -1; + } -### 将时间戳转为Date类型 -``` java -/** - * 将时间戳转为Date类型 - */ -public static Date milliseconds2Date(long milliseconds) { - return new Date(milliseconds); -} -``` + /** + * 将时间字符串转为Date类型 + *

格式为yyyy-MM-dd HH:mm:ss

+ * + * @param time 时间字符串 + * @return Date类型 + */ + public static Date string2Date(String time) { + return string2Date(time, DEFAULT_SDF); + } -### 毫秒时间戳单位转换(单位:unit) -``` java -/** - * 毫秒时间戳单位转换(单位:unit) - *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- * 
- */ -private static long milliseconds2Unit(long milliseconds, int unit) { - switch (unit) { - case UNIT_MSEC: - case UNIT_SEC: - case UNIT_MIN: - case UNIT_HOUR: - case UNIT_DAY: - return Math.abs(milliseconds) / unit; + /** + * 将时间字符串转为Date类型 + *

格式为用户自定义

+ * + * @param time 时间字符串 + * @param format 时间格式 + * @return Date类型 + */ + public static Date string2Date(String time, SimpleDateFormat format) { + return new Date(string2Milliseconds(time, format)); } - return -1; -} -``` -### 获取两个时间差(单位:unit) -``` java -/** - * 获取两个时间差(单位:unit) - *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- * 
- *

time1和time2格式都为yyyy-MM-dd HH:mm:ss - */ -public static long getIntervalTime(String time1, String time2, int unit) { - return getIntervalTime(time1, time2, unit, DEFAULT_SDF); -} + /** + * 将Date类型转为时间字符串 + *

格式为yyyy-MM-dd HH:mm:ss

+ * + * @param time Date类型时间 + * @return 时间字符串 + */ + public static String date2String(Date time) { + return date2String(time, DEFAULT_SDF); + } -/** - * 获取两个时间差(单位:unit) - *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- * 
- *

time1和time2格式都为format - */ -public static long getIntervalTime(String time1, String time2, int unit, SimpleDateFormat for - return milliseconds2Unit(string2Milliseconds(time1, format) - - string2Milliseconds(time2, format), unit); -} + /** + * 将Date类型转为时间字符串 + *

格式为用户自定义

+ * + * @param time Date类型时间 + * @param format 时间格式 + * @return 时间字符串 + */ + public static String date2String(Date time, SimpleDateFormat format) { + return format.format(time); + } -/** - * 获取两个时间差(单位:unit) - *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- * 
- *

time1和time2都为Date - */ -public static long getIntervalTime(Date time1, Date time2, int unit) { - return milliseconds2Unit(date2Milliseconds(time2) - date2Milliseconds(time1), unit); -} -``` + /** + * 将Date类型转为时间戳 + * + * @param time Date类型时间 + * @return 毫秒时间戳 + */ + public static long date2Milliseconds(Date time) { + return time.getTime(); + } -### 获取当前时间 -``` java -/** - * 获取当前时间 - *

单位(毫秒) - */ -public static long getCurTimeMills() { - return System.currentTimeMillis(); -} + /** + * 将时间戳转为Date类型 + * + * @param milliseconds 毫秒时间戳 + * @return Date类型时间 + */ + public static Date milliseconds2Date(long milliseconds) { + return new Date(milliseconds); + } -/** - * 获取当前时间 - *

格式为yyyy-MM-dd HH:mm:ss - */ -public static String getCurTimeString() { - return milliseconds2String(getCurTimeMills()); -} + /** + * 毫秒时间戳单位转换(单位:unit) + * + * @param milliseconds 毫秒时间戳 + * @param unit

    + *
  • UNIT_MSEC:毫秒
  • + *
  • UNIT_SEC :秒
  • + *
  • UNIT_MIN :分
  • + *
  • UNIT_HOUR:小时
  • + *
  • UNIT_DAY :天
  • + *
+ * @return unit时间戳 + */ + private static long milliseconds2Unit(long milliseconds, int unit) { + switch (unit) { + case UNIT_MSEC: + case UNIT_SEC: + case UNIT_MIN: + case UNIT_HOUR: + case UNIT_DAY: + return Math.abs(milliseconds) / unit; + } + return -1; + } -/** - * 获取当前时间 - *

格式为用户自定义 - */ -public static String getCurTimeString(SimpleDateFormat format) { - return milliseconds2String(getCurTimeMills(), format); -} + /** + * 获取两个时间差(单位:unit) + *

time1和time2格式都为yyyy-MM-dd HH:mm:ss

+ * + * @param time1 时间字符串1 + * @param time2 时间字符串2 + * @param unit
    + *
  • UNIT_MSEC:毫秒
  • + *
  • UNIT_SEC :秒
  • + *
  • UNIT_MIN :分
  • + *
  • UNIT_HOUR:小时
  • + *
  • UNIT_DAY :天
  • + *
+ * @return unit时间戳 + */ + public static long getIntervalTime(String time1, String time2, int unit) { + return getIntervalTime(time1, time2, unit, DEFAULT_SDF); + } -/** - * 获取当前时间 - *

Date类型 - */ -public static Date getCurTimeDate() { - return new Date(); -} -``` + /** + * 获取两个时间差(单位:unit) + *

time1和time2格式都为format

+ * + * @param time1 时间字符串1 + * @param time2 时间字符串2 + * @param unit
    + *
  • UNIT_MSEC:毫秒
  • + *
  • UNIT_SEC :秒
  • + *
  • UNIT_MIN :分
  • + *
  • UNIT_HOUR:小时
  • + *
  • UNIT_DAY :天
  • + *
+ * @param format 时间格式 + * @return unit时间戳 + */ + public static long getIntervalTime(String time1, String time2, int unit, SimpleDateFormat format) { + return milliseconds2Unit(string2Milliseconds(time1, format) + - string2Milliseconds(time2, format), unit); + } -### 获取与当前时间的差(单位:unit) -``` java -/** - * 获取与当前时间的差(单位:unit) - *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- * 

time1和time2格式都为yyyy-MM-dd HH:mm:ss - */ -public static long getIntervalByNow(String time, int unit) { - return getIntervalByNow(time, unit, DEFAULT_SDF); -} + /** + * 获取两个时间差(单位:unit) + *

time1和time2都为Date类型

+ * + * @param time1 Date类型时间1 + * @param time2 Date类型时间2 + * @param unit
    + *
  • UNIT_MSEC:毫秒
  • + *
  • UNIT_SEC :秒
  • + *
  • UNIT_MIN :分
  • + *
  • UNIT_HOUR:小时
  • + *
  • UNIT_DAY :天
  • + *
+ * @return unit时间戳 + */ + public static long getIntervalTime(Date time1, Date time2, int unit) { + return milliseconds2Unit(date2Milliseconds(time2) - date2Milliseconds(time1), unit); + } -/** - * 获取与当前时间的差(单位:unit) - *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- * 

time1和time2格式都为format - */ -public static long getIntervalByNow(String time, int unit, SimpleDateFormat format) { - return getIntervalTime(getCurTimeString(), time, unit, format); -} + /** + * 获取当前时间 + * + * @return 毫秒时间戳 + */ + public static long getCurTimeMills() { + return System.currentTimeMillis(); + } -/** - * 获取与当前时间的差(单位:unit) - *

- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- * 

time1和time2格式都为format - */ -public static long getIntervalByNow(Date time, int unit) { - return getIntervalTime(getCurTimeDate(), time, unit); -} -``` + /** + * 获取当前时间 + *

格式为yyyy-MM-dd HH:mm:ss

+ * + * @return 时间字符串 + */ + public static String getCurTimeString() { + return milliseconds2String(getCurTimeMills()); + } + + /** + * 获取当前时间 + *

格式为用户自定义

+ * + * @param format 时间格式 + * @return 时间字符串 + */ + public static String getCurTimeString(SimpleDateFormat format) { + return milliseconds2String(getCurTimeMills(), format); + } + + /** + * 获取当前时间 + *

Date类型

+ * + * @return Date类型时间 + */ + public static Date getCurTimeDate() { + return new Date(); + } + + /** + * 获取与当前时间的差(单位:unit) + *

time格式为yyyy-MM-dd HH:mm:ss

+ * + * @param time 时间字符串 + * @param unit
    + *
  • UNIT_MSEC:毫秒
  • + *
  • UNIT_SEC :秒
  • + *
  • UNIT_MIN :分
  • + *
  • UNIT_HOUR:小时
  • + *
  • UNIT_DAY :天
  • + *
+ * @return unit时间戳 + */ + public static long getIntervalByNow(String time, int unit) { + return getIntervalByNow(time, unit, DEFAULT_SDF); + } + + /** + * 获取与当前时间的差(单位:unit) + *

time格式为format

+ * + * @param time 时间字符串 + * @param unit
    + *
  • UNIT_MSEC:毫秒
  • + *
  • UNIT_SEC :秒
  • + *
  • UNIT_MIN :分
  • + *
  • UNIT_HOUR:小时
  • + *
  • UNIT_DAY :天
  • + *
+ * @param format 时间格式 + * @return unit时间戳 + */ + public static long getIntervalByNow(String time, int unit, SimpleDateFormat format) { + return getIntervalTime(getCurTimeString(), time, unit, format); + } + + /** + * 获取与当前时间的差(单位:unit) + *

time为Date类型

+ * + * @param time Date类型时间 + * @param unit
    + *
  • UNIT_MSEC:毫秒
  • + *
  • UNIT_SEC :秒
  • + *
  • UNIT_MIN :分
  • + *
  • UNIT_HOUR:小时
  • + *
  • UNIT_DAY :天
  • + *
+ * @return unit时间戳 + */ + public static long getIntervalByNow(Date time, int unit) { + return getIntervalTime(getCurTimeDate(), time, unit); + } + + /** + * 判断闰年 + * + * @param year 年份 + * @return true: 闰年
false: 平年 + */ + public static boolean isLeapYear(int year) { + return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; + } -### 判断闰年 -``` java -/** - * 判断闰年 - */ -public static boolean isLeapYear(int year) { - return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; } -``` +``` \ No newline at end of file diff --git a/md/about_unclassified.md b/md/about_unclassified.md index 7aeb2377034259773b91a2bd53008a380e44a804..351337fa800b7d4445b818f482f08f872c194f85 100644 --- a/md/about_unclassified.md +++ b/md/about_unclassified.md @@ -1,23 +1,64 @@ # 未归类 -### 获取服务是否开启 -``` +``` java +import android.app.ActivityManager; +import android.app.ActivityManager.RunningServiceInfo; +import android.content.ComponentName; +import android.content.Context; + +import java.util.List; + /** - * 获取服务是否开启 - * @param className 完整包名的服务类名 + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2016/8/2
+ *     desc  : 未归类的工具类
+ * 
*/ -public static boolean isRunningService(String className, Context context) { - // 进程的管理者,活动的管理者 - ActivityManager activityManager = (ActivityManager) - context.getSystemService(Context.ACTIVITY_SERVICE); - // 获取正在运行的服务,最多获取1000个 - List runningServices = activityManager.getRunningServices(1000); - // 遍历集合 - for (RunningServiceInfo runningServiceInfo : runningServices) { - ComponentName service = runningServiceInfo.service; - if (className.equals(service.getClassName())) { - return true; +public class UnclassifiedUtils { + + private UnclassifiedUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } + + /** + * 获取服务是否开启 + * + * @param context 上下文 + * @param className 完整包名的服务类名 + * @return true: 是
false: 否 + */ + public static boolean isRunningService(Context context, String className) { + // 进程的管理者,活动的管理者 + ActivityManager activityManager = (ActivityManager) + context.getSystemService(Context.ACTIVITY_SERVICE); + // 获取正在运行的服务,最多获取1000个 + List runningServices = activityManager.getRunningServices(1000); + // 遍历集合 + for (RunningServiceInfo runningServiceInfo : runningServices) { + ComponentName service = runningServiceInfo.service; + if (className.equals(service.getClassName())) { + return true; + } } + return false; + } + + /** + * HTML字符转义 + *

对输入参数中的敏感字符进行过滤替换,防止用户利用JavaScript等方式输入恶意代码

+ * + * @param html html文本 + * @return 过滤后的文本 + */ + public static String htmlEscape(String html) { + return html.replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll(" ", " ") + .replaceAll("'", "'") + .replaceAll("\"", """) + .replaceAll("\n", "
"); } - return false; } ```