├── README.md ├── about_app.md ├── about_device.md ├── about_encrypt.md ├── about_keyboard.md ├── about_network.md ├── about_phone.md ├── about_regular.md ├── about_screen.md ├── about_size.md ├── about_time.md ├── about_unclassified.md ├── update_log.md └── utilcode ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── src ├── androidTest │ └── java │ │ └── com │ │ └── blankj │ │ └── utilcode │ │ └── ApplicationTest.java ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── blankj │ │ │ └── utilcode │ │ │ └── utils │ │ │ ├── AppUtils.java │ │ │ ├── DeviceUtils.java │ │ │ ├── EncryptUtils.java │ │ │ ├── KeyboardUtils.java │ │ │ ├── NetworkUtils.java │ │ │ ├── PhoneUtils.java │ │ │ ├── RegularUtils.java │ │ │ ├── ScreenUtils.java │ │ │ ├── SizeUtils.java │ │ │ ├── TimeUtils.java │ │ │ └── UnclassifiedUtils.java │ └── res │ │ └── values │ │ └── strings.xml └── test │ └── java │ └── com │ └── blankj │ └── utilcode │ └── utils │ └── EncryptUtilsTest.java └── utilcode.iml /README.md: -------------------------------------------------------------------------------- 1 | # Android开发人员不得不收集的代码(持续更新中) 2 | 为方便查找,已进行大致归类,其目录如下所示: 3 | > - [App相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_app.md)→[AppUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/AppUtils.java) 4 | > - 安装指定路径下的Apk *installApp* 5 | > - 卸载指定包名的App *uninstallApp* 6 | > - 获取当前App信息 *getAppInfo* 7 | > - 获取所有已安装App信息 *getAllAppsInfo* 8 | > - 打开指定包名的App *openAppByPackageName* 9 | > - 打开指定包名的App应用信息界面 *openAppInfo* 10 | > - 可用来做App信息分享 *shareAppInfo* 11 | > - 判断当前App处于前台还是后台 *isApplicationBackground* 12 | 13 | > - [设备相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_device.md)→[DeviceUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/DeviceUtils.java) 14 | > - 获取设备MAC地址 *getMacAddress* 15 | > - 获取设备厂商,如Xiaomi *getManufacturer* 16 | > - 获取设备型号,如MI2SC *getModel* 17 | > - 获取设备SD卡是否可用 *isSDCardEnable* 18 | > - 获取设备SD卡路径 *getSDCardPath* 19 | 20 | > - [加解密相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_encrypt.md)→[EncryptUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/EncryptUtils.java) 21 | > - MD5加密 *getMD5* *encryptMD5* *getMD5File* 22 | > - SHA加密 *getSHA* *encryptSHA* 23 | 24 | > - [键盘相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_keyboard.md)→[KeyboardUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/KeyboardUtils.java) 25 | > - 避免输入法面板遮挡 26 | > - 动态隐藏软键盘 *hideSoftInput* 27 | > - 点击屏幕空白区域隐藏软键盘(注释萌萌哒) *clickBlankArea2HideSoftInput0* 28 | > - 动态显示软键盘 *showSoftInput* 29 | > - 切换键盘显示与否状态 *toggleSoftInput* 30 | 31 | > - [网络相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_network.md)→[NetworkUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/NetworkUtils.java) 32 | > - 打开网络设置界面 *openWirelessSettings* 33 | > - 判断网络是否可用 *isAvailable* 34 | > - 判断网络是否连接 *isConnected* 35 | > - 判断网络是否是4G *is4G* 36 | > - 判断wifi是否连接状态 *isWifiConnected* 37 | > - 获取移动网络运营商名称 *getNetworkOperatorName* 38 | > - 获取移动终端类型 *getPhoneType* 39 | > - 获取当前的网络类型(WIFI,2G,3G,4G) *getNetWorkType* *getNetWorkTypeName* 40 | 41 | > - [手机相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_phone.md)→[PhoneUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/PhoneUtils.java) 42 | > - 判断设备是否是手机 *isPhone* 43 | > - 获取手机的IMIE *getDeviceIMEI* 44 | > - 获取手机状态信息 *getPhoneStatus* 45 | > - 跳至填充好phoneNumber的拨号界面 *dial* 46 | > - 拨打phoneNumber *call* 47 | > - 发送短信 *sendSms* 48 | > - 获取手机联系人 *getAllContactInfo* 49 | > - 打开手机联系人界面点击联系人后便获取该号码(注释萌萌哒) *getContantNum* 50 | > - 获取手机短信并保存到xml中 *getAllSMS* 51 | 52 | > - [正则相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_regular.md)→[RegularUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/RegularUtils.java) 53 | > - 正则工具类 54 | 55 | > - [屏幕相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_screen.md)→[ScreenUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ScreenUtils.java) 56 | > - 获取手机分辨率 *getDeviceWidth*、*getDeviceHeight* 57 | > - 设置透明状态栏(api >= 19方可使用) *setTransparentStatusBar* 58 | > - 隐藏状态栏(注释萌萌哒) *hideStatusBar* 59 | > - 获取状态栏高度 *getStatusBarHeight* 60 | > - 判断状态栏是否存在 *isStatusBarExists* 61 | > - 获取ActionBar高度 *getActionBarHeight* 62 | > - 设置屏幕为横屏(注释萌萌哒) *setLandscape* 63 | > - 获取屏幕截图 *snapShotWithStatusBar*、*snapShotWithoutStatusBar* 64 | > - 判断是否锁屏 *isScreenLock* 65 | 66 | > - [尺寸相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_size.md)→[SizeUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/SizeUtils.java) 67 | > - dp与px转换 *dp2px*、*px2dp* 68 | > - sp与px转换 *sp2px*、*px2sp* 69 | > - 各种单位转换 *applyDimension* 70 | > - 在onCreate()即可强行获取View的尺寸 *forceGetViewSize* 71 | > - ListView中提前测量View尺寸(注释萌萌哒) *measureView* 72 | 73 | > - [时间相关](https://github.com/Blankj/AndroidUtilCode/blob/master/about_time.md)→[TimeUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/TimeUtils.java) 74 | > - 将时间戳转为时间字符串 *milliseconds2String* 75 | > - 将时间字符串转为时间戳 *string2Milliseconds* 76 | > - 将时间字符串转为Date类型 *string2Date* 77 | > - 将Date类型转为时间字符串 *date2String* 78 | > - 将Date类型转为时间戳 *date2Milliseconds* 79 | > - 将时间戳转为Date类型 *milliseconds2Date* 80 | > - 毫秒时间戳单位转换(单位:unit) *milliseconds2Unit* 81 | > - 获取两个时间差(单位:unit) *getIntervalTime* 82 | > - 获取当前时间 *getCurTimeMills* *getCurTimeString* *getCurTimeDate* 83 | > - 获取与当前时间的差(单位:unit) *getIntervalByNow* 84 | > - 判断闰年 *isLeapYear* 85 | 86 | > - [未归类](https://github.com/Blankj/AndroidUtilCode/blob/master/unclassified.md)→[UnclassifiedUtils.java](https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/UnclassifiedUtils.java) 87 | > - 获取服务是否开启 *isRunningService* 88 | > - [更新Log](https://github.com/Blankj/AndroidUtilCode/blob/master/update_log.md) 89 | 90 | *** 91 | 92 |   **做这份整理只是想把它作为Android的一本小字典,当遇到一些琐碎问题时,不用再面向百度或者谷歌查询API的使用,费时费力,这里有的话,大家尽管撸走。希望它能逐日壮大起来,期待你的Star和完善,用途的话大家想把它们整理成工具类或者什么的话都可以,之后我也会封装工具类并分享之,但本篇只是提供查阅,毕竟看md比看类文件要爽多了,其中好多代码我也是各种搜刮来的,也要谢谢各位的总结,大部分代码已验证过可行,如有错误,请及时告之,开设QQ群提供讨论,群号:74721490** 93 | 94 | # 更新Log 95 | #### 2016/07/31 新增点击屏幕空白区域隐藏软键盘 96 | #### 2016/07/31 未能成功增加本页目录跳转功能(不支持) 97 | #### 2016/08/01 新增获取当前App版本Code 98 | #### 2016/08/01 新增目录中显示方法名 99 | #### 2016/08/01 新增获取SD卡路径,手机和设备进行分类,代码bug修改部分,小修排版,正在封装类 100 | #### 2016/08/02 wifi设置界面bug修复,注释排版还在修改,获取mac地址增加判空,新增QQ群:74721490,欢迎加入 101 | #### 2016/08/02 新增隐藏状态栏,注释更加全面,工具类已封装,写的时候真的是一个一个测试过去的,宝宝心里苦 102 | #### 2016/08/03 修复在onCreate中获取view尺寸的bug,MD5和SHA的Bug修复完成(在此感谢ssyijiu) 103 | #### 2016/08/04 新增时间工具类(在此感谢yi520000给的补充),手机正则分简单和精确(在此感谢MIkeeJY),新增判断是否锁屏,注释分段落,目录按首字母排序 104 | #### 2016/08/05 加密新增MD5盐加密,完善NetworkUtils,新增判断状态栏是否存在(在此感谢tiandawu) 105 | #### 2016/08/06 重命名包名,新增加密相关的单元测试,MD5加密新增文件加密重载。 106 | 107 | 108 | ##[关于Blankj](http://blankj.com/about) -------------------------------------------------------------------------------- /about_app.md: -------------------------------------------------------------------------------- 1 | # App相关 2 | ### 安装指定路径下的Apk 3 | ``` java 4 | /** 5 | * 安装指定路径下的Apk 6 | *

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

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

这里做不了回调,后续自己做处理 9 | */ 10 | public static boolean installApp(Context context, String filePath) { 11 | if (filePath != null && filePath.length() > 4 12 | && filePath.toLowerCase().substring(filePath.length() - 4).equals(".apk")) { 13 | Intent intent = new Intent(Intent.ACTION_VIEW); 14 | File file = new File(filePath); 15 | if (file.exists() && file.isFile() && file.length() > 0) { 16 | intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 17 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 18 | context.startActivity(intent); 19 | return true; 20 | } 21 | } 22 | return false; 23 | } 24 | ``` 25 | 26 | ### 卸载指定包名的App 27 | ``` java 28 | /** 29 | * 卸载指定包名的App 30 | *

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

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

这里做不了回调,后续自己做处理 33 | */ 34 | public boolean uninstallApp(Context context, String packageName) { 35 | if (!TextUtils.isEmpty(packageName)) { 36 | Intent intent = new Intent(Intent.ACTION_DELETE); 37 | intent.setData(Uri.parse("package:" + packageName)); 38 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 39 | context.startActivity(intent); 40 | return true; 41 | } 42 | return false; 43 | } 44 | ``` 45 | 46 | ### 获取当前App信息 47 | ``` java 48 | /** 49 | * 封装App信息的Bean类 50 | */ 51 | public static class AppInfo { 52 | 53 | private String name; 54 | private Drawable icon; 55 | private String packagName; 56 | private String versionName; 57 | private int versionCode; 58 | private boolean isSD; 59 | private boolean isUser; 60 | 61 | public Drawable getIcon() { 62 | return icon; 63 | } 64 | 65 | public void setIcon(Drawable icon) { 66 | this.icon = icon; 67 | } 68 | 69 | public boolean isSD() { 70 | return isSD; 71 | } 72 | 73 | public void setSD(boolean SD) { 74 | isSD = SD; 75 | } 76 | 77 | public boolean isUser() { 78 | return isUser; 79 | } 80 | 81 | public void setUser(boolean user) { 82 | isUser = user; 83 | } 84 | 85 | public String getName() { 86 | return name; 87 | } 88 | 89 | public void setName(String name) { 90 | this.name = name; 91 | } 92 | 93 | public String getPackagName() { 94 | return packagName; 95 | } 96 | 97 | public void setPackagName(String packagName) { 98 | this.packagName = packagName; 99 | } 100 | 101 | public int getVersionCode() { 102 | return versionCode; 103 | } 104 | 105 | public void setVersionCode(int versionCode) { 106 | this.versionCode = versionCode; 107 | } 108 | 109 | public String getVersionName() { 110 | return versionName; 111 | } 112 | 113 | public void setVersionName(String versionName) { 114 | this.versionName = versionName; 115 | } 116 | 117 | /** 118 | * @param name 名称 119 | * @param icon 图标 120 | * @param packagName 包名 121 | * @param versionName 版本号 122 | * @param versionCode 版本Code 123 | * @param isSD 是否安装在SD卡 124 | * @param isUser 是否是用户程序 125 | */ 126 | public AppInfo(String name, Drawable icon, String packagName, 127 | String versionName, int versionCode, boolean isSD, boolean isUser) { 128 | this.setName(name); 129 | this.setIcon(icon); 130 | this.setPackagName(packagName); 131 | this.setVersionName(versionName); 132 | this.setVersionCode(versionCode); 133 | this.setSD(isSD); 134 | this.setUser(isUser); 135 | } 136 | 137 | /*@Override 138 | public String toString() { 139 | return getName() + "\n" 140 | + getIcon() + "\n" 141 | + getPackagName() + "\n" 142 | + getVersionName() + "\n" 143 | + getVersionCode() + "\n" 144 | + isSD() + "\n" 145 | + isUser() + "\n"; 146 | }*/ 147 | } 148 | 149 | /** 150 | * 获取当前App信息 151 | *

AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序) 152 | */ 153 | public static AppInfo getAppInfo(Context context) { 154 | PackageManager pm = context.getPackageManager(); 155 | PackageInfo pi = null; 156 | try { 157 | pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); 158 | } catch (PackageManager.NameNotFoundException e) { 159 | e.printStackTrace(); 160 | } 161 | return pi != null ? getBean(pm, pi) : null; 162 | } 163 | 164 | /** 165 | * 得到AppInfo的Bean 166 | */ 167 | private static AppInfo getBean(PackageManager pm, PackageInfo pi) { 168 | ApplicationInfo ai = pi.applicationInfo; 169 | String name = ai.loadLabel(pm).toString(); 170 | Drawable icon = ai.loadIcon(pm); 171 | String packageName = pi.packageName; 172 | String versionName = pi.versionName; 173 | int versionCode = pi.versionCode; 174 | boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; 175 | boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; 176 | return new AppInfo(name, icon, packageName, versionName, versionCode, isSD, isUser); 177 | } 178 | ``` 179 | 180 | ### 获取所有已安装App信息 181 | ``` 182 | /** 183 | * 获取所有已安装App信息 184 | *

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

依赖上面的getBean方法 186 | */ 187 | public static List getAllAppsInfo(Context context) { 188 | List list = new ArrayList<>(); 189 | PackageManager pm = context.getPackageManager(); 190 | // 获取系统中安装的所有软件信息 191 | List installedPackages = pm.getInstalledPackages(0); 192 | for (PackageInfo pi : installedPackages) { 193 | if (pi != null) { 194 | list.add(getBean(pm, pi)); 195 | } 196 | } 197 | return list; 198 | } 199 | ``` 200 | 201 | ### 打开指定包名的App 202 | ``` 203 | /** 204 | * 打开指定包名的App 205 | */ 206 | public static boolean openAppByPackageName(Context context, String packageName) { 207 | if (!TextUtils.isEmpty(packageName)) { 208 | PackageManager pm = context.getPackageManager(); 209 | Intent launchIntentForPackage = pm.getLaunchIntentForPackage(packageName); 210 | if (launchIntentForPackage != null) { 211 | context.startActivity(launchIntentForPackage); 212 | return true; 213 | } 214 | } 215 | return false; 216 | } 217 | ``` 218 | 219 | ### 打开指定包名的App应用信息界面 220 | ``` java 221 | /** 222 | * 打开指定包名的App应用信息界面 223 | */ 224 | public static boolean openAppInfo(Context context, String packageName) { 225 | if (!TextUtils.isEmpty(packageName)) { 226 | Intent intent = new Intent(); 227 | intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); 228 | intent.setData(Uri.parse("package:" + packageName)); 229 | context.startActivity(intent); 230 | return true; 231 | } 232 | return false; 233 | } 234 | ``` 235 | 236 | ### 可用来做App信息分享 237 | ``` java 238 | /** 239 | * 可用来做App信息分享 240 | */ 241 | public static void shareAppInfo(Context context, String info) { 242 | if (!TextUtils.isEmpty(info)) { 243 | Intent intent = new Intent(Intent.ACTION_SEND); 244 | intent.setType("text/plain"); 245 | intent.putExtra(Intent.EXTRA_TEXT, info); 246 | context.startActivity(intent); 247 | } 248 | } 249 | ``` 250 | 251 | ### 判断当前App处于前台还是后台 252 | ``` java 253 | /** 254 | * 判断当前App处于前台还是后台 255 | *

需添加 256 | *

并且必须是系统应用该方法才有效 257 | */ 258 | public static boolean isAppBackground(Context context) { 259 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 260 | @SuppressWarnings("deprecation") 261 | List tasks = am.getRunningTasks(1); 262 | if (!tasks.isEmpty()) { 263 | ComponentName topActivity = tasks.get(0).topActivity; 264 | if (!topActivity.getPackageName().equals(context.getPackageName())) { 265 | return true; 266 | } 267 | } 268 | return false; 269 | } 270 | ``` 271 | -------------------------------------------------------------------------------- /about_device.md: -------------------------------------------------------------------------------- 1 | # 设备相关 2 | ### 获取设备MAC地址 3 | ``` java 4 | /** 5 | * 获取设备MAC地址 6 | *

需添加权限 7 | */ 8 | public static String getMacAddress(Context context) { 9 | String macAddress; 10 | WifiManager wifi = (WifiManager) context 11 | .getSystemService(Context.WIFI_SERVICE); 12 | WifiInfo info = wifi.getConnectionInfo(); 13 | macAddress = info.getMacAddress(); 14 | if (null == macAddress) { 15 | return ""; 16 | } 17 | macAddress = macAddress.replace(":", ""); 18 | return macAddress; 19 | } 20 | ``` 21 | 22 | ### 获取设备厂商,如Xiaomi 23 | ``` java 24 | /** 25 | * 获取设备厂商,如Xiaomi 26 | */ 27 | public static String getManufacturer() { 28 | String MANUFACTURER = Build.MANUFACTURER; 29 | return MANUFACTURER; 30 | } 31 | ``` 32 | 33 | ### 获取设备型号,如MI2SC 34 | ``` java 35 | /** 36 | * 获取设备型号,如MI2SC 37 | */ 38 | public static String getModel() { 39 | String model = Build.MODEL; 40 | if (model != null) { 41 | model = model.trim().replaceAll("\\s*", ""); 42 | } else { 43 | model = ""; 44 | } 45 | return model; 46 | } 47 | ``` 48 | 49 | ### 获取设备SD卡是否可用 50 | ``` java 51 | /** 52 | * 获取设备SD卡是否可用 53 | */ 54 | public static boolean isSDCardEnable() { 55 | return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); 56 | } 57 | ``` 58 | 59 | ### 获取设备SD卡路径 60 | ``` 61 | /** 62 | * 获取设备SD卡路径 63 | *

一般是/storage/emulated/0/ 64 | */ 65 | public static String getSDCardPath() { 66 | return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator; 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /about_encrypt.md: -------------------------------------------------------------------------------- 1 | # 加解密相关 2 | ### MD5加密 3 | ``` java 4 | /** 5 | * MD5加密 6 | * 7 | * @param data 明文字符串 8 | * @return 密文 9 | */ 10 | public static String getMD5(String data) { 11 | return getMD5(data.getBytes()); 12 | } 13 | 14 | /** 15 | * MD5加密 16 | * 17 | * @param data 明文字符串 18 | * @param salt 盐 19 | * @return 密文 20 | */ 21 | public static String getMD5(String data, String salt) { 22 | return bytes2Hex(encryptMD5((data + salt).getBytes())); 23 | } 24 | 25 | /** 26 | * MD5加密 27 | * 28 | * @param data 明文字节数组 29 | * @return 密文 30 | */ 31 | public static String getMD5(byte[] data) { 32 | return bytes2Hex(encryptMD5(data)); 33 | } 34 | 35 | /** 36 | * MD5加密 37 | * 38 | * @param data 明文字节数组 39 | * @param salt 盐字节数组 40 | * @return 密文 41 | */ 42 | public static String getMD5(byte[] data, byte[] salt) { 43 | byte[] dataSalt = new byte[data.length + salt.length]; 44 | System.arraycopy(data, 0, dataSalt, 0, data.length); 45 | System.arraycopy(salt, 0, dataSalt, data.length, salt.length); 46 | return bytes2Hex(encryptMD5(dataSalt)); 47 | } 48 | 49 | /** 50 | * MD5加密 51 | * 52 | * @param data 明文字节数组 53 | * @return 密文字节数组 54 | */ 55 | public static byte[] encryptMD5(byte[] data) { 56 | try { 57 | MessageDigest md = MessageDigest.getInstance("MD5"); 58 | md.update(data); 59 | return md.digest(); 60 | } catch (NoSuchAlgorithmException e) { 61 | e.printStackTrace(); 62 | } 63 | return new byte[0]; 64 | } 65 | 66 | /** 67 | * 获取文件的MD5校验码 68 | * 69 | * @param filePath 文件路径 70 | * @return 文件的MD5校验码 71 | */ 72 | public static String getMD5File(String filePath) { 73 | FileInputStream in = null; 74 | try { 75 | MessageDigest md = MessageDigest.getInstance("MD5"); 76 | in = new FileInputStream(filePath); 77 | int len; 78 | byte[] buffer = new byte[1024]; 79 | while ((len = in.read(buffer)) != -1) { 80 | md.update(buffer, 0, len); 81 | } 82 | return bytes2Hex(md.digest()); 83 | } catch (NoSuchAlgorithmException | IOException e) { 84 | e.printStackTrace(); 85 | } finally { 86 | if (in != null) { 87 | try { 88 | in.close(); 89 | } catch (IOException ignored) { 90 | } 91 | } 92 | } 93 | return ""; 94 | } 95 | ``` 96 | 97 | ### SHA加密 98 | ``` 99 | /** 100 | * SHA加密 101 | * 102 | * @param data 明文字符串 103 | * @return 密文 104 | */ 105 | public static String getSHA(String data) { 106 | return getSHA(data.getBytes()); 107 | } 108 | 109 | /** 110 | * SHA加密 111 | * 112 | * @param data 明文字节数组 113 | * @return 密文 114 | */ 115 | public static String getSHA(byte[] data) { 116 | return bytes2Hex(encryptSHA(data)); 117 | } 118 | 119 | /** 120 | * SHA加密 121 | * 122 | * @param data 明文字节数组 123 | * @return 密文字节数组 124 | */ 125 | public static byte[] encryptSHA(byte[] data) { 126 | try { 127 | MessageDigest md = MessageDigest.getInstance("SHA"); 128 | md.update(data); 129 | return md.digest(); 130 | } catch (NoSuchAlgorithmException e) { 131 | e.printStackTrace(); 132 | } 133 | return new byte[0]; 134 | } 135 | 136 | /** 137 | * 一个byte转为2个hex字符 138 | */ 139 | public static String bytes2Hex(byte[] src) { 140 | char[] res = new char[src.length * 2]; 141 | final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 142 | for (int i = 0, j = 0; i < src.length; i++) { 143 | res[j++] = hexDigits[src[i] >>> 4 & 0x0f]; 144 | res[j++] = hexDigits[src[i] & 0x0f]; 145 | } 146 | return new String(res); 147 | } 148 | ``` 149 | -------------------------------------------------------------------------------- /about_keyboard.md: -------------------------------------------------------------------------------- 1 | # 键盘相关 2 | ### 避免输入法面板遮挡 3 | ``` java 4 | // 在manifest.xml中activity中设置 5 | android:windowSoftInputMode="stateVisible|adjustResize" 6 | ``` 7 | 8 | ### 动态隐藏软键盘 9 | ``` java 10 | /** 11 | * 动态隐藏软键盘 12 | */ 13 | public static void hideSoftInput(Activity activity) { 14 | View view = activity.getWindow().peekDecorView(); 15 | if (view != null) { 16 | InputMethodManager inputmanger = (InputMethodManager) activity 17 | .getSystemService(Context.INPUT_METHOD_SERVICE); 18 | inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0); 19 | } 20 | } 21 | 22 | /** 23 | * 动态隐藏软键盘 24 | */ 25 | public static void hideSoftInput(Context context, EditText edit) { 26 | edit.clearFocus(); 27 | InputMethodManager inputmanger = (InputMethodManager) context 28 | .getSystemService(Context.INPUT_METHOD_SERVICE); 29 | inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0); 30 | } 31 | ``` 32 | 33 | ### 点击屏幕空白区域隐藏软键盘 34 | ``` java 35 | /** 36 | * 点击屏幕空白区域隐藏软键盘(方法0) 37 | *

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

参照以下注释代码 39 | */ 40 | public static void clickBlankArea2HideSoftInput0() { 41 | Log.i("tips", "U should copy the following code."); 42 | /* 43 | @Override 44 | public boolean onTouchEvent (MotionEvent event){ 45 | if (null != this.getCurrentFocus()) { 46 | InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 47 | return mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); 48 | } 49 | return super.onTouchEvent(event); 50 | } 51 | */ 52 | } 53 | 54 | /** 55 | * 点击屏幕空白区域隐藏软键盘(方法1) 56 | *

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

需重写dispatchTouchEvent 58 | *

参照以下注释代码 59 | */ 60 | public static void clickBlankArea2HideSoftInput1() { 61 | Log.i("tips", "U should copy the following code."); 62 | /* 63 | @Override 64 | public boolean dispatchTouchEvent(MotionEvent ev) { 65 | if (ev.getAction() == MotionEvent.ACTION_DOWN) { 66 | View v = getCurrentFocus(); 67 | if (isShouldHideKeyboard(v, ev)) { 68 | hideKeyboard(v.getWindowToken()); 69 | } 70 | } 71 | return super.dispatchTouchEvent(ev); 72 | } 73 | // 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 74 | private boolean isShouldHideKeyboard(View v, MotionEvent event) { 75 | if (v != null && (v instanceof EditText)) { 76 | int[] l = {0, 0}; 77 | v.getLocationInWindow(l); 78 | int left = l[0], 79 | top = l[1], 80 | bottom = top + v.getHeight(), 81 | right = left + v.getWidth(); 82 | return !(event.getX() > left && event.getX() < right 83 | && event.getY() > top && event.getY() < bottom); 84 | } 85 | return false; 86 | } 87 | // 获取InputMethodManager,隐藏软键盘 88 | private void hideKeyboard(IBinder token) { 89 | if (token != null) { 90 | InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 91 | im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); 92 | } 93 | } 94 | */ 95 | } 96 | ``` 97 | 98 | ### 动态显示软键盘 99 | ``` java 100 | /** 101 | * 动态显示软键盘 102 | */ 103 | public static void showSoftInput(Context context, EditText edit) { 104 | edit.setFocusable(true); 105 | edit.setFocusableInTouchMode(true); 106 | edit.requestFocus(); 107 | InputMethodManager inputManager = (InputMethodManager) context 108 | .getSystemService(Context.INPUT_METHOD_SERVICE); 109 | inputManager.showSoftInput(edit, 0); 110 | } 111 | ``` 112 | 113 | ### 切换键盘显示与否状态 114 | ``` java 115 | /** 116 | * 切换键盘显示与否状态 117 | */ 118 | public static void toggleSoftInput(Context context, EditText edit) { 119 | edit.setFocusable(true); 120 | edit.setFocusableInTouchMode(true); 121 | edit.requestFocus(); 122 | InputMethodManager inputManager = (InputMethodManager) context 123 | .getSystemService(Context.INPUT_METHOD_SERVICE); 124 | inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); 125 | } 126 | ``` 127 | -------------------------------------------------------------------------------- /about_network.md: -------------------------------------------------------------------------------- 1 | # 网络相关 2 | ### 打开网络设置界面 3 | ``` java 4 | /** 5 | * 打开网络设置界面 6 | *

3.0以下打开设置界面 7 | */ 8 | public static void openWirelessSettings(Context context) { 9 | if (android.os.Build.VERSION.SDK_INT > 10) { 10 | context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS)); 11 | } else { 12 | context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS)); 13 | } 14 | } 15 | ``` 16 | 17 | ### 判断网络是否可用 18 | ``` java 19 | /** 20 | * 获取活动网路信息 21 | */ 22 | private static NetworkInfo getActiveNetworkInfo(Context context) { 23 | ConnectivityManager cm = (ConnectivityManager) context 24 | .getSystemService(Context.CONNECTIVITY_SERVICE); 25 | return cm.getActiveNetworkInfo(); 26 | } 27 | 28 | /** 29 | * 判断网络是否可用 30 | *

需添加权限 31 | */ 32 | public static boolean isAvailable(Context context) { 33 | NetworkInfo info = getActiveNetworkInfo(context); 34 | return info != null && info.isAvailable(); 35 | } 36 | ``` 37 | 38 | ### 判断网络是否连接 39 | ``` java 40 | /** 41 | * 判断网络是否连接 42 | *

需添加权限 43 | */ 44 | public static boolean isConnected(Context context) { 45 | NetworkInfo info = getActiveNetworkInfo(context); 46 | return info != null && info.isConnected(); 47 | } 48 | ``` 49 | 50 | ### 判断网络是否是4G 51 | ``` java 52 | /** 53 | * 判断网络是否是4G 54 | *

需添加权限 55 | */ 56 | public static boolean is4G(Context context) { 57 | NetworkInfo info = getActiveNetworkInfo(context); 58 | return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE; 59 | } 60 | ``` 61 | 62 | ### 判断wifi是否连接状态 63 | ``` java 64 | /** 65 | * 判断wifi是否连接状态 66 | *

需添加权限 67 | */ 68 | public static boolean isWifiConnected(Context context) { 69 | ConnectivityManager cm = (ConnectivityManager) context 70 | .getSystemService(Context.CONNECTIVITY_SERVICE); 71 | return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; 72 | } 73 | ``` 74 | 75 | ### 获取移动网络运营商名称 76 | ``` java 77 | /** 78 | * 获取移动网络运营商名称 79 | *

如中国联通、中国移动、中国电信 80 | */ 81 | public static String getNetworkOperatorName(Context context) { 82 | TelephonyManager tm = (TelephonyManager) context 83 | .getSystemService(Context.TELEPHONY_SERVICE); 84 | return tm != null ? tm.getNetworkOperatorName() : null; 85 | } 86 | ``` 87 | 88 | ### 获取移动终端类型 89 | ``` java 90 | /** 91 | * 获取移动终端类型 92 | * 93 | * @return 手机制式 94 | *

100 | */ 101 | public static int getPhoneType(Context context) { 102 | TelephonyManager tm = (TelephonyManager) context 103 | .getSystemService(Context.TELEPHONY_SERVICE); 104 | return tm != null ? tm.getPhoneType() : -1; 105 | } 106 | ``` 107 | 108 | ### 获取当前的网络类型(WIFI,2G,3G,4G) 109 | ``` java 110 | /** 111 | * 获取当前的网络类型(WIFI,2G,3G,4G) 112 | *

需添加权限 113 | * 114 | * @return 网络类型 115 | *

123 | */ 124 | public static int getNetWorkType(Context context) { 125 | int netType = NETWORK_NO; 126 | NetworkInfo info = getActiveNetworkInfo(context); 127 | if (info != null && info.isAvailable()) { 128 | 129 | if (info.getType() == ConnectivityManager.TYPE_WIFI) { 130 | netType = NETWORK_WIFI; 131 | } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { 132 | switch (info.getSubtype()) { 133 | 134 | case NETWORK_TYPE_GSM: 135 | case TelephonyManager.NETWORK_TYPE_GPRS: 136 | case TelephonyManager.NETWORK_TYPE_CDMA: 137 | case TelephonyManager.NETWORK_TYPE_EDGE: 138 | case TelephonyManager.NETWORK_TYPE_1xRTT: 139 | case TelephonyManager.NETWORK_TYPE_IDEN: 140 | netType = NETWORK_2G; 141 | break; 142 | 143 | case NETWORK_TYPE_TD_SCDMA: 144 | case TelephonyManager.NETWORK_TYPE_EVDO_A: 145 | case TelephonyManager.NETWORK_TYPE_UMTS: 146 | case TelephonyManager.NETWORK_TYPE_EVDO_0: 147 | case TelephonyManager.NETWORK_TYPE_HSDPA: 148 | case TelephonyManager.NETWORK_TYPE_HSUPA: 149 | case TelephonyManager.NETWORK_TYPE_HSPA: 150 | case TelephonyManager.NETWORK_TYPE_EVDO_B: 151 | case TelephonyManager.NETWORK_TYPE_EHRPD: 152 | case TelephonyManager.NETWORK_TYPE_HSPAP: 153 | netType = NETWORK_3G; 154 | break; 155 | 156 | case NETWORK_TYPE_IWLAN: 157 | case TelephonyManager.NETWORK_TYPE_LTE: 158 | netType = NETWORK_4G; 159 | break; 160 | default: 161 | 162 | String subtypeName = info.getSubtypeName(); 163 | if (subtypeName.equalsIgnoreCase("TD-SCDMA") 164 | || subtypeName.equalsIgnoreCase("WCDMA") 165 | || subtypeName.equalsIgnoreCase("CDMA2000")) { 166 | netType = NETWORK_3G; 167 | } else { 168 | netType = NETWORK_UNKNOWN; 169 | } 170 | break; 171 | } 172 | } else { 173 | netType = NETWORK_UNKNOWN; 174 | } 175 | } 176 | return netType; 177 | } 178 | 179 | /** 180 | * 获取当前的网络类型(WIFI,2G,3G,4G) 181 | * 依赖上面的方法 182 | * 183 | * @param context 184 | * @return 网络类型名称 185 | * 193 | */ 194 | public static String getNetWorkTypeName(Context context) { 195 | switch (getNetWorkType(context)) { 196 | case NETWORK_WIFI: 197 | return "NETWORK_WIFI"; 198 | case NETWORK_4G: 199 | return "NETWORK_4G"; 200 | case NETWORK_3G: 201 | return "NETWORK_3G"; 202 | case NETWORK_2G: 203 | return "NETWORK_2G"; 204 | case NETWORK_NO: 205 | return "NETWORK_NO"; 206 | default: 207 | return "NETWORK_UNKNOWN"; 208 | } 209 | } 210 | ``` 211 | -------------------------------------------------------------------------------- /about_phone.md: -------------------------------------------------------------------------------- 1 | # 手机相关 2 | ### 判断设备是否是手机 3 | ``` java 4 | /** 5 | * 判断设备是否是手机 6 | */ 7 | public static boolean isPhone(Context context) { 8 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 9 | return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; 10 | } 11 | ``` 12 | 13 | ### 获取手机的IMIE 14 | ``` java 15 | /** 16 | * 获取当前设备的IMIE 17 | *

需与上面的isPhone一起使用 18 | *

需添加权限 19 | */ 20 | public static String getPhoneIMEI(Context context) { 21 | String deviceId; 22 | if (isPhone(context)) { 23 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 24 | deviceId = tm.getDeviceId(); 25 | } else { 26 | deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); 27 | } 28 | return deviceId; 29 | } 30 | ``` 31 | 32 | ### 获取手机状态信息 33 | ``` java 34 | /** 35 | * 获取手机状态信息 36 | *

需添加权限 37 | *

返回如下 38 | *

 39 |  * DeviceId(IMEI) = 99000311726612
 40 |  * DeviceSoftwareVersion = 00
 41 |  * Line1Number =
 42 |  * NetworkCountryIso = cn
 43 |  * NetworkOperator = 46003
 44 |  * NetworkOperatorName = 中国电信
 45 |  * NetworkType = 6
 46 |  * honeType = 2
 47 |  * SimCountryIso = cn
 48 |  * SimOperator = 46003
 49 |  * SimOperatorName = 中国电信
 50 |  * SimSerialNumber = 89860315045710604022
 51 |  * SimState = 5
 52 |  * SubscriberId(IMSI) = 460030419724900
 53 |  * VoiceMailNumber = *86
 54 |  * 
 55 |  */
 56 | public static String getPhoneStatus(Context context) {
 57 |     TelephonyManager tm = (TelephonyManager) context
 58 |             .getSystemService(Context.TELEPHONY_SERVICE);
 59 |     String str = "";
 60 |     str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n";
 61 |     str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
 62 |     str += "Line1Number = " + tm.getLine1Number() + "\n";
 63 |     str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
 64 |     str += "NetworkOperator = " + tm.getNetworkOperator() + "\n";
 65 |     str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n";
 66 |     str += "NetworkType = " + tm.getNetworkType() + "\n";
 67 |     str += "honeType = " + tm.getPhoneType() + "\n";
 68 |     str += "SimCountryIso = " + tm.getSimCountryIso() + "\n";
 69 |     str += "SimOperator = " + tm.getSimOperator() + "\n";
 70 |     str += "SimOperatorName = " + tm.getSimOperatorName() + "\n";
 71 |     str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n";
 72 |     str += "SimState = " + tm.getSimState() + "\n";
 73 |     str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n";
 74 |     str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n";
 75 |     return str;
 76 | }
 77 | ```
 78 | 
 79 | ### 跳至填充好phoneNumber的拨号界面
 80 | ``` java
 81 | /**
 82 |  * 跳至填充好phoneNumber的拨号界面
 83 |  */
 84 | public static void dial(Context context, String phoneNumber) {
 85 |     context.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)));
 86 | }
 87 | ```
 88 | 
 89 | ### 拨打phoneNumber
 90 | ``` java
 91 | /**
 92 |  * 拨打phoneNumber
 93 |  * 

需添加权限 94 | */ 95 | public static void call(Context context, String phoneNumber) { 96 | context.startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber))); 97 | } 98 | ``` 99 | 100 | ### 发送短信 101 | ``` java 102 | /** 103 | * 发送短信 104 | */ 105 | public static void sendSms(Context context, String phoneNumber, String content) { 106 | Uri uri = Uri.parse("smsto:" + (TextUtils.isEmpty(phoneNumber) ? "" : phoneNumber)); 107 | Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 108 | intent.putExtra("sms_body", TextUtils.isEmpty(content) ? "" : content); 109 | context.startActivity(intent); 110 | } 111 | ``` 112 | 113 | ### 获取手机联系人 114 | ``` java 115 | /** 116 | * 获取手机联系人 117 | *

需添加权限 118 | *

需添加权限 119 | */ 120 | public static List> getAllContactInfo(Context context) { 121 | SystemClock.sleep(3000); 122 | ArrayList> list = new ArrayList>(); 123 | // 1.获取内容解析者 124 | ContentResolver resolver = context.getContentResolver(); 125 | // 2.获取内容提供者的地址:com.android.contacts 126 | // raw_contacts表的地址 :raw_contacts 127 | // view_data表的地址 : data 128 | // 3.生成查询地址 129 | Uri raw_uri = Uri.parse("content://com.android.contacts/raw_contacts"); 130 | Uri date_uri = Uri.parse("content://com.android.contacts/data"); 131 | // 4.查询操作,先查询raw_contacts,查询contact_id 132 | // projection : 查询的字段 133 | Cursor cursor = resolver.query(raw_uri, new String[] { "contact_id" }, 134 | null, null, null); 135 | // 5.解析cursor 136 | while (cursor.moveToNext()) { 137 | // 6.获取查询的数据 138 | String contact_id = cursor.getString(0); 139 | // cursor.getString(cursor.getColumnIndex("contact_id"));//getColumnIndex 140 | // : 查询字段在cursor中索引值,一般都是用在查询字段比较多的时候 141 | // 判断contact_id是否为空 142 | if (!TextUtils.isEmpty(contact_id)) {//null "" 143 | // 7.根据contact_id查询view_data表中的数据 144 | // selection : 查询条件 145 | // selectionArgs :查询条件的参数 146 | // sortOrder : 排序 147 | // 空指针: 1.null.方法 2.参数为null 148 | Cursor c = resolver.query(date_uri, new String[] { "data1", 149 | "mimetype" }, "raw_contact_id=?", 150 | new String[] { contact_id }, null); 151 | HashMap map = new HashMap(); 152 | // 8.解析c 153 | while (c.moveToNext()) { 154 | // 9.获取数据 155 | String data1 = c.getString(0); 156 | String mimetype = c.getString(1); 157 | // 10.根据类型去判断获取的data1数据并保存 158 | if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { 159 | // 电话 160 | map.put("phone", data1); 161 | } else if (mimetype.equals("vnd.android.cursor.item/name")) { 162 | // 姓名 163 | map.put("name", data1); 164 | } 165 | } 166 | // 11.添加到集合中数据 167 | list.add(map); 168 | // 12.关闭cursor 169 | c.close(); 170 | } 171 | } 172 | // 12.关闭cursor 173 | cursor.close(); 174 | return list; 175 | } 176 | ``` 177 | 178 | ### 打开手机联系人界面点击联系人后便获取该号码 179 | ``` java 180 | /** 181 | * 打开手机联系人界面点击联系人后便获取该号码 182 | *

参照以下注释代码 183 | */ 184 | public static void getContantNum() { 185 | Log.i("tips", "U should copy the follow code."); 186 | /* 187 | Intent intent = new Intent(); 188 | intent.setAction("android.intent.action.PICK"); 189 | intent.setType("vnd.android.cursor.dir/phone_v2"); 190 | startActivityForResult(intent, 0); 191 | @Override 192 | protected void onActivityResult ( int requestCode, int resultCode, Intent data){ 193 | super.onActivityResult(requestCode, resultCode, data); 194 | if (data != null) { 195 | Uri uri = data.getData(); 196 | String num = null; 197 | // 创建内容解析者 198 | ContentResolver contentResolver = getContentResolver(); 199 | Cursor cursor = contentResolver.query(uri, 200 | null, null, null, null); 201 | while (cursor.moveToNext()) { 202 | num = cursor.getString(cursor.getColumnIndex("data1")); 203 | } 204 | cursor.close(); 205 | num = num.replaceAll("-", "");//替换的操作,555-6 -> 5556 206 | } 207 | } 208 | */ 209 | } 210 | ``` 211 | 212 | ### 获取手机短信并保存到xml中 213 | ``` java 214 | /** 215 | * 获取手机短信并保存到xml中 216 | *

需添加权限 217 | *

需添加权限 218 | */ 219 | public static void getAllSMS(Context context) { 220 | //1.获取短信 221 | //1.1获取内容解析者 222 | ContentResolver resolver = context.getContentResolver(); 223 | //1.2获取内容提供者地址 sms,sms表的地址:null 不写 224 | //1.3获取查询路径 225 | Uri uri = Uri.parse("content://sms"); 226 | //1.4.查询操作 227 | //projection : 查询的字段 228 | //selection : 查询的条件 229 | //selectionArgs : 查询条件的参数 230 | //sortOrder : 排序 231 | Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null); 232 | //设置最大进度 233 | int count = cursor.getCount();//获取短信的个数 234 | //2.备份短信 235 | //2.1获取xml序列器 236 | XmlSerializer xmlSerializer = Xml.newSerializer(); 237 | try { 238 | //2.2设置xml文件保存的路径 239 | //os : 保存的位置 240 | //encoding : 编码格式 241 | xmlSerializer.setOutput(new FileOutputStream(new File("/mnt/sdcard/backupsms.xml")), "utf-8"); 242 | //2.3设置头信息 243 | //standalone : 是否独立保存 244 | xmlSerializer.startDocument("utf-8", true); 245 | //2.4设置根标签 246 | xmlSerializer.startTag(null, "smss"); 247 | //1.5.解析cursor 248 | while (cursor.moveToNext()) { 249 | SystemClock.sleep(1000); 250 | //2.5设置短信的标签 251 | xmlSerializer.startTag(null, "sms"); 252 | //2.6设置文本内容的标签 253 | xmlSerializer.startTag(null, "address"); 254 | String address = cursor.getString(0); 255 | //2.7设置文本内容 256 | xmlSerializer.text(address); 257 | xmlSerializer.endTag(null, "address"); 258 | xmlSerializer.startTag(null, "date"); 259 | String date = cursor.getString(1); 260 | xmlSerializer.text(date); 261 | xmlSerializer.endTag(null, "date"); 262 | xmlSerializer.startTag(null, "type"); 263 | String type = cursor.getString(2); 264 | xmlSerializer.text(type); 265 | xmlSerializer.endTag(null, "type"); 266 | xmlSerializer.startTag(null, "body"); 267 | String body = cursor.getString(3); 268 | xmlSerializer.text(body); 269 | xmlSerializer.endTag(null, "body"); 270 | xmlSerializer.endTag(null, "sms"); 271 | System.out.println("address:" + address + " date:" + date + " type:" + type + " body:" + body); 272 | } 273 | xmlSerializer.endTag(null, "smss"); 274 | xmlSerializer.endDocument(); 275 | //2.8将数据刷新到文件中 276 | xmlSerializer.flush(); 277 | } catch (Exception e) { 278 | // TODO Auto-generated catch block 279 | e.printStackTrace(); 280 | } 281 | } 282 | ``` 283 | -------------------------------------------------------------------------------- /about_regular.md: -------------------------------------------------------------------------------- 1 | # 正则相关 2 | ### 正则工具类 3 | ``` java 4 | import android.text.TextUtils; 5 | 6 | import java.util.regex.Pattern; 7 | 8 | /********************************************* 9 | * author: Blankj on 2016/8/2 21:19 10 | * blog: http://blankj.com 11 | * e-mail: blankj@qq.com 12 | *********************************************/ 13 | public class RegularUtils { 14 | 15 | private RegularUtils() { 16 | throw new UnsupportedOperationException("u can't fuck me..."); 17 | } 18 | 19 | /** 20 | * 验证手机号(简单) 21 | */ 22 | private static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$"; 23 | /** 24 | * 验证手机号(精确) 25 | *

26 | *

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

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

电信:133、153、173、177、180、181、189 29 | *

全球星:1349 30 | *

虚拟运营商:170 31 | */ 32 | private static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-8])|(17[0,3,5-8])|(18[0-9])|(147))\\d{8}$"; 33 | /** 34 | * 验证座机号,正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx/ 35 | */ 36 | private static final String REGEX_TEL = "^0\\d{2,3}[- ]?\\d{7,8}"; 37 | /** 38 | * 验证邮箱 39 | */ 40 | private static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; 41 | /** 42 | * 验证url 43 | */ 44 | private static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?"; 45 | /** 46 | * 验证汉字 47 | */ 48 | private static final String REGEX_CHZ = "^[\\u4e00-\\u9fa5]+$"; 49 | /** 50 | * 验证用户名,取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位 51 | */ 52 | private static final String REGEX_USERNAME = "^[\\w\\u4e00-\\u9fa5]{6,20}(?= 19方可使用) 26 | ``` java 27 | /** 28 | * 设置透明状态栏(api >= 19方可使用) 29 | *

可在Activity的onCreat()中调用 30 | *

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

android:clipToPadding="true" 32 | *

android:fitsSystemWindows="true" 33 | */ 34 | public static void setTransparentStatusBar(Activity activity) { 35 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 36 | //透明状态栏 37 | activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS); 38 | //透明导航栏 39 | activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 40 | } 41 | } 42 | ``` 43 | 44 | ### 隐藏状态栏 45 | ``` java 46 | /** 47 | * 隐藏状态栏 48 | *

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

此方法Activity可以继承AppCompatActivity 50 | *

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

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

如加了以上配置Activity不能继承AppCompatActivity,会报错 53 | */ 54 | public static void hideStatusBar(Activity activity) { 55 | activity.requestWindowFeature(Window.FEATURE_NO_TITLE); 56 | activity.getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, 57 | LayoutParams.FLAG_FULLSCREEN); 58 | } 59 | ``` 60 | 61 | ### 获取状态栏高度 62 | ``` java 63 | /** 64 | * 获取状态栏高度 65 | */ 66 | public static int getStatusBarHeight(Context context) { 67 | int result = 0; 68 | int resourceId = context.getResources() 69 | .getIdentifier("status_bar_height", "dimen", "android"); 70 | if (resourceId > 0) { 71 | result = context.getResources().getDimensionPixelSize(resourceId); 72 | } 73 | return result; 74 | } 75 | ``` 76 | 77 | ### 判断状态栏是否存在 78 | ``` java 79 | /** 80 | * 判断状态栏是否存在 81 | * 82 | * @param activity 83 | * @return

87 | */ 88 | public static boolean isStatusBarExists(Activity activity) { 89 | WindowManager.LayoutParams params = activity.getWindow().getAttributes(); 90 | return (params.flags & LayoutParams.FLAG_FULLSCREEN) != LayoutParams.FLAG_FULLSCREEN; 91 | } 92 | ``` 93 | 94 | ### 获取ActionBar高度 95 | ``` java 96 | /** 97 | * 获取ActionBar高度 98 | */ 99 | public static int getActionBarHeight(Activity activity) { 100 | TypedValue tv = new TypedValue(); 101 | if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { 102 | return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics()); 103 | } 104 | return 0; 105 | } 106 | ``` 107 | 108 | ### 设置屏幕为横屏 109 | ``` 110 | /** 111 | * 设置屏幕为横屏 112 | *

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

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

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

设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时 116 | * 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法 117 | */ 118 | public static void setLandscape(Activity activity) { 119 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 120 | } 121 | ``` 122 | 123 | ### 获取当前屏幕截图 124 | ``` java 125 | /** 126 | * 获取当前屏幕截图,包含状态栏 127 | */ 128 | public static Bitmap captureWithStatusBar(Activity activity) { 129 | View view = activity.getWindow().getDecorView(); 130 | view.setDrawingCacheEnabled(true); 131 | view.buildDrawingCache(); 132 | Bitmap bmp = view.getDrawingCache(); 133 | int width = getScreenWidth(activity); 134 | int height = getScreenHeight(activity); 135 | Bitmap bp = Bitmap.createBitmap(bmp, 0, 0, width, height); 136 | view.destroyDrawingCache(); 137 | return bp; 138 | } 139 | 140 | /** 141 | * 获取当前屏幕截图,不包含状态栏 142 | *

需要用到上面获取状态栏高度的方法 143 | */ 144 | public static Bitmap captureWithoutStatusBar(Activity activity) { 145 | View view = activity.getWindow().getDecorView(); 146 | view.setDrawingCacheEnabled(true); 147 | view.buildDrawingCache(); 148 | Bitmap bmp = view.getDrawingCache(); 149 | int statusBarHeight = getStatusBarHeight(activity); 150 | int width = getScreenWidth(activity); 151 | int height = getScreenHeight(activity); 152 | Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); 153 | view.destroyDrawingCache(); 154 | return bp; 155 | } 156 | ``` 157 | 158 | ### 判断是否锁屏 159 | ``` java 160 | /** 161 | * 判断是否锁屏 162 | */ 163 | public static boolean isScreenLock(Context context) { 164 | KeyguardManager km = (KeyguardManager) context 165 | .getSystemService(Context.KEYGUARD_SERVICE); 166 | return km.inKeyguardRestrictedInputMode(); 167 | } 168 | ``` 169 | 170 | *** 171 | # 尺寸相关 172 | ### dp与px转换 173 | ``` java 174 | /** 175 | * dp转px 176 | */ 177 | public static int dp2px(Context context, float dpValue) { 178 | final float scale = context.getResources().getDisplayMetrics().density; 179 | return (int) (dpValue * scale + 0.5f); 180 | } 181 | 182 | /** 183 | * px转dp 184 | */ 185 | public static int px2dp(Context context, float pxValue) { 186 | final float scale = context.getResources().getDisplayMetrics().density; 187 | return (int) (pxValue / scale + 0.5f); 188 | } 189 | ``` 190 | -------------------------------------------------------------------------------- /about_size.md: -------------------------------------------------------------------------------- 1 | # 尺寸相关 2 | ### dp与px转换 3 | ``` java 4 | /** 5 | * dp转px 6 | */ 7 | public static int dp2px(Context context, float dpValue) { 8 | final float scale = context.getResources().getDisplayMetrics().density; 9 | return (int) (dpValue * scale + 0.5f); 10 | } 11 | 12 | /** 13 | * px转dp 14 | */ 15 | public static int px2dp(Context context, float pxValue) { 16 | final float scale = context.getResources().getDisplayMetrics().density; 17 | return (int) (pxValue / scale + 0.5f); 18 | } 19 | ``` 20 | 21 | ### sp与px转换 22 | ``` java 23 | /** 24 | * sp转px 25 | */ 26 | public static int sp2px(Context context, float spValue) { 27 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 28 | return (int) (spValue * fontScale + 0.5f); 29 | } 30 | 31 | /** 32 | * px转sp 33 | */ 34 | public static int px2sp(Context context, float pxValue) { 35 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 36 | return (int) (pxValue / fontScale + 0.5f); 37 | } 38 | ``` 39 | 40 | ### 各种单位转换 41 | ``` java 42 | /** 43 | * 各种单位转换 44 | *

该方法存在于TypedValue 45 | */ 46 | public static float applyDimension(int unit, float value, DisplayMetrics metrics) { 47 | switch (unit) { 48 | case TypedValue.COMPLEX_UNIT_PX: 49 | return value; 50 | case TypedValue.COMPLEX_UNIT_DIP: 51 | return value * metrics.density; 52 | case TypedValue.COMPLEX_UNIT_SP: 53 | return value * metrics.scaledDensity; 54 | case TypedValue.COMPLEX_UNIT_PT: 55 | return value * metrics.xdpi * (1.0f / 72); 56 | case TypedValue.COMPLEX_UNIT_IN: 57 | return value * metrics.xdpi; 58 | case TypedValue.COMPLEX_UNIT_MM: 59 | return value * metrics.xdpi * (1.0f / 25.4f); 60 | } 61 | return 0; 62 | } 63 | ``` 64 | 65 | ### 在onCreate()即可强行获取View的尺寸 66 | ``` java 67 | /** 68 | * 在onCreate()即可强行获取View的尺寸 69 | *

需回调onGetSizeListener接口,在onGetSize中获取view宽高 70 | * 用法示例如下所示 71 | * SizeUtils.forceGetViewSize(view); 72 | * SizeUtils.setListener(new SizeUtils.onGetSizeListener() { 73 | * @Override 74 | * public void onGetSize(View view) { 75 | * Log.d("tag", view.getWidth() + " " + view.getHeight()); 76 | * } 77 | * }); 78 | */ 79 | public static void forceGetViewSize(final View view) { 80 | view.post(new Runnable() { 81 | @Override 82 | public void run() { 83 | if (mListener != null) { 84 | mListener.onGetSize(view); 85 | } 86 | } 87 | }); 88 | } 89 | 90 | /** 91 | * 获取到View尺寸的监听 92 | */ 93 | public interface onGetSizeListener { 94 | void onGetSize(View view); 95 | } 96 | 97 | public static void setListener(onGetSizeListener listener) { 98 | mListener = listener; 99 | } 100 | 101 | private static onGetSizeListener mListener; 102 | ``` 103 | 104 | ### ListView中提前测量View尺寸 105 | ``` java 106 | /** 107 | * ListView中提前测量View尺寸,如headerView 108 | *

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

参照以下注释代码 110 | */ 111 | public static void measureViewInLV(View view) { 112 | Log.i("tips", "U should copy the follow code."); 113 | /* 114 | ViewGroup.LayoutParams p = view.getLayoutParams(); 115 | if (p == null) { 116 | p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 117 | ViewGroup.LayoutParams.WRAP_CONTENT); 118 | } 119 | int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); 120 | int height; 121 | int tempHeight = p.height; 122 | if (tempHeight > 0) { 123 | height = MeasureSpec.makeMeasureSpec(tempHeight, 124 | MeasureSpec.EXACTLY); 125 | } else { 126 | height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 127 | } 128 | view.measure(width, height); 129 | */ 130 | } 131 | ``` 132 | -------------------------------------------------------------------------------- /about_time.md: -------------------------------------------------------------------------------- 1 | # 时间相关 2 | ### 将时间戳转为时间字符串 3 | ``` java 4 | /** 5 | * 将时间戳转为时间字符串 6 | *

格式为yyyy-MM-dd HH:mm:ss 7 | */ 8 | public static String milliseconds2String(long milliseconds) { 9 | return milliseconds2String(milliseconds, DEFAULT_SDF); 10 | } 11 | 12 | /** 13 | * 将时间戳转为时间字符串 14 | *

格式为用户自定义 15 | */ 16 | public static String milliseconds2String(long milliseconds, SimpleDateFormat format) { 17 | return format.format(new Date(milliseconds)); 18 | } 19 | ``` 20 | 21 | ### 将时间字符串转为时间戳 22 | ``` java 23 | /** 24 | * 将时间字符串转为时间戳 25 | *

格式为yyyy-MM-dd HH:mm:ss 26 | */ 27 | public static long string2Milliseconds(String time) { 28 | return string2Milliseconds(time, DEFAULT_SDF); 29 | } 30 | 31 | /** 32 | * 将时间字符串转为时间戳 33 | *

格式为用户自定义 34 | */ 35 | public static long string2Milliseconds(String time, SimpleDateFormat format) { 36 | try { 37 | return format.parse(time).getTime(); 38 | } catch (ParseException e) { 39 | e.printStackTrace(); 40 | } 41 | return -1; 42 | } 43 | ``` 44 | 45 | ### 将时间字符串转为Date类型 46 | ``` java 47 | /** 48 | * 将时间字符串转为Date类型 49 | *

格式为yyyy-MM-dd HH:mm:ss 50 | */ 51 | public static Date string2Date(String formatDate) { 52 | return string2Date(formatDate, DEFAULT_SDF); 53 | } 54 | 55 | /** 56 | * 将时间字符串转为Date类型 57 | *

格式为用户自定义 58 | */ 59 | public static Date string2Date(String formatDate, SimpleDateFormat format) { 60 | return new Date(string2Milliseconds(formatDate, format)); 61 | } 62 | ``` 63 | 64 | ### 将Date类型转为时间字符串 65 | ``` java 66 | /** 67 | * 将Date类型转为时间字符串 68 | *

格式为yyyy-MM-dd HH:mm:ss 69 | */ 70 | public static String date2String(Date date) { 71 | return date2String(date, DEFAULT_SDF); 72 | } 73 | 74 | /** 75 | * 将Date类型转为时间字符串 76 | *

格式为用户自定义 77 | */ 78 | public static String date2String(Date date, SimpleDateFormat format) { 79 | return format.format(date); 80 | } 81 | ``` 82 | 83 | ### 将Date类型转为时间戳 84 | ``` java 85 | /** 86 | * 将Date类型转为时间戳 87 | */ 88 | public static long date2Milliseconds(Date date) { 89 | return date.getTime(); 90 | } 91 | ``` 92 | 93 | ### 将时间戳转为Date类型 94 | ``` java 95 | /** 96 | * 将时间戳转为Date类型 97 | */ 98 | public static Date milliseconds2Date(long milliseconds) { 99 | return new Date(milliseconds); 100 | } 101 | ``` 102 | 103 | ### 毫秒时间戳单位转换(单位:unit) 104 | ``` java 105 | /** 106 | * 毫秒时间戳单位转换(单位:unit) 107 | *

108 |  * UNIT_MSEC:毫秒
109 |  * UNIT_SEC :秒
110 |  * UNIT_MIN :分
111 |  * UNIT_HOUR:小时
112 |  * UNIT_DAY :天
113 |  * 
114 | */ 115 | private static long milliseconds2Unit(long milliseconds, int unit) { 116 | switch (unit) { 117 | case UNIT_MSEC: 118 | case UNIT_SEC: 119 | case UNIT_MIN: 120 | case UNIT_HOUR: 121 | case UNIT_DAY: 122 | return Math.abs(milliseconds) / unit; 123 | } 124 | return -1; 125 | } 126 | ``` 127 | 128 | ### 获取两个时间差(单位:unit) 129 | ``` java 130 | /** 131 | * 获取两个时间差(单位:unit) 132 | *
133 |  * UNIT_MSEC:毫秒
134 |  * UNIT_SEC :秒
135 |  * UNIT_MIN :分
136 |  * UNIT_HOUR:小时
137 |  * UNIT_DAY :天
138 |  * 
139 | *

time1和time2格式都为yyyy-MM-dd HH:mm:ss 140 | */ 141 | public static long getIntervalTime(String time1, String time2, int unit) { 142 | return getIntervalTime(time1, time2, unit, DEFAULT_SDF); 143 | } 144 | 145 | /** 146 | * 获取两个时间差(单位:unit) 147 | *

148 |  * UNIT_MSEC:毫秒
149 |  * UNIT_SEC :秒
150 |  * UNIT_MIN :分
151 |  * UNIT_HOUR:小时
152 |  * UNIT_DAY :天
153 |  * 
154 | *

time1和time2格式都为format 155 | */ 156 | public static long getIntervalTime(String time1, String time2, int unit, SimpleDateFormat for 157 | return milliseconds2Unit(string2Milliseconds(time1, format) 158 | - string2Milliseconds(time2, format), unit); 159 | } 160 | 161 | /** 162 | * 获取两个时间差(单位:unit) 163 | *

164 |  * UNIT_MSEC:毫秒
165 |  * UNIT_SEC :秒
166 |  * UNIT_MIN :分
167 |  * UNIT_HOUR:小时
168 |  * UNIT_DAY :天
169 |  * 
170 | *

time1和time2都为Date 171 | */ 172 | public static long getIntervalTime(Date time1, Date time2, int unit) { 173 | return milliseconds2Unit(date2Milliseconds(time2) - date2Milliseconds(time1), unit); 174 | } 175 | ``` 176 | 177 | ### 获取当前时间 178 | ``` java 179 | /** 180 | * 获取当前时间 181 | *

单位(毫秒) 182 | */ 183 | public static long getCurTimeMills() { 184 | return System.currentTimeMillis(); 185 | } 186 | 187 | /** 188 | * 获取当前时间 189 | *

格式为yyyy-MM-dd HH:mm:ss 190 | */ 191 | public static String getCurTimeString() { 192 | return milliseconds2String(getCurTimeMills()); 193 | } 194 | 195 | /** 196 | * 获取当前时间 197 | *

格式为用户自定义 198 | */ 199 | public static String getCurTimeString(SimpleDateFormat format) { 200 | return milliseconds2String(getCurTimeMills(), format); 201 | } 202 | 203 | /** 204 | * 获取当前时间 205 | *

Date类型 206 | */ 207 | public static Date getCurTimeDate() { 208 | return new Date(); 209 | } 210 | ``` 211 | 212 | ### 获取与当前时间的差(单位:unit) 213 | ``` java 214 | /** 215 | * 获取与当前时间的差(单位:unit) 216 | *

217 |  * UNIT_MSEC:毫秒
218 |  * UNIT_SEC :秒
219 |  * UNIT_MIN :分
220 |  * UNIT_HOUR:小时
221 |  * UNIT_DAY :天
222 |  * 

time1和time2格式都为yyyy-MM-dd HH:mm:ss 223 | */ 224 | public static long getIntervalByNow(String time, int unit) { 225 | return getIntervalByNow(time, unit, DEFAULT_SDF); 226 | } 227 | 228 | /** 229 | * 获取与当前时间的差(单位:unit) 230 | *

231 |  * UNIT_MSEC:毫秒
232 |  * UNIT_SEC :秒
233 |  * UNIT_MIN :分
234 |  * UNIT_HOUR:小时
235 |  * UNIT_DAY :天
236 |  * 

time1和time2格式都为format 237 | */ 238 | public static long getIntervalByNow(String time, int unit, SimpleDateFormat format) { 239 | return getIntervalTime(getCurTimeString(), time, unit, format); 240 | } 241 | 242 | /** 243 | * 获取与当前时间的差(单位:unit) 244 | *

245 |  * UNIT_MSEC:毫秒
246 |  * UNIT_SEC :秒
247 |  * UNIT_MIN :分
248 |  * UNIT_HOUR:小时
249 |  * UNIT_DAY :天
250 |  * 

time1和time2格式都为format 251 | */ 252 | public static long getIntervalByNow(Date time, int unit) { 253 | return getIntervalTime(getCurTimeDate(), time, unit); 254 | } 255 | ``` 256 | 257 | ### 判断闰年 258 | ``` java 259 | /** 260 | * 判断闰年 261 | */ 262 | public static boolean isLeapYear(int year) { 263 | return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 264 | } 265 | ``` 266 | -------------------------------------------------------------------------------- /about_unclassified.md: -------------------------------------------------------------------------------- 1 | # 未归类 2 | ### 获取服务是否开启 3 | ``` 4 | /** 5 | * 获取服务是否开启 6 | * @param className 完整包名的服务类名 7 | */ 8 | public static boolean isRunningService(String className, Context context) { 9 | // 进程的管理者,活动的管理者 10 | ActivityManager activityManager = (ActivityManager) 11 | context.getSystemService(Context.ACTIVITY_SERVICE); 12 | // 获取正在运行的服务,最多获取1000个 13 | List runningServices = activityManager.getRunningServices(1000); 14 | // 遍历集合 15 | for (RunningServiceInfo runningServiceInfo : runningServices) { 16 | ComponentName service = runningServiceInfo.service; 17 | if (className.equals(service.getClassName())) { 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /update_log.md: -------------------------------------------------------------------------------- 1 | # 更新Log 2 | #### 2016/07/31 新增点击屏幕空白区域隐藏软键盘 3 | #### 2016/07/31 未能成功增加本页目录跳转功能(不支持) 4 | #### 2016/08/01 新增获取当前App版本Code 5 | #### 2016/08/01 新增目录中显示方法名 6 | #### 2016/08/01 新增获取SD卡路径,手机和设备进行分类,代码bug修改部分,小修排版,正在封装类 7 | #### 2016/08/02 wifi设置界面bug修复,注释排版还在修改,获取mac地址增加判空,新增QQ群:74721490,欢迎加入 8 | #### 2016/08/02 新增隐藏状态栏,注释更加全面,工具类已封装,写的时候真的是一个一个测试过去的,宝宝心里苦 9 | #### 2016/08/03 修复在onCreate中获取view尺寸的bug,MD5和SHA的Bug修复完成(在此感谢ssyijiu) 10 | #### 2016/08/04 新增时间工具类(在此感谢yi520000给的补充),手机正则分简单和精确(在此感谢MIkeeJY),新增判断是否锁屏,注释分段落,目录按首字母排序 11 | #### 2016/08/05 加密新增MD5盐加密,完善NetworkUtils,新增判断状态栏是否存在(在此感谢tiandawu) 12 | #### 2016/08/06 重命名包名,新增加密相关的单元测试,MD5加密新增文件加密重载。 -------------------------------------------------------------------------------- /utilcode/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /utilcode/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "24.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 11 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | compile 'com.android.support:appcompat-v7:24.1.1' 25 | } 26 | -------------------------------------------------------------------------------- /utilcode/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in G:\Android_IDE\ADT\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /utilcode/src/androidTest/java/com/blankj/utilcode/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /utilcode/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.pm.ApplicationInfo; 8 | import android.content.pm.PackageInfo; 9 | import android.content.pm.PackageManager; 10 | import android.graphics.drawable.Drawable; 11 | import android.net.Uri; 12 | import android.text.TextUtils; 13 | 14 | import java.io.File; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /********************************************* 19 | * author: Blankj on 2016/8/2 1:53 20 | * blog: http://blankj.com 21 | * e-mail: blankj@qq.com 22 | *********************************************/ 23 | public class AppUtils { 24 | 25 | private AppUtils() { 26 | throw new UnsupportedOperationException("u can't fuck me..."); 27 | } 28 | 29 | /** 30 | * 安装指定路径下的Apk 31 | *

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

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

这里做不了回调,后续自己做处理 34 | */ 35 | public static boolean installApp(Context context, String filePath) { 36 | if (filePath != null && filePath.length() > 4 37 | && filePath.toLowerCase().substring(filePath.length() - 4).equals(".apk")) { 38 | Intent intent = new Intent(Intent.ACTION_VIEW); 39 | File file = new File(filePath); 40 | if (file.exists() && file.isFile() && file.length() > 0) { 41 | intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 42 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 43 | context.startActivity(intent); 44 | return true; 45 | } 46 | } 47 | return false; 48 | } 49 | 50 | /** 51 | * 卸载指定包名的App 52 | *

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

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

这里做不了回调,后续自己做处理 55 | */ 56 | public boolean uninstallApp(Context context, String packageName) { 57 | if (!TextUtils.isEmpty(packageName)) { 58 | Intent intent = new Intent(Intent.ACTION_DELETE); 59 | intent.setData(Uri.parse("package:" + packageName)); 60 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 61 | context.startActivity(intent); 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | /** 68 | * 封装App信息的Bean类 69 | */ 70 | public static class AppInfo { 71 | 72 | private String name; 73 | private Drawable icon; 74 | private String packagName; 75 | private String versionName; 76 | private int versionCode; 77 | private boolean isSD; 78 | private boolean isUser; 79 | 80 | public Drawable getIcon() { 81 | return icon; 82 | } 83 | 84 | public void setIcon(Drawable icon) { 85 | this.icon = icon; 86 | } 87 | 88 | public boolean isSD() { 89 | return isSD; 90 | } 91 | 92 | public void setSD(boolean SD) { 93 | isSD = SD; 94 | } 95 | 96 | public boolean isUser() { 97 | return isUser; 98 | } 99 | 100 | public void setUser(boolean user) { 101 | isUser = user; 102 | } 103 | 104 | public String getName() { 105 | return name; 106 | } 107 | 108 | public void setName(String name) { 109 | this.name = name; 110 | } 111 | 112 | public String getPackagName() { 113 | return packagName; 114 | } 115 | 116 | public void setPackagName(String packagName) { 117 | this.packagName = packagName; 118 | } 119 | 120 | public int getVersionCode() { 121 | return versionCode; 122 | } 123 | 124 | public void setVersionCode(int versionCode) { 125 | this.versionCode = versionCode; 126 | } 127 | 128 | public String getVersionName() { 129 | return versionName; 130 | } 131 | 132 | public void setVersionName(String versionName) { 133 | this.versionName = versionName; 134 | } 135 | 136 | /** 137 | * @param name 名称 138 | * @param icon 图标 139 | * @param packagName 包名 140 | * @param versionName 版本号 141 | * @param versionCode 版本Code 142 | * @param isSD 是否安装在SD卡 143 | * @param isUser 是否是用户程序 144 | */ 145 | public AppInfo(String name, Drawable icon, String packagName, 146 | String versionName, int versionCode, boolean isSD, boolean isUser) { 147 | this.setName(name); 148 | this.setIcon(icon); 149 | this.setPackagName(packagName); 150 | this.setVersionName(versionName); 151 | this.setVersionCode(versionCode); 152 | this.setSD(isSD); 153 | this.setUser(isUser); 154 | } 155 | 156 | /*@Override 157 | public String toString() { 158 | return getName() + "\n" 159 | + getIcon() + "\n" 160 | + getPackagName() + "\n" 161 | + getVersionName() + "\n" 162 | + getVersionCode() + "\n" 163 | + isSD() + "\n" 164 | + isUser() + "\n"; 165 | }*/ 166 | } 167 | 168 | /** 169 | * 获取当前App信息 170 | *

AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序) 171 | */ 172 | public static AppInfo getAppInfo(Context context) { 173 | PackageManager pm = context.getPackageManager(); 174 | PackageInfo pi = null; 175 | try { 176 | pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); 177 | } catch (PackageManager.NameNotFoundException e) { 178 | e.printStackTrace(); 179 | } 180 | return pi != null ? getBean(pm, pi) : null; 181 | } 182 | 183 | /** 184 | * 得到AppInfo的Bean 185 | */ 186 | private static AppInfo getBean(PackageManager pm, PackageInfo pi) { 187 | ApplicationInfo ai = pi.applicationInfo; 188 | String name = ai.loadLabel(pm).toString(); 189 | Drawable icon = ai.loadIcon(pm); 190 | String packageName = pi.packageName; 191 | String versionName = pi.versionName; 192 | int versionCode = pi.versionCode; 193 | boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; 194 | boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; 195 | return new AppInfo(name, icon, packageName, versionName, versionCode, isSD, isUser); 196 | } 197 | 198 | /** 199 | * 获取所有已安装App信息 200 | *

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

依赖上面的getBean方法 202 | */ 203 | public static List getAllAppsInfo(Context context) { 204 | List list = new ArrayList<>(); 205 | PackageManager pm = context.getPackageManager(); 206 | // 获取系统中安装的所有软件信息 207 | List installedPackages = pm.getInstalledPackages(0); 208 | for (PackageInfo pi : installedPackages) { 209 | if (pi != null) { 210 | list.add(getBean(pm, pi)); 211 | } 212 | } 213 | return list; 214 | } 215 | 216 | /** 217 | * 打开指定包名的App 218 | */ 219 | public static boolean openAppByPackageName(Context context, String packageName) { 220 | if (!TextUtils.isEmpty(packageName)) { 221 | PackageManager pm = context.getPackageManager(); 222 | Intent launchIntentForPackage = pm.getLaunchIntentForPackage(packageName); 223 | if (launchIntentForPackage != null) { 224 | context.startActivity(launchIntentForPackage); 225 | return true; 226 | } 227 | } 228 | return false; 229 | } 230 | 231 | /** 232 | * 打开指定包名的App应用信息界面 233 | */ 234 | public static boolean openAppInfo(Context context, String packageName) { 235 | if (!TextUtils.isEmpty(packageName)) { 236 | Intent intent = new Intent(); 237 | intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); 238 | intent.setData(Uri.parse("package:" + packageName)); 239 | context.startActivity(intent); 240 | return true; 241 | } 242 | return false; 243 | } 244 | 245 | /** 246 | * 可用来做App信息分享 247 | */ 248 | public static void shareAppInfo(Context context, String info) { 249 | if (!TextUtils.isEmpty(info)) { 250 | Intent intent = new Intent(Intent.ACTION_SEND); 251 | intent.setType("text/plain"); 252 | intent.putExtra(Intent.EXTRA_TEXT, info); 253 | context.startActivity(intent); 254 | } 255 | } 256 | 257 | /** 258 | * 判断当前App处于前台还是后台 259 | *

需添加 260 | *

并且必须是系统应用该方法才有效 261 | */ 262 | public static boolean isAppBackground(Context context) { 263 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 264 | @SuppressWarnings("deprecation") 265 | List tasks = am.getRunningTasks(1); 266 | if (!tasks.isEmpty()) { 267 | ComponentName topActivity = tasks.get(0).topActivity; 268 | if (!topActivity.getPackageName().equals(context.getPackageName())) { 269 | return true; 270 | } 271 | } 272 | return false; 273 | } 274 | } 275 | 276 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/DeviceUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.content.Context; 4 | import android.net.wifi.WifiInfo; 5 | import android.net.wifi.WifiManager; 6 | import android.os.Build; 7 | import android.os.Environment; 8 | 9 | import java.io.File; 10 | 11 | /********************************************* 12 | * author: Blankj on 2016/8/1 19:43 13 | * blog: http://blankj.com 14 | * e-mail: blankj@qq.com 15 | *********************************************/ 16 | public class DeviceUtils { 17 | 18 | private DeviceUtils() { 19 | throw new UnsupportedOperationException("u can't fuck me..."); 20 | } 21 | 22 | /** 23 | * 获取设备MAC地址 24 | *

需添加权限 25 | */ 26 | public static String getMacAddress(Context context) { 27 | String macAddress; 28 | WifiManager wifi = (WifiManager) context 29 | .getSystemService(Context.WIFI_SERVICE); 30 | WifiInfo info = wifi.getConnectionInfo(); 31 | macAddress = info.getMacAddress(); 32 | if (null == macAddress) { 33 | return ""; 34 | } 35 | macAddress = macAddress.replace(":", ""); 36 | return macAddress; 37 | } 38 | 39 | /** 40 | * 获取设备厂商,如Xiaomi 41 | */ 42 | public static String getManufacturer() { 43 | String MANUFACTURER = Build.MANUFACTURER; 44 | return MANUFACTURER; 45 | } 46 | 47 | /** 48 | * 获取设备型号,如MI2SC 49 | */ 50 | public static String getModel() { 51 | String model = Build.MODEL; 52 | if (model != null) { 53 | model = model.trim().replaceAll("\\s*", ""); 54 | } else { 55 | model = ""; 56 | } 57 | return model; 58 | } 59 | 60 | /** 61 | * 获取设备SD卡是否可用 62 | */ 63 | public static boolean isSDCardEnable() { 64 | return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); 65 | } 66 | 67 | /** 68 | * 获取设备SD卡路径 69 | *

一般是/storage/emulated/0/ 70 | */ 71 | public static String getSDCardPath() { 72 | return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/EncryptUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.nio.MappedByteBuffer; 7 | import java.nio.channels.FileChannel; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | 11 | /********************************************* 12 | * author: Blankj on 2016/8/2 21:22 13 | * blog: http://blankj.com 14 | * e-mail: blankj@qq.com 15 | *********************************************/ 16 | public class EncryptUtils { 17 | 18 | private EncryptUtils() { 19 | throw new UnsupportedOperationException("u can't fuck me..."); 20 | } 21 | 22 | /** 23 | * MD5加密 24 | * 25 | * @param data 明文字符串 26 | * @return 密文 27 | */ 28 | public static String getMD5(String data) { 29 | return getMD5(data.getBytes()); 30 | } 31 | 32 | /** 33 | * MD5加密 34 | * 35 | * @param data 明文字符串 36 | * @param salt 盐 37 | * @return 密文 38 | */ 39 | public static String getMD5(String data, String salt) { 40 | return bytes2Hex(encryptMD5((data + salt).getBytes())); 41 | } 42 | 43 | /** 44 | * MD5加密 45 | * 46 | * @param data 明文字节数组 47 | * @return 密文 48 | */ 49 | public static String getMD5(byte[] data) { 50 | return bytes2Hex(encryptMD5(data)); 51 | } 52 | 53 | /** 54 | * MD5加密 55 | * 56 | * @param data 明文字节数组 57 | * @param salt 盐字节数组 58 | * @return 密文 59 | */ 60 | public static String getMD5(byte[] data, byte[] salt) { 61 | byte[] dataSalt = new byte[data.length + salt.length]; 62 | System.arraycopy(data, 0, dataSalt, 0, data.length); 63 | System.arraycopy(salt, 0, dataSalt, data.length, salt.length); 64 | return bytes2Hex(encryptMD5(dataSalt)); 65 | } 66 | 67 | /** 68 | * MD5加密 69 | * 70 | * @param data 明文字节数组 71 | * @return 密文字节数组 72 | */ 73 | public static byte[] encryptMD5(byte[] data) { 74 | try { 75 | MessageDigest md = MessageDigest.getInstance("MD5"); 76 | md.update(data); 77 | return md.digest(); 78 | } catch (NoSuchAlgorithmException e) { 79 | e.printStackTrace(); 80 | } 81 | return new byte[0]; 82 | } 83 | 84 | /** 85 | * 获取文件的MD5校验码 86 | * 87 | * @param filePath 文件路径 88 | * @return 文件的MD5校验码 89 | */ 90 | public static String getMD5File(String filePath) { 91 | return getMD5File(new File(filePath)); 92 | } 93 | 94 | /** 95 | * 获取文件的MD5校验码 96 | * 97 | * @param file 文件 98 | * @return 文件的MD5校验码 99 | */ 100 | public static String getMD5File(File file) { 101 | FileInputStream in = null; 102 | try { 103 | in = new FileInputStream(file); 104 | FileChannel channel = in.getChannel(); 105 | MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); 106 | MessageDigest md = MessageDigest.getInstance("MD5"); 107 | md.update(buffer); 108 | return bytes2Hex(md.digest()); 109 | } catch (NoSuchAlgorithmException | IOException e) { 110 | e.printStackTrace(); 111 | } finally { 112 | if (in != null) { 113 | try { 114 | in.close(); 115 | } catch (IOException ignored) { 116 | } 117 | } 118 | } 119 | return ""; 120 | } 121 | 122 | /** 123 | * SHA加密 124 | * 125 | * @param data 明文字符串 126 | * @return 密文 127 | */ 128 | public static String getSHA(String data) { 129 | return getSHA(data.getBytes()); 130 | } 131 | 132 | /** 133 | * SHA加密 134 | * 135 | * @param data 明文字节数组 136 | * @return 密文 137 | */ 138 | public static String getSHA(byte[] data) { 139 | return bytes2Hex(encryptSHA(data)); 140 | } 141 | 142 | /** 143 | * SHA加密 144 | * 145 | * @param data 明文字节数组 146 | * @return 密文字节数组 147 | */ 148 | public static byte[] encryptSHA(byte[] data) { 149 | try { 150 | MessageDigest md = MessageDigest.getInstance("SHA"); 151 | md.update(data); 152 | return md.digest(); 153 | } catch (NoSuchAlgorithmException e) { 154 | e.printStackTrace(); 155 | } 156 | return new byte[0]; 157 | } 158 | 159 | /** 160 | * 一个byte转为2个hex字符 161 | */ 162 | public static String bytes2Hex(byte[] src) { 163 | char[] res = new char[src.length * 2]; 164 | final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 165 | for (int i = 0, j = 0; i < src.length; i++) { 166 | res[j++] = hexDigits[src[i] >>> 4 & 0x0f]; 167 | res[j++] = hexDigits[src[i] & 0x0f]; 168 | } 169 | return new String(res); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/KeyboardUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.inputmethod.InputMethodManager; 8 | import android.widget.EditText; 9 | 10 | /********************************************* 11 | * author: Blankj on 2016/8/2 21:18 12 | * blog: http://blankj.com 13 | * e-mail: blankj@qq.com 14 | *********************************************/ 15 | public class KeyboardUtils { 16 | 17 | private KeyboardUtils() { 18 | throw new UnsupportedOperationException("u can't fuck me..."); 19 | } 20 | 21 | /** 22 | * 动态隐藏软键盘 23 | */ 24 | public static void hideSoftInput(Activity activity) { 25 | View view = activity.getWindow().peekDecorView(); 26 | if (view != null) { 27 | InputMethodManager inputmanger = (InputMethodManager) activity 28 | .getSystemService(Context.INPUT_METHOD_SERVICE); 29 | inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0); 30 | } 31 | } 32 | 33 | /** 34 | * 动态隐藏软键盘 35 | */ 36 | public static void hideSoftInput(Context context, EditText edit) { 37 | edit.clearFocus(); 38 | InputMethodManager inputmanger = (InputMethodManager) context 39 | .getSystemService(Context.INPUT_METHOD_SERVICE); 40 | inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0); 41 | } 42 | 43 | /** 44 | * 点击屏幕空白区域隐藏软键盘(方法1) 45 | *

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

参照以下注释代码 47 | */ 48 | public static void clickBlankArea2HideSoftInput0() { 49 | Log.i("tips", "U should copy the following code."); 50 | /* 51 | @Override 52 | public boolean onTouchEvent (MotionEvent event){ 53 | if (null != this.getCurrentFocus()) { 54 | InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 55 | return mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); 56 | } 57 | return super.onTouchEvent(event); 58 | } 59 | */ 60 | } 61 | 62 | /** 63 | * 点击屏幕空白区域隐藏软键盘(方法2) 64 | *

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

需重写dispatchTouchEvent 66 | *

参照以下注释代码 67 | */ 68 | public static void clickBlankArea2HideSoftInput1() { 69 | Log.i("tips", "U should copy the following code."); 70 | /* 71 | @Override 72 | public boolean dispatchTouchEvent(MotionEvent ev) { 73 | if (ev.getAction() == MotionEvent.ACTION_DOWN) { 74 | View v = getCurrentFocus(); 75 | if (isShouldHideKeyboard(v, ev)) { 76 | hideKeyboard(v.getWindowToken()); 77 | } 78 | } 79 | return super.dispatchTouchEvent(ev); 80 | } 81 | 82 | // 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 83 | private boolean isShouldHideKeyboard(View v, MotionEvent event) { 84 | if (v != null && (v instanceof EditText)) { 85 | int[] l = {0, 0}; 86 | v.getLocationInWindow(l); 87 | int left = l[0], 88 | top = l[1], 89 | bottom = top + v.getHeight(), 90 | right = left + v.getWidth(); 91 | return !(event.getX() > left && event.getX() < right 92 | && event.getY() > top && event.getY() < bottom); 93 | } 94 | return false; 95 | } 96 | 97 | // 获取InputMethodManager,隐藏软键盘 98 | private void hideKeyboard(IBinder token) { 99 | if (token != null) { 100 | InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 101 | im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); 102 | } 103 | } 104 | */ 105 | } 106 | 107 | /** 108 | * 动态显示软键盘 109 | */ 110 | public static void showSoftInput(Context context, EditText edit) { 111 | edit.setFocusable(true); 112 | edit.setFocusableInTouchMode(true); 113 | edit.requestFocus(); 114 | InputMethodManager inputManager = (InputMethodManager) context 115 | .getSystemService(Context.INPUT_METHOD_SERVICE); 116 | inputManager.showSoftInput(edit, 0); 117 | } 118 | 119 | /** 120 | * 切换键盘显示与否状态 121 | */ 122 | public static void toggleSoftInput(Context context, EditText edit) { 123 | edit.setFocusable(true); 124 | edit.setFocusableInTouchMode(true); 125 | edit.requestFocus(); 126 | InputMethodManager inputManager = (InputMethodManager) context 127 | .getSystemService(Context.INPUT_METHOD_SERVICE); 128 | inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.ConnectivityManager; 7 | import android.net.NetworkInfo; 8 | import android.telephony.TelephonyManager; 9 | 10 | /********************************************* 11 | * author: Blankj on 2016/8/1 21:33 12 | * blog: http://blankj.com 13 | * e-mail: blankj@qq.com 14 | *********************************************/ 15 | public class NetworkUtils { 16 | 17 | private NetworkUtils() { 18 | throw new UnsupportedOperationException("u can't fuck me..."); 19 | } 20 | 21 | /** 22 | * 打开网络设置界面 23 | *

3.0以下打开设置界面 24 | */ 25 | public static void openWirelessSettings(Context context) { 26 | if (android.os.Build.VERSION.SDK_INT > 10) { 27 | context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS)); 28 | } else { 29 | context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS)); 30 | } 31 | } 32 | 33 | /** 34 | * 判断是否网络连接 35 | *

需添加权限 36 | */ 37 | public static boolean isConnected(Context context) { 38 | ConnectivityManager cm = (ConnectivityManager) context 39 | .getSystemService(Activity.CONNECTIVITY_SERVICE); 40 | NetworkInfo info = cm.getActiveNetworkInfo(); 41 | return info != null && info.isConnected(); 42 | } 43 | 44 | /** 45 | * 判断wifi是否连接状态 46 | *

需添加权限 47 | */ 48 | public static boolean isWifiConnected(Context context) { 49 | ConnectivityManager cm = (ConnectivityManager) context 50 | .getSystemService(Context.CONNECTIVITY_SERVICE); 51 | return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; 52 | } 53 | 54 | /** 55 | * 获取移动网络运营商名称 56 | *

如中国联通、中国移动、中国电信 57 | */ 58 | public static String getNetworkOperatorName(Context context) { 59 | TelephonyManager tm = (TelephonyManager) context 60 | .getSystemService(Context.TELEPHONY_SERVICE); 61 | return tm != null ? tm.getNetworkOperatorName() : null; 62 | } 63 | 64 | /** 65 | * 获取移动终端类型 66 | *

 67 |      * PHONE_TYPE_NONE  : 0 手机制式未知
 68 |      * PHONE_TYPE_GSM   : 1 手机制式为GSM,移动和联通
 69 |      * PHONE_TYPE_CDMA  : 2 手机制式为CDMA,电信
 70 |      * PHONE_TYPE_SIP   : 3
 71 |      * 
 72 |      */
 73 |     public static int getPhoneType(Context context) {
 74 |         TelephonyManager tm = (TelephonyManager) context
 75 |                 .getSystemService(Context.TELEPHONY_SERVICE);
 76 |         return tm != null ? tm.getPhoneType() : -1;
 77 |     }
 78 | 
 79 |     /**
 80 |      * 获取手机连接的网络类型(2G,3G,4G)
 81 |      * 

联通的3G为UMTS或HSDPA,移动和联通的2G为GPRS或EGDE,电信的2G为CDMA,电信的3G为EVDO 82 | */ 83 | public static int getNetworkTpye(Context context) { 84 | TelephonyManager tm = (TelephonyManager) context 85 | .getSystemService(Context.TELEPHONY_SERVICE); 86 | switch (tm.getNetworkType()) { 87 | case TelephonyManager.NETWORK_TYPE_GPRS: 88 | case TelephonyManager.NETWORK_TYPE_EDGE: 89 | case TelephonyManager.NETWORK_TYPE_CDMA: 90 | case TelephonyManager.NETWORK_TYPE_1xRTT: 91 | case TelephonyManager.NETWORK_TYPE_IDEN: 92 | return Constants.NETWORK_CLASS_2_G; 93 | case TelephonyManager.NETWORK_TYPE_UMTS: 94 | case TelephonyManager.NETWORK_TYPE_EVDO_0: 95 | case TelephonyManager.NETWORK_TYPE_EVDO_A: 96 | case TelephonyManager.NETWORK_TYPE_HSDPA: 97 | case TelephonyManager.NETWORK_TYPE_HSUPA: 98 | case TelephonyManager.NETWORK_TYPE_HSPA: 99 | case TelephonyManager.NETWORK_TYPE_EVDO_B: 100 | case TelephonyManager.NETWORK_TYPE_EHRPD: 101 | case TelephonyManager.NETWORK_TYPE_HSPAP: 102 | return Constants.NETWORK_CLASS_3_G; 103 | case TelephonyManager.NETWORK_TYPE_LTE: 104 | return Constants.NETWORK_CLASS_4_G; 105 | default: 106 | return Constants.NETWORK_CLASS_UNKNOWN; 107 | } 108 | } 109 | 110 | public class Constants { 111 | // Unknown network class 112 | public static final int NETWORK_CLASS_UNKNOWN = 0; 113 | // wifi network 114 | public static final int NETWORK_WIFI = 1; 115 | // "2G" networks 116 | public static final int NETWORK_CLASS_2_G = 2; 117 | // "3G" networks 118 | public static final int NETWORK_CLASS_3_G = 3; 119 | // "4G" networks 120 | public static final int NETWORK_CLASS_4_G = 4; 121 | } 122 | 123 | /** 124 | * 获取当前手机的网络类型(WIFI,2G,3G,4G) 125 | *

需添加权限 126 | *

需要用到上面的方法 127 | */ 128 | public static int getCurNetworkType(Context context) { 129 | int netWorkType = Constants.NETWORK_CLASS_UNKNOWN; 130 | ConnectivityManager cm = (ConnectivityManager) context 131 | .getSystemService(Context.CONNECTIVITY_SERVICE); 132 | NetworkInfo networkInfo = cm.getActiveNetworkInfo(); 133 | if (networkInfo != null && networkInfo.isConnected()) { 134 | int type = networkInfo.getType(); 135 | if (type == ConnectivityManager.TYPE_WIFI) { 136 | netWorkType = Constants.NETWORK_WIFI; 137 | } else if (type == ConnectivityManager.TYPE_MOBILE) { 138 | netWorkType = getNetworkTpye(context); 139 | } 140 | } 141 | return netWorkType; 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/PhoneUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.os.SystemClock; 9 | import android.provider.Settings; 10 | import android.telephony.TelephonyManager; 11 | import android.text.TextUtils; 12 | import android.util.Log; 13 | import android.util.Xml; 14 | 15 | import org.xmlpull.v1.XmlSerializer; 16 | 17 | import java.io.File; 18 | import java.io.FileOutputStream; 19 | import java.util.ArrayList; 20 | import java.util.HashMap; 21 | import java.util.List; 22 | 23 | /********************************************* 24 | * author: Blankj on 2016/8/1 19:57 25 | * blog: http://blankj.com 26 | * e-mail: blankj@qq.com 27 | *********************************************/ 28 | public class PhoneUtils { 29 | 30 | private PhoneUtils() { 31 | throw new UnsupportedOperationException("u can't fuck me..."); 32 | } 33 | 34 | /** 35 | * 判断设备是否是手机 36 | */ 37 | public static boolean isPhone(Context context) { 38 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 39 | return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; 40 | } 41 | 42 | /** 43 | * 获取当前设备的IMIE 44 | *

需与上面的isPhone一起使用 45 | *

需添加权限 46 | */ 47 | public static String getDeviceIMEI(Context context) { 48 | String deviceId; 49 | if (isPhone(context)) { 50 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 51 | deviceId = tm.getDeviceId(); 52 | } else { 53 | deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); 54 | } 55 | return deviceId; 56 | } 57 | 58 | /** 59 | * 获取手机状态信息 60 | *

需添加权限 61 | *

返回如下 62 | *

 63 |      * DeviceId(IMEI) = 99000311726612
 64 |      * DeviceSoftwareVersion = 00
 65 |      * Line1Number =
 66 |      * NetworkCountryIso = cn
 67 |      * NetworkOperator = 46003
 68 |      * NetworkOperatorName = 中国电信
 69 |      * NetworkType = 6
 70 |      * honeType = 2
 71 |      * SimCountryIso = cn
 72 |      * SimOperator = 46003
 73 |      * SimOperatorName = 中国电信
 74 |      * SimSerialNumber = 89860315045710604022
 75 |      * SimState = 5
 76 |      * SubscriberId(IMSI) = 460030419724900
 77 |      * VoiceMailNumber = *86
 78 |      * 
 79 |      */
 80 |     public static String getPhoneStatus(Context context) {
 81 |         TelephonyManager tm = (TelephonyManager) context
 82 |                 .getSystemService(Context.TELEPHONY_SERVICE);
 83 |         String str = "";
 84 |         str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n";
 85 |         str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
 86 |         str += "Line1Number = " + tm.getLine1Number() + "\n";
 87 |         str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
 88 |         str += "NetworkOperator = " + tm.getNetworkOperator() + "\n";
 89 |         str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n";
 90 |         str += "NetworkType = " + tm.getNetworkType() + "\n";
 91 |         str += "honeType = " + tm.getPhoneType() + "\n";
 92 |         str += "SimCountryIso = " + tm.getSimCountryIso() + "\n";
 93 |         str += "SimOperator = " + tm.getSimOperator() + "\n";
 94 |         str += "SimOperatorName = " + tm.getSimOperatorName() + "\n";
 95 |         str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n";
 96 |         str += "SimState = " + tm.getSimState() + "\n";
 97 |         str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n";
 98 |         str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n";
 99 |         return str;
100 |     }
101 | 
102 |     /**
103 |      * 跳至填充好phoneNumber的拨号界面
104 |      */
105 |     public static void dial(Context context, String phoneNumber) {
106 |         context.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)));
107 |     }
108 | 
109 |     /**
110 |      * 拨打phoneNumber
111 |      * 

需添加权限 112 | */ 113 | public static void call(Context context, String phoneNumber) { 114 | context.startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber))); 115 | } 116 | 117 | /** 118 | * 发送短信 119 | */ 120 | public static void sendSms(Context context, String phoneNumber, String content) { 121 | Uri uri = Uri.parse("smsto:" + (TextUtils.isEmpty(phoneNumber) ? "" : phoneNumber)); 122 | Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 123 | intent.putExtra("sms_body", TextUtils.isEmpty(content) ? "" : content); 124 | context.startActivity(intent); 125 | } 126 | 127 | /** 128 | * 获取手机联系人 129 | *

需添加权限 130 | *

需添加权限 131 | */ 132 | public static List> getAllContactInfo(Context context) { 133 | SystemClock.sleep(3000); 134 | ArrayList> list = new ArrayList>(); 135 | // 1.获取内容解析者 136 | ContentResolver resolver = context.getContentResolver(); 137 | // 2.获取内容提供者的地址:com.android.contacts 138 | // raw_contacts表的地址 :raw_contacts 139 | // view_data表的地址 : data 140 | // 3.生成查询地址 141 | Uri raw_uri = Uri.parse("content://com.android.contacts/raw_contacts"); 142 | Uri date_uri = Uri.parse("content://com.android.contacts/data"); 143 | // 4.查询操作,先查询raw_contacts,查询contact_id 144 | // projection : 查询的字段 145 | Cursor cursor = resolver.query(raw_uri, new String[]{"contact_id"}, 146 | null, null, null); 147 | // 5.解析cursor 148 | while (cursor.moveToNext()) { 149 | // 6.获取查询的数据 150 | String contact_id = cursor.getString(0); 151 | // cursor.getString(cursor.getColumnIndex("contact_id"));//getColumnIndex 152 | // : 查询字段在cursor中索引值,一般都是用在查询字段比较多的时候 153 | // 判断contact_id是否为空 154 | if (!TextUtils.isEmpty(contact_id)) {//null "" 155 | // 7.根据contact_id查询view_data表中的数据 156 | // selection : 查询条件 157 | // selectionArgs :查询条件的参数 158 | // sortOrder : 排序 159 | // 空指针: 1.null.方法 2.参数为null 160 | Cursor c = resolver.query(date_uri, new String[]{"data1", 161 | "mimetype"}, "raw_contact_id=?", 162 | new String[]{contact_id}, null); 163 | HashMap map = new HashMap(); 164 | // 8.解析c 165 | while (c.moveToNext()) { 166 | // 9.获取数据 167 | String data1 = c.getString(0); 168 | String mimetype = c.getString(1); 169 | // 10.根据类型去判断获取的data1数据并保存 170 | if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { 171 | // 电话 172 | map.put("phone", data1); 173 | } else if (mimetype.equals("vnd.android.cursor.item/name")) { 174 | // 姓名 175 | map.put("name", data1); 176 | } 177 | } 178 | // 11.添加到集合中数据 179 | list.add(map); 180 | // 12.关闭cursor 181 | c.close(); 182 | } 183 | } 184 | // 12.关闭cursor 185 | cursor.close(); 186 | return list; 187 | } 188 | 189 | /** 190 | * 打开手机联系人界面点击联系人后便获取该号码 191 | *

参照以下注释代码 192 | */ 193 | public static void getContantNum() { 194 | Log.i("tips", "U should copy the following code."); 195 | /* 196 | Intent intent = new Intent(); 197 | intent.setAction("android.intent.action.PICK"); 198 | intent.setType("vnd.android.cursor.dir/phone_v2"); 199 | startActivityForResult(intent, 0); 200 | 201 | @Override 202 | protected void onActivityResult ( int requestCode, int resultCode, Intent data){ 203 | super.onActivityResult(requestCode, resultCode, data); 204 | if (data != null) { 205 | Uri uri = data.getData(); 206 | String num = null; 207 | // 创建内容解析者 208 | ContentResolver contentResolver = getContentResolver(); 209 | Cursor cursor = contentResolver.query(uri, 210 | null, null, null, null); 211 | while (cursor.moveToNext()) { 212 | num = cursor.getString(cursor.getColumnIndex("data1")); 213 | } 214 | cursor.close(); 215 | num = num.replaceAll("-", "");//替换的操作,555-6 -> 5556 216 | } 217 | } 218 | */ 219 | } 220 | 221 | /** 222 | * 获取手机短信并保存到xml中 223 | *

需添加权限 224 | *

需添加权限 225 | */ 226 | public static void getAllSMS(Context context) { 227 | //1.获取短信 228 | //1.1获取内容解析者 229 | ContentResolver resolver = context.getContentResolver(); 230 | //1.2获取内容提供者地址 sms,sms表的地址:null 不写 231 | //1.3获取查询路径 232 | Uri uri = Uri.parse("content://sms"); 233 | //1.4.查询操作 234 | //projection : 查询的字段 235 | //selection : 查询的条件 236 | //selectionArgs : 查询条件的参数 237 | //sortOrder : 排序 238 | Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null); 239 | //设置最大进度 240 | int count = cursor.getCount();//获取短信的个数 241 | //2.备份短信 242 | //2.1获取xml序列器 243 | XmlSerializer xmlSerializer = Xml.newSerializer(); 244 | try { 245 | //2.2设置xml文件保存的路径 246 | //os : 保存的位置 247 | //encoding : 编码格式 248 | xmlSerializer.setOutput(new FileOutputStream(new File("/mnt/sdcard/backupsms.xml")), "utf-8"); 249 | //2.3设置头信息 250 | //standalone : 是否独立保存 251 | xmlSerializer.startDocument("utf-8", true); 252 | //2.4设置根标签 253 | xmlSerializer.startTag(null, "smss"); 254 | //1.5.解析cursor 255 | while (cursor.moveToNext()) { 256 | SystemClock.sleep(1000); 257 | //2.5设置短信的标签 258 | xmlSerializer.startTag(null, "sms"); 259 | //2.6设置文本内容的标签 260 | xmlSerializer.startTag(null, "address"); 261 | String address = cursor.getString(0); 262 | //2.7设置文本内容 263 | xmlSerializer.text(address); 264 | xmlSerializer.endTag(null, "address"); 265 | xmlSerializer.startTag(null, "date"); 266 | String date = cursor.getString(1); 267 | xmlSerializer.text(date); 268 | xmlSerializer.endTag(null, "date"); 269 | xmlSerializer.startTag(null, "type"); 270 | String type = cursor.getString(2); 271 | xmlSerializer.text(type); 272 | xmlSerializer.endTag(null, "type"); 273 | xmlSerializer.startTag(null, "body"); 274 | String body = cursor.getString(3); 275 | xmlSerializer.text(body); 276 | xmlSerializer.endTag(null, "body"); 277 | xmlSerializer.endTag(null, "sms"); 278 | System.out.println("address:" + address + " date:" + date + " type:" + type + " body:" + body); 279 | } 280 | xmlSerializer.endTag(null, "smss"); 281 | xmlSerializer.endDocument(); 282 | //2.8将数据刷新到文件中 283 | xmlSerializer.flush(); 284 | } catch (Exception e) { 285 | // TODO Auto-generated catch block 286 | e.printStackTrace(); 287 | } 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/RegularUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.util.regex.Pattern; 6 | 7 | /********************************************* 8 | * author: Blankj on 2016/8/2 21:19 9 | * blog: http://blankj.com 10 | * e-mail: blankj@qq.com 11 | *********************************************/ 12 | public class RegularUtils { 13 | 14 | private RegularUtils() { 15 | throw new UnsupportedOperationException("u can't fuck me..."); 16 | } 17 | 18 | /** 19 | * 验证手机号(简单) 20 | */ 21 | private static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$"; 22 | /** 23 | * 验证手机号(精确) 24 | *

25 | *

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

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

电信:133、153、173、177、180、181、189 28 | *

全球星:1349 29 | *

虚拟运营商:170 30 | */ 31 | private static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-8])|(17[0,3,5-8])|(18[0-9])|(147))\\d{8}$"; 32 | /** 33 | * 验证座机号,正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx/ 34 | */ 35 | private static final String REGEX_TEL = "^0\\d{2,3}[- ]?\\d{7,8}"; 36 | /** 37 | * 验证邮箱 38 | */ 39 | private static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; 40 | /** 41 | * 验证url 42 | */ 43 | private static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?"; 44 | /** 45 | * 验证汉字 46 | */ 47 | private static final String REGEX_CHZ = "^[\\u4e00-\\u9fa5]+$"; 48 | /** 49 | * 验证用户名,取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位 50 | */ 51 | private static final String REGEX_USERNAME = "^[\\w\\u4e00-\\u9fa5]{6,20}(?= 19方可使用) 49 | *

可在Activity的onCreat()中调用 50 | *

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

android:clipToPadding="true" 52 | *

android:fitsSystemWindows="true" 53 | */ 54 | public static void setTransparentStatusBar(Activity activity) { 55 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 56 | //透明状态栏 57 | activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS); 58 | //透明导航栏 59 | activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 60 | } 61 | } 62 | 63 | /** 64 | * 隐藏状态栏 65 | *

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

此方法Activity可以继承AppCompatActivity 67 | *

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

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

如加了以上配置Activity不能继承AppCompatActivity,会报错 70 | */ 71 | public static void hideStatusBar(Activity activity) { 72 | activity.requestWindowFeature(Window.FEATURE_NO_TITLE); 73 | activity.getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, 74 | LayoutParams.FLAG_FULLSCREEN); 75 | } 76 | 77 | /** 78 | * 获取状态栏高度 79 | */ 80 | public static int getStatusBarHeight(Context context) { 81 | int result = 0; 82 | int resourceId = context.getResources() 83 | .getIdentifier("status_bar_height", "dimen", "android"); 84 | if (resourceId > 0) { 85 | result = context.getResources().getDimensionPixelSize(resourceId); 86 | } 87 | return result; 88 | } 89 | 90 | /** 91 | * 判断状态栏是否存在 92 | * 93 | * @param activity 94 | * @return

    95 | *
  • true: 存在
  • 96 | *
  • false: 不存在
  • 97 | *
98 | */ 99 | public static boolean isStatusBarExists(Activity activity) { 100 | LayoutParams params = activity.getWindow().getAttributes(); 101 | return (params.flags & LayoutParams.FLAG_FULLSCREEN) != LayoutParams.FLAG_FULLSCREEN; 102 | } 103 | 104 | /** 105 | * 获取ActionBar高度 106 | */ 107 | public static int getActionBarHeight(Activity activity) { 108 | TypedValue tv = new TypedValue(); 109 | if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { 110 | return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics()); 111 | } 112 | return 0; 113 | } 114 | 115 | /** 116 | * 设置屏幕为横屏 117 | *

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

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

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

设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时 121 | * 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法 122 | */ 123 | public static void setLandscape(Activity activity) { 124 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 125 | } 126 | 127 | /** 128 | * 获取当前屏幕截图,包含状态栏 129 | */ 130 | public static Bitmap captureWithStatusBar(Activity activity) { 131 | View view = activity.getWindow().getDecorView(); 132 | view.setDrawingCacheEnabled(true); 133 | view.buildDrawingCache(); 134 | Bitmap bmp = view.getDrawingCache(); 135 | int width = getScreenWidth(activity); 136 | int height = getScreenHeight(activity); 137 | Bitmap bp = Bitmap.createBitmap(bmp, 0, 0, width, height); 138 | view.destroyDrawingCache(); 139 | return bp; 140 | } 141 | 142 | /** 143 | * 获取当前屏幕截图,不包含状态栏 144 | *

需要用到上面获取状态栏高度的方法 145 | */ 146 | public static Bitmap captureWithoutStatusBar(Activity activity) { 147 | View view = activity.getWindow().getDecorView(); 148 | view.setDrawingCacheEnabled(true); 149 | view.buildDrawingCache(); 150 | Bitmap bmp = view.getDrawingCache(); 151 | int statusBarHeight = getStatusBarHeight(activity); 152 | int width = getScreenWidth(activity); 153 | int height = getScreenHeight(activity); 154 | Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); 155 | view.destroyDrawingCache(); 156 | return bp; 157 | } 158 | 159 | /** 160 | * 判断是否锁屏 161 | */ 162 | public static boolean isScreenLock(Context context) { 163 | KeyguardManager km = (KeyguardManager) context 164 | .getSystemService(Context.KEYGUARD_SERVICE); 165 | return km.inKeyguardRestrictedInputMode(); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/SizeUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.util.Log; 6 | import android.util.TypedValue; 7 | import android.view.View; 8 | 9 | /********************************************* 10 | * author: Blankj on 2016/8/1 19:12 11 | * blog: http://blankj.com 12 | * e-mail: blankj@qq.com 13 | *********************************************/ 14 | public class SizeUtils { 15 | 16 | private SizeUtils() { 17 | throw new UnsupportedOperationException("u can't fuck me..."); 18 | } 19 | 20 | /** 21 | * dp转px 22 | */ 23 | public static int dp2px(Context context, float dpValue) { 24 | final float scale = context.getResources().getDisplayMetrics().density; 25 | return (int) (dpValue * scale + 0.5f); 26 | } 27 | 28 | /** 29 | * px转dp 30 | */ 31 | public static int px2dp(Context context, float pxValue) { 32 | final float scale = context.getResources().getDisplayMetrics().density; 33 | return (int) (pxValue / scale + 0.5f); 34 | } 35 | 36 | /** 37 | * sp转px 38 | */ 39 | public static int sp2px(Context context, float spValue) { 40 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 41 | return (int) (spValue * fontScale + 0.5f); 42 | } 43 | 44 | /** 45 | * px转sp 46 | */ 47 | public static int px2sp(Context context, float pxValue) { 48 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 49 | return (int) (pxValue / fontScale + 0.5f); 50 | } 51 | 52 | /** 53 | * 各种单位转换 54 | *

该方法存在于TypedValue 55 | */ 56 | public static float applyDimension(int unit, float value, DisplayMetrics metrics) { 57 | switch (unit) { 58 | case TypedValue.COMPLEX_UNIT_PX: 59 | return value; 60 | case TypedValue.COMPLEX_UNIT_DIP: 61 | return value * metrics.density; 62 | case TypedValue.COMPLEX_UNIT_SP: 63 | return value * metrics.scaledDensity; 64 | case TypedValue.COMPLEX_UNIT_PT: 65 | return value * metrics.xdpi * (1.0f / 72); 66 | case TypedValue.COMPLEX_UNIT_IN: 67 | return value * metrics.xdpi; 68 | case TypedValue.COMPLEX_UNIT_MM: 69 | return value * metrics.xdpi * (1.0f / 25.4f); 70 | } 71 | return 0; 72 | } 73 | 74 | /** 75 | * 在onCreate()即可强行获取View的尺寸 76 | *

需回调onGetSizeListener接口,在onGetSize中获取view宽高 77 | * 用法示例如下所示 78 | * SizeUtils.forceGetViewSize(view); 79 | * SizeUtils.setListener(new SizeUtils.onGetSizeListener() { 80 | * @Override 81 | * public void onGetSize(View view) { 82 | * Log.d("tag", view.getWidth() + " " + view.getHeight()); 83 | * } 84 | * }); 85 | */ 86 | public static void forceGetViewSize(final View view) { 87 | view.post(new Runnable() { 88 | @Override 89 | public void run() { 90 | if (mListener != null) { 91 | mListener.onGetSize(view); 92 | } 93 | } 94 | }); 95 | } 96 | 97 | /** 98 | * 获取到View尺寸的监听 99 | */ 100 | public interface onGetSizeListener { 101 | void onGetSize(View view); 102 | } 103 | public static void setListener(onGetSizeListener listener) { 104 | mListener = listener; 105 | } 106 | private static onGetSizeListener mListener; 107 | 108 | /** 109 | * ListView中提前测量View尺寸,如headerView 110 | *

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

参照以下注释代码 112 | */ 113 | public static void measureViewInLV(View view) { 114 | Log.i("tips", "U should copy the following code."); 115 | /* 116 | ViewGroup.LayoutParams p = view.getLayoutParams(); 117 | if (p == null) { 118 | p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 119 | ViewGroup.LayoutParams.WRAP_CONTENT); 120 | } 121 | int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); 122 | int height; 123 | int tempHeight = p.height; 124 | if (tempHeight > 0) { 125 | height = MeasureSpec.makeMeasureSpec(tempHeight, 126 | MeasureSpec.EXACTLY); 127 | } else { 128 | height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 129 | } 130 | view.measure(width, height); 131 | */ 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/TimeUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | 7 | /********************************************* 8 | * author: Blankj on 2016/8/3 20:25 9 | * blog: http://blankj.com 10 | * e-mail: blankj@qq.com 11 | *********************************************/ 12 | public class TimeUtils { 13 | 14 | private TimeUtils() { 15 | throw new UnsupportedOperationException("u can't fuck me..."); 16 | } 17 | 18 | /** 19 | *

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

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

27 | * 定义了以下模式字母(所有其他字符 'A' 到 'Z' 和 'a' 到 'z' 都被保留):
28 | * 29 | * 30 | * 31 | * 32 | * 33 | * 34 | * 35 | * 36 | * 37 | * 38 | * 39 | * 40 | * 41 | * 42 | * 43 | * 44 | * 45 | * 46 | * 47 | * 48 | * 49 | *
字母 日期或时间元素 表示 示例
G Era 标志符 Text AD
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
50 | *

51 | *

52 | *

 53 |      *                     yyyy-MM-dd 1969-12-31
 54 |      *                     yyyy-MM-dd 1970-01-01
 55 |      *               yyyy-MM-dd HH:mm 1969-12-31 16:00
 56 |      *               yyyy-MM-dd HH:mm 1970-01-01 00:00
 57 |      *              yyyy-MM-dd HH:mmZ 1969-12-31 16:00-0800
 58 |      *              yyyy-MM-dd HH:mmZ 1970-01-01 00:00+0000
 59 |      *       yyyy-MM-dd HH:mm:ss.SSSZ 1969-12-31 16:00:00.000-0800
 60 |      *       yyyy-MM-dd HH:mm:ss.SSSZ 1970-01-01 00:00:00.000+0000
 61 |      *     yyyy-MM-dd'T'HH:mm:ss.SSSZ 1969-12-31T16:00:00.000-0800
 62 |      *     yyyy-MM-dd'T'HH:mm:ss.SSSZ 1970-01-01T00:00:00.000+0000
 63 |      * 
64 | */ 65 | public static final SimpleDateFormat DEFAULT_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 66 | /** 67 | * 各时间单位与毫秒的倍数 68 | */ 69 | public static final int UNIT_MSEC = 1; 70 | public static final int UNIT_SEC = 1000; 71 | public static final int UNIT_MIN = 60000; 72 | public static final int UNIT_HOUR = 3600000; 73 | public static final int UNIT_DAY = 86400000; 74 | 75 | /** 76 | * 将时间戳转为时间字符串 77 | *

格式为yyyy-MM-dd HH:mm:ss 78 | */ 79 | public static String milliseconds2String(long milliseconds) { 80 | return milliseconds2String(milliseconds, DEFAULT_SDF); 81 | } 82 | 83 | /** 84 | * 将时间戳转为时间字符串 85 | *

格式为用户自定义 86 | */ 87 | public static String milliseconds2String(long milliseconds, SimpleDateFormat format) { 88 | return format.format(new Date(milliseconds)); 89 | } 90 | 91 | /** 92 | * 将时间字符串转为时间戳 93 | *

格式为yyyy-MM-dd HH:mm:ss 94 | */ 95 | public static long string2Milliseconds(String time) { 96 | return string2Milliseconds(time, DEFAULT_SDF); 97 | } 98 | 99 | /** 100 | * 将时间字符串转为时间戳 101 | *

格式为用户自定义 102 | */ 103 | public static long string2Milliseconds(String time, SimpleDateFormat format) { 104 | try { 105 | return format.parse(time).getTime(); 106 | } catch (ParseException e) { 107 | e.printStackTrace(); 108 | } 109 | return -1; 110 | } 111 | 112 | /** 113 | * 将时间字符串转为Date类型 114 | *

格式为yyyy-MM-dd HH:mm:ss 115 | */ 116 | public static Date string2Date(String formatDate) { 117 | return string2Date(formatDate, DEFAULT_SDF); 118 | } 119 | 120 | /** 121 | * 将时间字符串转为Date类型 122 | *

格式为用户自定义 123 | */ 124 | public static Date string2Date(String formatDate, SimpleDateFormat format) { 125 | return new Date(string2Milliseconds(formatDate, format)); 126 | } 127 | 128 | /** 129 | * 将Date类型转为时间字符串 130 | *

格式为yyyy-MM-dd HH:mm:ss 131 | */ 132 | public static String date2String(Date date) { 133 | return date2String(date, DEFAULT_SDF); 134 | } 135 | 136 | /** 137 | * 将Date类型转为时间字符串 138 | *

格式为用户自定义 139 | */ 140 | public static String date2String(Date date, SimpleDateFormat format) { 141 | return format.format(date); 142 | } 143 | 144 | /** 145 | * 将Date类型转为时间戳 146 | */ 147 | public static long date2Milliseconds(Date date) { 148 | return date.getTime(); 149 | } 150 | 151 | /** 152 | * 将时间戳转为Date类型 153 | */ 154 | public static Date milliseconds2Date(long milliseconds) { 155 | return new Date(milliseconds); 156 | } 157 | 158 | /** 159 | * 毫秒时间戳单位转换(单位:unit) 160 | *

161 |      * UNIT_MSEC:毫秒
162 |      * UNIT_SEC :秒
163 |      * UNIT_MIN :分
164 |      * UNIT_HOUR:小时
165 |      * UNIT_DAY :天
166 |      * 
167 | */ 168 | private static long milliseconds2Unit(long milliseconds, int unit) { 169 | switch (unit) { 170 | case UNIT_MSEC: 171 | case UNIT_SEC: 172 | case UNIT_MIN: 173 | case UNIT_HOUR: 174 | case UNIT_DAY: 175 | return Math.abs(milliseconds) / unit; 176 | } 177 | return -1; 178 | } 179 | 180 | /** 181 | * 获取两个时间差(单位:unit) 182 | *
183 |      * UNIT_MSEC:毫秒
184 |      * UNIT_SEC :秒
185 |      * UNIT_MIN :分
186 |      * UNIT_HOUR:小时
187 |      * UNIT_DAY :天
188 |      * 
189 | *

time1和time2格式都为yyyy-MM-dd HH:mm:ss 190 | */ 191 | public static long getIntervalTime(String time1, String time2, int unit) { 192 | return getIntervalTime(time1, time2, unit, DEFAULT_SDF); 193 | } 194 | 195 | /** 196 | * 获取两个时间差(单位:unit) 197 | *

198 |      * UNIT_MSEC:毫秒
199 |      * UNIT_SEC :秒
200 |      * UNIT_MIN :分
201 |      * UNIT_HOUR:小时
202 |      * UNIT_DAY :天
203 |      * 
204 | *

time1和time2格式都为format 205 | */ 206 | public static long getIntervalTime(String time1, String time2, int unit, SimpleDateFormat format) { 207 | return milliseconds2Unit(string2Milliseconds(time1, format) 208 | - string2Milliseconds(time2, format), unit); 209 | } 210 | 211 | /** 212 | * 获取两个时间差(单位:unit) 213 | *

214 |      * UNIT_MSEC:毫秒
215 |      * UNIT_SEC :秒
216 |      * UNIT_MIN :分
217 |      * UNIT_HOUR:小时
218 |      * UNIT_DAY :天
219 |      * 
220 | *

time1和time2都为Date 221 | */ 222 | public static long getIntervalTime(Date time1, Date time2, int unit) { 223 | return milliseconds2Unit(date2Milliseconds(time2) - date2Milliseconds(time1), unit); 224 | } 225 | 226 | /** 227 | * 获取当前时间 228 | *

单位(毫秒) 229 | */ 230 | public static long getCurTimeMills() { 231 | return System.currentTimeMillis(); 232 | } 233 | 234 | /** 235 | * 获取当前时间 236 | *

格式为yyyy-MM-dd HH:mm:ss 237 | */ 238 | public static String getCurTimeString() { 239 | return milliseconds2String(getCurTimeMills()); 240 | } 241 | 242 | /** 243 | * 获取当前时间 244 | *

格式为用户自定义 245 | */ 246 | public static String getCurTimeString(SimpleDateFormat format) { 247 | return milliseconds2String(getCurTimeMills(), format); 248 | } 249 | 250 | /** 251 | * 获取当前时间 252 | *

Date类型 253 | */ 254 | public static Date getCurTimeDate() { 255 | return new Date(); 256 | } 257 | 258 | /** 259 | * 获取与当前时间的差(单位:unit) 260 | *

261 |      * UNIT_MSEC:毫秒
262 |      * UNIT_SEC :秒
263 |      * UNIT_MIN :分
264 |      * UNIT_HOUR:小时
265 |      * UNIT_DAY :天
266 |      * 

time1和time2格式都为yyyy-MM-dd HH:mm:ss 267 | */ 268 | public static long getIntervalByNow(String time, int unit) { 269 | return getIntervalByNow(time, unit, DEFAULT_SDF); 270 | } 271 | 272 | /** 273 | * 获取与当前时间的差(单位:unit) 274 | *

275 |      * UNIT_MSEC:毫秒
276 |      * UNIT_SEC :秒
277 |      * UNIT_MIN :分
278 |      * UNIT_HOUR:小时
279 |      * UNIT_DAY :天
280 |      * 

time1和time2格式都为format 281 | */ 282 | public static long getIntervalByNow(String time, int unit, SimpleDateFormat format) { 283 | return getIntervalTime(getCurTimeString(), time, unit, format); 284 | } 285 | 286 | /** 287 | * 获取与当前时间的差(单位:unit) 288 | *

289 |      * UNIT_MSEC:毫秒
290 |      * UNIT_SEC :秒
291 |      * UNIT_MIN :分
292 |      * UNIT_HOUR:小时
293 |      * UNIT_DAY :天
294 |      * 

time1和time2格式都为format 295 | */ 296 | public static long getIntervalByNow(Date time, int unit) { 297 | return getIntervalTime(getCurTimeDate(), time, unit); 298 | } 299 | 300 | /** 301 | * 判断闰年 302 | */ 303 | public static boolean isLeapYear(int year) { 304 | return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 305 | } 306 | 307 | } 308 | 309 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/UnclassifiedUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.app.ActivityManager; 4 | import android.app.ActivityManager.RunningServiceInfo; 5 | import android.content.ComponentName; 6 | import android.content.Context; 7 | 8 | import java.util.List; 9 | 10 | /********************************************* 11 | * author: Blankj on 2016/8/2 21:24 12 | * blog: http://blankj.com 13 | * e-mail: blankj@qq.com 14 | *********************************************/ 15 | public class UnclassifiedUtils { 16 | 17 | private UnclassifiedUtils() { 18 | throw new UnsupportedOperationException("u can't fuck me..."); 19 | } 20 | 21 | /** 22 | * 获取服务是否开启 23 | * @param className 完整包名的服务类名 24 | */ 25 | public static boolean isRunningService(String className, Context context) { 26 | // 进程的管理者,活动的管理者 27 | ActivityManager activityManager = (ActivityManager) 28 | context.getSystemService(Context.ACTIVITY_SERVICE); 29 | // 获取正在运行的服务,最多获取1000个 30 | List runningServices = activityManager.getRunningServices(1000); 31 | // 遍历集合 32 | for (RunningServiceInfo runningServiceInfo : runningServices) { 33 | ComponentName service = runningServiceInfo.service; 34 | if (className.equals(service.getClassName())) { 35 | return true; 36 | } 37 | } 38 | return false; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /utilcode/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | UtilCode 3 | 4 | -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/EncryptUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /********************************************* 8 | * author: Blankj on 2016/8/6 14:02 9 | * blog: http://blankj.com 10 | * e-mail: blankj@qq.com 11 | *********************************************/ 12 | public class EncryptUtilsTest { 13 | 14 | @Before 15 | public void setUp() throws Exception { 16 | 17 | } 18 | 19 | @Test 20 | public void testGetMD5() throws Exception { 21 | Assert.assertEquals(EncryptUtils.getMD5("blankj"), "AAC25CD336E01C8655F4EC7875445A60"); 22 | } 23 | 24 | @Test 25 | public void testGetMD51() throws Exception { 26 | Assert.assertEquals(EncryptUtils.getMD5("blank", "j"), "AAC25CD336E01C8655F4EC7875445A60"); 27 | } 28 | 29 | @Test 30 | public void testGetMD52() throws Exception { 31 | Assert.assertEquals(EncryptUtils.getMD5("blankj".getBytes()), "AAC25CD336E01C8655F4EC7875445A60"); 32 | } 33 | 34 | @Test 35 | public void testGetMD53() throws Exception { 36 | Assert.assertEquals(EncryptUtils.getMD5("blank".getBytes(), "j".getBytes()), "AAC25CD336E01C8655F4EC7875445A60"); 37 | } 38 | 39 | @Test 40 | public void testEncryptMD5() throws Exception { 41 | Assert.assertEquals(EncryptUtils.bytes2Hex(EncryptUtils.encryptMD5("blankj".getBytes())), "AAC25CD336E01C8655F4EC7875445A60"); 42 | } 43 | 44 | @Test 45 | public void testGetMD5File() throws Exception { 46 | 47 | } 48 | 49 | @Test 50 | public void testGetMD5File1() throws Exception { 51 | 52 | } 53 | 54 | @Test 55 | public void testGetSHA() throws Exception { 56 | Assert.assertEquals(EncryptUtils.getSHA("blankj"), "C606ACCB1FEB669E19D080ADDDDBB8E6CDA5F43C"); 57 | } 58 | 59 | @Test 60 | public void testGetSHA1() throws Exception { 61 | Assert.assertEquals(EncryptUtils.getSHA("blankj".getBytes()), "C606ACCB1FEB669E19D080ADDDDBB8E6CDA5F43C"); 62 | } 63 | 64 | @Test 65 | public void testEncryptSHA() throws Exception { 66 | Assert.assertEquals(EncryptUtils.bytes2Hex(EncryptUtils.encryptSHA("blankj".getBytes())), "C606ACCB1FEB669E19D080ADDDDBB8E6CDA5F43C"); 67 | } 68 | 69 | @Test 70 | public void testBytes2Hex() throws Exception { 71 | Assert.assertEquals(EncryptUtils.bytes2Hex(new byte[]{(byte) 0xff, (byte) 0x11}), "FF11"); 72 | } 73 | } -------------------------------------------------------------------------------- /utilcode/utilcode.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | --------------------------------------------------------------------------------