├── utilcode ├── src │ ├── test │ │ ├── res │ │ │ ├── file │ │ │ │ ├── GBK.txt │ │ │ │ ├── child │ │ │ │ │ └── GBk.txt │ │ │ │ ├── UTF8.txt │ │ │ │ ├── UTF16BE.txt │ │ │ │ └── Unicode.txt │ │ │ ├── encrypt │ │ │ │ └── MD5.txt │ │ │ └── image │ │ │ │ └── lena.png │ │ └── java │ │ │ └── com │ │ │ └── blankj │ │ │ └── utilcode │ │ │ └── utils │ │ │ ├── SDCardUtilsTest.java │ │ │ ├── TestUtils.java │ │ │ ├── StringUtilsTest.java │ │ │ ├── ConvertUtilsTest.java │ │ │ ├── ImageUtilsTest.java │ │ │ ├── EncodeUtilsTest.java │ │ │ ├── SPUtilsTest.java │ │ │ ├── RegularUtilsTest.java │ │ │ ├── TimeUtilsTest.java │ │ │ ├── EncryptUtilsTest.java │ │ │ └── FileUtilsTest.java │ ├── main │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── blankj │ │ │ └── utilcode │ │ │ └── utils │ │ │ ├── UnclassifiedUtils.java │ │ │ ├── DeviceUtils.java │ │ │ ├── StringUtils.java │ │ │ ├── ConstUtils.java │ │ │ ├── RegularUtils.java │ │ │ ├── SizeUtils.java │ │ │ ├── KeyboardUtils.java │ │ │ ├── SPUtils.java │ │ │ ├── EncodeUtils.java │ │ │ ├── SDCardUtils.java │ │ │ ├── ShellUtils.java │ │ │ ├── ScreenUtils.java │ │ │ ├── ZipUtils.java │ │ │ ├── NetworkUtils.java │ │ │ ├── ThreadPoolUtils.java │ │ │ ├── AppUtils.java │ │ │ ├── ConvertUtils.java │ │ │ ├── PhoneUtils.java │ │ │ ├── TimeUtils.java │ │ │ └── EncryptUtils.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── blankj │ │ └── utilcode │ │ └── ApplicationTest.java ├── .gitignore ├── build.gradle └── proguard-rules.pro ├── update_log.md └── README.md /utilcode/src/test/res/file/GBK.txt: -------------------------------------------------------------------------------- 1 | GBK -------------------------------------------------------------------------------- /utilcode/src/test/res/encrypt/MD5.txt: -------------------------------------------------------------------------------- 1 | MD5 -------------------------------------------------------------------------------- /utilcode/src/test/res/file/child/GBk.txt: -------------------------------------------------------------------------------- 1 | GBK -------------------------------------------------------------------------------- /utilcode/src/test/res/file/UTF8.txt: -------------------------------------------------------------------------------- 1 | UTF8 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 -------------------------------------------------------------------------------- /utilcode/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | project.properties 3 | local.properties 4 | utilcode.iml -------------------------------------------------------------------------------- /utilcode/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | UtilCode 3 | 4 | -------------------------------------------------------------------------------- /utilcode/src/test/res/image/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfh1991/AndroidUtilCode/HEAD/utilcode/src/test/res/image/lena.png -------------------------------------------------------------------------------- /utilcode/src/test/res/file/UTF16BE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfh1991/AndroidUtilCode/HEAD/utilcode/src/test/res/file/UTF16BE.txt -------------------------------------------------------------------------------- /utilcode/src/test/res/file/Unicode.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfh1991/AndroidUtilCode/HEAD/utilcode/src/test/res/file/Unicode.txt -------------------------------------------------------------------------------- /utilcode/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /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/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 11 9 | targetSdkVersion 23 10 | versionCode 7 11 | versionName "1.1.5" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | testCompile 'junit:junit:4.12' 23 | testCompile 'org.robolectric:robolectric:3.1.2' 24 | testCompile 'com.google.truth:truth:0.29' 25 | } 26 | apply from: "https://raw.githubusercontent.com/xiaopansky/android-library-publish-to-jcenter/master/bintrayUpload.gradle" 27 | // gradlew bintrayUpload -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/SDCardUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.robolectric.RobolectricTestRunner; 6 | import org.robolectric.annotation.Config; 7 | 8 | /** 9 | *
10 |  *     author: Blankj
11 |  *     blog  : http://blankj.com
12 |  *     time  : 2016/8/23
13 |  *     desc  : SDCard单元测试
14 |  * 
15 | */ 16 | @RunWith(RobolectricTestRunner.class) 17 | @Config(manifest = Config.NONE) 18 | public class SDCardUtilsTest { 19 | 20 | @Test 21 | public void testIsSDCardEnable() throws Exception { 22 | System.out.println(SDCardUtils.isSDCardEnable()); 23 | } 24 | 25 | @Test 26 | public void testGetSDCardPath() throws Exception { 27 | System.out.println(SDCardUtils.getSDCardPath()); 28 | } 29 | } -------------------------------------------------------------------------------- /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 | 19 | 20 | #-keep class com.blankj.utilcode.** { *; } 21 | #-keep classmembers class com.blankj.utilcode.** { *; } 22 | #-dontwarn com.blankj.utilcode.** -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/TestUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.content.Context; 4 | 5 | import org.junit.runner.RunWith; 6 | import org.robolectric.RobolectricTestRunner; 7 | import org.robolectric.annotation.Config; 8 | import org.robolectric.shadows.ShadowApplication; 9 | 10 | import java.io.File; 11 | 12 | /** 13 | *
14 |  *     author: Blankj
15 |  *     blog  : http://blankj.com
16 |  *     time  : 2016/8/21
17 |  *     desc  : 单元测试工具类
18 |  * 
19 | */ 20 | @RunWith(RobolectricTestRunner.class) 21 | @Config(manifest = Config.NONE) 22 | public class TestUtils { 23 | 24 | private TestUtils() { 25 | throw new UnsupportedOperationException("u can't fuck me..."); 26 | } 27 | 28 | public static final char SEP = File.separatorChar; 29 | 30 | public static final String BASEPATH = System.getProperty("user.dir") 31 | + SEP + "src" + SEP + "test" + SEP + "res" + SEP; 32 | 33 | public static Context getContext() { 34 | return ShadowApplication.getInstance().getApplicationContext(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /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 | *
12 |  *     author: Blankj
13 |  *     blog  : http://blankj.com
14 |  *     time  : 2016/8/2
15 |  *     desc  : 未归类工具类
16 |  * 
17 | */ 18 | public class UnclassifiedUtils { 19 | 20 | private UnclassifiedUtils() { 21 | throw new UnsupportedOperationException("u can't fuck me..."); 22 | } 23 | 24 | /** 25 | * 获取服务是否开启 26 | * 27 | * @param context 上下文 28 | * @param className 完整包名的服务类名 29 | * @return {@code true}: 是
{@code false}: 否 30 | */ 31 | public static boolean isRunningService(Context context, String className) { 32 | // 进程的管理者,活动的管理者 33 | ActivityManager activityManager = (ActivityManager) 34 | context.getSystemService(Context.ACTIVITY_SERVICE); 35 | // 获取正在运行的服务,最多获取1000个 36 | List runningServices = activityManager.getRunningServices(1000); 37 | // 遍历集合 38 | for (RunningServiceInfo runningServiceInfo : runningServices) { 39 | ComponentName service = runningServiceInfo.service; 40 | if (className.equals(service.getClassName())) { 41 | return true; 42 | } 43 | } 44 | return false; 45 | } 46 | } -------------------------------------------------------------------------------- /update_log.md: -------------------------------------------------------------------------------- 1 | ### 更新日志 2 | #### 16/08/31 ImageUtils单元测试中,之后7天鸡儿岭放假,停更 3 | #### 16/08/30 ImageUtils单元测试中(获取保存图片有问题,卡卡卡住了) 4 | #### 16/08/29 完善ImageUtils,新增stack模糊算法和快速模糊 5 | #### 16/08/28 完善ImageUtils 6 | #### 16/08/27 完善ConvertUtils,新增ZipUtils 7 | #### 16/08/26 ThreadPoolUtils线程池相关工具类完善完毕 8 | #### 16/08/25 ConstUtils时间和存储相关常量新增枚举,传参改为枚举更为友好,新增ThreadPoolUtils线程池相关工具类 9 | #### 16/08/24 ConvertUtils新增InputStream与byte[]和String相互转换,应用在FileUtils中读文件 10 | #### 16/08/23 小修bug,接下来完善SDCardUtils和ImageUtils 11 | #### 16/08/22 SPUtils将commit改为apply提高效率,将SPUtils改为构造函数法创建,FileUtils新增查找函数,规范JavaDoc 12 | #### 16/08/21 FileUtils单元测试完毕,修复FileUtils的bug,发布版本1.1.2 13 | #### 16/08/20 更新目录,继续完善FileUtils单元测试,发布版本1.1.1 14 | #### 16/08/19 继续完善FileUtils及单元测试,及其他小修小补(在此感谢vpop的三次Pr) 15 | #### 16/08/18 完善FileUtils及单元测试,完善ImageUtils 16 | #### 16/08/17 完善FileUtils 17 | #### 16/08/16 新增StringUtils及单元测试,完善正则工具类,版本更新1.1.0 18 | #### 16/08/15 新增3DES和AES加密及单元检测,加密解密工具类基本完善,目录更新 19 | #### 16/08/14 新增DES加密及单元检测 20 | #### 16/08/13 新增MD2,SHA224,SHA256,SHA384,SHA512加密及单元测试,正折腾DES加密 21 | #### 16/08/12 新增Base64和Html编码解码及他们的单元测试,新增TimeUtils单元测试,更新md 22 | #### 16/08/11 新增SDCardUtils,UnitUtils,单元测试慢慢完善中 23 | #### 16/08/09 目录排版更新,新增Download,Proguard和License 24 | #### 16/08/08 新增Shell工具类,已传jcenter()遇到好多坑,javaDoc惹的祸,注释一定要规范 25 | #### 16/08/07 新增6.0获取Mac地址方法,新增对HTML转义,新增编码解码工具类,新增SP工具类 26 | #### 16/08/06 重命名包名,新增加密相关的单元测试,MD5加密新增文件加密重载 27 | #### 16/08/05 加密新增MD5盐加密,完善NetworkUtils,新增判断状态栏是否存在(在此感谢tiandawu) 28 | #### 16/08/04 新增时间工具类(在此感谢yi520000给的补充),手机正则分简单和精确(在此感谢MIkeeJY),新增判断是否锁屏,注释分段落,目录按首字母排序 29 | #### 16/08/03 修复在onCreate中获取view尺寸的bug,MD5和SHA的Bug修复完成(在此感谢ssyijiu) 30 | #### 16/08/02 wifi设置界面bug修复,注释排版还在修改,获取mac地址增加判空,新增QQ群:74721490,欢迎加入,新增隐藏状态栏,注释更加全面,工具类已封装,写的时候真的是一个一个测试过去的,宝宝心里苦 31 | #### 16/08/01 新增获取SD卡路径,手机和设备进行分类,代码bug修改部分,小修排版,正在封装类,新增目录中显示方法名,新增获取当前App版本Code 32 | #### 16/07/31 新增点击屏幕空白区域隐藏软键盘,未能成功增加本页目录跳转功能(不支持) -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/StringUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Test; 4 | 5 | import static com.blankj.utilcode.utils.StringUtils.*; 6 | import static com.google.common.truth.Truth.assertThat; 7 | 8 | /** 9 | *
10 |  *     author: Blankj
11 |  *     blog  : http://blankj.com
12 |  *     time  : 2016/8/16
13 |  *     desc  : StringUtils单元测试
14 |  * 
15 | */ 16 | public class StringUtilsTest { 17 | 18 | @Test 19 | public void testIsEmpty() throws Exception { 20 | assertThat(isEmpty("")).isTrue(); 21 | assertThat(isEmpty(null)).isTrue(); 22 | assertThat(isEmpty(" ")).isFalse(); 23 | } 24 | 25 | @Test 26 | public void testIsSpace() throws Exception { 27 | assertThat(isSpace("")).isTrue(); 28 | assertThat(isSpace(null)).isTrue(); 29 | assertThat(isSpace(" ")).isTrue(); 30 | assertThat(isSpace(" ")).isFalse(); 31 | } 32 | 33 | @Test 34 | public void testNull2Length0() throws Exception { 35 | assertThat(null2Length0(null)).isEqualTo(""); 36 | } 37 | 38 | @Test 39 | public void testLength() throws Exception { 40 | assertThat(length(null)).isEqualTo(0); 41 | assertThat(length("")).isEqualTo(0); 42 | assertThat(length("blankj")).isEqualTo(6); 43 | } 44 | 45 | @Test 46 | public void testUpperFirstLetter() throws Exception { 47 | assertThat(upperFirstLetter("blankj")).isEqualTo("Blankj"); 48 | assertThat(upperFirstLetter("Blankj")).isEqualTo("Blankj"); 49 | assertThat(upperFirstLetter("1Blankj")).isEqualTo("1Blankj"); 50 | } 51 | 52 | @Test 53 | public void testLowerFirstLetter() throws Exception { 54 | assertThat(lowerFirstLetter("blankj")).isEqualTo("blankj"); 55 | assertThat(lowerFirstLetter("Blankj")).isEqualTo("blankj"); 56 | assertThat(lowerFirstLetter("1blankj")).isEqualTo("1blankj"); 57 | } 58 | 59 | @Test 60 | public void testToDBC() throws Exception { 61 | assertThat(toDBC(" ,.&")).isEqualTo(" ,.&"); 62 | } 63 | 64 | @Test 65 | public void testToSBC() throws Exception { 66 | assertThat(toSBC(" ,.&")).isEqualTo(" ,.&"); 67 | } 68 | } -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/ConvertUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | 4 | import org.junit.Test; 5 | 6 | import static com.blankj.utilcode.utils.ConvertUtils.bytes2Chars; 7 | import static com.blankj.utilcode.utils.ConvertUtils.bytes2HexString; 8 | import static com.blankj.utilcode.utils.ConvertUtils.bytes2InputStream; 9 | import static com.blankj.utilcode.utils.ConvertUtils.chars2Bytes; 10 | import static com.blankj.utilcode.utils.ConvertUtils.hexString2Bytes; 11 | import static com.blankj.utilcode.utils.ConvertUtils.inputStream2Bytes; 12 | import static com.blankj.utilcode.utils.ConvertUtils.inputStream2String; 13 | import static com.blankj.utilcode.utils.ConvertUtils.string2InputStream; 14 | import static com.google.common.truth.Truth.assertThat; 15 | 16 | 17 | /** 18 | *
19 |  *     author: Blankj
20 |  *     blog  : http://blankj.com
21 |  *     time  : 2016/8/13
22 |  *     desc  : ConvertUtils单元测试
23 |  * 
24 | */ 25 | public class ConvertUtilsTest { 26 | 27 | byte[] mBytes = new byte[]{0x00, 0x08, (byte) 0xdb, 0x33, 0x45, (byte) 0xab, 0x02, 0x23}; 28 | String hexString = "0008DB3345AB0223"; 29 | 30 | @Test 31 | public void testBytes2HexString() throws Exception { 32 | assertThat(bytes2HexString(mBytes)).isEqualTo(hexString); 33 | } 34 | 35 | @Test 36 | public void testHexString2Bytes() throws Exception { 37 | assertThat(hexString2Bytes(hexString)).isEqualTo(mBytes); 38 | } 39 | 40 | char[] mChars1 = new char[]{'0', '1', '2'}; 41 | byte[] mBytes1 = new byte[]{48, 49, 50}; 42 | 43 | @Test 44 | public void testChars2Bytes() throws Exception { 45 | assertThat(chars2Bytes(mChars1)).isEqualTo(mBytes1); 46 | } 47 | 48 | @Test 49 | public void testBytes2Chars() throws Exception { 50 | assertThat(bytes2Chars(mBytes1)).isEqualTo(mChars1); 51 | } 52 | 53 | @Test 54 | public void testInputStream2BytesAndBytes2InputStream() throws Exception { 55 | String string = "this is test string"; 56 | assertThat(new String(inputStream2Bytes( 57 | bytes2InputStream(string.getBytes("UTF-8"))))) 58 | .isEqualTo(string); 59 | } 60 | 61 | @Test 62 | public void testInputStream2StringAndString2InputStream() throws Exception { 63 | String string = "this is test string"; 64 | assertThat(inputStream2String( 65 | string2InputStream(string, "UTF-8") 66 | , "UTF-8")).isEqualTo(string); 67 | } 68 | } -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/ImageUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.robolectric.RobolectricTestRunner; 8 | import org.robolectric.annotation.Config; 9 | 10 | import static com.blankj.utilcode.utils.TestUtils.BASEPATH; 11 | import static com.blankj.utilcode.utils.TestUtils.SEP; 12 | 13 | /** 14 | *
 15 |  *     author: Blankj
 16 |  *     blog  : http://blankj.com
 17 |  *     time  : 2016/8/30
 18 |  *     desc  : ImageUtils单元测试
 19 |  * 
20 | */ 21 | @RunWith(RobolectricTestRunner.class) 22 | @Config(manifest = Config.NONE) 23 | public class ImageUtilsTest { 24 | 25 | String path = BASEPATH + "image" + SEP; 26 | 27 | @Test 28 | public void testBitmap2Bytes() throws Exception { 29 | FileUtils.createOrExistsFile(path + "new1.png"); 30 | Bitmap bitmap = ImageUtils.getBitmapByFile(path + "lena.png"); 31 | System.out.println(ImageUtils.save(bitmap, path + "new1.png", Bitmap.CompressFormat.PNG)); 32 | } 33 | 34 | @Test 35 | public void testBytes2Bitmap() throws Exception { 36 | 37 | } 38 | 39 | @Test 40 | public void testDrawable2Bitmap() throws Exception { 41 | 42 | } 43 | 44 | @Test 45 | public void testBitmap2Drawable() throws Exception { 46 | 47 | } 48 | 49 | @Test 50 | public void testDrawable2Bytes() throws Exception { 51 | 52 | } 53 | 54 | @Test 55 | public void testBytes2Drawable() throws Exception { 56 | 57 | } 58 | 59 | @Test 60 | public void testGetBitmap() throws Exception { 61 | 62 | } 63 | 64 | @Test 65 | public void testScaleImage() throws Exception { 66 | 67 | } 68 | 69 | @Test 70 | public void testToRound() throws Exception { 71 | 72 | } 73 | 74 | @Test 75 | public void testToRoundCorner() throws Exception { 76 | 77 | } 78 | 79 | @Test 80 | public void testFastBlur() throws Exception { 81 | 82 | } 83 | 84 | @Test 85 | public void testRenderScriptBlur() throws Exception { 86 | 87 | } 88 | 89 | @Test 90 | public void testStackBlur() throws Exception { 91 | 92 | } 93 | 94 | @Test 95 | public void testAddFrame() throws Exception { 96 | 97 | } 98 | 99 | @Test 100 | public void testAddReflection() throws Exception { 101 | 102 | } 103 | 104 | @Test 105 | public void testSaveBitmap() throws Exception { 106 | 107 | } 108 | } -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/EncodeUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.robolectric.RobolectricTestRunner; 6 | import org.robolectric.annotation.Config; 7 | 8 | import static com.blankj.utilcode.utils.EncodeUtils.*; 9 | import static com.google.common.truth.Truth.assertThat; 10 | 11 | /** 12 | *
13 |  *     author: Blankj
14 |  *     blog  : http://blankj.com
15 |  *     time  : 2016/8/12
16 |  *     desc  : EncodeUtils单元测试
17 |  * 
18 | */ 19 | @RunWith(RobolectricTestRunner.class) 20 | @Config(manifest = Config.NONE) 21 | public class EncodeUtilsTest { 22 | 23 | String urlEncodeString = "%E5%93%88%E5%93%88%E5%93%88"; 24 | String html = "" + 25 | "" + 26 | "我的第一个 HTML 页面" + 27 | "" + 28 | "" + 29 | "

body 元素的内容会显示在浏览器中。

" + 30 | "

title 元素的内容会显示在浏览器的标题栏中。

" + 31 | "" + 32 | ""; 33 | String encodeHtml = "<html><head><title>我的第一个 HTML 页面</title></head><body><p>body 元素的内容会显示在浏览器中。</p><p>title 元素的内容会显示在浏览器的标题栏中。</p></body></html>"; 34 | 35 | @Test 36 | public void testUrlEncode() throws Exception { 37 | assertThat(urlEncode("哈哈哈")).isEqualTo(urlEncodeString); 38 | assertThat(urlEncode("哈哈哈", "UTF-8")).isEqualTo(urlEncodeString); 39 | } 40 | 41 | @Test 42 | public void testUrlDecode() throws Exception { 43 | assertThat(urlDecode(urlEncodeString)).isEqualTo("哈哈哈"); 44 | assertThat(urlDecode(urlEncodeString, "UTF-8")).isEqualTo("哈哈哈"); 45 | } 46 | 47 | @Test 48 | public void testBase64EncodeAndDecode() throws Exception { 49 | assertThat(base64Decode(base64Encode("blankj"))) 50 | .isEqualTo("blankj".getBytes()); 51 | assertThat(base64Decode(base64Encode2String("blankj".getBytes()))) 52 | .isEqualTo("blankj".getBytes()); 53 | assertThat(base64Encode2String("blankj".getBytes())) 54 | .isEqualTo("Ymxhbmtq"); 55 | assertThat(base64Encode("blankj".getBytes())) 56 | .isEqualTo("Ymxhbmtq".getBytes()); 57 | } 58 | 59 | @Test 60 | public void testHtmlEncode() throws Exception { 61 | assertThat(htmlEncode(html)).isEqualTo(encodeHtml); 62 | } 63 | 64 | @Test 65 | public void testHtmlDecode() throws Exception { 66 | assertThat(htmlDecode(encodeHtml)).isEqualTo(html); 67 | } 68 | } -------------------------------------------------------------------------------- /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 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.LineNumberReader; 13 | 14 | /** 15 | *
16 |  *     author: Blankj
17 |  *     blog  : http://blankj.com
18 |  *     time  : 2016/8/1
19 |  *     desc  : 设备相关工具类
20 |  * 
21 | */ 22 | public class DeviceUtils { 23 | 24 | private DeviceUtils() { 25 | throw new UnsupportedOperationException("u can't fuck me..."); 26 | } 27 | 28 | /** 29 | * 获取设备MAC地址 30 | *

需添加权限 {@code }

31 | * 32 | * @param context 上下文 33 | * @return MAC地址 34 | */ 35 | public static String getMacAddress(Context context) { 36 | WifiManager wifi = (WifiManager) context 37 | .getSystemService(Context.WIFI_SERVICE); 38 | WifiInfo info = wifi.getConnectionInfo(); 39 | String macAddress = info.getMacAddress().replace(":", ""); 40 | return macAddress == null ? "" : macAddress; 41 | } 42 | 43 | /** 44 | * 获取设备MAC地址 45 | * 46 | *

需添加权限 {@code }

47 | * 48 | * @return MAC地址 49 | */ 50 | public static String getMacAddress() { 51 | String macAddress = null; 52 | LineNumberReader reader = null; 53 | try { 54 | Process pp = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address"); 55 | InputStreamReader ir = new InputStreamReader(pp.getInputStream()); 56 | reader = new LineNumberReader(ir); 57 | macAddress = reader.readLine().replace(":", ""); 58 | } catch (IOException ex) { 59 | ex.printStackTrace(); 60 | } finally { 61 | try { 62 | if (reader != null) reader.close(); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | return macAddress == null ? "" : macAddress; 68 | } 69 | 70 | /** 71 | * 获取设备厂商,如Xiaomi 72 | * 73 | * @return 设备厂商 74 | */ 75 | public static String getManufacturer() { 76 | return Build.MANUFACTURER; 77 | } 78 | 79 | /** 80 | * 获取设备型号,如MI2SC 81 | * 82 | * @return 设备型号 83 | */ 84 | public static String getModel() { 85 | String model = Build.MODEL; 86 | if (model != null) { 87 | model = model.trim().replaceAll("\\s*", ""); 88 | } else { 89 | model = ""; 90 | } 91 | return model; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/SPUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.robolectric.RobolectricTestRunner; 7 | import org.robolectric.annotation.Config; 8 | 9 | import java.util.Map; 10 | 11 | import static com.google.common.truth.Truth.assertThat; 12 | 13 | /** 14 | *
15 |  *     author: Blankj
16 |  *     blog  : http://blankj.com
17 |  *     time  : 2016/8/22
18 |  *     desc  : SPUtils单元测试
19 |  * 
20 | */ 21 | @RunWith(RobolectricTestRunner.class) 22 | @Config(manifest = Config.NONE) 23 | public class SPUtilsTest { 24 | 25 | SPUtils spUtils; 26 | 27 | @Before 28 | public void setUp() throws Exception { 29 | if (spUtils == null) { 30 | spUtils = new SPUtils(TestUtils.getContext(), "test"); 31 | spUtils.putString("stringKey", "stringVal"); 32 | spUtils.putInt("intKey", 1); 33 | spUtils.putLong("longKey", 1L); 34 | spUtils.putFloat("floatKey", 1f); 35 | spUtils.putBoolean("booleanKey", true); 36 | } 37 | } 38 | 39 | @Test 40 | public void testGetString() throws Exception { 41 | assertThat(spUtils.getString("stringKey")).isEqualTo("stringVal"); 42 | assertThat(spUtils.getString("stringKey1", "stringVal1")).isEqualTo("stringVal1"); 43 | assertThat(spUtils.getString("stringKey1")).isNull(); 44 | } 45 | 46 | @Test 47 | public void testGetInt() throws Exception { 48 | assertThat(spUtils.getInt("intKey")).isEqualTo(1); 49 | assertThat(spUtils.getInt("intKey1", 10086)).isEqualTo(10086); 50 | assertThat(spUtils.getInt("intKey1")).isEqualTo(-1); 51 | } 52 | 53 | @Test 54 | public void testGetLong() throws Exception { 55 | assertThat(spUtils.getLong("longKey")).isEqualTo(1L); 56 | assertThat(spUtils.getLong("longKey1", 10086L)).isEqualTo(10086L); 57 | assertThat(spUtils.getLong("longKey1")).isEqualTo(-1L); 58 | } 59 | 60 | @Test 61 | public void testGetFloat() throws Exception { 62 | assertThat(spUtils.getFloat("floatKey") - 1.f).isWithin(0.f); 63 | assertThat(spUtils.getFloat("floatKey1", 10086f) - 10086f).isWithin(0.f); 64 | assertThat(spUtils.getFloat("floatKey1") + 1.f).isWithin(0.f); 65 | } 66 | 67 | @Test 68 | public void testGetBoolean() throws Exception { 69 | assertThat(spUtils.getBoolean("booleanKey")).isTrue(); 70 | assertThat(spUtils.getBoolean("booleanKey1", true)).isTrue(); 71 | assertThat(spUtils.getBoolean("booleanKey1")).isFalse(); 72 | } 73 | 74 | @Test 75 | public void testGetAll() throws Exception { 76 | Map map = spUtils.getAll(); 77 | for (Map.Entry entry : map.entrySet()) { 78 | System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); 79 | } 80 | } 81 | 82 | @Test 83 | public void testRemove() throws Exception { 84 | spUtils.remove("stringKey"); 85 | testGetAll(); 86 | } 87 | 88 | @Test 89 | public void testContains() throws Exception { 90 | assertThat(spUtils.contains("stringKey")).isTrue(); 91 | assertThat(spUtils.contains("string")).isFalse(); 92 | } 93 | 94 | @Test 95 | public void testClear() throws Exception { 96 | spUtils.clear(); 97 | testGetAll(); 98 | } 99 | } -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/RegularUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Test; 4 | 5 | import static com.blankj.utilcode.utils.RegularUtils.*; 6 | import static com.google.common.truth.Truth.assertThat; 7 | 8 | /** 9 | *
 10 |  *     author: Blankj
 11 |  *     blog  : http://blankj.com
 12 |  *     time  : 2016/8/16
 13 |  *     desc  : RegularUtils单元测试
 14 |  * 
15 | */ 16 | public class RegularUtilsTest { 17 | 18 | @Test 19 | public void testIsMobileSimple() throws Exception { 20 | assertThat(isMobileSimple("11111111111")).isTrue(); 21 | } 22 | 23 | @Test 24 | public void testIsMobileExact() throws Exception { 25 | assertThat(isMobileExact("11111111111")).isFalse(); 26 | assertThat(isMobileExact("13888880000")).isTrue(); 27 | } 28 | 29 | @Test 30 | public void testIsTel() throws Exception { 31 | assertThat(isTel("033-88888888")).isTrue(); 32 | assertThat(isTel("033-7777777")).isTrue(); 33 | assertThat(isTel("0444-88888888")).isTrue(); 34 | assertThat(isTel("0444-7777777")).isTrue(); 35 | assertThat(isTel("033 88888888")).isTrue(); 36 | assertThat(isTel("033 7777777")).isTrue(); 37 | assertThat(isTel("0444 88888888")).isTrue(); 38 | assertThat(isTel("0444 7777777")).isTrue(); 39 | assertThat(isTel("03388888888")).isTrue(); 40 | assertThat(isTel("0337777777")).isTrue(); 41 | assertThat(isTel("044488888888")).isTrue(); 42 | assertThat(isTel("04447777777")).isTrue(); 43 | 44 | assertThat(isTel("133-88888888")).isFalse(); 45 | assertThat(isTel("033-666666")).isFalse(); 46 | assertThat(isTel("0444-999999999")).isFalse(); 47 | } 48 | 49 | @Test 50 | public void testIsIDCard() throws Exception { 51 | assertThat(isIDCard18("33698418400112523x")).isTrue(); 52 | assertThat(isIDCard18("336984184001125233")).isTrue(); 53 | assertThat(isIDCard18("336984184021125233")).isFalse(); 54 | } 55 | 56 | @Test 57 | public void testIsEmail() throws Exception { 58 | assertThat(isEmail("blankj@qq.com")).isTrue(); 59 | assertThat(isEmail("blankj@qq")).isFalse(); 60 | } 61 | 62 | @Test 63 | public void testIsURL() throws Exception { 64 | assertThat(isURL("http://blankj.com")).isTrue(); 65 | assertThat(isURL("http://blank")).isFalse(); 66 | } 67 | 68 | @Test 69 | public void testIsChz() throws Exception { 70 | assertThat(isChz("我")).isTrue(); 71 | assertThat(isChz("wo")).isFalse(); 72 | } 73 | 74 | @Test 75 | public void testIsUsername() throws Exception { 76 | assertThat(isUsername("小明233333")).isTrue(); 77 | assertThat(isUsername("小明")).isFalse(); 78 | assertThat(isUsername("小明233333_")).isFalse(); 79 | } 80 | 81 | @Test 82 | public void testIsDate() throws Exception { 83 | assertThat(isDate("2016-08-16")).isTrue(); 84 | assertThat(isDate("2016-02-29")).isTrue(); 85 | assertThat(isDate("2015-02-29")).isFalse(); 86 | assertThat(isDate("2016-8-16")).isFalse(); 87 | } 88 | 89 | @Test 90 | public void testIsIP() throws Exception { 91 | assertThat(isIP("255.255.255.0")).isTrue(); 92 | assertThat(isIP("256.255.255.0")).isFalse(); 93 | } 94 | 95 | @Test 96 | public void testIsMatch() throws Exception { 97 | assertThat(isMatch("\\d?", "1")).isTrue(); 98 | assertThat(isMatch("\\d?", "a")).isFalse(); 99 | } 100 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | /** 4 | *
  5 |  *     author: Blankj
  6 |  *     blog  : http://blankj.com
  7 |  *     time  : 2016/8/16
  8 |  *     desc  : 字符串相关工具类
  9 |  * 
10 | */ 11 | public class StringUtils { 12 | 13 | private StringUtils() { 14 | throw new UnsupportedOperationException("u can't fuck me..."); 15 | } 16 | 17 | /** 18 | * 判断字符串是否为null或长度为0 19 | * 20 | * @param string 待校验字符串 21 | * @return {@code true}: 空
{@code false}: 不为空 22 | */ 23 | public static boolean isEmpty(CharSequence string) { 24 | return string == null || string.length() == 0; 25 | } 26 | 27 | /** 28 | * 判断字符串是否为null或全为空格 29 | * 30 | * @param string 待校验字符串 31 | * @return {@code true}: null或全空格
{@code false}: 不为null且不全空格 32 | */ 33 | public static boolean isSpace(String string) { 34 | return (string == null || string.trim().length() == 0); 35 | } 36 | 37 | /** 38 | * null转为长度为0的字符串 39 | * 40 | * @param string 待转字符串 41 | * @return string为null转为长度为0字符串,否则不改变 42 | */ 43 | public static String null2Length0(String string) { 44 | return string == null ? "" : string; 45 | } 46 | 47 | /** 48 | * 返回字符串长度 49 | * 50 | * @param string 字符串 51 | * @return null返回0,其他返回自身长度 52 | */ 53 | public static int length(CharSequence string) { 54 | return string == null ? 0 : string.length(); 55 | } 56 | 57 | /** 58 | * 首字母大写 59 | * 60 | * @param string 待转字符串 61 | * @return 首字母大写字符串 62 | */ 63 | public static String upperFirstLetter(String string) { 64 | if (isEmpty(string) || !Character.isLowerCase(string.charAt(0))) { 65 | return string; 66 | } 67 | return String.valueOf((char) (string.charAt(0) - 32)) + string.substring(1); 68 | } 69 | 70 | /** 71 | * 首字母小写 72 | * 73 | * @param string 待转字符串 74 | * @return 首字母小写字符串 75 | */ 76 | public static String lowerFirstLetter(String string) { 77 | if (isEmpty(string) || !Character.isUpperCase(string.charAt(0))) { 78 | return string; 79 | } 80 | return String.valueOf((char) (string.charAt(0) + 32)) + string.substring(1); 81 | } 82 | 83 | /** 84 | * 转化为半角字符 85 | * 86 | * @param string 待转字符串 87 | * @return 半角字符串 88 | */ 89 | public static String toDBC(String string) { 90 | if (isEmpty(string)) { 91 | return string; 92 | } 93 | char[] chars = string.toCharArray(); 94 | for (int i = 0, len = chars.length; i < len; i++) { 95 | if (chars[i] == 12288) { 96 | chars[i] = ' '; 97 | } else if (65281 <= chars[i] && chars[i] <= 65374) { 98 | chars[i] = (char) (chars[i] - 65248); 99 | } else { 100 | chars[i] = chars[i]; 101 | } 102 | } 103 | return new String(chars); 104 | } 105 | 106 | /** 107 | * 转化为全角字符 108 | * 109 | * @param string 待转字符串 110 | * @return 全角字符串 111 | */ 112 | public static String toSBC(String string) { 113 | if (isEmpty(string)) { 114 | return string; 115 | } 116 | char[] chars = string.toCharArray(); 117 | for (int i = 0, len = chars.length; i < len; i++) { 118 | if (chars[i] == ' ') { 119 | chars[i] = (char) 12288; 120 | } else if (33 <= chars[i] && chars[i] <= 126) { 121 | chars[i] = (char) (chars[i] + 65248); 122 | } else { 123 | chars[i] = chars[i]; 124 | } 125 | } 126 | return new String(chars); 127 | } 128 | } -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/TimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Test; 4 | 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | import java.util.Locale; 8 | 9 | import static com.blankj.utilcode.utils.TimeUtils.*; 10 | import static com.google.common.truth.Truth.assertThat; 11 | 12 | 13 | /** 14 | *
 15 |  *     author: Blankj
 16 |  *     blog  : http://blankj.com
 17 |  *     time  : 2016/8/12
 18 |  *     desc  : TimeUtils单元测试
 19 |  * 
20 | */ 21 | public class TimeUtilsTest { 22 | 23 | 24 | SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzzz", Locale.getDefault()); 25 | long milliseconds = 1470991049000L; 26 | Date timeDate = new Date(milliseconds); 27 | String timeString = "2016-08-12 16:37:29"; 28 | String myTimeString = "2016-08-12 16:37:29 中国标准时间"; 29 | String timeString0 = "2016-08-12 16:00:00"; 30 | String timeString1 = "2016-08-12 17:10:10"; 31 | String myTimeString0 = "2016-08-12 16:00:00 中国标准时间"; 32 | String myTimeString1 = "2016-08-12 17:10:10 中国标准时间"; 33 | 34 | 35 | @Test 36 | public void testMilliseconds2String() throws Exception { 37 | assertThat(milliseconds2String(milliseconds)).isEqualTo(timeString); 38 | assertThat(milliseconds2String(milliseconds, myFormat)).isEqualTo(myTimeString); 39 | } 40 | 41 | @Test 42 | public void testString2Milliseconds() throws Exception { 43 | assertThat(string2Milliseconds(timeString)).isEqualTo(milliseconds); 44 | assertThat(string2Milliseconds(myTimeString, myFormat)).isEqualTo(milliseconds); 45 | } 46 | 47 | @Test 48 | public void testString2Date() throws Exception { 49 | assertThat(string2Date(timeString)).isEqualTo(timeDate); 50 | assertThat(string2Date(myTimeString, myFormat)).isEqualTo(timeDate); 51 | } 52 | 53 | @Test 54 | public void testDate2String() throws Exception { 55 | assertThat(date2String(timeDate)).isEqualTo(timeString); 56 | assertThat(date2String(timeDate, myFormat)).isEqualTo(myTimeString); 57 | } 58 | 59 | @Test 60 | public void testDate2Milliseconds() throws Exception { 61 | assertThat(date2Milliseconds(timeDate)).isEqualTo(milliseconds); 62 | } 63 | 64 | @Test 65 | public void testMilliseconds2Date() throws Exception { 66 | assertThat(milliseconds2Date(milliseconds)).isEqualTo(timeDate); 67 | } 68 | 69 | @Test 70 | public void testGetIntervalTime() throws Exception { 71 | assertThat(getIntervalTime(timeString0, timeString1, ConstUtils.TimeUnit.SEC)).isEqualTo(4210); 72 | assertThat(getIntervalTime(myTimeString0, myTimeString1, ConstUtils.TimeUnit.SEC, myFormat)).isEqualTo(4210); 73 | assertThat(getIntervalTime(new Date(4210000), new Date(0), ConstUtils.TimeUnit.SEC)).isEqualTo(4210); 74 | } 75 | 76 | @Test 77 | public void testGetCurTimeMills() throws Exception { 78 | long interval = getCurTimeMills() - System.currentTimeMillis(); 79 | assertThat(interval).isLessThan(10L); 80 | } 81 | 82 | @Test 83 | public void testGetCurTimeString() throws Exception { 84 | System.out.println(getCurTimeString()); 85 | System.out.println(getCurTimeString(myFormat)); 86 | } 87 | 88 | @Test 89 | public void testGetCurTimeDate() throws Exception { 90 | 91 | } 92 | 93 | @Test 94 | public void testGetIntervalByNow() throws Exception { 95 | 96 | } 97 | 98 | @Test 99 | public void testIsLeapYear() throws Exception { 100 | assertThat(isLeapYear(2012)).isEqualTo(true); 101 | assertThat(isLeapYear(2000)).isEqualTo(true); 102 | assertThat(isLeapYear(1900)).isEqualTo(false); 103 | } 104 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/ConstUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | /** 4 | *
  5 |  *     author: Blankj
  6 |  *     blog  : http://blankj.com
  7 |  *     time  : 2016/8/11
  8 |  *     desc  : 常量相关工具类
  9 |  * 
10 | */ 11 | public class ConstUtils { 12 | 13 | private ConstUtils() { 14 | throw new UnsupportedOperationException("u can't fuck me..."); 15 | } 16 | 17 | /******************** 存储相关常量 ********************/ 18 | /** 19 | * Byte与Byte的倍数 20 | */ 21 | public static final int BYTE = 1; 22 | /** 23 | * KB与Byte的倍数 24 | */ 25 | public static final int KB = 1024; 26 | /** 27 | * MB与Byte的倍数 28 | */ 29 | public static final int MB = 1048576; 30 | /** 31 | * GB与Byte的倍数 32 | */ 33 | public static final int GB = 1073741824; 34 | 35 | public enum MemoryUnit { 36 | BYTE, 37 | KB, 38 | MB, 39 | GB 40 | } 41 | 42 | /******************** 时间相关常量 ********************/ 43 | /** 44 | * 毫秒与毫秒的倍数 45 | */ 46 | public static final int MSEC = 1; 47 | /** 48 | * 秒与毫秒的倍数 49 | */ 50 | public static final int SEC = 1000; 51 | /** 52 | * 分与毫秒的倍数 53 | */ 54 | public static final int MIN = 60000; 55 | /** 56 | * 时与毫秒的倍数 57 | */ 58 | public static final int HOUR = 3600000; 59 | /** 60 | * 天与毫秒的倍数 61 | */ 62 | public static final int DAY = 86400000; 63 | 64 | public enum TimeUnit { 65 | MSEC, 66 | SEC, 67 | MIN, 68 | HOUR, 69 | DAY 70 | } 71 | 72 | /******************** 正则相关常量 ********************/ 73 | /** 74 | * 正则:手机号(简单) 75 | */ 76 | public static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$"; 77 | /** 78 | * 正则:手机号(精确) 79 | *

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

80 | *

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

81 | *

电信:133、153、173、177、180、181、189

82 | *

全球星:1349

83 | *

虚拟运营商:170

84 | */ 85 | public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|(147))\\d{8}$"; 86 | /** 87 | * 正则:电话号码 88 | */ 89 | public static final String REGEX_TEL = "^0\\d{2,3}[- ]?\\d{7,8}"; 90 | /** 91 | * 正则:身份证号码15位 92 | */ 93 | public static final String REGEX_IDCARD15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$"; 94 | /** 95 | * 正则:身份证号码18位 96 | */ 97 | public static final String REGEX_IDCARD18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9Xx])$"; 98 | /** 99 | * 正则:邮箱 100 | */ 101 | public static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; 102 | /** 103 | * 正则:URL 104 | */ 105 | public static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?"; 106 | /** 107 | * 正则:汉字 108 | */ 109 | public static final String REGEX_CHZ = "^[\\u4e00-\\u9fa5]+$"; 110 | /** 111 | * 正则:用户名,取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位 112 | */ 113 | public static final String REGEX_USERNAME = "^[\\w\\u4e00-\\u9fa5]{6,20}(? 9 | * author: Blankj 10 | * blog : http://blankj.com 11 | * time : 2016/8/2 12 | * desc : 正则相关工具类 13 | * 14 | */ 15 | public class RegularUtils { 16 | 17 | private RegularUtils() { 18 | throw new UnsupportedOperationException("u can't fuck me..."); 19 | } 20 | 21 | /** 22 | * If u want more please visit http://toutiao.com/i6231678548520731137/ 23 | */ 24 | 25 | /** 26 | * 验证手机号(简单) 27 | * 28 | * @param string 待验证文本 29 | * @return {@code true}: 匹配
{@code false}: 不匹配 30 | */ 31 | public static boolean isMobileSimple(String string) { 32 | return isMatch(REGEX_MOBILE_SIMPLE, string); 33 | } 34 | 35 | /** 36 | * 验证手机号(精确) 37 | * 38 | * @param string 待验证文本 39 | * @return {@code true}: 匹配
{@code false}: 不匹配 40 | */ 41 | public static boolean isMobileExact(String string) { 42 | return isMatch(REGEX_MOBILE_EXACT, string); 43 | } 44 | 45 | /** 46 | * 验证电话号码 47 | * 48 | * @param string 待验证文本 49 | * @return {@code true}: 匹配
{@code false}: 不匹配 50 | */ 51 | public static boolean isTel(String string) { 52 | return isMatch(REGEX_TEL, string); 53 | } 54 | 55 | /** 56 | * 验证身份证号码15位 57 | * 58 | * @param string 待验证文本 59 | * @return {@code true}: 匹配
{@code false}: 不匹配 60 | */ 61 | public static boolean isIDCard15(String string) { 62 | return isMatch(REGEX_IDCARD15, string); 63 | } 64 | 65 | /** 66 | * 验证身份证号码18位 67 | * 68 | * @param string 待验证文本 69 | * @return {@code true}: 匹配
{@code false}: 不匹配 70 | */ 71 | public static boolean isIDCard18(String string) { 72 | return isMatch(REGEX_IDCARD18, string); 73 | } 74 | 75 | /** 76 | * 验证邮箱 77 | * 78 | * @param string 待验证文本 79 | * @return {@code true}: 匹配
{@code false}: 不匹配 80 | */ 81 | public static boolean isEmail(String string) { 82 | return isMatch(REGEX_EMAIL, string); 83 | } 84 | 85 | /** 86 | * 验证URL 87 | * 88 | * @param string 待验证文本 89 | * @return {@code true}: 匹配
{@code false}: 不匹配 90 | */ 91 | public static boolean isURL(String string) { 92 | return isMatch(REGEX_URL, string); 93 | } 94 | 95 | /** 96 | * 验证汉字 97 | * 98 | * @param string 待验证文本 99 | * @return {@code true}: 匹配
{@code false}: 不匹配 100 | */ 101 | public static boolean isChz(String string) { 102 | return isMatch(REGEX_CHZ, string); 103 | } 104 | 105 | /** 106 | * 验证用户名 107 | *

取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位

108 | * 109 | * @param string 待验证文本 110 | * @return {@code true}: 匹配
{@code false}: 不匹配 111 | */ 112 | public static boolean isUsername(String string) { 113 | return isMatch(REGEX_USERNAME, string); 114 | } 115 | 116 | /** 117 | * 验证yyyy-MM-dd格式的日期校验,已考虑平闰年 118 | * 119 | * @param string 待验证文本 120 | * @return {@code true}: 匹配
{@code false}: 不匹配 121 | */ 122 | public static boolean isDate(String string) { 123 | return isMatch(REGEX_DATE, string); 124 | } 125 | 126 | /** 127 | * 验证IP地址 128 | * 129 | * @param string 待验证文本 130 | * @return {@code true}: 匹配
{@code false}: 不匹配 131 | */ 132 | public static boolean isIP(String string) { 133 | return isMatch(REGEX_IP, string); 134 | } 135 | 136 | /** 137 | * string是否匹配regex 138 | * 139 | * @param regex 正则表达式字符串 140 | * @param string 要匹配的字符串 141 | * @return {@code true}: 匹配
{@code false}: 不匹配 142 | */ 143 | public static boolean isMatch(String regex, String string) { 144 | return !StringUtils.isEmpty(string) && Pattern.matches(regex, string); 145 | } 146 | } -------------------------------------------------------------------------------- /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 | *
 11 |  *     author: Blankj
 12 |  *     blog  : http://blankj.com
 13 |  *     time  : 2016/8/2
 14 |  *     desc  : 尺寸相关工具类
 15 |  * 
16 | */ 17 | public class SizeUtils { 18 | 19 | private SizeUtils() { 20 | throw new UnsupportedOperationException("u can't fuck me..."); 21 | } 22 | 23 | /** 24 | * dp转px 25 | * 26 | * @param context 上下文 27 | * @param dpValue dp值 28 | * @return px值 29 | */ 30 | public static int dp2px(Context context, float dpValue) { 31 | final float scale = context.getResources().getDisplayMetrics().density; 32 | return (int) (dpValue * scale + 0.5f); 33 | } 34 | 35 | /** 36 | * px转dp 37 | * 38 | * @param context 上下文 39 | * @param pxValue px值 40 | * @return dp值 41 | */ 42 | public static int px2dp(Context context, float pxValue) { 43 | final float scale = context.getResources().getDisplayMetrics().density; 44 | return (int) (pxValue / scale + 0.5f); 45 | } 46 | 47 | /** 48 | * sp转px 49 | * 50 | * @param context 上下文 51 | * @param spValue sp值 52 | * @return px值 53 | */ 54 | public static int sp2px(Context context, float spValue) { 55 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 56 | return (int) (spValue * fontScale + 0.5f); 57 | } 58 | 59 | /** 60 | * px转sp 61 | * 62 | * @param context 上下文 63 | * @param pxValue px值 64 | * @return sp值 65 | */ 66 | public static int px2sp(Context context, float pxValue) { 67 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 68 | return (int) (pxValue / fontScale + 0.5f); 69 | } 70 | 71 | /** 72 | * 各种单位转换 73 | *

该方法存在于TypedValue

74 | * 75 | * @param unit 单位 76 | * @param value 值 77 | * @param metrics DisplayMetrics 78 | * @return 转换结果 79 | */ 80 | public static float applyDimension(int unit, float value, DisplayMetrics metrics) { 81 | switch (unit) { 82 | case TypedValue.COMPLEX_UNIT_PX: 83 | return value; 84 | case TypedValue.COMPLEX_UNIT_DIP: 85 | return value * metrics.density; 86 | case TypedValue.COMPLEX_UNIT_SP: 87 | return value * metrics.scaledDensity; 88 | case TypedValue.COMPLEX_UNIT_PT: 89 | return value * metrics.xdpi * (1.0f / 72); 90 | case TypedValue.COMPLEX_UNIT_IN: 91 | return value * metrics.xdpi; 92 | case TypedValue.COMPLEX_UNIT_MM: 93 | return value * metrics.xdpi * (1.0f / 25.4f); 94 | } 95 | return 0; 96 | } 97 | 98 | /** 99 | * 在onCreate()即可强行获取View的尺寸 100 | *

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

101 | *

用法示例如下所示

102 | *
{@code
103 |      * SizeUtils.forceGetViewSize(view);
104 |      * SizeUtils.setListener(new SizeUtils.onGetSizeListener() {
105 |      *     public void onGetSize(View view) {
106 |      *         Log.d("tag", view.getWidth() + " " + view.getHeight());
107 |      *     }
108 |      * });}
109 |      * 
110 | * 111 | * @param view 视图 112 | */ 113 | public static void forceGetViewSize(final View view) { 114 | view.post(new Runnable() { 115 | @Override 116 | public void run() { 117 | if (mListener != null) { 118 | mListener.onGetSize(view); 119 | } 120 | } 121 | }); 122 | } 123 | 124 | /** 125 | * 获取到View尺寸的监听 126 | */ 127 | public interface onGetSizeListener { 128 | void onGetSize(View view); 129 | } 130 | 131 | public static void setListener(onGetSizeListener listener) { 132 | mListener = listener; 133 | } 134 | 135 | private static onGetSizeListener mListener; 136 | 137 | /** 138 | * ListView中提前测量View尺寸,如headerView 139 | *

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

140 | *

参照以下注释代码

141 | * 142 | * @param view 视图 143 | */ 144 | public static void measureViewInLV(View view) { 145 | Log.i("tips", "U should copy the following code."); 146 | /* 147 | ViewGroup.LayoutParams p = view.getLayoutParams(); 148 | if (p == null) { 149 | p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 150 | ViewGroup.LayoutParams.WRAP_CONTENT); 151 | } 152 | int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); 153 | int height; 154 | int tempHeight = p.height; 155 | if (tempHeight > 0) { 156 | height = MeasureSpec.makeMeasureSpec(tempHeight, 157 | MeasureSpec.EXACTLY); 158 | } else { 159 | height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 160 | } 161 | view.measure(width, height); 162 | */ 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /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 | *
 12 |  *     author: Blankj
 13 |  *     blog  : http://blankj.com
 14 |  *     time  : 2016/8/2
 15 |  *     desc  : 键盘相关工具类
 16 |  * 
17 | */ 18 | public class KeyboardUtils { 19 | 20 | private KeyboardUtils() { 21 | throw new UnsupportedOperationException("u can't fuck me..."); 22 | } 23 | 24 | /** 25 | * 避免输入法面板遮挡 26 | *

在manifest.xml中activity中设置

27 | *

android:windowSoftInputMode="stateVisible|adjustResize"

28 | */ 29 | 30 | /** 31 | * 动态隐藏软键盘 32 | * 33 | * @param activity activity 34 | */ 35 | public static void hideSoftInput(Activity activity) { 36 | View view = activity.getWindow().peekDecorView(); 37 | if (view != null) { 38 | InputMethodManager inputmanger = (InputMethodManager) activity 39 | .getSystemService(Context.INPUT_METHOD_SERVICE); 40 | inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0); 41 | } 42 | } 43 | 44 | /** 45 | * 动态隐藏软键盘 46 | * 47 | * @param context 上下文 48 | * @param edit 输入框 49 | */ 50 | public static void hideSoftInput(Context context, EditText edit) { 51 | edit.clearFocus(); 52 | InputMethodManager inputmanger = (InputMethodManager) context 53 | .getSystemService(Context.INPUT_METHOD_SERVICE); 54 | inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0); 55 | } 56 | 57 | /** 58 | * 点击屏幕空白区域隐藏软键盘(方法1) 59 | *

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

60 | *

参照以下注释代码

61 | */ 62 | public static void clickBlankArea2HideSoftInput0() { 63 | Log.i("tips", "U should copy the following code."); 64 | /* 65 | @Override 66 | public boolean onTouchEvent (MotionEvent event){ 67 | if (null != this.getCurrentFocus()) { 68 | InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 69 | return mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); 70 | } 71 | return super.onTouchEvent(event); 72 | } 73 | */ 74 | } 75 | 76 | /** 77 | * 点击屏幕空白区域隐藏软键盘(方法2) 78 | *

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

79 | *

需重写dispatchTouchEvent

80 | *

参照以下注释代码

81 | */ 82 | public static void clickBlankArea2HideSoftInput1() { 83 | Log.i("tips", "U should copy the following code."); 84 | /* 85 | @Override 86 | public boolean dispatchTouchEvent(MotionEvent ev) { 87 | if (ev.getAction() == MotionEvent.ACTION_DOWN) { 88 | View v = getCurrentFocus(); 89 | if (isShouldHideKeyboard(v, ev)) { 90 | hideKeyboard(v.getWindowToken()); 91 | } 92 | } 93 | return super.dispatchTouchEvent(ev); 94 | } 95 | 96 | // 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 97 | private boolean isShouldHideKeyboard(View v, MotionEvent event) { 98 | if (v != null && (v instanceof EditText)) { 99 | int[] l = {0, 0}; 100 | v.getLocationInWindow(l); 101 | int left = l[0], 102 | top = l[1], 103 | bottom = top + v.getHeight(), 104 | right = left + v.getWidth(); 105 | return !(event.getX() > left && event.getX() < right 106 | && event.getY() > top && event.getY() < bottom); 107 | } 108 | return false; 109 | } 110 | 111 | // 获取InputMethodManager,隐藏软键盘 112 | private void hideKeyboard(IBinder token) { 113 | if (token != null) { 114 | InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 115 | im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); 116 | } 117 | } 118 | */ 119 | } 120 | 121 | /** 122 | * 动态显示软键盘 123 | * 124 | * @param context 上下文 125 | * @param edit 输入框 126 | */ 127 | public static void showSoftInput(Context context, EditText edit) { 128 | edit.setFocusable(true); 129 | edit.setFocusableInTouchMode(true); 130 | edit.requestFocus(); 131 | InputMethodManager inputManager = (InputMethodManager) context 132 | .getSystemService(Context.INPUT_METHOD_SERVICE); 133 | inputManager.showSoftInput(edit, 0); 134 | } 135 | 136 | /** 137 | * 切换键盘显示与否状态 138 | * 139 | * @param context 上下文 140 | * @param edit 输入框 141 | */ 142 | public static void toggleSoftInput(Context context, EditText edit) { 143 | edit.setFocusable(true); 144 | edit.setFocusableInTouchMode(true); 145 | edit.requestFocus(); 146 | InputMethodManager inputManager = (InputMethodManager) context 147 | .getSystemService(Context.INPUT_METHOD_SERVICE); 148 | inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); 149 | } 150 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/SPUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | *
 10 |  *     author: Blankj
 11 |  *     blog  : http://blankj.com
 12 |  *     time  : 2016/8/2
 13 |  *     desc  : SP相关工具类
 14 |  * 
15 | */ 16 | public class SPUtils { 17 | 18 | private SharedPreferences sp; 19 | private SharedPreferences.Editor editor; 20 | 21 | /** 22 | * SPUtils构造函数 23 | * 24 | * @param context 上下文 25 | * @param spName spName 26 | */ 27 | public SPUtils(Context context, String spName) { 28 | sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE); 29 | editor = sp.edit(); 30 | editor.apply(); 31 | } 32 | 33 | /** 34 | * SP中写入String类型value 35 | * 36 | * @param key 键 37 | * @param value 值 38 | */ 39 | public void putString(String key, String value) { 40 | editor.putString(key, value).apply(); 41 | } 42 | 43 | /** 44 | * SP中读取String 45 | * 46 | * @param key 键 47 | * @return 存在返回对应值,不存在返回默认值{@code null} 48 | */ 49 | public String getString(String key) { 50 | return getString(key, null); 51 | } 52 | 53 | /** 54 | * SP中读取String 55 | * 56 | * @param key 键 57 | * @param defaultValue 默认值 58 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 59 | */ 60 | public String getString(String key, String defaultValue) { 61 | return sp.getString(key, defaultValue); 62 | } 63 | 64 | /** 65 | * SP中写入int类型value 66 | * 67 | * @param key 键 68 | * @param value 值 69 | */ 70 | public void putInt(String key, int value) { 71 | editor.putInt(key, value).apply(); 72 | } 73 | 74 | /** 75 | * SP中读取int 76 | * 77 | * @param key 键 78 | * @return 存在返回对应值,不存在返回默认值-1 79 | */ 80 | public int getInt(String key) { 81 | return getInt(key, -1); 82 | } 83 | 84 | /** 85 | * SP中读取int 86 | * 87 | * @param key 键 88 | * @param defaultValue 默认值 89 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 90 | */ 91 | public int getInt(String key, int defaultValue) { 92 | return sp.getInt(key, defaultValue); 93 | } 94 | 95 | /** 96 | * SP中写入long类型value 97 | * 98 | * @param key 键 99 | * @param value 值 100 | */ 101 | public void putLong(String key, long value) { 102 | editor.putLong(key, value).apply(); 103 | } 104 | 105 | /** 106 | * SP中读取long 107 | * 108 | * @param key 键 109 | * @return 存在返回对应值,不存在返回默认值-1 110 | */ 111 | public long getLong(String key) { 112 | return getLong(key, -1L); 113 | } 114 | 115 | /** 116 | * SP中读取long 117 | * 118 | * @param key 键 119 | * @param defaultValue 默认值 120 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 121 | */ 122 | public long getLong(String key, long defaultValue) { 123 | return sp.getLong(key, defaultValue); 124 | } 125 | 126 | /** 127 | * SP中写入float类型value 128 | * 129 | * @param key 键 130 | * @param value 值 131 | */ 132 | public void putFloat(String key, float value) { 133 | editor.putFloat(key, value).apply(); 134 | } 135 | 136 | /** 137 | * SP中读取float 138 | * 139 | * @param key 键 140 | * @return 存在返回对应值,不存在返回默认值-1 141 | */ 142 | public float getFloat(String key) { 143 | return getFloat(key, -1f); 144 | } 145 | 146 | /** 147 | * SP中读取float 148 | * 149 | * @param key 键 150 | * @param defaultValue 默认值 151 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 152 | */ 153 | public float getFloat(String key, float defaultValue) { 154 | return sp.getFloat(key, defaultValue); 155 | } 156 | 157 | /** 158 | * SP中写入boolean类型value 159 | * 160 | * @param key 键 161 | * @param value 值 162 | */ 163 | public void putBoolean(String key, boolean value) { 164 | editor.putBoolean(key, value).apply(); 165 | } 166 | 167 | /** 168 | * SP中读取boolean 169 | * 170 | * @param key 键 171 | * @return 存在返回对应值,不存在返回默认值{@code false} 172 | */ 173 | public boolean getBoolean(String key) { 174 | return getBoolean(key, false); 175 | } 176 | 177 | /** 178 | * SP中读取boolean 179 | * 180 | * @param key 键 181 | * @param defaultValue 默认值 182 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 183 | */ 184 | public boolean getBoolean(String key, boolean defaultValue) { 185 | return sp.getBoolean(key, defaultValue); 186 | } 187 | 188 | /** 189 | * 获取SP中所有键值对 190 | * 191 | * @return Map对象 192 | */ 193 | public Map getAll() { 194 | return sp.getAll(); 195 | } 196 | 197 | /** 198 | * 从SP中移除该key 199 | * 200 | * @param key 键 201 | */ 202 | public void remove(String key) { 203 | editor.remove(key).apply(); 204 | } 205 | 206 | /** 207 | * 判断SP中是否存在该key 208 | * 209 | * @param key 键 210 | * @return {@code true}: 存在
{@code false}: 不存在 211 | */ 212 | public boolean contains(String key) { 213 | return sp.contains(key); 214 | } 215 | 216 | /** 217 | * 清除SP中所有数据 218 | */ 219 | public void clear() { 220 | editor.clear().apply(); 221 | } 222 | 223 | 224 | } 225 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/EncodeUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.os.Build; 4 | import android.text.Html; 5 | import android.util.Base64; 6 | 7 | import java.io.UnsupportedEncodingException; 8 | import java.net.URLDecoder; 9 | import java.net.URLEncoder; 10 | 11 | /** 12 | *
 13 |  *     author: Blankj
 14 |  *     blog  : http://blankj.com
 15 |  *     time  : 2016/8/7
 16 |  *     desc  : 编码解码相关工具类
 17 |  * 
18 | */ 19 | public class EncodeUtils { 20 | 21 | private EncodeUtils() { 22 | throw new UnsupportedOperationException("u can't fuck me..."); 23 | } 24 | 25 | /** 26 | * URL编码 27 | *

若想自己指定字符集,可以使用{@link #urlEncode(String input, String charset)}方法

28 | * 29 | * @param input 要编码的字符 30 | * @return 编码为UTF-8的字符串 31 | */ 32 | public static String urlEncode(String input) { 33 | return urlEncode(input, "UTF-8"); 34 | } 35 | 36 | /** 37 | * URL编码 38 | *

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

39 | * 40 | * @param input 要编码的字符 41 | * @param charset 字符集 42 | * @return 编码为字符集的字符串 43 | */ 44 | public static String urlEncode(String input, String charset) { 45 | try { 46 | return URLEncoder.encode(input, charset); 47 | } catch (UnsupportedEncodingException e) { 48 | return input; 49 | } 50 | } 51 | 52 | /** 53 | * URL解码 54 | *

若想自己指定字符集,可以使用 {@link #urlDecode(String input, String charset)}方法

55 | * 56 | * @param input 要解码的字符串 57 | * @return URL解码后的字符串 58 | */ 59 | public static String urlDecode(String input) { 60 | return urlDecode(input, "UTF-8"); 61 | } 62 | 63 | /** 64 | * URL解码 65 | *

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

66 | * 67 | * @param input 要解码的字符串 68 | * @param charset 字符集 69 | * @return URL解码为指定字符集的字符串 70 | */ 71 | public static String urlDecode(String input, String charset) { 72 | try { 73 | return URLDecoder.decode(input, charset); 74 | } catch (UnsupportedEncodingException e) { 75 | return input; 76 | } 77 | } 78 | 79 | /** 80 | * Base64编码 81 | * 82 | * @param input 要编码的字符串 83 | * @return Base64编码后的字符串 84 | */ 85 | public static byte[] base64Encode(String input) { 86 | return base64Encode(input.getBytes()); 87 | } 88 | 89 | /** 90 | * Base64编码 91 | * 92 | * @param input 要编码的字节数组 93 | * @return Base64编码后的字符串 94 | */ 95 | public static byte[] base64Encode(byte[] input) { 96 | return Base64.encode(input, Base64.NO_WRAP); 97 | } 98 | 99 | /** 100 | * Base64编码 101 | * 102 | * @param input 要编码的字节数组 103 | * @return Base64编码后的字符串 104 | */ 105 | public static String base64Encode2String(byte[] input) { 106 | return Base64.encodeToString(input, Base64.NO_WRAP); 107 | } 108 | 109 | /** 110 | * Base64解码 111 | * 112 | * @param input 要解码的字符串 113 | * @return Base64解码后的字符串 114 | */ 115 | public static byte[] base64Decode(String input) { 116 | return Base64.decode(input, Base64.NO_WRAP); 117 | } 118 | 119 | /** 120 | * Base64解码 121 | * 122 | * @param input 要解码的字符串 123 | * @return Base64解码后的字符串 124 | */ 125 | public static byte[] base64Decode(byte[] input) { 126 | return Base64.decode(input, Base64.NO_WRAP); 127 | } 128 | 129 | /** 130 | * Base64URL安全编码 131 | *

将Base64中的URL非法字符�?,/=转为其他字符, 见RFC3548

132 | * 133 | * @param input 要Base64URL安全编码的字符串 134 | * @return Base64URL安全编码后的字符串 135 | */ 136 | public static byte[] base64UrlSafeEncode(String input) { 137 | return Base64.encode(input.getBytes(), Base64.URL_SAFE); 138 | } 139 | 140 | /** 141 | * Html编码 142 | * 143 | * @param input 要Html编码的字符串 144 | * @return Html编码后的字符串 145 | */ 146 | public static String htmlEncode(String input) { 147 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 148 | return Html.escapeHtml(input); 149 | } else { 150 | // 参照Html.escapeHtml()中代码 151 | StringBuilder out = new StringBuilder(); 152 | for (int i = 0, len = input.length(); i < len; i++) { 153 | char c = input.charAt(i); 154 | if (c == '<') { 155 | out.append("<"); 156 | } else if (c == '>') { 157 | out.append(">"); 158 | } else if (c == '&') { 159 | out.append("&"); 160 | } else if (c >= 0xD800 && c <= 0xDFFF) { 161 | if (c < 0xDC00 && i + 1 < len) { 162 | char d = input.charAt(i + 1); 163 | if (d >= 0xDC00 && d <= 0xDFFF) { 164 | i++; 165 | int codepoint = 0x010000 | (int) c - 0xD800 << 10 | (int) d - 0xDC00; 166 | out.append("&#").append(codepoint).append(";"); 167 | } 168 | } 169 | } else if (c > 0x7E || c < ' ') { 170 | out.append("&#").append((int) c).append(";"); 171 | } else if (c == ' ') { 172 | while (i + 1 < len && input.charAt(i + 1) == ' ') { 173 | out.append(" "); 174 | i++; 175 | } 176 | out.append(' '); 177 | } else { 178 | out.append(c); 179 | } 180 | } 181 | return out.toString(); 182 | } 183 | } 184 | 185 | /** 186 | * Html解码 187 | * 188 | * @param input 待解码的字符串 189 | * @return Html解码后的字符串 190 | */ 191 | public static String htmlDecode(String input) { 192 | return Html.fromHtml(input).toString(); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/SDCardUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.os.Environment; 4 | import android.os.StatFs; 5 | 6 | import java.io.File; 7 | 8 | import static com.blankj.utilcode.utils.ConstUtils.*; 9 | 10 | /** 11 | *
 12 |  *     author: Blankj
 13 |  *     blog  : http://blankj.com
 14 |  *     time  : 2016/8/11
 15 |  *     desc  : SD卡相关工具类
 16 |  * 
17 | */ 18 | public class SDCardUtils { 19 | 20 | private SDCardUtils() { 21 | throw new UnsupportedOperationException("u can't fuck me..."); 22 | } 23 | 24 | /** 25 | * 判断SD卡是否可用 26 | * 27 | * @return true : 可用
false : 不可用 28 | */ 29 | public static boolean isSDCardEnable() { 30 | return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); 31 | } 32 | 33 | /** 34 | * 获取SD卡路径 35 | *

一般是/storage/emulated/0/

36 | * 37 | * @return SD卡路径 38 | */ 39 | public static String getSDCardPath() { 40 | return Environment.getExternalStorageDirectory().getPath() + File.separator; 41 | } 42 | 43 | /** 44 | * 获取SD卡Data路径 45 | * 46 | * @return Data路径 47 | */ 48 | public static String getDataPath() { 49 | return Environment.getDataDirectory().getPath(); 50 | 51 | } 52 | 53 | /** 54 | * 计算SD卡的剩余空间 55 | * 56 | * @param unit
    57 | *
  • {@link MemoryUnit#BYTE}: 字节
  • 58 | *
  • {@link MemoryUnit#KB} : 千字节
  • 59 | *
  • {@link MemoryUnit#MB} : 兆
  • 60 | *
  • {@link MemoryUnit#GB} : GB
  • 61 | *
62 | * @return 返回-1,说明SD卡不可用,否则返回SD卡剩余空间 63 | */ 64 | public static double getFreeSpace(MemoryUnit unit) { 65 | if (isSDCardEnable()) { 66 | try { 67 | StatFs stat = new StatFs(getSDCardPath()); 68 | long blockSize, availableBlocks; 69 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { 70 | availableBlocks = stat.getAvailableBlocksLong(); 71 | blockSize = stat.getBlockSizeLong(); 72 | } else { 73 | availableBlocks = stat.getAvailableBlocks(); 74 | blockSize = stat.getBlockSize(); 75 | } 76 | return FileUtils.byte2Size(availableBlocks * blockSize, unit); 77 | } catch (Exception e) { 78 | e.printStackTrace(); 79 | return -1.0; 80 | } 81 | } else { 82 | return -1.0; 83 | } 84 | } 85 | 86 | // /** 87 | // * 获取指定路径所在空间的剩余可用容量字节数,单位byte 88 | // * 89 | // * @param filePath 90 | // * @return 容量字节 SDCard可用空间,内部存储可用空间 91 | // */ 92 | // public static long getFreeBytes(String filePath) { 93 | // // 如果是sd卡的下的路径,则获取sd卡可用容量 94 | // if (filePath.startsWith(getSDCardPath())) { 95 | // filePath = getSDCardPath(); 96 | // } else {// 如果是内部存储的路径,则获取内存存储的可用容量 97 | // filePath = Environment.getDataDirectory().getAbsolutePath(); 98 | // } 99 | // StatFs stat = new StatFs(filePath); 100 | // long availableBlocks = (long) stat.getAvailableBlocks() - 4; 101 | // return stat.getBlockSize() * availableBlocks; 102 | // } 103 | // 104 | // /** 105 | // * 获取系统存储路径 106 | // * 107 | // * @return 108 | // */ 109 | // public static String getRootDirectoryPath() { 110 | // return Environment.getRootDirectory().getAbsolutePath(); 111 | // } 112 | // 113 | // /** 114 | // * Check if the file is exists 115 | // * 116 | // * @param filePath 117 | // * @param fileName 118 | // * @return 119 | // */ 120 | // public static boolean isFileExistsInSDCard(String filePath, String fileName) { 121 | // boolean flag = false; 122 | // if (isSDCardEnable()) { 123 | // File file = new File(filePath, fileName); 124 | // if (file.exists()) { 125 | // flag = true; 126 | // } 127 | // } 128 | // return flag; 129 | // } 130 | // 131 | // /** 132 | // * Write file to SD card 133 | // * 134 | // * @param filePath 135 | // * @param filename 136 | // * @param content 137 | // * @return 138 | // * @throws Exception 139 | // */ 140 | // public static boolean saveFileToSDCard(String filePath, String filename, String content) 141 | // throws Exception { 142 | // boolean flag = false; 143 | // if (isSDCardEnable()) { 144 | // File dir = new File(filePath); 145 | // if (!dir.exists()) { 146 | // dir.mkdirs(); 147 | // } 148 | // File file = new File(filePath, filename); 149 | // FileOutputStream outStream = new FileOutputStream(file); 150 | // outStream.write(content.getBytes()); 151 | // outStream.close(); 152 | // flag = true; 153 | // } 154 | // return flag; 155 | // } 156 | // 157 | // /** 158 | // * Read file as stream from SD card 159 | // * 160 | // * @param fileName String PATH = 161 | // * Environment.getExternalStorageDirectory().getAbsolutePath() + 162 | // * "/dirName"; 163 | // * @return 164 | // */ 165 | // public static byte[] readFileFromSDCard(String filePath, String fileName) { 166 | // byte[] buffer = null; 167 | // FileInputStream fin = null; 168 | // try { 169 | // if (isSDCardEnable()) { 170 | // String filePaht = filePath + "/" + fileName; 171 | // fin = new FileInputStream(filePaht); 172 | // int length = fin.available(); 173 | // buffer = new byte[length]; 174 | // fin.read(buffer); 175 | // } 176 | // } catch (Exception e) { 177 | // e.printStackTrace(); 178 | // } finally { 179 | // try { 180 | // if (fin != null) fin.close(); 181 | // } catch (IOException e) { 182 | // e.printStackTrace(); 183 | // } 184 | // } 185 | // return buffer; 186 | // } 187 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/ShellUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.util.List; 8 | 9 | /** 10 | *
 11 |  *     author: Blankj
 12 |  *     blog  : http://blankj.com
 13 |  *     time  : 2016/8/7
 14 |  *     desc  : Shell相关工具类
 15 |  * 
16 | */ 17 | public class ShellUtils { 18 | 19 | private ShellUtils() { 20 | throw new UnsupportedOperationException("u can't fuck me..."); 21 | } 22 | 23 | public static final String COMMAND_SU = "su"; 24 | public static final String COMMAND_SH = "sh"; 25 | public static final String COMMAND_EXIT = "exit\n"; 26 | public static final String COMMAND_LINE_END = "\n"; 27 | 28 | /** 29 | * 判断设备是否root 30 | * @return {@code true}: root
{@code false}: 没root 31 | */ 32 | public static boolean isRoot() { 33 | return execCmd("echo root", true, false).result == 0; 34 | } 35 | 36 | /** 37 | * 是否是在root下执行命令 38 | * 39 | * @param command 命令 40 | * @param isRoot 是否root 41 | * @return CommandResult 42 | */ 43 | public static CommandResult execCmd(String command, boolean isRoot) { 44 | return execCmd(new String[]{command}, isRoot, true); 45 | } 46 | 47 | /** 48 | * 是否是在root下执行命令 49 | * 50 | * @param commands 多条命令链表 51 | * @param isRoot 是否root 52 | * @return CommandResult 53 | */ 54 | public static CommandResult execCmd(List commands, boolean isRoot) { 55 | return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, true); 56 | } 57 | 58 | /** 59 | * 是否是在root下执行命令 60 | * 61 | * @param commands 多条命令数组 62 | * @param isRoot 是否root 63 | * @return CommandResult 64 | */ 65 | public static CommandResult execCmd(String[] commands, boolean isRoot) { 66 | return execCmd(commands, isRoot, true); 67 | } 68 | 69 | /** 70 | * 是否是在root下执行命令 71 | * 72 | * @param command 命令 73 | * @param isRoot 是否root 74 | * @param isNeedResultMsg 是否需要结果消息 75 | * @return CommandResult 76 | */ 77 | public static CommandResult execCmd(String command, boolean isRoot, boolean isNeedResultMsg) { 78 | return execCmd(new String[]{command}, isRoot, isNeedResultMsg); 79 | } 80 | 81 | /** 82 | * 是否是在root下执行命令 83 | * 84 | * @param commands 命令链表 85 | * @param isRoot 是否root 86 | * @param isNeedResultMsg 是否需要结果消息 87 | * @return CommandResult 88 | */ 89 | public static CommandResult execCmd(List commands, boolean isRoot, boolean isNeedResultMsg) { 90 | return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg); 91 | } 92 | 93 | /** 94 | * 是否是在root下执行命令 95 | * 96 | * @param commands 命令数组 97 | * @param isRoot 是否root 98 | * @param isNeedResultMsg 是否需要结果消息 99 | * @return CommandResult 100 | */ 101 | public static CommandResult execCmd(String[] commands, boolean isRoot, boolean isNeedResultMsg) { 102 | int result = -1; 103 | if (commands == null || commands.length == 0) { 104 | return new CommandResult(result, null, null); 105 | } 106 | Process process = null; 107 | BufferedReader successResult = null; 108 | BufferedReader errorResult = null; 109 | StringBuilder successMsg = null; 110 | StringBuilder errorMsg = null; 111 | DataOutputStream os = null; 112 | try { 113 | process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); 114 | os = new DataOutputStream(process.getOutputStream()); 115 | for (String command : commands) { 116 | if (command == null) { 117 | continue; 118 | } 119 | os.write(command.getBytes()); 120 | os.writeBytes(COMMAND_LINE_END); 121 | os.flush(); 122 | } 123 | os.writeBytes(COMMAND_EXIT); 124 | os.flush(); 125 | 126 | result = process.waitFor(); 127 | if (isNeedResultMsg) { 128 | successMsg = new StringBuilder(); 129 | errorMsg = new StringBuilder(); 130 | successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); 131 | errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); 132 | String s; 133 | while ((s = successResult.readLine()) != null) { 134 | successMsg.append(s); 135 | } 136 | while ((s = errorResult.readLine()) != null) { 137 | errorMsg.append(s); 138 | } 139 | } 140 | } catch (Exception e) { 141 | e.printStackTrace(); 142 | } finally { 143 | try { 144 | if (os != null) { 145 | os.close(); 146 | } 147 | if (successResult != null) { 148 | successResult.close(); 149 | } 150 | if (errorResult != null) { 151 | errorResult.close(); 152 | } 153 | } catch (IOException e) { 154 | e.printStackTrace(); 155 | } 156 | 157 | if (process != null) { 158 | process.destroy(); 159 | } 160 | } 161 | return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null 162 | : errorMsg.toString()); 163 | } 164 | 165 | /** 166 | * 返回的命令结果 167 | */ 168 | public static class CommandResult { 169 | 170 | /** 171 | * 结果码 172 | **/ 173 | public int result; 174 | /** 175 | * 成功的信息 176 | **/ 177 | public String successMsg; 178 | /** 179 | * 错误信息 180 | **/ 181 | public String errorMsg; 182 | 183 | public CommandResult(int result) { 184 | this.result = result; 185 | } 186 | 187 | public CommandResult(int result, String successMsg, String errorMsg) { 188 | this.result = result; 189 | this.successMsg = successMsg; 190 | this.errorMsg = errorMsg; 191 | } 192 | } 193 | } -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/EncryptUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.robolectric.RobolectricTestRunner; 6 | import org.robolectric.annotation.Config; 7 | 8 | import java.io.File; 9 | 10 | import static com.blankj.utilcode.utils.ConvertUtils.*; 11 | import static com.blankj.utilcode.utils.EncodeUtils.*; 12 | import static com.blankj.utilcode.utils.EncryptUtils.*; 13 | import static com.google.common.truth.Truth.assertThat; 14 | 15 | /** 16 | *
 17 |  *     author: Blankj
 18 |  *     blog  : http://blankj.com
 19 |  *     time  : 2016/8/6
 20 |  *     desc  : EncryptUtils单元测试
 21 |  * 
22 | */ 23 | @RunWith(RobolectricTestRunner.class) 24 | @Config(manifest = Config.NONE) 25 | public class EncryptUtilsTest { 26 | 27 | String blankjMD2 = "15435017570D8A73449E25C4622E17A4"; 28 | String blankjMD5 = "AAC25CD336E01C8655F4EC7875445A60"; 29 | String blankjSHA1 = "C606ACCB1FEB669E19D080ADDDDBB8E6CDA5F43C"; 30 | String blankjSHA224 = "F4C5C0E8CF56CAC4D06DB6B523F67621859A9D79BDA4B2AC03097D5F"; 31 | String blankjSHA256 = "8BD80AE90DFBA112786367BEBDDEE60A638EF5B82682EDF8F3D3CA8E6BFEF648"; 32 | String blankjSHA384 = 33 | "BF831E5221FC108D6A72ACB888BA3EB0C030A5F01BA2F739856BE70681D86F992B85E0D461101C74BAEDA895BD422557"; 34 | String blankjSHA512 = 35 | "D59D31067F614ED3586F85A31FEFDB7F33096316DA26EBE0FF440B241C8560D96650F100D78C512560C976949EFA89CB5D5589DCF68C7FAADE98F03BCFEC2B45"; 36 | 37 | @Test 38 | public void testEncryptMD2() throws Exception { 39 | assertThat(encryptMD2ToString("blankj")).isEqualTo(blankjMD2); 40 | assertThat(encryptMD2ToString("blankj".getBytes())).isEqualTo(blankjMD2); 41 | assertThat(encryptMD2("blankj".getBytes())).isEqualTo(hexString2Bytes(blankjMD2)); 42 | } 43 | 44 | @Test 45 | public void testEncryptMD5() throws Exception { 46 | assertThat(encryptMD5ToString("blankj")).isEqualTo(blankjMD5); 47 | assertThat(encryptMD5ToString("blankj".getBytes())).isEqualTo(blankjMD5); 48 | assertThat(encryptMD5("blankj".getBytes())).isEqualTo(hexString2Bytes(blankjMD5)); 49 | } 50 | 51 | @Test 52 | public void testEncryptSHA1() throws Exception { 53 | assertThat(encryptSHA1ToString("blankj")).isEqualTo(blankjSHA1); 54 | assertThat(encryptSHA1ToString("blankj".getBytes())).isEqualTo(blankjSHA1); 55 | assertThat(encryptSHA1("blankj".getBytes())).isEqualTo(hexString2Bytes(blankjSHA1)); 56 | } 57 | 58 | @Test 59 | public void testEncryptSHA224() throws Exception { 60 | assertThat(encryptSHA224ToString("blankj")).isEqualTo(blankjSHA224); 61 | assertThat(encryptSHA224ToString("blankj".getBytes())).isEqualTo(blankjSHA224); 62 | assertThat(encryptSHA224("blankj".getBytes())).isEqualTo(hexString2Bytes(blankjSHA224)); 63 | } 64 | 65 | @Test 66 | public void testEncryptSHA256() throws Exception { 67 | assertThat(encryptSHA256ToString("blankj")).isEqualTo(blankjSHA256); 68 | assertThat(encryptSHA256ToString("blankj".getBytes())).isEqualTo(blankjSHA256); 69 | assertThat(encryptSHA256("blankj".getBytes())).isEqualTo(hexString2Bytes(blankjSHA256)); 70 | } 71 | 72 | @Test 73 | public void testEncryptSHA384() throws Exception { 74 | assertThat(encryptSHA384ToString("blankj")).isEqualTo(blankjSHA384); 75 | assertThat(encryptSHA384ToString("blankj".getBytes())).isEqualTo(blankjSHA384); 76 | assertThat(encryptSHA384("blankj".getBytes())).isEqualTo(hexString2Bytes(blankjSHA384)); 77 | } 78 | 79 | @Test 80 | public void testEncryptSHA512() throws Exception { 81 | assertThat(encryptSHA512ToString("blankj")).isEqualTo(blankjSHA512); 82 | assertThat(encryptSHA512ToString("blankj".getBytes())).isEqualTo(blankjSHA512); 83 | assertThat(encryptSHA512("blankj".getBytes())).isEqualTo(hexString2Bytes(blankjSHA512)); 84 | } 85 | 86 | String dataDES = "0008DB3345AB0223"; 87 | String keyDES = "6801020304050607"; 88 | String resDES = "1F7962581118F360"; 89 | byte[] bytesDataDES = hexString2Bytes(dataDES); 90 | byte[] bytesKeyDES = hexString2Bytes(keyDES); 91 | byte[] bytesResDES = hexString2Bytes(resDES); 92 | 93 | @Test 94 | public void testEncryptDES() throws Exception { 95 | assertThat(encryptDES(bytesDataDES, bytesKeyDES)).isEqualTo(bytesResDES); 96 | assertThat(encryptDES2HexString(bytesDataDES, bytesKeyDES)).isEqualTo(resDES); 97 | assertThat(encryptDES2Base64(bytesDataDES, bytesKeyDES)).isEqualTo(base64Encode 98 | (bytesResDES)); 99 | } 100 | 101 | @Test 102 | public void testDecryptDES() throws Exception { 103 | assertThat(decryptDES(bytesResDES, bytesKeyDES)).isEqualTo(bytesDataDES); 104 | assertThat(decryptHexStringDES(resDES, bytesKeyDES)).isEqualTo(bytesDataDES); 105 | assertThat(decryptBase64DES(base64Encode(bytesResDES), bytesKeyDES)).isEqualTo 106 | (bytesDataDES); 107 | } 108 | 109 | String data3DES = "1111111111111111"; 110 | String key3DES = "111111111111111111111111111111111111111111111111"; 111 | String res3DES = "F40379AB9E0EC533"; 112 | byte[] bytesDataDES3 = hexString2Bytes(data3DES); 113 | byte[] bytesKeyDES3 = hexString2Bytes(key3DES); 114 | byte[] bytesResDES3 = hexString2Bytes(res3DES); 115 | 116 | @Test 117 | public void testEncrypt3DES() throws Exception { 118 | assertThat(encrypt3DES(bytesDataDES3, bytesKeyDES3)).isEqualTo(bytesResDES3); 119 | assertThat(encrypt3DES2HexString(bytesDataDES3, bytesKeyDES3)).isEqualTo(res3DES); 120 | assertThat(encrypt3DES2Base64(bytesDataDES3, bytesKeyDES3)).isEqualTo(base64Encode 121 | (bytesResDES3)); 122 | } 123 | 124 | @Test 125 | public void testDecrypt3DES() throws Exception { 126 | assertThat(decrypt3DES(bytesResDES3, bytesKeyDES3)).isEqualTo(bytesDataDES3); 127 | assertThat(decryptHexString3DES(res3DES, bytesKeyDES3)).isEqualTo(bytesDataDES3); 128 | assertThat(decryptBase64_3DES(base64Encode(bytesResDES3), bytesKeyDES3)).isEqualTo 129 | (bytesDataDES3); 130 | } 131 | 132 | String dataAES = "11111111111111111111111111111111"; 133 | String keyAES = "11111111111111111111111111111111"; 134 | String resAES = "E56E26F5608B8D268F2556E198A0E01B"; 135 | byte[] bytesDataAES = hexString2Bytes(dataAES); 136 | byte[] bytesKeyAES = hexString2Bytes(keyAES); 137 | byte[] bytesResAES = hexString2Bytes(resAES); 138 | 139 | @Test 140 | public void testEncryptAES() throws Exception { 141 | assertThat(encryptAES(bytesDataAES, bytesKeyAES)).isEqualTo(bytesResAES); 142 | assertThat(encryptAES2HexString(bytesDataAES, bytesKeyAES)).isEqualTo(resAES); 143 | assertThat(encryptAES2Base64(bytesDataAES, bytesKeyAES)).isEqualTo(base64Encode 144 | (bytesResAES)); 145 | } 146 | 147 | @Test 148 | public void testDecryptAES() throws Exception { 149 | assertThat(decryptAES(bytesResAES, bytesKeyAES)).isEqualTo(bytesDataAES); 150 | assertThat(decryptHexStringAES(resAES, bytesKeyAES)).isEqualTo(bytesDataAES); 151 | assertThat(decryptBase64AES(base64Encode(bytesResAES), bytesKeyAES)).isEqualTo 152 | (bytesDataAES); 153 | } 154 | 155 | String path = TestUtils.BASEPATH + "encrypt" + TestUtils.SEP; 156 | String md5 = "7F138A09169B250E9DCB378140907378"; 157 | 158 | @Test 159 | public void testEncryptMD5File() throws Exception { 160 | assertThat(encryptMD5File2String(new File(path + "MD5.txt"))).isEqualTo(md5); 161 | } 162 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/ScreenUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.app.Activity; 4 | import android.app.KeyguardManager; 5 | import android.content.Context; 6 | import android.content.pm.ActivityInfo; 7 | import android.graphics.Bitmap; 8 | import android.os.Build; 9 | import android.util.DisplayMetrics; 10 | import android.util.TypedValue; 11 | import android.view.View; 12 | import android.view.Window; 13 | import android.view.WindowManager; 14 | import android.view.WindowManager.LayoutParams; 15 | 16 | import java.lang.reflect.Method; 17 | 18 | /** 19 | *
 20 |  *     author: Blankj
 21 |  *     blog  : http://blankj.com
 22 |  *     time  : 2016/8/2
 23 |  *     desc  : 屏幕相关工具类
 24 |  * 
25 | */ 26 | public class ScreenUtils { 27 | 28 | private ScreenUtils() { 29 | throw new UnsupportedOperationException("u can't fuck me..."); 30 | } 31 | 32 | /** 33 | * 获取屏幕的宽度px 34 | * 35 | * @param context 上下文 36 | * @return 屏幕宽px 37 | */ 38 | public static int getScreenWidth(Context context) { 39 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 40 | DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 41 | windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 42 | return outMetrics.widthPixels; 43 | } 44 | 45 | /** 46 | * 获取屏幕的高度px 47 | * 48 | * @param context 上下文 49 | * @return 屏幕高px 50 | */ 51 | public static int getScreenHeight(Context context) { 52 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 53 | DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 54 | windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 55 | return outMetrics.heightPixels; 56 | } 57 | 58 | /** 59 | * 设置透明状态栏(api大于19方可使用) 60 | *

可在Activity的onCreat()中调用

61 | *

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

62 | *

android:clipToPadding="true"

63 | *

android:fitsSystemWindows="true"

64 | * 65 | * @param activity activity 66 | */ 67 | public static void setTransparentStatusBar(Activity activity) { 68 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 69 | //透明状态栏 70 | activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS); 71 | //透明导航栏 72 | activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 73 | } 74 | } 75 | 76 | /** 77 | * 隐藏状态栏 78 | *

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

79 | *

此方法Activity可以继承AppCompatActivity

80 | *

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

81 | *

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

82 | *

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

83 | * 84 | * @param activity activity 85 | */ 86 | public static void hideStatusBar(Activity activity) { 87 | activity.requestWindowFeature(Window.FEATURE_NO_TITLE); 88 | activity.getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, 89 | LayoutParams.FLAG_FULLSCREEN); 90 | } 91 | 92 | /** 93 | * 获取状态栏高度 94 | * 95 | * @param context 上下文 96 | * @return 状态栏高度 97 | */ 98 | public static int getStatusBarHeight(Context context) { 99 | int result = 0; 100 | int resourceId = context.getResources() 101 | .getIdentifier("status_bar_height", "dimen", "android"); 102 | if (resourceId > 0) { 103 | result = context.getResources().getDimensionPixelSize(resourceId); 104 | } 105 | return result; 106 | } 107 | 108 | /** 109 | * 判断状态栏是否存在 110 | * 111 | * @param activity activity 112 | * @return {@code true}: 存在
{@code false}: 不存在 113 | */ 114 | public static boolean isStatusBarExists(Activity activity) { 115 | LayoutParams params = activity.getWindow().getAttributes(); 116 | return (params.flags & LayoutParams.FLAG_FULLSCREEN) != LayoutParams.FLAG_FULLSCREEN; 117 | } 118 | 119 | /** 120 | * 获取ActionBar高度 121 | * 122 | * @param activity activity 123 | * @return ActionBar高度 124 | */ 125 | public static int getActionBarHeight(Activity activity) { 126 | TypedValue tv = new TypedValue(); 127 | if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { 128 | return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics()); 129 | } 130 | return 0; 131 | } 132 | 133 | /** 134 | * 显示通知栏 135 | *

需添加权限 {@code }

136 | * 137 | * @param context 上下文 138 | * @param isSettingPanel {@code true}: 打开设置
{@code false}: 打开通知 139 | */ 140 | public static void showNotificationBar(Context context, boolean isSettingPanel) { 141 | String methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" 142 | : (isSettingPanel ? "expandSettingsPanel" : "expandNotificationsPanel"); 143 | invokePanels(context, methodName); 144 | } 145 | 146 | /** 147 | * 隐藏通知栏 148 | *

需添加权限 {@code }

149 | * 150 | * @param context 上下文 151 | */ 152 | public static void hideNotificationBar(Context context) { 153 | String methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels"; 154 | invokePanels(context, methodName); 155 | } 156 | 157 | /** 158 | * 反射唤醒通知栏 159 | * 160 | * @param context 上下文 161 | * @param methodName 方法名 162 | */ 163 | private static void invokePanels(Context context, String methodName) { 164 | try { 165 | Object service = context.getSystemService("statusbar"); 166 | Class statusBarManager = Class.forName("android.app.StatusBarManager"); 167 | Method expand = statusBarManager.getMethod(methodName); 168 | expand.invoke(service); 169 | } catch (Exception e) { 170 | e.printStackTrace(); 171 | } 172 | } 173 | 174 | /** 175 | * 设置屏幕为横屏 176 | *

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

177 | *

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

178 | *

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

179 | *

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

181 | * 182 | * @param activity activity 183 | */ 184 | public static void setLandscape(Activity activity) { 185 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 186 | } 187 | 188 | /** 189 | * 获取当前屏幕截图,包含状态栏 190 | * 191 | * @param activity activity 192 | * @return Bitmap 193 | */ 194 | public static Bitmap captureWithStatusBar(Activity activity) { 195 | View view = activity.getWindow().getDecorView(); 196 | view.setDrawingCacheEnabled(true); 197 | view.buildDrawingCache(); 198 | Bitmap bmp = view.getDrawingCache(); 199 | int width = getScreenWidth(activity); 200 | int height = getScreenHeight(activity); 201 | Bitmap bp = Bitmap.createBitmap(bmp, 0, 0, width, height); 202 | view.destroyDrawingCache(); 203 | return bp; 204 | } 205 | 206 | /** 207 | * 获取当前屏幕截图,不包含状态栏 208 | *

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

209 | * 210 | * @param activity activity 211 | * @return Bitmap 212 | */ 213 | public static Bitmap captureWithoutStatusBar(Activity activity) { 214 | View view = activity.getWindow().getDecorView(); 215 | view.setDrawingCacheEnabled(true); 216 | view.buildDrawingCache(); 217 | Bitmap bmp = view.getDrawingCache(); 218 | int statusBarHeight = getStatusBarHeight(activity); 219 | int width = getScreenWidth(activity); 220 | int height = getScreenHeight(activity); 221 | Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); 222 | view.destroyDrawingCache(); 223 | return bp; 224 | } 225 | 226 | /** 227 | * 判断是否锁屏 228 | * 229 | * @param context 上下文 230 | * @return {@code true}: 是
{@code false}: 否 231 | */ 232 | public static boolean isScreenLock(Context context) { 233 | KeyguardManager km = (KeyguardManager) context 234 | .getSystemService(Context.KEYGUARD_SERVICE); 235 | return km.inKeyguardRestrictedInputMode(); 236 | } 237 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/ZipUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | 4 | import java.io.BufferedInputStream; 5 | import java.io.BufferedOutputStream; 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.FileNotFoundException; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | import java.io.UnsupportedEncodingException; 14 | import java.util.ArrayList; 15 | import java.util.Collection; 16 | import java.util.Enumeration; 17 | import java.util.zip.ZipEntry; 18 | import java.util.zip.ZipException; 19 | import java.util.zip.ZipFile; 20 | import java.util.zip.ZipOutputStream; 21 | 22 | /** 23 | *
 24 |  *     author: Blankj
 25 |  *     blog  : http://blankj.com
 26 |  *     time  : 2016/8/27
 27 |  *     desc  : 压缩相关工具类
 28 |  * 
29 | */ 30 | public class ZipUtils { 31 | 32 | private ZipUtils() { 33 | throw new UnsupportedOperationException("u can't fuck me..."); 34 | } 35 | 36 | /** 37 | * 批量压缩文件 38 | * 39 | * @param resFileList 要压缩的文件(夹)列表 40 | * @param zipFile 生成的压缩文件 41 | * @throws IOException 当压缩过程出错时抛出 42 | */ 43 | public static void zipFiles(Collection resFileList, File zipFile) throws IOException { 44 | ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream( 45 | zipFile), ConstUtils.MB)); 46 | for (File resFile : resFileList) { 47 | zipFile(resFile, zipout, ""); 48 | } 49 | zipout.close(); 50 | } 51 | 52 | /** 53 | * 批量压缩文件(夹) 54 | * 55 | * @param resFileList 要压缩的文件(夹)列表 56 | * @param zipFile 生成的压缩文件 57 | * @param comment 压缩文件的注释 58 | * @throws IOException 当压缩过程出错时抛出 59 | */ 60 | public static void zipFiles(Collection resFileList, File zipFile, String comment) 61 | throws IOException { 62 | ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream( 63 | zipFile), ConstUtils.MB)); 64 | for (File resFile : resFileList) { 65 | zipFile(resFile, zipout, ""); 66 | } 67 | zipout.setComment(comment); 68 | zipout.close(); 69 | } 70 | 71 | /** 72 | * 压缩文件 73 | * 74 | * @param resFile 需要压缩的文件(夹) 75 | * @param zipout 压缩的目的文件 76 | * @param rootpath 压缩的文件路径 77 | * @throws FileNotFoundException 找不到文件时抛出 78 | * @throws IOException 当压缩过程出错时抛出 79 | */ 80 | private static void zipFile(File resFile, ZipOutputStream zipout, String rootpath) 81 | throws FileNotFoundException, IOException { 82 | rootpath = rootpath + (rootpath.trim().length() == 0 ? "" : File.separator) 83 | + resFile.getName(); 84 | rootpath = new String(rootpath.getBytes("8859_1"), "GB2312"); 85 | if (resFile.isDirectory()) { 86 | File[] fileList = resFile.listFiles(); 87 | for (File file : fileList) { 88 | zipFile(file, zipout, rootpath); 89 | } 90 | } else { 91 | byte buffer[] = new byte[ConstUtils.MB]; 92 | BufferedInputStream in = new BufferedInputStream(new FileInputStream(resFile), ConstUtils.MB); 93 | zipout.putNextEntry(new ZipEntry(rootpath)); 94 | int realLength; 95 | while ((realLength = in.read(buffer)) != -1) { 96 | zipout.write(buffer, 0, realLength); 97 | } 98 | in.close(); 99 | zipout.flush(); 100 | zipout.closeEntry(); 101 | } 102 | } 103 | 104 | 105 | /** 106 | * 解压缩一个文件 107 | * 108 | * @param zipFile 压缩文件 109 | * @param folderPath 解压缩的目标目录 110 | * @throws IOException 当解压缩过程出错时抛出 111 | */ 112 | public static void upZipFile(File zipFile, String folderPath) throws ZipException, IOException { 113 | File desDir = new File(folderPath); 114 | if (!desDir.exists()) { 115 | desDir.mkdirs(); 116 | } 117 | ZipFile zf = new ZipFile(zipFile); 118 | for (Enumeration entries = zf.entries(); entries.hasMoreElements(); ) { 119 | ZipEntry entry = ((ZipEntry) entries.nextElement()); 120 | InputStream in = zf.getInputStream(entry); 121 | String str = folderPath + File.separator + entry.getName(); 122 | str = new String(str.getBytes("8859_1"), "GB2312"); 123 | File desFile = new File(str); 124 | if (!desFile.exists()) { 125 | File fileParentDir = desFile.getParentFile(); 126 | if (!fileParentDir.exists()) { 127 | fileParentDir.mkdirs(); 128 | } 129 | desFile.createNewFile(); 130 | } 131 | OutputStream out = new FileOutputStream(desFile); 132 | byte buffer[] = new byte[ConstUtils.MB]; 133 | int realLength; 134 | while ((realLength = in.read(buffer)) > 0) { 135 | out.write(buffer, 0, realLength); 136 | } 137 | in.close(); 138 | out.close(); 139 | } 140 | } 141 | 142 | /** 143 | * 解压文件名包含传入文字的文件 144 | * 145 | * @param zipFile 压缩文件 146 | * @param folderPath 目标文件夹 147 | * @param nameContains 传入的文件匹配名 148 | * @throws ZipException 压缩格式有误时抛出 149 | * @throws IOException IO错误时抛出 150 | */ 151 | public static ArrayList upZipSelectedFile(File zipFile, String folderPath, 152 | String nameContains) throws ZipException, IOException { 153 | ArrayList fileList = new ArrayList(); 154 | 155 | File desDir = new File(folderPath); 156 | if (!desDir.exists()) { 157 | desDir.mkdir(); 158 | } 159 | 160 | ZipFile zf = new ZipFile(zipFile); 161 | for (Enumeration entries = zf.entries(); entries.hasMoreElements(); ) { 162 | ZipEntry entry = ((ZipEntry) entries.nextElement()); 163 | if (entry.getName().contains(nameContains)) { 164 | InputStream in = zf.getInputStream(entry); 165 | String str = folderPath + File.separator + entry.getName(); 166 | str = new String(str.getBytes("8859_1"), "GB2312"); 167 | // str.getBytes("GB2312"),"8859_1" 输出 168 | // str.getBytes("8859_1"),"GB2312" 输入 169 | File desFile = new File(str); 170 | if (!desFile.exists()) { 171 | File fileParentDir = desFile.getParentFile(); 172 | if (!fileParentDir.exists()) { 173 | fileParentDir.mkdirs(); 174 | } 175 | desFile.createNewFile(); 176 | } 177 | OutputStream out = new FileOutputStream(desFile); 178 | byte buffer[] = new byte[ConstUtils.MB]; 179 | int realLength; 180 | while ((realLength = in.read(buffer)) > 0) { 181 | out.write(buffer, 0, realLength); 182 | } 183 | in.close(); 184 | out.close(); 185 | fileList.add(desFile); 186 | } 187 | } 188 | return fileList; 189 | } 190 | 191 | /** 192 | * 获得压缩文件内文件列表 193 | * 194 | * @param zipFile 压缩文件 195 | * @return 压缩文件内文件名称 196 | * @throws ZipException 压缩文件格式有误时抛出 197 | * @throws IOException 当解压缩过程出错时抛出 198 | */ 199 | public static ArrayList getEntriesNames(File zipFile) throws ZipException, IOException { 200 | ArrayList entryNames = new ArrayList(); 201 | Enumeration entries = getEntriesEnumeration(zipFile); 202 | while (entries.hasMoreElements()) { 203 | ZipEntry entry = ((ZipEntry) entries.nextElement()); 204 | entryNames.add(new String(getEntryName(entry).getBytes("GB2312"), "8859_1")); 205 | } 206 | return entryNames; 207 | } 208 | 209 | /** 210 | * 获得压缩文件内压缩文件对象以取得其属性 211 | * 212 | * @param zipFile 压缩文件 213 | * @return 返回一个压缩文件列表 214 | * @throws ZipException 压缩文件格式有误时抛出 215 | * @throws IOException IO操作有误时抛出 216 | */ 217 | public static Enumeration getEntriesEnumeration(File zipFile) throws ZipException, 218 | IOException { 219 | ZipFile zf = new ZipFile(zipFile); 220 | return zf.entries(); 221 | 222 | } 223 | 224 | /** 225 | * 取得压缩文件对象的注释 226 | * 227 | * @param entry 压缩文件对象 228 | * @return 压缩文件对象的注释 229 | * @throws UnsupportedEncodingException 230 | */ 231 | public static String getEntryComment(ZipEntry entry) throws UnsupportedEncodingException { 232 | return new String(entry.getComment().getBytes("GB2312"), "8859_1"); 233 | } 234 | 235 | /** 236 | * 取得压缩文件对象的名称 237 | * 238 | * @param entry 压缩文件对象 239 | * @return 压缩文件对象的名称 240 | * @throws UnsupportedEncodingException 241 | */ 242 | public static String getEntryName(ZipEntry entry) throws UnsupportedEncodingException { 243 | return new String(entry.getName().getBytes("GB2312"), "8859_1"); 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.ConnectivityManager; 6 | import android.net.NetworkInfo; 7 | import android.telephony.TelephonyManager; 8 | 9 | /** 10 | *
 11 |  *     author: Blankj
 12 |  *     blog  : http://blankj.com
 13 |  *     time  : 2016/8/2
 14 |  *     desc  : 网络相关工具类
 15 |  * 
16 | */ 17 | public class NetworkUtils { 18 | 19 | private NetworkUtils() { 20 | throw new UnsupportedOperationException("u can't fuck me..."); 21 | } 22 | 23 | public static final int NETWORK_WIFI = 1; // wifi network 24 | public static final int NETWORK_4G = 4; // "4G" networks 25 | public static final int NETWORK_3G = 3; // "3G" networks 26 | public static final int NETWORK_2G = 2; // "2G" networks 27 | public static final int NETWORK_UNKNOWN = 5; // unknown network 28 | public static final int NETWORK_NO = -1; // no network 29 | 30 | private static final int NETWORK_TYPE_GSM = 16; 31 | private static final int NETWORK_TYPE_TD_SCDMA = 17; 32 | private static final int NETWORK_TYPE_IWLAN = 18; 33 | 34 | /** 35 | * 打开网络设置界面 36 | *

3.0以下打开设置界面

37 | * 38 | * @param context 上下文 39 | */ 40 | public static void openWirelessSettings(Context context) { 41 | if (android.os.Build.VERSION.SDK_INT > 10) { 42 | context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS)); 43 | } else { 44 | context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS)); 45 | } 46 | } 47 | 48 | /** 49 | * 获取活动网络信息 50 | * 51 | * @param context 上下文 52 | * @return NetworkInfo 53 | */ 54 | private static NetworkInfo getActiveNetworkInfo(Context context) { 55 | ConnectivityManager cm = (ConnectivityManager) context 56 | .getSystemService(Context.CONNECTIVITY_SERVICE); 57 | return cm.getActiveNetworkInfo(); 58 | } 59 | 60 | /** 61 | * 判断网络是否可用 62 | *

需添加权限 {@code }

63 | * 64 | * @param context 上下文 65 | * @return {@code true}: 可用
{@code false}: 不可用 66 | */ 67 | public static boolean isAvailable(Context context) { 68 | NetworkInfo info = getActiveNetworkInfo(context); 69 | return info != null && info.isAvailable(); 70 | } 71 | 72 | /** 73 | * 判断网络是否连接 74 | *

需添加权限 {@code }

75 | * 76 | * @param context 上下文 77 | * @return {@code true}: 是
{@code false}: 否 78 | */ 79 | public static boolean isConnected(Context context) { 80 | NetworkInfo info = getActiveNetworkInfo(context); 81 | return info != null && info.isConnected(); 82 | } 83 | 84 | /** 85 | * 判断网络是否是4G 86 | *

需添加权限 {@code }

87 | * 88 | * @param context 上下文 89 | * @return {@code true}: 是
{@code false}: 不是 90 | */ 91 | public static boolean is4G(Context context) { 92 | NetworkInfo info = getActiveNetworkInfo(context); 93 | return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE; 94 | } 95 | 96 | /** 97 | * 判断wifi是否连接状态 98 | *

需添加权限 {@code }

99 | * 100 | * @param context 上下文 101 | * @return {@code true}: 连接
{@code false}: 未连接 102 | */ 103 | public static boolean isWifiConnected(Context context) { 104 | ConnectivityManager cm = (ConnectivityManager) context 105 | .getSystemService(Context.CONNECTIVITY_SERVICE); 106 | return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; 107 | } 108 | 109 | /** 110 | * 获取移动网络运营商名称 111 | *

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

112 | * 113 | * @param context 上下文 114 | * @return 移动网络运营商名称 115 | */ 116 | public static String getNetworkOperatorName(Context context) { 117 | TelephonyManager tm = (TelephonyManager) context 118 | .getSystemService(Context.TELEPHONY_SERVICE); 119 | return tm != null ? tm.getNetworkOperatorName() : null; 120 | } 121 | 122 | /** 123 | * 获取移动终端类型 124 | * 125 | * @param context 上下文 126 | * @return 手机制式 127 | *
    128 | *
  • {@link TelephonyManager#PHONE_TYPE_NONE } : 0 手机制式未知
  • 129 | *
  • {@link TelephonyManager#PHONE_TYPE_GSM } : 1 手机制式为GSM,移动和联通
  • 130 | *
  • {@link TelephonyManager#PHONE_TYPE_CDMA } : 2 手机制式为CDMA,电信
  • 131 | *
  • {@link TelephonyManager#PHONE_TYPE_SIP } : 3
  • 132 | *
133 | */ 134 | public static int getPhoneType(Context context) { 135 | TelephonyManager tm = (TelephonyManager) context 136 | .getSystemService(Context.TELEPHONY_SERVICE); 137 | return tm != null ? tm.getPhoneType() : -1; 138 | } 139 | 140 | 141 | /** 142 | * 获取当前的网络类型(WIFI,2G,3G,4G) 143 | *

需添加权限 {@code }

144 | * 145 | * @param context 上下文 146 | * @return 网络类型 147 | *
    148 | *
  • {@link #NETWORK_WIFI } = 1;
  • 149 | *
  • {@link #NETWORK_4G } = 4;
  • 150 | *
  • {@link #NETWORK_3G } = 3;
  • 151 | *
  • {@link #NETWORK_2G } = 2;
  • 152 | *
  • {@link #NETWORK_UNKNOWN} = 5;
  • 153 | *
  • {@link #NETWORK_NO } = -1;
  • 154 | *
155 | */ 156 | public static int getNetWorkType(Context context) { 157 | int netType = NETWORK_NO; 158 | NetworkInfo info = getActiveNetworkInfo(context); 159 | if (info != null && info.isAvailable()) { 160 | 161 | if (info.getType() == ConnectivityManager.TYPE_WIFI) { 162 | netType = NETWORK_WIFI; 163 | } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { 164 | switch (info.getSubtype()) { 165 | 166 | case NETWORK_TYPE_GSM: 167 | case TelephonyManager.NETWORK_TYPE_GPRS: 168 | case TelephonyManager.NETWORK_TYPE_CDMA: 169 | case TelephonyManager.NETWORK_TYPE_EDGE: 170 | case TelephonyManager.NETWORK_TYPE_1xRTT: 171 | case TelephonyManager.NETWORK_TYPE_IDEN: 172 | netType = NETWORK_2G; 173 | break; 174 | 175 | case NETWORK_TYPE_TD_SCDMA: 176 | case TelephonyManager.NETWORK_TYPE_EVDO_A: 177 | case TelephonyManager.NETWORK_TYPE_UMTS: 178 | case TelephonyManager.NETWORK_TYPE_EVDO_0: 179 | case TelephonyManager.NETWORK_TYPE_HSDPA: 180 | case TelephonyManager.NETWORK_TYPE_HSUPA: 181 | case TelephonyManager.NETWORK_TYPE_HSPA: 182 | case TelephonyManager.NETWORK_TYPE_EVDO_B: 183 | case TelephonyManager.NETWORK_TYPE_EHRPD: 184 | case TelephonyManager.NETWORK_TYPE_HSPAP: 185 | netType = NETWORK_3G; 186 | break; 187 | 188 | case NETWORK_TYPE_IWLAN: 189 | case TelephonyManager.NETWORK_TYPE_LTE: 190 | netType = NETWORK_4G; 191 | break; 192 | default: 193 | 194 | String subtypeName = info.getSubtypeName(); 195 | if (subtypeName.equalsIgnoreCase("TD-SCDMA") 196 | || subtypeName.equalsIgnoreCase("WCDMA") 197 | || subtypeName.equalsIgnoreCase("CDMA2000")) { 198 | netType = NETWORK_3G; 199 | } else { 200 | netType = NETWORK_UNKNOWN; 201 | } 202 | break; 203 | } 204 | } else { 205 | netType = NETWORK_UNKNOWN; 206 | } 207 | } 208 | return netType; 209 | } 210 | 211 | /** 212 | * 获取当前的网络类型(WIFI,2G,3G,4G) 213 | *

依赖上面的方法

214 | * 215 | * @param context 上下文 216 | * @return 网络类型名称 217 | *
    218 | *
  • NETWORK_WIFI
  • 219 | *
  • NETWORK_4G
  • 220 | *
  • NETWORK_3G
  • 221 | *
  • NETWORK_2G
  • 222 | *
  • NETWORK_UNKNOWN
  • 223 | *
  • NETWORK_NO
  • 224 | *
225 | */ 226 | public static String getNetWorkTypeName(Context context) { 227 | switch (getNetWorkType(context)) { 228 | case NETWORK_WIFI: 229 | return "NETWORK_WIFI"; 230 | case NETWORK_4G: 231 | return "NETWORK_4G"; 232 | case NETWORK_3G: 233 | return "NETWORK_3G"; 234 | case NETWORK_2G: 235 | return "NETWORK_2G"; 236 | case NETWORK_NO: 237 | return "NETWORK_NO"; 238 | default: 239 | return "NETWORK_UNKNOWN"; 240 | } 241 | } 242 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/ThreadPoolUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | import java.util.concurrent.Future; 10 | import java.util.concurrent.ScheduledExecutorService; 11 | import java.util.concurrent.ScheduledFuture; 12 | import java.util.concurrent.TimeUnit; 13 | import java.util.concurrent.TimeoutException; 14 | 15 | /** 16 | *
 17 |  *     author: Blankj
 18 |  *     blog  : http://blankj.com
 19 |  *     time  : 2016/8/25
 20 |  *     desc  : 线程池相关工具类
 21 |  * 
22 | */ 23 | public class ThreadPoolUtils { 24 | 25 | public enum Type { 26 | FixedThread, 27 | CachedThread, 28 | SingleThread, 29 | } 30 | 31 | private ExecutorService exec; 32 | private ScheduledExecutorService scheduleExec; 33 | 34 | /** 35 | * ThreadPoolUtils构造函数 36 | * 37 | * @param type 线程池类型 38 | * @param corePoolSize 只对Fixed和Scheduled线程池起效 39 | */ 40 | public ThreadPoolUtils(Type type, int corePoolSize) { 41 | // 构造有定时功能的线程池 42 | // ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 10L, TimeUnit.MILLISECONDS, new BlockingQueue) 43 | scheduleExec = Executors.newScheduledThreadPool(corePoolSize); 44 | switch (type) { 45 | case FixedThread: 46 | // 构造一个固定线程数目的线程池 47 | // ThreadPoolExecutor(corePoolSize, corePoolSize, 0L, TimeUnit.MILLISECONDS, new 48 | // LinkedBlockingQueue()); 49 | exec = Executors.newFixedThreadPool(corePoolSize); 50 | break; 51 | case SingleThread: 52 | // 构造一个只支持一个线程的线程池,相当于newFixedThreadPool(1) 53 | // ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()) 54 | exec = Executors.newSingleThreadExecutor(); 55 | break; 56 | case CachedThread: 57 | // 构造一个缓冲功能的线程池 58 | // ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); 59 | exec = Executors.newCachedThreadPool(); 60 | break; 61 | default: 62 | exec = scheduleExec; 63 | break; 64 | } 65 | } 66 | 67 | /** 68 | * 在未来某个时间执行给定的命令 69 | *

该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。

70 | * 71 | * @param command 命令 72 | */ 73 | public void execute(Runnable command) { 74 | exec.execute(command); 75 | } 76 | 77 | /** 78 | * 在未来某个时间执行给定的命令链表 79 | *

该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。

80 | * 81 | * @param commands 命令链表 82 | */ 83 | public void execute(List commands) { 84 | for (Runnable command : commands) { 85 | exec.execute(command); 86 | } 87 | } 88 | 89 | /** 90 | * 待以前提交的任务执行完毕后关闭线程池 91 | *

启动一次顺序关闭,执行以前提交的任务,但不接受新任务。 92 | * 如果已经关闭,则调用没有作用。

93 | */ 94 | public void shutDown() { 95 | exec.shutdown(); 96 | } 97 | 98 | /** 99 | * 试图停止所有正在执行的活动任务 100 | *

试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。

101 | *

无法保证能够停止正在处理的活动执行任务,但是会尽力尝试。

102 | * 103 | * @return 等待执行的任务的列表 104 | */ 105 | public List shutDownNow() { 106 | return exec.shutdownNow(); 107 | } 108 | 109 | /** 110 | * 判断线程池是否已关闭 111 | * 112 | * @return {@code true}: 是
{@code false}: 否 113 | */ 114 | public boolean isShutDown() { 115 | return exec.isShutdown(); 116 | } 117 | 118 | /** 119 | * 关闭线程池后判断所有任务是否都已完成 120 | *

注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。

121 | * 122 | * @return {@code true}: 是
{@code false}: 否 123 | */ 124 | public boolean isTerminated() { 125 | return exec.isTerminated(); 126 | } 127 | 128 | 129 | /** 130 | * 请求关闭、发生超时或者当前线程中断 131 | *

无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。

132 | * 133 | * @param timeout 最长等待时间 134 | * @param unit 时间单位 135 | * @return {@code true}: 请求成功
{@code false}: 请求超时 136 | */ 137 | public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { 138 | return exec.awaitTermination(timeout, unit); 139 | } 140 | 141 | /** 142 | * 提交一个Callable任务用于执行 143 | *

如果想立即阻塞任务的等待,则可以使用{@code result = exec.submit(aCallable).get();}形式的构造。

144 | * 145 | * @param task 任务 146 | * @return 表示任务等待完成的Future, 该Future的{@code get}方法在成功完成时将会返回该任务的结果。 147 | */ 148 | public Future submit(Callable task) { 149 | return exec.submit(task); 150 | } 151 | 152 | /** 153 | * 提交一个Runnable任务用于执行 154 | * 155 | * @param task 任务 156 | * @param result 返回的结果 157 | * @return 表示任务等待完成的Future, 该Future的{@code get}方法在成功完成时将会返回该任务的结果。 158 | */ 159 | public Future submit(Runnable task, T result) { 160 | return exec.submit(task, result); 161 | } 162 | 163 | /** 164 | * 提交一个Runnable任务用于执行 165 | * 166 | * @param task 任务 167 | * @return 表示任务等待完成的Future, 该Future的{@code get}方法在成功完成时将会返回null结果。 168 | */ 169 | public Future submit(Runnable task) { 170 | return exec.submit(task); 171 | } 172 | 173 | /** 174 | * 执行给定的任务 175 | *

当所有任务完成时,返回保持任务状态和结果的Future列表。 176 | * 返回列表的所有元素的{@link Future#isDone}为{@code true}。 177 | * 注意,可以正常地或通过抛出异常来终止已完成任务。 178 | * 如果正在进行此操作时修改了给定的 collection,则此方法的结果是不确定的。

179 | * 180 | * @param tasks 任务集合 181 | * @return 表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同,每个任务都已完成。 182 | * @throws InterruptedException 如果等待时发生中断,在这种情况下取消尚未完成的任务。 183 | */ 184 | public List> invokeAll(Collection> tasks) throws InterruptedException { 185 | return exec.invokeAll(tasks); 186 | } 187 | 188 | /** 189 | * 执行给定的任务 190 | *

当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的Future列表。 191 | * 返回列表的所有元素的{@link Future#isDone}为{@code true}。 192 | * 一旦返回后,即取消尚未完成的任务。 193 | * 注意,可以正常地或通过抛出异常来终止已完成任务。 194 | * 如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。

195 | * 196 | * @param tasks 任务集合 197 | * @param timeout 最长等待时间 198 | * @param unit 时间单位 199 | * @return 表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同。如果操作未超时,则已完成所有任务。如果确实超时了,则某些任务尚未完成。 200 | * @throws InterruptedException 如果等待时发生中断,在这种情况下取消尚未完成的任务 201 | */ 202 | public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws 203 | InterruptedException { 204 | return exec.invokeAll(tasks, timeout, unit); 205 | } 206 | 207 | /** 208 | * 执行给定的任务 209 | *

如果某个任务已成功完成(也就是未抛出异常),则返回其结果。 210 | * 一旦正常或异常返回后,则取消尚未完成的任务。 211 | * 如果此操作正在进行时修改了给定的collection,则此方法的结果是不确定的。

212 | * 213 | * @param tasks 任务集合 214 | * @return 某个任务返回的结果 215 | * @throws InterruptedException 如果等待时发生中断 216 | * @throws ExecutionException 如果没有任务成功完成 217 | */ 218 | public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { 219 | return exec.invokeAny(tasks); 220 | } 221 | 222 | /** 223 | * 执行给定的任务 224 | *

如果在给定的超时期满前某个任务已成功完成(也就是未抛出异常),则返回其结果。 225 | * 一旦正常或异常返回后,则取消尚未完成的任务。 226 | * 如果此操作正在进行时修改了给定的collection,则此方法的结果是不确定的。

227 | * 228 | * @param tasks 任务集合 229 | * @param timeout 最长等待时间 230 | * @param unit 时间单位 231 | * @return 某个任务返回的结果 232 | * @throws InterruptedException 如果等待时发生中断 233 | * @throws ExecutionException 如果没有任务成功完成 234 | * @throws TimeoutException 如果在所有任务成功完成之前给定的超时期满 235 | */ 236 | public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws 237 | InterruptedException, ExecutionException, TimeoutException { 238 | return exec.invokeAny(tasks, timeout, unit); 239 | } 240 | 241 | /** 242 | * 延迟执行Runnable命令 243 | * 244 | * @param command 命令 245 | * @param delay 延迟时间 246 | * @param unit 单位 247 | * @return 表示挂起任务完成的ScheduledFuture,并且其{@code get()}方法在完成后将返回{@code null} 248 | */ 249 | public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { 250 | return scheduleExec.schedule(command, delay, unit); 251 | } 252 | 253 | /** 254 | * 延迟执行Callable命令 255 | * 256 | * @param callable 命令 257 | * @param delay 延迟时间 258 | * @param unit 时间单位 259 | * @return 可用于提取结果或取消的ScheduledFuture 260 | */ 261 | public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { 262 | return scheduleExec.schedule(callable, delay, unit); 263 | } 264 | 265 | /** 266 | * 延迟并循环执行命令 267 | * 268 | * @param command 命令 269 | * @param initialDelay 首次执行的延迟时间 270 | * @param period 连续执行之间的周期 271 | * @param unit 时间单位 272 | * @return 表示挂起任务完成的ScheduledFuture,并且其{@code get()}方法在取消后将抛出异常 273 | */ 274 | public ScheduledFuture scheduleWithFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { 275 | return scheduleExec.scheduleAtFixedRate(command, initialDelay, period, unit); 276 | } 277 | 278 | /** 279 | * 延迟并以固定休息时间循环执行命令 280 | * 281 | * @param command 命令 282 | * @param initialDelay 首次执行的延迟时间 283 | * @param delay 每一次执行终止和下一次执行开始之间的延迟 284 | * @param unit 时间单位 285 | * @return 表示挂起任务完成的ScheduledFuture,并且其{@code get()}方法在取消后将抛出异常 286 | */ 287 | public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { 288 | return scheduleExec.scheduleWithFixedDelay(command, initialDelay, delay, unit); 289 | } 290 | } -------------------------------------------------------------------------------- /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 | 13 | import java.io.File; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | *
 19 |  *     author: Blankj
 20 |  *     blog  : http://blankj.com
 21 |  *     time  : 2016/8/2
 22 |  *     desc  : App相关工具类
 23 |  * 
24 | */ 25 | public class AppUtils { 26 | 27 | private AppUtils() { 28 | throw new UnsupportedOperationException("u can't fuck me..."); 29 | } 30 | 31 | /** 32 | * 安装App 33 | *

根据路径安装App

34 | * 35 | * @param context 上下文 36 | * @param filePath 文件路径 37 | */ 38 | public static void installApp(Context context, String filePath) { 39 | installApp(context, new File(filePath)); 40 | } 41 | 42 | /** 43 | * 安装App 44 | *

根据文件安装App

45 | * 46 | * @param context 上下文 47 | * @param file 文件 48 | */ 49 | public static void installApp(Context context, File file) { 50 | Intent intent = new Intent(Intent.ACTION_VIEW); 51 | intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 52 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 53 | context.startActivity(intent); 54 | } 55 | 56 | /** 57 | * 卸载指定包名的App 58 | * 59 | * @param context 上下文 60 | * @param packageName 包名 61 | */ 62 | public void uninstallApp(Context context, String packageName) { 63 | Intent intent = new Intent(Intent.ACTION_DELETE); 64 | intent.setData(Uri.parse("package:" + packageName)); 65 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 66 | context.startActivity(intent); 67 | } 68 | 69 | /** 70 | * 封装App信息的Bean类 71 | */ 72 | public static class AppInfo { 73 | 74 | private String name; 75 | private Drawable icon; 76 | private String packageName; 77 | private String packagePath; 78 | private String versionName; 79 | private int versionCode; 80 | private boolean isSD; 81 | private boolean isUser; 82 | 83 | public Drawable getIcon() { 84 | return icon; 85 | } 86 | 87 | public void setIcon(Drawable icon) { 88 | this.icon = icon; 89 | } 90 | 91 | public boolean isSD() { 92 | return isSD; 93 | } 94 | 95 | public void setSD(boolean SD) { 96 | isSD = SD; 97 | } 98 | 99 | public boolean isUser() { 100 | return isUser; 101 | } 102 | 103 | public void setUser(boolean user) { 104 | isUser = user; 105 | } 106 | 107 | public String getName() { 108 | return name; 109 | } 110 | 111 | public void setName(String name) { 112 | this.name = name; 113 | } 114 | 115 | public String getPackageName() { 116 | return packageName; 117 | } 118 | 119 | public void setPackageName(String packagName) { 120 | this.packageName = packagName; 121 | } 122 | 123 | public String getPackagePath() { 124 | return packagePath; 125 | } 126 | 127 | public void setPackagePath(String packagePath) { 128 | this.packagePath = packagePath; 129 | } 130 | 131 | public int getVersionCode() { 132 | return versionCode; 133 | } 134 | 135 | public void setVersionCode(int versionCode) { 136 | this.versionCode = versionCode; 137 | } 138 | 139 | public String getVersionName() { 140 | return versionName; 141 | } 142 | 143 | public void setVersionName(String versionName) { 144 | this.versionName = versionName; 145 | } 146 | 147 | /** 148 | * @param name 名称 149 | * @param icon 图标 150 | * @param packageName 包名 151 | * @param packagePath 包路径 152 | * @param versionName 版本号 153 | * @param versionCode 版本Code 154 | * @param isSD 是否安装在SD卡 155 | * @param isUser 是否是用户程序 156 | */ 157 | public AppInfo(String name, Drawable icon, String packageName, String packagePath, 158 | String versionName, int versionCode, boolean isSD, boolean isUser) { 159 | this.setName(name); 160 | this.setIcon(icon); 161 | this.setPackageName(packageName); 162 | this.setPackagePath(packagePath); 163 | this.setVersionName(versionName); 164 | this.setVersionCode(versionCode); 165 | this.setSD(isSD); 166 | this.setUser(isUser); 167 | } 168 | 169 | // @Override 170 | // public String toString() { 171 | // return getName() + "\n" 172 | // + getIcon() + "\n" 173 | // + getPackageName() + "\n" 174 | // + getPackagePath() + "\n" 175 | // + getVersionName() + "\n" 176 | // + getVersionCode() + "\n" 177 | // + isSD() + "\n" 178 | // + isUser() + "\n"; 179 | // } 180 | } 181 | 182 | /** 183 | * 获取当前App信息 184 | *

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

185 | * 186 | * @param context 上下文 187 | * @return 当前应用的AppInfo 188 | */ 189 | public static AppInfo getAppInfo(Context context) { 190 | PackageManager pm = context.getPackageManager(); 191 | PackageInfo pi = null; 192 | try { 193 | pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); 194 | } catch (PackageManager.NameNotFoundException e) { 195 | e.printStackTrace(); 196 | } 197 | return pi != null ? getBean(pm, pi) : null; 198 | } 199 | 200 | /** 201 | * 得到AppInfo的Bean 202 | * 203 | * @param pm 包的管理 204 | * @param pi 包的信息 205 | * @return AppInfo类 206 | */ 207 | private static AppInfo getBean(PackageManager pm, PackageInfo pi) { 208 | ApplicationInfo ai = pi.applicationInfo; 209 | String name = ai.loadLabel(pm).toString(); 210 | Drawable icon = ai.loadIcon(pm); 211 | String packageName = pi.packageName; 212 | String packagePath = ai.sourceDir; 213 | String versionName = pi.versionName; 214 | int versionCode = pi.versionCode; 215 | boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; 216 | boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; 217 | return new AppInfo(name, icon, packageName, packagePath, versionName, versionCode, isSD, isUser); 218 | } 219 | 220 | /** 221 | * 获取所有已安装App信息 222 | *

{@link #getBean(PackageManager, PackageInfo)}(名称,图标,包名,包路径,版本号,版本Code,是否安装在SD卡,是否是用户程序)

223 | *

依赖上面的getBean方法

224 | * 225 | * @param context 上下文 226 | * @return 所有已安装的AppInfo列表 227 | */ 228 | public static List getAllAppsInfo(Context context) { 229 | List list = new ArrayList<>(); 230 | PackageManager pm = context.getPackageManager(); 231 | // 获取系统中安装的所有软件信息 232 | List installedPackages = pm.getInstalledPackages(0); 233 | for (PackageInfo pi : installedPackages) { 234 | if (pi != null) { 235 | list.add(getBean(pm, pi)); 236 | } 237 | } 238 | return list; 239 | } 240 | 241 | /** 242 | * 根据包名获取意图 243 | * 244 | * @param context 上下文 245 | * @param packageName 包名 246 | * @return 意图 247 | */ 248 | private static Intent getIntentByPackageName(Context context, String packageName) { 249 | return context.getPackageManager().getLaunchIntentForPackage(packageName); 250 | } 251 | 252 | /** 253 | * 根据包名判断App是否安装 254 | * 255 | * @param context 上下文 256 | * @param packageName 包名 257 | * @return {@code true}: 已安装
{@code false}: 未安装 258 | */ 259 | public static boolean isInstallApp(Context context, String packageName) { 260 | return getIntentByPackageName(context, packageName) != null; 261 | } 262 | 263 | /** 264 | * 打开指定包名的App 265 | * 266 | * @param context 上下文 267 | * @param packageName 包名 268 | * @return {@code true}: 打开成功
{@code false}: 打开失败 269 | */ 270 | public static boolean openAppByPackageName(Context context, String packageName) { 271 | Intent intent = getIntentByPackageName(context, packageName); 272 | if (intent != null) { 273 | context.startActivity(intent); 274 | return true; 275 | } 276 | return false; 277 | } 278 | 279 | /** 280 | * 打开指定包名的App应用信息界面 281 | * 282 | * @param context 上下文 283 | * @param packageName 包名 284 | */ 285 | public static void openAppInfo(Context context, String packageName) { 286 | Intent intent = new Intent(); 287 | intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); 288 | intent.setData(Uri.parse("package:" + packageName)); 289 | context.startActivity(intent); 290 | } 291 | 292 | /** 293 | * 可用来做App信息分享 294 | * 295 | * @param context 上下文 296 | * @param info 分享信息 297 | */ 298 | public static void shareAppInfo(Context context, String info) { 299 | Intent intent = new Intent(Intent.ACTION_SEND); 300 | intent.setType("text/plain"); 301 | intent.putExtra(Intent.EXTRA_TEXT, info); 302 | context.startActivity(intent); 303 | } 304 | 305 | /** 306 | * 判断当前App处于前台还是后台 307 | *

需添加权限 {@code }

308 | *

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

309 | * 310 | * @param context 上下文 311 | * @return {@code true}: 后台
{@code false}: 前台 312 | */ 313 | public static boolean isAppBackground(Context context) { 314 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 315 | @SuppressWarnings("deprecation") 316 | List tasks = am.getRunningTasks(1); 317 | if (!tasks.isEmpty()) { 318 | ComponentName topActivity = tasks.get(0).topActivity; 319 | if (!topActivity.getPackageName().equals(context.getPackageName())) { 320 | return true; 321 | } 322 | } 323 | return false; 324 | } 325 | } -------------------------------------------------------------------------------- /utilcode/src/test/java/com/blankj/utilcode/utils/FileUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FilenameFilter; 8 | 9 | import static com.blankj.utilcode.utils.FileUtils.byte2Size; 10 | import static com.blankj.utilcode.utils.FileUtils.copyDir; 11 | import static com.blankj.utilcode.utils.FileUtils.copyFile; 12 | import static com.blankj.utilcode.utils.FileUtils.createFileByDeleteOldFile; 13 | import static com.blankj.utilcode.utils.FileUtils.createOrExistsDir; 14 | import static com.blankj.utilcode.utils.FileUtils.createOrExistsFile; 15 | import static com.blankj.utilcode.utils.FileUtils.deleteDir; 16 | import static com.blankj.utilcode.utils.FileUtils.deleteFile; 17 | import static com.blankj.utilcode.utils.FileUtils.getDirName; 18 | import static com.blankj.utilcode.utils.FileUtils.getFileByPath; 19 | import static com.blankj.utilcode.utils.FileUtils.getFileCharsetSimple; 20 | import static com.blankj.utilcode.utils.FileUtils.getFileExtension; 21 | import static com.blankj.utilcode.utils.FileUtils.getFileLines; 22 | import static com.blankj.utilcode.utils.FileUtils.getFileName; 23 | import static com.blankj.utilcode.utils.FileUtils.getFileNameNoExtension; 24 | import static com.blankj.utilcode.utils.FileUtils.getFileSize; 25 | import static com.blankj.utilcode.utils.FileUtils.isDir; 26 | import static com.blankj.utilcode.utils.FileUtils.isFile; 27 | import static com.blankj.utilcode.utils.FileUtils.isFileExists; 28 | import static com.blankj.utilcode.utils.FileUtils.listFilesInDir; 29 | import static com.blankj.utilcode.utils.FileUtils.listFilesInDirWithFilter; 30 | import static com.blankj.utilcode.utils.FileUtils.moveDir; 31 | import static com.blankj.utilcode.utils.FileUtils.moveFile; 32 | import static com.blankj.utilcode.utils.FileUtils.readFile2Bytes; 33 | import static com.blankj.utilcode.utils.FileUtils.readFile2List; 34 | import static com.blankj.utilcode.utils.FileUtils.readFile2String; 35 | import static com.blankj.utilcode.utils.FileUtils.searchFileInDir; 36 | import static com.blankj.utilcode.utils.FileUtils.writeFileFromIS; 37 | import static com.blankj.utilcode.utils.FileUtils.writeFileFromString; 38 | import static com.blankj.utilcode.utils.TestUtils.BASEPATH; 39 | import static com.blankj.utilcode.utils.TestUtils.SEP; 40 | import static com.google.common.truth.Truth.assertThat; 41 | 42 | /** 43 | *
 44 |  *     author: Blankj
 45 |  *     blog  : http://blankj.com
 46 |  *     time  : 2016/8/19
 47 |  *     desc  : FileUtils单元测试
 48 |  * 
49 | */ 50 | public class FileUtilsTest { 51 | 52 | 53 | String path = BASEPATH + "file" + SEP; 54 | 55 | @Test 56 | public void testGetFileByPath() throws Exception { 57 | System.out.println(new byte[0].length); 58 | assertThat(getFileByPath(" ")).isNull(); 59 | assertThat(getFileByPath("c:")).isNotNull(); 60 | } 61 | 62 | @Test 63 | public void testIsFileExists() throws Exception { 64 | assertThat(isFileExists(path + "UTF8.txt")).isTrue(); 65 | assertThat(isFileExists(path + "UTF8")).isFalse(); 66 | } 67 | 68 | @Test 69 | public void testIsDir() throws Exception { 70 | assertThat(isDir(path + "UTF8.txt")).isFalse(); 71 | assertThat(isDir(path)).isTrue(); 72 | } 73 | 74 | @Test 75 | public void testIsFile() throws Exception { 76 | assertThat(isFile(path + "UTF8.txt")).isTrue(); 77 | assertThat(isFile(path)).isFalse(); 78 | } 79 | 80 | @Test 81 | public void testCreateOrExistsDir() throws Exception { 82 | assertThat(createOrExistsDir(path + "new Dir")).isTrue(); 83 | assertThat(createOrExistsDir(path)).isTrue(); 84 | } 85 | 86 | @Test 87 | public void testCreateOrExistsFile() throws Exception { 88 | assertThat(createOrExistsFile(path + "new File")).isTrue(); 89 | assertThat(createOrExistsFile(path)).isFalse(); 90 | } 91 | 92 | @Test 93 | public void testCreateFileByDeleteOldFile() throws Exception { 94 | assertThat(createFileByDeleteOldFile(path + "new File")).isTrue(); 95 | assertThat(createFileByDeleteOldFile(path)).isFalse(); 96 | } 97 | 98 | String path1 = BASEPATH + "file1" + SEP; 99 | 100 | @Test 101 | public void testCopyDir() throws Exception { 102 | assertThat(copyDir(path, path)).isFalse(); 103 | assertThat(copyDir(path, path + "new Dir")).isFalse(); 104 | assertThat(copyDir(path, path1)).isTrue(); 105 | } 106 | 107 | @Test 108 | public void testCopyFile() throws Exception { 109 | assertThat(copyFile(path + "GBK.txt", path + "GBK.txt")).isFalse(); 110 | assertThat(copyFile(path + "GBK.txt", path + "new Dir" + SEP + "GBK.txt")).isTrue(); 111 | assertThat(copyFile(path + "GBK.txt", path1 + "GBK.txt")).isTrue(); 112 | } 113 | 114 | @Test 115 | public void testMoveDir() throws Exception { 116 | assertThat(moveDir(path, path)).isFalse(); 117 | assertThat(moveDir(path, path + "new Dir")).isFalse(); 118 | assertThat(moveDir(path, path1)).isTrue(); 119 | assertThat(moveDir(path1, path)).isTrue(); 120 | } 121 | 122 | @Test 123 | public void testMoveFile() throws Exception { 124 | assertThat(moveFile(path + "GBK.txt", path + "GBK.txt")).isFalse(); 125 | assertThat(moveFile(path + "GBK.txt", path1 + "GBK.txt")).isTrue(); 126 | assertThat(moveFile(path1 + "GBK.txt", path + "GBK.txt")).isTrue(); 127 | } 128 | 129 | @Test 130 | public void testDeleteDir() throws Exception { 131 | assertThat(deleteDir(path + "GBK.txt")).isFalse(); 132 | assertThat(deleteDir(path + "del")).isTrue(); 133 | } 134 | 135 | @Test 136 | public void testDeleteFile() throws Exception { 137 | assertThat(deleteFile(path)).isFalse(); 138 | assertThat(deleteFile(path + "GBK1.txt")).isTrue(); 139 | assertThat(deleteFile(path + "del.txt")).isTrue(); 140 | } 141 | 142 | @Test 143 | public void testListFilesInDir() throws Exception { 144 | System.out.println(listFilesInDir(path, false).toString()); 145 | System.out.println(listFilesInDir(path, true).toString()); 146 | } 147 | 148 | FilenameFilter filter = new FilenameFilter() { 149 | public boolean accept(File dir, String name) { 150 | return name.endsWith("k.txt"); 151 | } 152 | }; 153 | 154 | @Test 155 | public void testListFilesInDirWithFiltere() throws Exception { 156 | System.out.println(listFilesInDirWithFilter(path, "k.txt", false).toString()); 157 | System.out.println(listFilesInDirWithFilter(path, "k.txt", true).toString()); 158 | System.out.println(listFilesInDirWithFilter(path, filter, false).toString()); 159 | System.out.println(listFilesInDirWithFilter(path, filter, true).toString()); 160 | } 161 | 162 | @Test 163 | public void testSearchFile() throws Exception { 164 | System.out.println(searchFileInDir(path, "GBK.txt").toString()); 165 | System.out.println(searchFileInDir(path, "child").toString()); 166 | } 167 | 168 | @Test 169 | public void testWriteFileFromIS() throws Exception { 170 | assertThat(writeFileFromIS(path + "NEW.txt", new FileInputStream(path + "UTF8.txt"), false)) 171 | .isTrue(); 172 | assertThat(writeFileFromIS(path + "NEW.txt", new FileInputStream(path + "UTF8.txt"), true)) 173 | .isTrue(); 174 | } 175 | 176 | @Test 177 | public void testWriteFileFromString() throws Exception { 178 | assertThat(writeFileFromString(path + "NEW.txt", "这是新的", false)).isTrue(); 179 | assertThat(writeFileFromString(path + "NEW.txt", "\r\n这是追加的", true)).isTrue(); 180 | } 181 | 182 | @Test 183 | public void testGetFileCharsetSimple() throws Exception { 184 | assertThat(getFileCharsetSimple(path + "GBK.txt")).isEqualTo("GBK"); 185 | assertThat(getFileCharsetSimple(path + "Unicode.txt")).isEqualTo("Unicode"); 186 | assertThat(getFileCharsetSimple(path + "UTF8.txt")).isEqualTo("UTF-8"); 187 | assertThat(getFileCharsetSimple(path + "UTF16BE.txt")).isEqualTo("UTF-16BE"); 188 | } 189 | 190 | @Test 191 | public void testGetFileLines() throws Exception { 192 | assertThat(getFileLines(path + "UTF8.txt")).isEqualTo(7); 193 | } 194 | 195 | @Test 196 | public void testReadFile2List() throws Exception { 197 | System.out.println(readFile2List(path + "UTF8.txt", "").toString()); 198 | System.out.println(readFile2List(path + "UTF8.txt", "UTF-8").toString()); 199 | System.out.println(readFile2List(path + "UTF8.txt", 2, 5, "UTF-8").toString()); 200 | System.out.println(readFile2List(path + "UTF8.txt", "GBK").toString()); 201 | } 202 | 203 | @Test 204 | public void testReadFile2String() throws Exception { 205 | System.out.println(readFile2String(path + "UTF8.txt", "")); 206 | System.out.println(readFile2String(path + "UTF8.txt", "UTF-8")); 207 | System.out.println(readFile2String(path + "UTF8.txt", "GBK")); 208 | } 209 | 210 | 211 | @Test 212 | public void testReadFile2Bytes() throws Exception { 213 | System.out.println(new String(readFile2Bytes(path + "UTF8.txt")) ); 214 | } 215 | 216 | @Test 217 | public void testByte2Unit() throws Exception { 218 | assertThat(byte2Size(ConstUtils.GB, ConstUtils.MemoryUnit.MB) - 1024).isWithin(0.001); 219 | } 220 | 221 | @Test 222 | public void testGetFileSize() throws Exception { 223 | assertThat(getFileSize(path + "UTF8.txt", ConstUtils.MemoryUnit.BYTE) - 25).isWithin(0.001); 224 | } 225 | 226 | @Test 227 | public void testGetDirName() throws Exception { 228 | assertThat(getDirName(new File(path + "UTF8.txt"))).isEqualTo(path); 229 | assertThat(getDirName(path + "UTF8.txt")).isEqualTo(path); 230 | } 231 | 232 | @Test 233 | public void testGetFileName() throws Exception { 234 | assertThat(getFileName(new File(path + "UTF8.txt"))).isEqualTo("UTF8.txt"); 235 | assertThat(getFileName(path + "UTF8.txt")).isEqualTo("UTF8.txt"); 236 | } 237 | 238 | @Test 239 | public void testGetFileNameNoExtension() throws Exception { 240 | assertThat(getFileNameNoExtension(new File(path + "UTF8.txt"))).isEqualTo("UTF8"); 241 | assertThat(getFileNameNoExtension(path + "UTF8.txt")).isEqualTo("UTF8"); 242 | } 243 | 244 | @Test 245 | public void testGetFileExtension() throws Exception { 246 | assertThat(getFileExtension(new File(path + "UTF8.txt"))).isEqualTo(".txt"); 247 | assertThat(getFileExtension(path + "UTF8.txt")).isEqualTo(".txt"); 248 | } 249 | } -------------------------------------------------------------------------------- /utilcode/src/main/java/com/blankj/utilcode/utils/ConvertUtils.java: -------------------------------------------------------------------------------- 1 | package com.blankj.utilcode.utils; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.drawable.BitmapDrawable; 8 | import android.graphics.drawable.Drawable; 9 | 10 | import java.io.ByteArrayInputStream; 11 | import java.io.ByteArrayOutputStream; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.io.OutputStream; 15 | import java.io.UnsupportedEncodingException; 16 | 17 | /** 18 | *
 19 |  *     author: Blankj
 20 |  *     blog  : http://blankj.com
 21 |  *     time  : 2016/8/13
 22 |  *     desc  : 转换相关工具类
 23 |  * 
24 | */ 25 | public class ConvertUtils { 26 | 27 | static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 28 | 29 | /** 30 | * byteArr转hexString 31 | *

例如:

32 | * bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns 00A8 33 | * 34 | * @param bytes byte数组 35 | * @return 16进制大写字符串 36 | */ 37 | public static String bytes2HexString(byte[] bytes) { 38 | char[] res = new char[bytes.length << 1]; 39 | for (int i = 0, j = 0; i < bytes.length; i++) { 40 | res[j++] = hexDigits[bytes[i] >>> 4 & 0x0f]; 41 | res[j++] = hexDigits[bytes[i] & 0x0f]; 42 | } 43 | return new String(res); 44 | } 45 | 46 | /** 47 | * hexString转byteArr 48 | *

例如:

49 | * hexString2Bytes("00A8") returns { 0, (byte) 0xA8 } 50 | * 51 | * @param hexString 十六进制字符串 52 | * @return 字节数组 53 | */ 54 | public static byte[] hexString2Bytes(String hexString) { 55 | int len = hexString.length(); 56 | if (len % 2 != 0) { 57 | throw new IllegalArgumentException("长度不是偶数"); 58 | } 59 | char[] hexBytes = hexString.toUpperCase().toCharArray(); 60 | byte[] res = new byte[len >>> 1]; 61 | for (int i = 0; i < len; i += 2) { 62 | res[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1])); 63 | } 64 | return res; 65 | } 66 | 67 | /** 68 | * hexChar转int 69 | * 70 | * @param hexChar hex单个字节 71 | * @return 0..15 72 | */ 73 | private static int hex2Dec(char hexChar) { 74 | if (hexChar >= '0' && hexChar <= '9') { 75 | return hexChar - '0'; 76 | } else if (hexChar >= 'A' && hexChar <= 'F') { 77 | return hexChar - 'A' + 10; 78 | } else { 79 | throw new IllegalArgumentException(); 80 | } 81 | } 82 | 83 | /** 84 | * charArr转byteArr 85 | * 86 | * @param chars 字符数组 87 | * @return 字节数组 88 | */ 89 | public static byte[] chars2Bytes(char[] chars) { 90 | int len = chars.length; 91 | byte[] bytes = new byte[len]; 92 | for (int i = 0; i < len; i++) { 93 | bytes[i] = (byte) (chars[i]); 94 | } 95 | return bytes; 96 | } 97 | 98 | /** 99 | * byteArr转charArr 100 | * 101 | * @param bytes 字节数组 102 | * @return 字符数组 103 | */ 104 | public static char[] bytes2Chars(byte[] bytes) { 105 | int len = bytes.length; 106 | char[] chars = new char[len]; 107 | for (int i = 0; i < len; i++) { 108 | chars[i] = (char) (bytes[i] & 0xff); 109 | } 110 | return chars; 111 | } 112 | 113 | /** 114 | * inputStream转outputStream 115 | * 116 | * @param is 输入流 117 | * @return outputStream子类 118 | */ 119 | public static ByteArrayOutputStream input2OutputStream(InputStream is) { 120 | if (is == null) return null; 121 | try { 122 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 123 | byte[] b = new byte[ConstUtils.KB]; 124 | int len; 125 | while ((len = is.read(b)) != -1) { 126 | os.write(b, 0, len); 127 | } 128 | return os; 129 | } catch (IOException e) { 130 | e.printStackTrace(); 131 | return null; 132 | } finally { 133 | FileUtils.closeIO(is); 134 | } 135 | } 136 | 137 | /** 138 | * outputStream转inputStream 139 | * 140 | * @param out 输出流 141 | * @return inputStream子类 142 | */ 143 | public ByteArrayInputStream output2InputStream(OutputStream out) { 144 | if (out == null) return null; 145 | return new ByteArrayInputStream(((ByteArrayOutputStream) out).toByteArray()); 146 | } 147 | 148 | /** 149 | * inputStream转byteArr 150 | * 151 | * @param is 输入流 152 | * @return 字节数组 153 | */ 154 | public static byte[] inputStream2Bytes(InputStream is) { 155 | return input2OutputStream(is).toByteArray(); 156 | } 157 | 158 | /** 159 | * byteArr转inputStream 160 | * 161 | * @param bytes 字节数组 162 | * @return 输入流 163 | */ 164 | public static InputStream bytes2InputStream(byte[] bytes) { 165 | return new ByteArrayInputStream(bytes); 166 | } 167 | 168 | /** 169 | * outputStream转byteArr 170 | * 171 | * @param out 输出流 172 | * @return 字节数组 173 | */ 174 | public static byte[] outputStream2Bytes(OutputStream out) { 175 | if (out == null) return null; 176 | return ((ByteArrayOutputStream) out).toByteArray(); 177 | } 178 | 179 | /** 180 | * outputStream转byteArr 181 | * 182 | * @param bytes 字节数组 183 | * @return 字节数组 184 | */ 185 | public static OutputStream bytes2OutputStream(byte[] bytes) { 186 | ByteArrayOutputStream os = null; 187 | try { 188 | os = new ByteArrayOutputStream(); 189 | os.write(bytes); 190 | return os; 191 | } catch (IOException e) { 192 | e.printStackTrace(); 193 | return null; 194 | } finally { 195 | FileUtils.closeIO(os); 196 | } 197 | } 198 | 199 | /** 200 | * inputStream转string按编码 201 | * 202 | * @param is 输入流 203 | * @param charsetName 编码格式 204 | * @return 字符串 205 | */ 206 | public static String inputStream2String(InputStream is, String charsetName) { 207 | if (is == null || StringUtils.isSpace(charsetName)) return null; 208 | try { 209 | return new String(inputStream2Bytes(is), charsetName); 210 | } catch (UnsupportedEncodingException e) { 211 | e.printStackTrace(); 212 | return null; 213 | } 214 | } 215 | 216 | /** 217 | * string转inputStream按编码 218 | * 219 | * @param string 字符串 220 | * @param charsetName 编码格式 221 | * @return 输入流 222 | */ 223 | public static InputStream string2InputStream(String string, String charsetName) { 224 | if (string == null || StringUtils.isSpace(charsetName)) return null; 225 | try { 226 | return new ByteArrayInputStream(string.getBytes(charsetName)); 227 | } catch (UnsupportedEncodingException e) { 228 | e.printStackTrace(); 229 | return null; 230 | } 231 | } 232 | 233 | /** 234 | * outputStream转string按编码 235 | * 236 | * @param out 输出流 237 | * @param charsetName 编码格式 238 | * @return 字符串 239 | */ 240 | public static String outputStream2String(OutputStream out, String charsetName) { 241 | if (out == null) return null; 242 | try { 243 | return new String(outputStream2Bytes(out), charsetName); 244 | } catch (UnsupportedEncodingException e) { 245 | e.printStackTrace(); 246 | return null; 247 | } 248 | } 249 | 250 | /** 251 | * string转outputStream按编码 252 | * 253 | * @param string 字符串 254 | * @param charsetName 编码格式 255 | * @return 输入流 256 | */ 257 | public static OutputStream string2OutputStream(String string, String charsetName) { 258 | if (string == null || StringUtils.isSpace(charsetName)) return null; 259 | try { 260 | return bytes2OutputStream(string.getBytes(charsetName)); 261 | } catch (UnsupportedEncodingException e) { 262 | e.printStackTrace(); 263 | return null; 264 | } 265 | } 266 | 267 | /** 268 | * bitmap转byteArr 269 | * 270 | * @param bitmap bitmap对象 271 | * @param format 格式 272 | * @return 字节数组 273 | */ 274 | public static byte[] bitmap2Bytes(Bitmap bitmap, Bitmap.CompressFormat format) { 275 | if (bitmap == null) return null; 276 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 277 | bitmap.compress(format, 100, baos); 278 | return baos.toByteArray(); 279 | } 280 | 281 | /** 282 | * byteArr转bitmap 283 | * 284 | * @param bytes 字节数组 285 | * @return bitmap对象 286 | */ 287 | public static Bitmap bytes2Bitmap(byte[] bytes) { 288 | return (bytes == null || bytes.length == 0) ? null : BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 289 | } 290 | 291 | /** 292 | * drawable转bitmap 293 | * 294 | * @param drawable drawable对象 295 | * @return bitmap对象 296 | */ 297 | public static Bitmap drawable2Bitmap(Drawable drawable) { 298 | return drawable == null ? null : ((BitmapDrawable) drawable).getBitmap(); 299 | } 300 | 301 | /** 302 | * bitmap转drawable 303 | * 304 | * @param resources resources对象 305 | * @param bitmap bitmap对象 306 | * @return drawable对象 307 | */ 308 | public static Drawable bitmap2Drawable(Resources resources, Bitmap bitmap) { 309 | return bitmap == null ? null : new BitmapDrawable(resources, bitmap); 310 | } 311 | 312 | /** 313 | * drawable转byteArr 314 | * 315 | * @param drawable drawable对象 316 | * @param format 格式 317 | * @return 字节数组 318 | */ 319 | public static byte[] drawable2Bytes(Drawable drawable, Bitmap.CompressFormat format) { 320 | return bitmap2Bytes(drawable2Bitmap(drawable), format); 321 | } 322 | 323 | /** 324 | * byteArr转drawable 325 | * 326 | * @param resources resources对象 327 | * @param bytes 字节数组 328 | * @return drawable对象 329 | */ 330 | public static Drawable bytes2Drawable(Resources resources, byte[] bytes) { 331 | return bitmap2Drawable(resources, bytes2Bitmap(bytes)); 332 | } 333 | 334 | /** 335 | * dp转px 336 | * 337 | * @param context 上下文 338 | * @param dpValue dp值 339 | * @return px值 340 | */ 341 | public static int dp2px(Context context, float dpValue) { 342 | final float scale = context.getResources().getDisplayMetrics().density; 343 | return (int) (dpValue * scale + 0.5f); 344 | } 345 | 346 | /** 347 | * px转dp 348 | * 349 | * @param context 上下文 350 | * @param pxValue px值 351 | * @return dp值 352 | */ 353 | public static int px2dp(Context context, float pxValue) { 354 | final float scale = context.getResources().getDisplayMetrics().density; 355 | return (int) (pxValue / scale + 0.5f); 356 | } 357 | 358 | /** 359 | * sp转px 360 | * 361 | * @param context 上下文 362 | * @param spValue sp值 363 | * @return px值 364 | */ 365 | public static int sp2px(Context context, float spValue) { 366 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 367 | return (int) (spValue * fontScale + 0.5f); 368 | } 369 | 370 | /** 371 | * px转sp 372 | * 373 | * @param context 上下文 374 | * @param pxValue px值 375 | * @return sp值 376 | */ 377 | public static int px2sp(Context context, float pxValue) { 378 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 379 | return (int) (pxValue / fontScale + 0.5f); 380 | } 381 | } 382 | -------------------------------------------------------------------------------- /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.util.Log; 12 | import android.util.Xml; 13 | 14 | import org.xmlpull.v1.XmlSerializer; 15 | 16 | import java.io.File; 17 | import java.io.FileOutputStream; 18 | import java.util.ArrayList; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | 22 | /** 23 | *
 24 |  *     author: Blankj
 25 |  *     blog  : http://blankj.com
 26 |  *     time  : 2016/8/2
 27 |  *     desc  : 手机相关工具类
 28 |  * 
29 | */ 30 | public class PhoneUtils { 31 | 32 | private PhoneUtils() { 33 | throw new UnsupportedOperationException("u can't fuck me..."); 34 | } 35 | 36 | /** 37 | * 判断设备是否是手机 38 | * 39 | * @param context 上下文 40 | * @return {@code true}: 是
{@code false}: 否 41 | */ 42 | public static boolean isPhone(Context context) { 43 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 44 | return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; 45 | } 46 | 47 | /** 48 | * 获取手机的IMIE 49 | *

需与{@link #isPhone(Context)}一起使用

50 | *

需添加权限 {@code }

51 | * 52 | * @param context 上下文 53 | * @return IMIE码 54 | */ 55 | public static String getPhoneIMEI(Context context) { 56 | String deviceId; 57 | if (isPhone(context)) { 58 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 59 | deviceId = tm.getDeviceId(); 60 | } else { 61 | deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); 62 | } 63 | return deviceId; 64 | } 65 | 66 | /** 67 | * 获取手机状态信息 68 | *

需添加权限 {@code }

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

需添加权限 {@code }

122 | * 123 | * @param context 上下文 124 | * @param phoneNumber 电话号码 125 | */ 126 | public static void call(Context context, String phoneNumber) { 127 | context.startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber))); 128 | } 129 | 130 | /** 131 | * 发送短信 132 | * 133 | * @param context 上下文 134 | * @param phoneNumber 电话号码 135 | * @param content 内容 136 | */ 137 | public static void sendSms(Context context, String phoneNumber, String content) { 138 | Uri uri = Uri.parse("smsto:" + (StringUtils.isEmpty(phoneNumber) ? "" : phoneNumber)); 139 | Intent intent = new Intent(Intent.ACTION_SENDTO, uri); 140 | intent.putExtra("sms_body", StringUtils.isEmpty(content) ? "" : content); 141 | context.startActivity(intent); 142 | } 143 | 144 | /** 145 | * 获取手机联系人 146 | *

需添加权限 {@code }

147 | *

需添加权限 {@code }

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

参照以下注释代码

212 | */ 213 | public static void getContantNum() { 214 | Log.i("tips", "U should copy the following code."); 215 | /* 216 | Intent intent = new Intent(); 217 | intent.setAction("android.intent.action.PICK"); 218 | intent.setType("vnd.android.cursor.dir/phone_v2"); 219 | startActivityForResult(intent, 0); 220 | 221 | @Override 222 | protected void onActivityResult ( int requestCode, int resultCode, Intent data){ 223 | super.onActivityResult(requestCode, resultCode, data); 224 | if (data != null) { 225 | Uri uri = data.getData(); 226 | String num = null; 227 | // 创建内容解析者 228 | ContentResolver contentResolver = getContentResolver(); 229 | Cursor cursor = contentResolver.query(uri, 230 | null, null, null, null); 231 | while (cursor.moveToNext()) { 232 | num = cursor.getString(cursor.getColumnIndex("data1")); 233 | } 234 | cursor.close(); 235 | num = num.replaceAll("-", "");//替换的操作,555-6 -> 5556 236 | } 237 | } 238 | */ 239 | } 240 | 241 | /** 242 | * 获取手机短信并保存到xml中 243 | *

需添加权限 {@code }

244 | *

需添加权限 {@code }

245 | * 246 | * @param context 上下文 247 | */ 248 | public static void getAllSMS(Context context) { 249 | // 1.获取短信 250 | // 1.1获取内容解析者 251 | ContentResolver resolver = context.getContentResolver(); 252 | // 1.2获取内容提供者地址 sms,sms表的地址:null 不写 253 | // 1.3获取查询路径 254 | Uri uri = Uri.parse("content://sms"); 255 | // 1.4.查询操作 256 | // projection : 查询的字段 257 | // selection : 查询的条件 258 | // selectionArgs : 查询条件的参数 259 | // sortOrder : 排序 260 | Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null); 261 | // 设置最大进度 262 | int count = cursor.getCount();//获取短信的个数 263 | // 2.备份短信 264 | // 2.1获取xml序列器 265 | XmlSerializer xmlSerializer = Xml.newSerializer(); 266 | try { 267 | // 2.2设置xml文件保存的路径 268 | // os : 保存的位置 269 | // encoding : 编码格式 270 | xmlSerializer.setOutput(new FileOutputStream(new File("/mnt/sdcard/backupsms.xml")), "utf-8"); 271 | // 2.3设置头信息 272 | // standalone : 是否独立保存 273 | xmlSerializer.startDocument("utf-8", true); 274 | // 2.4设置根标签 275 | xmlSerializer.startTag(null, "smss"); 276 | // 1.5.解析cursor 277 | while (cursor.moveToNext()) { 278 | SystemClock.sleep(1000); 279 | // 2.5设置短信的标签 280 | xmlSerializer.startTag(null, "sms"); 281 | // 2.6设置文本内容的标签 282 | xmlSerializer.startTag(null, "address"); 283 | String address = cursor.getString(0); 284 | // 2.7设置文本内容 285 | xmlSerializer.text(address); 286 | xmlSerializer.endTag(null, "address"); 287 | xmlSerializer.startTag(null, "date"); 288 | String date = cursor.getString(1); 289 | xmlSerializer.text(date); 290 | xmlSerializer.endTag(null, "date"); 291 | xmlSerializer.startTag(null, "type"); 292 | String type = cursor.getString(2); 293 | xmlSerializer.text(type); 294 | xmlSerializer.endTag(null, "type"); 295 | xmlSerializer.startTag(null, "body"); 296 | String body = cursor.getString(3); 297 | xmlSerializer.text(body); 298 | xmlSerializer.endTag(null, "body"); 299 | xmlSerializer.endTag(null, "sms"); 300 | System.out.println("address:" + address + " date:" + date + " type:" + type + " body:" + body); 301 | } 302 | xmlSerializer.endTag(null, "smss"); 303 | xmlSerializer.endDocument(); 304 | // 2.8将数据刷新到文件中 305 | xmlSerializer.flush(); 306 | } catch (Exception e) { 307 | e.printStackTrace(); 308 | } 309 | } 310 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Android开发人员不得不收集的代码([持续更新中][update_log.md]) 2 | *** 3 | 为方便查找,已进行大致归类,其目录如下所示: 4 | > - **App相关→[AppUtils.java][app.java]** 5 | > - 安装App *installApp* 6 | > - 卸载指定包名的App *uninstallApp* 7 | > - 获取当前App信息 *getAppInfo* 8 | > - 获取所有已安装App信息 *getAllAppsInfo* 9 | > - 根据包名判断App是否安装 *isInstallApp* 10 | > - 打开指定包名的App *openAppByPackageName* 11 | > - 打开指定包名的App应用信息界面 *openAppInfo* 12 | > - 可用来做App信息分享 *shareAppInfo* 13 | > - 判断当前App处于前台还是后台 *isAppBackground* 14 | 15 | > - **常量相关→[ConstUtils.java][const.java]** 16 | > - 存储相关常量 17 | > - 时间相关常量 18 | > - 正则相关常量 19 | 20 | > - **转换相关→[ConvertUtils.java][convert.java]→[Test][convert.test]** 21 | > - byteArr与hexString互转 *bytes2HexString*、*hexString2Bytes* 22 | > - charArr与byteArr互转 *chars2Bytes*、*bytes2Chars* 23 | > - inputStream与outputStream互转 *input2OutputStream*、*output2InputStream* 24 | > - inputStream与byteArr互转 *inputStream2Bytes*、*bytes2InputStream* 25 | > - outputStream与byteArr互转 *outputStream2Bytes*、*bytes2OutputStream* 26 | > - inputStream与string按编码互转 *inputStream2String*、*string2InputStream* 27 | > - outputStream与string按编码互转 *outputStream2String*、*string2OutputStream* 28 | > - bitmap与byteArr互转 *bitmap2Bytes*、*bytes2Bitmap* 29 | > - drawable与bitmap互转 *drawable2Bitmap*、*bitmap2Drawable* 30 | > - drawable与byteArr互转 *drawable2Bytes*、*bytes2Drawable* 31 | > - dp与px互转 *dp2px*、*px2dp* 32 | > - sp与px互转 *sp2px*、*px2sp* 33 | 34 | > - **设备相关→[DeviceUtils.java][device.java]** 35 | > - 获取设备MAC地址 *getMacAddress* 36 | > - 获取设备厂商,如Xiaomi *getManufacturer* 37 | > - 获取设备型号,如MI2SC *getModel* 38 | 39 | > - **编码解码相关→[EncodeUtils.java][encode.java]→[Test][encode.test]** 40 | > - URL编码 *urlEncode* 41 | > - URL解码 *urlDecode* 42 | > - Base64编码 *base64Encode*、*base64Encode2String* 43 | > - Base64解码 *base64Decode* 44 | > - Base64URL安全编码 *base64UrlSafeEncode* 45 | > - Html编码 *htmlEncode* 46 | > - Html解码 *htmlDecode* 47 | 48 | > - **加密解密相关→[EncryptUtils.java][encrypt.java]→[Test][encrypt.test]** 49 | > - MD2加密 *encryptMD2ToString*、*encryptMD2* 50 | > - MD5加密 *encryptMD5ToString*、*encryptMD5* 51 | > - SHA1加密 *encryptSHA1ToString*、*encryptSHA1* 52 | > - SHA224加密 *encryptSHA224ToString*、*encryptSHA224* 53 | > - SHA256加密 *encryptSHA256ToString*、*encryptSHA256* 54 | > - SHA384加密 *encryptSHA384ToString*、*encryptSHA384* 55 | > - SHA512加密 *encryptSHA512ToString*、*encryptSHA512* 56 | > - 获取文件的MD5校验码 *encryptMD5File2String*、*encryptMD5File* 57 | > - DES加密后转为Base64编码 *encryptDES2Base64* 58 | > - DES加密后转为16进制 *encryptDES2HexString* 59 | > - DES加密 *encryptDES* 60 | > - DES解密Base64编码密文 *decryptBase64DES* 61 | > - DES解密16进制密文 *decryptHexStringDES* 62 | > - DES解密 *decryptDES* 63 | > - 3DES加密后转为Base64编码 *encrypt3DES2Base64* 64 | > - 3DES加密后转为16进制 *encrypt3DES2HexString* 65 | > - 3DES加密 *encrypt3DES* 66 | > - 3DES解密Base64编码密文 *decryptBase64_3DES* 67 | > - 3DES解密16进制密文 *decryptHexString3DES* 68 | > - 3DES解密 *decrypt3DES* 69 | > - AES加密后转为Base64编码 *encryptAES2Base64* 70 | > - AES加密后转为16进制 *encryptAES2HexString* 71 | > - AES加密 *encryptAES* 72 | > - AES解密Base64编码密文 *decryptBase64AES* 73 | > - AES解密16进制密文 *decryptHexStringAES* 74 | > - AES解密 *decryptAES* 75 | 76 | > - **文件相关→[FileUtils.java][file.java]→[Test][file.test]** 77 | > - 根据文件路径获取文件 *getFileByPath* 78 | > - 判断文件是否存在 *isFileExists* 79 | > - 判断是否是目录 *isDir* 80 | > - 判断是否是文件 *isFile* 81 | > - 判断目录是否存在,不存在则判断是否创建成功 *createOrExistsDir* 82 | > - 判断文件是否存在,不存在则判断是否创建成功 *createOrExistsFile* 83 | > - 判断文件是否存在,存在则在创建之前删除 *createFileByDeleteOldFile* 84 | > - 复制目录 *copyDir* 85 | > - 复制文件 *copyFile* 86 | > - 移动目录 *moveDir* 87 | > - 移动文件 *moveFile* 88 | > - 删除目录 *deleteDir* 89 | > - 删除文件 *deleteFile* 90 | > - 获取目录下所有文件 *listFilesInDir* 91 | > - 获取目录下所有文件包括子目录 *listFilesInDir* 92 | > - 获取目录下所有后缀名为suffix的文件 *listFilesInDirWithFilter* 93 | > - 获取目录下所有后缀名为suffix的文件包括子目录 *listFilesInDirWithFilter* 94 | > - 获取目录下所有符合filter的文件 *listFilesInDirWithFilter* 95 | > - 获取目录下所有符合filter的文件包括子目录 *listFilesInDirWithFilter* 96 | > - 获取目录下指定文件名的文件包括子目录 *searchFileInDir* 97 | > - 将输入流写入文件 *writeFileFromIS* 98 | > - 将字符串写入文件 *writeFileFromString* 99 | > - 简单获取文件编码格式 *getFileCharsetSimple* 100 | > - 获取文件行数 *getFileLines* 101 | > - 指定编码按行读取文件到List *readFile2List* 102 | > - 指定编码按行读取文件到StringBuilder中 *readFile2SB* 103 | > - 字节数转以unit为单位的size *byte2Size* 104 | > - 以unit为单位的size转字节数 *size2Byte* 105 | > - 获取文件大小 *getFileSize* 106 | > - 关闭IO *closeIO* 107 | > - 根据全路径获取最长目录 *getDirName* 108 | > - 根据全路径获取文件名 *getFileName* 109 | > - 根据全路径获取文件名不带拓展名 *getFileNameNoExtension* 110 | > - 根据全路径获取文件拓展名 *getFileExtension* 111 | 112 | > - **图片相关→[ImageUtils.java][image.java]** 113 | > - bitmap与byteArr互转 *bitmap2Bytes*、*bytes2Bitmap* 114 | > - drawable与bitmap互转 *drawable2Bitmap*、*bitmap2Drawable* 115 | > - drawable与byteArr互转 *drawable2Bytes*、*bytes2Drawable* 116 | > - 缩放图片 *scaleImage* 117 | > - 转为圆形图片 *toRound* 118 | > - 转为圆角图片 *toRoundCorner* 119 | > - 快速模糊 *fastBlur* 120 | > - renderScript模糊图片 *renderScriptBlur* 121 | > - stack模糊图片 *stackBlur* 122 | > - 添加颜色边框 *addFrame* 123 | > - 添加倒影 *addReflection* 124 | > - 添加水印文字 *addText* 125 | > - 压缩图片 *compress* 126 | > - 保存图片 *save* 127 | > - 判断文件是否为图片 *isImage* 128 | > - 获取图片类型 *getImageType* 129 | 130 | > - **键盘相关→[KeyboardUtils.java][keyboard.java]** 131 | > - 避免输入法面板遮挡 132 | > - 动态隐藏软键盘 *hideSoftInput* 133 | > - 点击屏幕空白区域隐藏软键盘(注释萌萌哒) *clickBlankArea2HideSoftInput0* 134 | > - 动态显示软键盘 *showSoftInput* 135 | > - 切换键盘显示与否状态 *toggleSoftInput* 136 | 137 | > - **网络相关→[NetworkUtils.java][network.java]** 138 | > - 打开网络设置界面 *openWirelessSettings* 139 | > - 判断网络是否可用 *isAvailable* 140 | > - 判断网络是否连接 *isConnected* 141 | > - 判断网络是否是4G *is4G* 142 | > - 判断wifi是否连接状态 *isWifiConnected* 143 | > - 获取移动网络运营商名称 *getNetworkOperatorName* 144 | > - 获取移动终端类型 *getPhoneType* 145 | > - 获取当前的网络类型(WIFI,2G,3G,4G) *getNetWorkType*、*getNetWorkTypeName* 146 | 147 | > - **手机相关→[PhoneUtils.java][phone.java]** 148 | > - 判断设备是否是手机 *isPhone* 149 | > - 获取手机的IMIE *getPhoneIMEI* 150 | > - 获取手机状态信息 *getPhoneStatus* 151 | > - 跳至填充好phoneNumber的拨号界面 *dial* 152 | > - 拨打phoneNumber *call* 153 | > - 发送短信 *sendSms* 154 | > - 获取手机联系人 *getAllContactInfo* 155 | > - 打开手机联系人界面点击联系人后便获取该号码(注释萌萌哒) *getContantNum* 156 | > - 获取手机短信并保存到xml中 *getAllSMS* 157 | 158 | > - **正则相关→[RegularUtils.java][regular.java]→[Test][regular.test]** 159 | > - 验证手机号(简单) *isMobileSimple* 160 | > - 验证手机号(精确) *isMobileExact* 161 | > - 验证电话号码 *isTel* 162 | > - 验证身份证号码15位 *isIDCard15* 163 | > - 验证身份证号码18位 *isIDCard18* 164 | > - 验证邮箱 *isEmail* 165 | > - 验证URL *isURL* 166 | > - 验证汉字 *isChz* 167 | > - 验证用户名 *isUsername* 168 | > - 验证yyyy-MM-dd格式的日期校验,已考虑平闰年 *isDate* 169 | > - 验证IP地址 *isIP* 170 | > - string是否匹配regex *isMatch* 171 | 172 | > - **屏幕相关→[ScreenUtils.java][screen.java]** 173 | > - 获取手机分辨率 *getDeviceWidth*、*getDeviceHeight* 174 | > - 设置透明状态栏(api大于19方可使用) *setTransparentStatusBar* 175 | > - 隐藏状态栏(注释萌萌哒) *hideStatusBar* 176 | > - 获取状态栏高度 *getStatusBarHeight* 177 | > - 判断状态栏是否存在 *isStatusBarExists* 178 | > - 获取ActionBar高度 *getActionBarHeight* 179 | > - 显示通知栏 *showNotificationBar* 180 | > - 隐藏通知栏 *hideNotificationBar* 181 | > - 设置屏幕为横屏(注释萌萌哒) *setLandscape* 182 | > - 获取屏幕截图 *snapShotWithStatusBar*、*snapShotWithoutStatusBar* 183 | > - 判断是否锁屏 *isScreenLock* 184 | 185 | > - **SD卡相关→[SDCardUtils.java][sdcard.java]** 186 | > - 判断SD卡是否可用 *isSDCardEnable* 187 | > - 获取SD卡路径 *getSDCardPath* 188 | > - 获取SD卡Data路径 *getDataPath* 189 | > - 计算SD卡的剩余空间 *getFreeSpace* 190 | 191 | > - **Shell相关→[ShellUtils.java][shell.java]** 192 | > - 判断设备是否root *isRoot* 193 | > - 是否是在root下执行命令 *execCmd* 194 | 195 | > - **尺寸相关→[SizeUtils.java][size.java]** 196 | > - dp与px转换 *dp2px*、*px2dp* 197 | > - sp与px转换 *sp2px*、*px2sp* 198 | > - 各种单位转换 *applyDimension* 199 | > - 在onCreate()即可强行获取View的尺寸 *forceGetViewSize* 200 | > - ListView中提前测量View尺寸(注释萌萌哒) *measureView* 201 | 202 | > - **SP相关→[SPUtils.java][sp.java]→[Test][sp.test]** 203 | > - SPUtils构造函数 *SPUtils* 204 | > - SP中写入String类型value *putString* 205 | > - SP中读取String *getString* 206 | > - SP中写入int类型value *putInt* 207 | > - SP中读取int *getInt* 208 | > - SP中写入long类型value *putLong* 209 | > - SP中读取long *getLong* 210 | > - SP中写入float类型value *putFloat* 211 | > - SP中读取float *getFloat* 212 | > - SP中写入boolean类型value *putBoolean* 213 | > - SP中读取boolean *getBoolean* 214 | > - 获取SP中所有键值对 *getAll* 215 | > - 从SP中移除该key *remove* 216 | > - 判断SP中是否存在该key *contains* 217 | > - 清除SP中所有数据 *clear* 218 | 219 | > - **字符串相关→[StringUtils.java][string.java]→[Test][string.test]** 220 | > - 判断字符串是否为null或长度为0 *isEmpty* 221 | > - 判断字符串是否为null或全为空格 *isSpace* 222 | > - null转为长度为0的字符串 *null2Length0* 223 | > - 返回字符串长度 *length* 224 | > - 首字母大写 *upperFirstLetter* 225 | > - 首字母小写 *lowerFirstLetter* 226 | > - 转化为半角字符 *toDBC* 227 | > - 转化为全角字符 *toSBC* 228 | 229 | > - **线程池相关工具类→[ThreadPoolUtils.java][thread_pool.java]** 230 | > - ThreadPoolUtils构造函数 *ThreadPoolUtils* 231 | > - 在未来某个时间执行给定的命令 *execute* 232 | > - 在未来某个时间执行给定的命令链表 *execute* 233 | > - 待以前提交的任务执行完毕后关闭线程池 *shutDown* 234 | > - 试图停止所有正在执行的活动任务 *shutDownNow* 235 | > - 判断线程池是否已关闭 *isShutDown* 236 | > - 关闭线程池后判断所有任务是否都已完成 *isTerminated* 237 | > - 请求关闭、发生超时或者当前线程中断 *awaitTermination* 238 | > - 提交一个Callable任务用于执行 *submit* 239 | > - 提交一个Runnable任务用于执行 *submit* 240 | > - 执行给定的任务 *invokeAll*、*invokeAny* 241 | > - 延迟执行Runnable命令 *schedule* 242 | > - 延迟执行Callable命令 *schedule* 243 | > - 延迟并循环执行命令 *scheduleWithFixedRate*、*scheduleWithFixedDelay* 244 | 245 | > - **时间相关→[TimeUtils.java][time.java]→[Test][time.test]** 246 | > - 将时间戳转为时间字符串 *milliseconds2String* 247 | > - 将时间字符串转为时间戳 *string2Milliseconds* 248 | > - 将时间字符串转为Date类型 *string2Date* 249 | > - 将Date类型转为时间字符串 *date2String* 250 | > - 将Date类型转为时间戳 *date2Milliseconds* 251 | > - 将时间戳转为Date类型 *milliseconds2Date* 252 | > - 毫秒时间戳单位转换(单位:unit) *milliseconds2Unit* 253 | > - 获取两个时间差(单位:unit) *getIntervalTime* 254 | > - 获取当前时间 *getCurTimeMills*、*getCurTimeString*、*getCurTimeDate* 255 | > - 获取与当前时间的差(单位:unit) *getIntervalByNow* 256 | > - 判断闰年 *isLeapYear* 257 | 258 | > - **未归类→[UnclassifiedUtils.java][unclassified.java]** 259 | > - 获取服务是否开启 *isRunningService* 260 | 261 | > - **压缩相关工具类→[ZipUtils.java][zip.java]** 262 | > - 批量压缩文件 *zipFiles* 263 | > - 压缩文件 *zipFile* 264 | > - 解压缩一个文件 *upZipFile* 265 | > - 解压文件名包含传入文字的文件 *upZipSelectedFile* 266 | > - 获得压缩文件内文件列表 *getEntriesNames* 267 | > - 获得压缩文件内压缩文件对象以取得其属性 *getEntriesEnumeration* 268 | > - 获得压缩文件对象的注释 *getEntryComment* 269 | > - 获得压缩文件对象的名称 *getEntryName* 270 | 271 | > - **更新Log→[update_log.md][update_log.md]** 272 | 273 | *** 274 | 275 | **做这份整理是想把它作为Android开发的小字典,当遇到一些琐碎问题时,不用再面向百度或者谷歌查询API的使用,费时费力,这里有的话,大家尽管撸走;同时也希望它能逐日壮大起来,期待大家的Star和完善,当然我也会一直更新发布版本和日志,为了方便大家导入,现已上传jcenter;其中很多代码也是汇四方之精华,谢谢前辈们的提供,当然最终还是要通过单元测试的,如有错误,请及时告之;开设QQ群提供讨论,群号:74721490,至于验证问题对大家来说肯定都是小case;** 276 | 277 | ### Download 278 | *** 279 | Gradle: 280 | ``` groovy 281 | compile 'com.blankj:utilcode:1.1.5' 282 | ``` 283 | 284 | ### Proguard 285 | *** 286 | ``` 287 | -keep class com.blankj.utilcode.** { *; } 288 | -keep classmembers class com.blankj.utilcode.** { *; } 289 | -dontwarn com.blankj.utilcode.** 290 | ``` 291 | 292 | ### License 293 | *** 294 | ``` 295 | Copyright 2016 Blankj 296 | 297 | Licensed under the Apache License, Version 2.0 (the "License"); 298 | you may not use this file except in compliance with the License. 299 | You may obtain a copy of the License at 300 | 301 | http://www.apache.org/licenses/LICENSE-2.0 302 | 303 | Unless required by applicable law or agreed to in writing, software 304 | distributed under the License is distributed on an "AS IS" BASIS, 305 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 306 | See the License for the specific language governing permissions and 307 | limitations under the License. 308 | ``` 309 | 310 | [app.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/AppUtils.java 311 | 312 | [const.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ConstUtils.java 313 | 314 | [convert.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ConvertUtils.java 315 | [convert.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/ConvertUtilsTest.java 316 | 317 | [device.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/DeviceUtils.java 318 | 319 | [encode.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/EncodeUtils.java 320 | [encode.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/EncodeUtilsTest.java 321 | 322 | [encrypt.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/EncryptUtils.java 323 | [encrypt.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/EncryptUtilsTest.java 324 | 325 | [file.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/FileUtils.java 326 | [file.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/FileUtilsTest.java 327 | 328 | [image.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ImageUtils.java 329 | 330 | [keyboard.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/KeyboardUtils.java 331 | 332 | [network.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/NetworkUtils.java 333 | 334 | [phone.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/PhoneUtils.java 335 | 336 | [regular.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/RegularUtils.java 337 | [regular.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/RegularUtilsTest.java 338 | 339 | [screen.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ScreenUtils.java 340 | 341 | [sdcard.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/SDCUtils.java 342 | 343 | [shell.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ShellUtils.java 344 | 345 | [size.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/SizeUtils.java 346 | 347 | [sp.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/SPUtils.java 348 | [sp.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/SPUtilsTest.java 349 | 350 | [string.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/StringUtils.java 351 | [string.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/StringUtilsTest.java 352 | 353 | [thread_pool.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ThreadPoolUtils.java 354 | 355 | [time.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/TimeUtils.java 356 | [time.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/test/java/com/blankj/utilcode/utils/TimeUtilsTest.java 357 | 358 | [unclassified.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/UnclassifiedUtils.java 359 | 360 | [zip.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/src/main/java/com/blankj/utilcode/utils/ZipUtils.java 361 | 362 | [update_log.md]: https://github.com/Blankj/AndroidUtilCode/blob/master/update_log.md 363 | -------------------------------------------------------------------------------- /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 | import java.util.Locale; 7 | 8 | import static com.blankj.utilcode.utils.ConstUtils.*; 9 | 10 | 11 | /** 12 | *
 13 |  *     author: Blankj
 14 |  *     blog  : http://blankj.com
 15 |  *     time  : 2016/8/2
 16 |  *     desc  : 时间相关工具类
 17 |  * 
18 | */ 19 | public class TimeUtils { 20 | 21 | private TimeUtils() { 22 | throw new UnsupportedOperationException("u can't fuck me..."); 23 | } 24 | 25 | /** 26 | *

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

27 | * 格式的意义如下: 日期和时间模式
28 | *

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

32 | * 定义了以下模式字母(所有其他字符 'A' 到 'Z' 和 'a' 到 'z' 都被保留):
33 | * 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 | * 113 | * 114 | * 115 | * 116 | * 117 | * 118 | * 119 | * 120 | * 121 | * 122 | * 123 | * 124 | * 125 | * 126 | * 127 | * 128 | * 129 | * 130 | * 131 | * 132 | * 133 | * 134 | * 135 | * 136 | * 137 | * 138 | * 139 | * 140 | * 141 | * 142 | * 143 | * 144 | * 145 | * 146 | * 147 | * 148 | * 149 | * 150 | * 151 | * 152 | * 153 | * 154 | * 155 | *
字母日期或时间元素表示示例
GEra 标志符TextAD
y Year 1996; 96
M 年中的月份 Month July; Jul; 07
w 年中的周数 Number 27
W 月份中的周数 Number 2
D 年中的天数 Number 189
d 月份中的天数 Number 10
F 月份中的星期 Number 2
E 星期中的天数 Text Tuesday; Tue
a Am/pm 标记 Text PM
H 一天中的小时数(0-23) Number 0
k 一天中的小时数(1-24) Number 24
K am/pm 中的小时数(0-11) Number 0
h am/pm 中的小时数(1-12) Number 12
m 小时中的分钟数 Number 30
s 分钟中的秒数 Number 55
S 毫秒数 Number 978
z 时区 General time zone Pacific Standard Time; PST; GMT-08:00
Z 时区 RFC 822 time zone -0800
156 | *
157 |      *                          HH:mm    15:44
158 |      *                         h:mm a    3:44 下午
159 |      *                        HH:mm z    15:44 CST
160 |      *                        HH:mm Z    15:44 +0800
161 |      *                     HH:mm zzzz    15:44 中国标准时间
162 |      *                       HH:mm:ss    15:44:40
163 |      *                     yyyy-MM-dd    2016-08-12
164 |      *               yyyy-MM-dd HH:mm    2016-08-12 15:44
165 |      *            yyyy-MM-dd HH:mm:ss    2016-08-12 15:44:40
166 |      *       yyyy-MM-dd HH:mm:ss zzzz    2016-08-12 15:44:40 中国标准时间
167 |      *  EEEE yyyy-MM-dd HH:mm:ss zzzz    星期五 2016-08-12 15:44:40 中国标准时间
168 |      *       yyyy-MM-dd HH:mm:ss.SSSZ    2016-08-12 15:44:40.461+0800
169 |      *     yyyy-MM-dd'T'HH:mm:ss.SSSZ    2016-08-12T15:44:40.461+0800
170 |      *   yyyy.MM.dd G 'at' HH:mm:ss z    2016.08.12 公元 at 15:44:40 CST
171 |      *                         K:mm a    3:44 下午
172 |      *               EEE, MMM d, ''yy    星期五, 八月 12, '16
173 |      *          hh 'o''clock' a, zzzz    03 o'clock 下午, 中国标准时间
174 |      *   yyyyy.MMMMM.dd GGG hh:mm aaa    02016.八月.12 公元 03:44 下午
175 |      *     EEE, d MMM yyyy HH:mm:ss Z    星期五, 12 八月 2016 15:44:40 +0800
176 |      *                  yyMMddHHmmssZ    160812154440+0800
177 |      *     yyyy-MM-dd'T'HH:mm:ss.SSSZ    2016-08-12T15:44:40.461+0800
178 |      * EEEE 'DATE('yyyy-MM-dd')' 'TIME('HH:mm:ss')' zzzz    星期五 DATE(2016-08-12) TIME(15:44:40) 中国标准时间
179 |      * 
180 | */ 181 | public static final SimpleDateFormat DEFAULT_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); 182 | 183 | 184 | /** 185 | * 将时间戳转为时间字符串 186 | *

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

187 | * 188 | * @param milliseconds 毫秒时间戳 189 | * @return 时间字符串 190 | */ 191 | public static String milliseconds2String(long milliseconds) { 192 | return milliseconds2String(milliseconds, DEFAULT_SDF); 193 | } 194 | 195 | /** 196 | * 将时间戳转为时间字符串 197 | *

格式为用户自定义

198 | * 199 | * @param milliseconds 毫秒时间戳 200 | * @param format 时间格式 201 | * @return 时间字符串 202 | */ 203 | public static String milliseconds2String(long milliseconds, SimpleDateFormat format) { 204 | return format.format(new Date(milliseconds)); 205 | } 206 | 207 | /** 208 | * 将时间字符串转为时间戳 209 | *

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

210 | * 211 | * @param time 时间字符串 212 | * @return 毫秒时间戳 213 | */ 214 | public static long string2Milliseconds(String time) { 215 | return string2Milliseconds(time, DEFAULT_SDF); 216 | } 217 | 218 | /** 219 | * 将时间字符串转为时间戳 220 | *

格式为用户自定义

221 | * 222 | * @param time 时间字符串 223 | * @param format 时间格式 224 | * @return 毫秒时间戳 225 | */ 226 | public static long string2Milliseconds(String time, SimpleDateFormat format) { 227 | try { 228 | return format.parse(time).getTime(); 229 | } catch (ParseException e) { 230 | e.printStackTrace(); 231 | } 232 | return -1; 233 | } 234 | 235 | /** 236 | * 将时间字符串转为Date类型 237 | *

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

238 | * 239 | * @param time 时间字符串 240 | * @return Date类型 241 | */ 242 | public static Date string2Date(String time) { 243 | return string2Date(time, DEFAULT_SDF); 244 | } 245 | 246 | /** 247 | * 将时间字符串转为Date类型 248 | *

格式为用户自定义

249 | * 250 | * @param time 时间字符串 251 | * @param format 时间格式 252 | * @return Date类型 253 | */ 254 | public static Date string2Date(String time, SimpleDateFormat format) { 255 | return new Date(string2Milliseconds(time, format)); 256 | } 257 | 258 | /** 259 | * 将Date类型转为时间字符串 260 | *

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

261 | * 262 | * @param time Date类型时间 263 | * @return 时间字符串 264 | */ 265 | public static String date2String(Date time) { 266 | return date2String(time, DEFAULT_SDF); 267 | } 268 | 269 | /** 270 | * 将Date类型转为时间字符串 271 | *

格式为用户自定义

272 | * 273 | * @param time Date类型时间 274 | * @param format 时间格式 275 | * @return 时间字符串 276 | */ 277 | public static String date2String(Date time, SimpleDateFormat format) { 278 | return format.format(time); 279 | } 280 | 281 | /** 282 | * 将Date类型转为时间戳 283 | * 284 | * @param time Date类型时间 285 | * @return 毫秒时间戳 286 | */ 287 | public static long date2Milliseconds(Date time) { 288 | return time.getTime(); 289 | } 290 | 291 | /** 292 | * 将时间戳转为Date类型 293 | * 294 | * @param milliseconds 毫秒时间戳 295 | * @return Date类型时间 296 | */ 297 | public static Date milliseconds2Date(long milliseconds) { 298 | return new Date(milliseconds); 299 | } 300 | 301 | /** 302 | * 毫秒时间戳单位转换(单位:unit) 303 | * 304 | * @param milliseconds 毫秒时间戳 305 | * @param unit
    306 | *
  • {@link TimeUnit#MSEC}: 毫秒
  • 307 | *
  • {@link TimeUnit#SEC }: 秒
  • 308 | *
  • {@link TimeUnit#MIN }: 分
  • 309 | *
  • {@link TimeUnit#HOUR}: 小时
  • 310 | *
  • {@link TimeUnit#DAY }: 天
  • 311 | *
312 | * @return unit时间戳 313 | */ 314 | private static long milliseconds2Unit(long milliseconds, TimeUnit unit) { 315 | switch (unit) { 316 | case MSEC: 317 | return milliseconds / MSEC; 318 | case SEC: 319 | return milliseconds / SEC; 320 | case MIN: 321 | return milliseconds / MIN; 322 | case HOUR: 323 | return milliseconds / HOUR; 324 | case DAY: 325 | return milliseconds / DAY; 326 | } 327 | return -1; 328 | } 329 | 330 | /** 331 | * 获取两个时间差(单位:unit) 332 | *

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

333 | * 334 | * @param time0 时间字符串1 335 | * @param time1 时间字符串2 336 | * @param unit
    337 | *
  • {@link TimeUnit#MSEC}: 毫秒
  • 338 | *
  • {@link TimeUnit#SEC }: 秒
  • 339 | *
  • {@link TimeUnit#MIN }: 分
  • 340 | *
  • {@link TimeUnit#HOUR}: 小时
  • 341 | *
  • {@link TimeUnit#DAY }: 天
  • 342 | *
343 | * @return unit时间戳 344 | */ 345 | public static long getIntervalTime(String time0, String time1, TimeUnit unit) { 346 | return getIntervalTime(time0, time1, unit, DEFAULT_SDF); 347 | } 348 | 349 | /** 350 | * 获取两个时间差(单位:unit) 351 | *

time1和time2格式都为format

352 | * 353 | * @param time0 时间字符串1 354 | * @param time1 时间字符串2 355 | * @param unit
    356 | *
  • {@link TimeUnit#MSEC}: 毫秒
  • 357 | *
  • {@link TimeUnit#SEC }: 秒
  • 358 | *
  • {@link TimeUnit#MIN }: 分
  • 359 | *
  • {@link TimeUnit#HOUR}: 小时
  • 360 | *
  • {@link TimeUnit#DAY }: 天
  • 361 | *
362 | * @param format 时间格式 363 | * @return unit时间戳 364 | */ 365 | public static long getIntervalTime(String time0, String time1, TimeUnit unit, SimpleDateFormat format) { 366 | return Math.abs(milliseconds2Unit(string2Milliseconds(time0, format) 367 | - string2Milliseconds(time1, format), unit)); 368 | } 369 | 370 | /** 371 | * 获取两个时间差(单位:unit) 372 | *

time1和time2都为Date类型

373 | * 374 | * @param time0 Date类型时间1 375 | * @param time1 Date类型时间2 376 | * @param unit
    377 | *
  • {@link TimeUnit#MSEC}: 毫秒
  • 378 | *
  • {@link TimeUnit#SEC }: 秒
  • 379 | *
  • {@link TimeUnit#MIN }: 分
  • 380 | *
  • {@link TimeUnit#HOUR}: 小时
  • 381 | *
  • {@link TimeUnit#DAY }: 天
  • 382 | *
383 | * @return unit时间戳 384 | */ 385 | public static long getIntervalTime(Date time0, Date time1, TimeUnit unit) { 386 | return Math.abs(milliseconds2Unit(date2Milliseconds(time1) 387 | - date2Milliseconds(time0), unit)); 388 | } 389 | 390 | /** 391 | * 获取当前时间 392 | * 393 | * @return 毫秒时间戳 394 | */ 395 | public static long getCurTimeMills() { 396 | return System.currentTimeMillis(); 397 | } 398 | 399 | /** 400 | * 获取当前时间 401 | *

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

402 | * 403 | * @return 时间字符串 404 | */ 405 | public static String getCurTimeString() { 406 | return date2String(new Date()); 407 | } 408 | 409 | /** 410 | * 获取当前时间 411 | *

格式为用户自定义

412 | * 413 | * @param format 时间格式 414 | * @return 时间字符串 415 | */ 416 | public static String getCurTimeString(SimpleDateFormat format) { 417 | return date2String(new Date(), format); 418 | } 419 | 420 | /** 421 | * 获取当前时间 422 | *

Date类型

423 | * 424 | * @return Date类型时间 425 | */ 426 | public static Date getCurTimeDate() { 427 | return new Date(); 428 | } 429 | 430 | /** 431 | * 获取与当前时间的差(单位:unit) 432 | *

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

433 | * 434 | * @param time 时间字符串 435 | * @param unit
    436 | *
  • {@link TimeUnit#MSEC}:毫秒
  • 437 | *
  • {@link TimeUnit#SEC }:秒
  • 438 | *
  • {@link TimeUnit#MIN }:分
  • 439 | *
  • {@link TimeUnit#HOUR}:小时
  • 440 | *
  • {@link TimeUnit#DAY }:天
  • 441 | *
442 | * @return unit时间戳 443 | */ 444 | public static long getIntervalByNow(String time, TimeUnit unit) { 445 | return getIntervalByNow(time, unit, DEFAULT_SDF); 446 | } 447 | 448 | /** 449 | * 获取与当前时间的差(单位:unit) 450 | *

time格式为format

451 | * 452 | * @param time 时间字符串 453 | * @param unit
    454 | *
  • {@link TimeUnit#MSEC}: 毫秒
  • 455 | *
  • {@link TimeUnit#SEC }: 秒
  • 456 | *
  • {@link TimeUnit#MIN }: 分
  • 457 | *
  • {@link TimeUnit#HOUR}: 小时
  • 458 | *
  • {@link TimeUnit#DAY }: 天
  • 459 | *
460 | * @param format 时间格式 461 | * @return unit时间戳 462 | */ 463 | public static long getIntervalByNow(String time, TimeUnit unit, SimpleDateFormat format) { 464 | return getIntervalTime(getCurTimeString(), time, unit, format); 465 | } 466 | 467 | /** 468 | * 获取与当前时间的差(单位:unit) 469 | *

time为Date类型

470 | * 471 | * @param time Date类型时间 472 | * @param unit
    473 | *
  • {@link TimeUnit#MSEC}: 毫秒
  • 474 | *
  • {@link TimeUnit#SEC }: 秒
  • 475 | *
  • {@link TimeUnit#MIN }: 分
  • 476 | *
  • {@link TimeUnit#HOUR}: 小时
  • 477 | *
  • {@link TimeUnit#DAY }: 天
  • 478 | *
479 | * @return unit时间戳 480 | */ 481 | public static long getIntervalByNow(Date time, TimeUnit unit) { 482 | return getIntervalTime(getCurTimeDate(), time, unit); 483 | } 484 | 485 | /** 486 | * 判断闰年 487 | * 488 | * @param year 年份 489 | * @return {@code true}: 闰年
{@code false}: 平年 490 | */ 491 | public static boolean isLeapYear(int year) { 492 | return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 493 | } 494 | } -------------------------------------------------------------------------------- /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 | import java.security.SecureRandom; 11 | 12 | import javax.crypto.Cipher; 13 | import javax.crypto.spec.SecretKeySpec; 14 | 15 | import static com.blankj.utilcode.utils.ConvertUtils.*; 16 | 17 | /** 18 | *
 19 |  *     author: Blankj
 20 |  *     blog  : http://blankj.com
 21 |  *     time  : 2016/8/2
 22 |  *     desc  : 加密解密相关的工具类
 23 |  * 
24 | */ 25 | public class EncryptUtils { 26 | 27 | private EncryptUtils() { 28 | throw new UnsupportedOperationException("u can't fuck me..."); 29 | } 30 | 31 | /*********************** 哈希加密相关 ***********************/ 32 | /** 33 | * MD2加密 34 | * 35 | * @param data 明文字符串 36 | * @return 16进制密文 37 | */ 38 | public static String encryptMD2ToString(String data) { 39 | return encryptMD2ToString(data.getBytes()); 40 | } 41 | 42 | /** 43 | * MD2加密 44 | * 45 | * @param data 明文字节数组 46 | * @return 16进制密文 47 | */ 48 | public static String encryptMD2ToString(byte[] data) { 49 | return bytes2HexString(encryptMD2(data)); 50 | } 51 | 52 | /** 53 | * MD2加密 54 | * 55 | * @param data 明文字节数组 56 | * @return 密文字节数组 57 | */ 58 | public static byte[] encryptMD2(byte[] data) { 59 | return encryptAlgorithm(data, "MD2"); 60 | } 61 | 62 | /** 63 | * MD5加密 64 | * 65 | * @param data 明文字符串 66 | * @return 16进制密文 67 | */ 68 | public static String encryptMD5ToString(String data) { 69 | return encryptMD5ToString(data.getBytes()); 70 | } 71 | 72 | /** 73 | * MD5加密 74 | * 75 | * @param data 明文字符串 76 | * @param salt 盐 77 | * @return 16进制加盐密文 78 | */ 79 | public static String encryptMD5ToString(String data, String salt) { 80 | return bytes2HexString(encryptMD5((data + salt).getBytes())); 81 | } 82 | 83 | /** 84 | * MD5加密 85 | * 86 | * @param data 明文字节数组 87 | * @return 16进制密文 88 | */ 89 | public static String encryptMD5ToString(byte[] data) { 90 | return bytes2HexString(encryptMD5(data)); 91 | } 92 | 93 | /** 94 | * MD5加密 95 | * 96 | * @param data 明文字节数组 97 | * @param salt 盐字节数组 98 | * @return 16进制加盐密文 99 | */ 100 | public static String encryptMD5ToString(byte[] data, byte[] salt) { 101 | byte[] dataSalt = new byte[data.length + salt.length]; 102 | System.arraycopy(data, 0, dataSalt, 0, data.length); 103 | System.arraycopy(salt, 0, dataSalt, data.length, salt.length); 104 | return bytes2HexString(encryptMD5(dataSalt)); 105 | } 106 | 107 | /** 108 | * MD5加密 109 | * 110 | * @param data 明文字节数组 111 | * @return 密文字节数组 112 | */ 113 | public static byte[] encryptMD5(byte[] data) { 114 | return encryptAlgorithm(data, "MD5"); 115 | } 116 | 117 | /** 118 | * SHA1加密 119 | * 120 | * @param data 明文字符串 121 | * @return 16进制密文 122 | */ 123 | public static String encryptSHA1ToString(String data) { 124 | return encryptSHA1ToString(data.getBytes()); 125 | } 126 | 127 | /** 128 | * SHA1加密 129 | * 130 | * @param data 明文字节数组 131 | * @return 16进制密文 132 | */ 133 | public static String encryptSHA1ToString(byte[] data) { 134 | return bytes2HexString(encryptSHA1(data)); 135 | } 136 | 137 | /** 138 | * SHA1加密 139 | * 140 | * @param data 明文字节数组 141 | * @return 密文字节数组 142 | */ 143 | public static byte[] encryptSHA1(byte[] data) { 144 | return encryptAlgorithm(data, "SHA-1"); 145 | } 146 | 147 | /** 148 | * SHA224加密 149 | * 150 | * @param data 明文字符串 151 | * @return 16进制密文 152 | */ 153 | public static String encryptSHA224ToString(String data) { 154 | return encryptSHA224ToString(data.getBytes()); 155 | } 156 | 157 | /** 158 | * SHA224加密 159 | * 160 | * @param data 明文字节数组 161 | * @return 16进制密文 162 | */ 163 | public static String encryptSHA224ToString(byte[] data) { 164 | return bytes2HexString(encryptSHA224(data)); 165 | } 166 | 167 | /** 168 | * SHA224加密 169 | * 170 | * @param data 明文字节数组 171 | * @return 密文字节数组 172 | */ 173 | public static byte[] encryptSHA224(byte[] data) { 174 | return encryptAlgorithm(data, "SHA-224"); 175 | } 176 | 177 | /** 178 | * SHA256加密 179 | * 180 | * @param data 明文字符串 181 | * @return 16进制密文 182 | */ 183 | public static String encryptSHA256ToString(String data) { 184 | return encryptSHA256ToString(data.getBytes()); 185 | } 186 | 187 | /** 188 | * SHA256加密 189 | * 190 | * @param data 明文字节数组 191 | * @return 16进制密文 192 | */ 193 | public static String encryptSHA256ToString(byte[] data) { 194 | return bytes2HexString(encryptSHA256(data)); 195 | } 196 | 197 | /** 198 | * SHA256加密 199 | * 200 | * @param data 明文字节数组 201 | * @return 密文字节数组 202 | */ 203 | public static byte[] encryptSHA256(byte[] data) { 204 | return encryptAlgorithm(data, "SHA-256"); 205 | } 206 | 207 | /** 208 | * SHA384加密 209 | * 210 | * @param data 明文字符串 211 | * @return 16进制密文 212 | */ 213 | public static String encryptSHA384ToString(String data) { 214 | return encryptSHA384ToString(data.getBytes()); 215 | } 216 | 217 | /** 218 | * SHA384加密 219 | * 220 | * @param data 明文字节数组 221 | * @return 16进制密文 222 | */ 223 | public static String encryptSHA384ToString(byte[] data) { 224 | return bytes2HexString(encryptSHA384(data)); 225 | } 226 | 227 | /** 228 | * SHA384加密 229 | * 230 | * @param data 明文字节数组 231 | * @return 密文字节数组 232 | */ 233 | public static byte[] encryptSHA384(byte[] data) { 234 | return encryptAlgorithm(data, "SHA-384"); 235 | } 236 | 237 | /** 238 | * SHA512加密 239 | * 240 | * @param data 明文字符串 241 | * @return 16进制密文 242 | */ 243 | public static String encryptSHA512ToString(String data) { 244 | return encryptSHA512ToString(data.getBytes()); 245 | } 246 | 247 | /** 248 | * SHA512加密 249 | * 250 | * @param data 明文字节数组 251 | * @return 16进制密文 252 | */ 253 | public static String encryptSHA512ToString(byte[] data) { 254 | return bytes2HexString(encryptSHA512(data)); 255 | } 256 | 257 | /** 258 | * SHA512加密 259 | * 260 | * @param data 明文字节数组 261 | * @return 密文字节数组 262 | */ 263 | public static byte[] encryptSHA512(byte[] data) { 264 | return encryptAlgorithm(data, "SHA-512"); 265 | } 266 | 267 | /** 268 | * 对data进行algorithm算法加密 269 | * 270 | * @param data 明文字节数组 271 | * @param algorithm 加密算法 272 | * @return 密文字节数组 273 | */ 274 | private static byte[] encryptAlgorithm(byte[] data, String algorithm) { 275 | try { 276 | MessageDigest md = MessageDigest.getInstance(algorithm); 277 | md.update(data); 278 | return md.digest(); 279 | } catch (NoSuchAlgorithmException e) { 280 | e.printStackTrace(); 281 | } 282 | return new byte[0]; 283 | } 284 | 285 | /** 286 | * 获取文件的MD5校验码 287 | * 288 | * @param filePath 文件路径 289 | * @return 文件的16进制密文 290 | */ 291 | public static String encryptMD5File2String(String filePath) { 292 | return encryptMD5File2String(new File(filePath)); 293 | } 294 | 295 | /** 296 | * 获取文件的MD5校验码 297 | * 298 | * @param filePath 文件路径 299 | * @return 文件的MD5校验码 300 | */ 301 | public static byte[] encryptMD5File(String filePath) { 302 | return encryptMD5File(new File(filePath)); 303 | } 304 | 305 | /** 306 | * 获取文件的MD5校验码 307 | * 308 | * @param file 文件 309 | * @return 文件的16进制密文 310 | */ 311 | public static String encryptMD5File2String(File file) { 312 | return encryptMD5File(file) != null ? bytes2HexString(encryptMD5File(file)) : ""; 313 | } 314 | 315 | /** 316 | * 获取文件的MD5校验码 317 | * 318 | * @param file 文件 319 | * @return 文件的MD5校验码 320 | */ 321 | public static byte[] encryptMD5File(File file) { 322 | FileInputStream in = null; 323 | try { 324 | in = new FileInputStream(file); 325 | FileChannel channel = in.getChannel(); 326 | MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); 327 | MessageDigest md = MessageDigest.getInstance("MD5"); 328 | md.update(buffer); 329 | return md.digest(); 330 | } catch (NoSuchAlgorithmException | IOException e) { 331 | e.printStackTrace(); 332 | } finally { 333 | if (in != null) { 334 | try { 335 | in.close(); 336 | } catch (IOException ignored) { 337 | } 338 | } 339 | } 340 | return null; 341 | } 342 | 343 | /************************ DES加密相关 ***********************/ 344 | /** 345 | * DES转变 346 | *

法算法名称/加密模式/填充方式

347 | *

加密模式有:电子密码本模式ECB、加密块链模式CBC、加密反馈模式CFB、输出反馈模式OFB

348 | *

填充方式有:NoPadding、ZerosPadding、PKCS5Padding

349 | */ 350 | public static String DES_Transformation = "DES/ECB/NoPadding"; 351 | private static final String DES_Algorithm = "DES"; 352 | 353 | /** 354 | * @param data 数据 355 | * @param key 秘钥 356 | * @param algorithm 采用何种DES算法 357 | * @param transformation 转变 358 | * @param isEncrypt 是否加密 359 | * @return 密文或者明文,适用于DES,3DES,AES 360 | */ 361 | public static byte[] DESTemplet(byte[] data, byte[] key, String algorithm, String transformation, boolean isEncrypt) { 362 | try { 363 | SecretKeySpec keySpec = new SecretKeySpec(key, algorithm); 364 | Cipher cipher = Cipher.getInstance(transformation); 365 | SecureRandom random = new SecureRandom(); 366 | cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, keySpec, random); 367 | return cipher.doFinal(data); 368 | } catch (Throwable e) { 369 | e.printStackTrace(); 370 | } 371 | return null; 372 | } 373 | 374 | /** 375 | * DES加密后转为Base64编码 376 | * 377 | * @param data 明文 378 | * @param key 8字节秘钥 379 | * @return Base64密文 380 | */ 381 | public static byte[] encryptDES2Base64(byte[] data, byte[] key) { 382 | return EncodeUtils.base64Encode(encryptDES(data, key)); 383 | } 384 | 385 | /** 386 | * DES加密后转为16进制 387 | * 388 | * @param data 明文 389 | * @param key 8字节秘钥 390 | * @return 16进制密文 391 | */ 392 | public static String encryptDES2HexString(byte[] data, byte[] key) { 393 | return bytes2HexString(encryptDES(data, key)); 394 | } 395 | 396 | /** 397 | * DES加密 398 | * 399 | * @param data 明文 400 | * @param key 8字节秘钥 401 | * @return 密文 402 | */ 403 | public static byte[] encryptDES(byte[] data, byte[] key) { 404 | return DESTemplet(data, key, DES_Algorithm, DES_Transformation, true); 405 | } 406 | 407 | /** 408 | * DES解密Base64编码密文 409 | * 410 | * @param data Base64编码密文 411 | * @param key 8字节秘钥 412 | * @return 明文 413 | */ 414 | public static byte[] decryptBase64DES(byte[] data, byte[] key) { 415 | return decryptDES(EncodeUtils.base64Decode(data), key); 416 | } 417 | 418 | /** 419 | * DES解密16进制密文 420 | * 421 | * @param data 16进制密文 422 | * @param key 8字节秘钥 423 | * @return 明文 424 | */ 425 | public static byte[] decryptHexStringDES(String data, byte[] key) { 426 | return decryptDES(hexString2Bytes(data), key); 427 | } 428 | 429 | /** 430 | * DES解密 431 | * 432 | * @param data 密文 433 | * @param key 8字节秘钥 434 | * @return 明文 435 | */ 436 | public static byte[] decryptDES(byte[] data, byte[] key) { 437 | return DESTemplet(data, key, DES_Algorithm, DES_Transformation, false); 438 | } 439 | 440 | /************************ 3DES加密相关 ***********************/ 441 | /** 442 | * 3DES转变 443 | *

法算法名称/加密模式/填充方式

444 | *

加密模式有:电子密码本模式ECB、加密块链模式CBC、加密反馈模式CFB、输出反馈模式OFB

445 | *

填充方式有:NoPadding、ZerosPadding、PKCS5Padding

446 | */ 447 | public static String TripleDES_Transformation = "DESede/ECB/NoPadding"; 448 | private static final String TripleDES_Algorithm = "DESede"; 449 | 450 | 451 | /** 452 | * 3DES加密后转为Base64编码 453 | * 454 | * @param data 明文 455 | * @param key 24字节秘钥 456 | * @return Base64密文 457 | */ 458 | public static byte[] encrypt3DES2Base64(byte[] data, byte[] key) { 459 | return EncodeUtils.base64Encode(encrypt3DES(data, key)); 460 | } 461 | 462 | /** 463 | * 3DES加密后转为16进制 464 | * 465 | * @param data 明文 466 | * @param key 24字节秘钥 467 | * @return 16进制密文 468 | */ 469 | public static String encrypt3DES2HexString(byte[] data, byte[] key) { 470 | return bytes2HexString(encrypt3DES(data, key)); 471 | } 472 | 473 | /** 474 | * 3DES加密 475 | * 476 | * @param data 明文 477 | * @param key 24字节密钥 478 | * @return 密文 479 | */ 480 | public static byte[] encrypt3DES(byte[] data, byte[] key) { 481 | return DESTemplet(data, key, TripleDES_Algorithm, TripleDES_Transformation, true); 482 | } 483 | 484 | /** 485 | * 3DES解密Base64编码密文 486 | * 487 | * @param data Base64编码密文 488 | * @param key 24字节秘钥 489 | * @return 明文 490 | */ 491 | public static byte[] decryptBase64_3DES(byte[] data, byte[] key) { 492 | return decrypt3DES(EncodeUtils.base64Decode(data), key); 493 | } 494 | 495 | /** 496 | * 3DES解密16进制密文 497 | * 498 | * @param data 16进制密文 499 | * @param key 24字节秘钥 500 | * @return 明文 501 | */ 502 | public static byte[] decryptHexString3DES(String data, byte[] key) { 503 | return decrypt3DES(hexString2Bytes(data), key); 504 | } 505 | 506 | /** 507 | * 3DES解密 508 | * 509 | * @param data 密文 510 | * @param key 24字节密钥 511 | * @return 明文 512 | */ 513 | public static byte[] decrypt3DES(byte[] data, byte[] key) { 514 | return DESTemplet(data, key, TripleDES_Algorithm, TripleDES_Transformation, false); 515 | } 516 | 517 | /************************ AES加密相关 ***********************/ 518 | /** 519 | * AES转变 520 | *

法算法名称/加密模式/填充方式

521 | *

加密模式有:电子密码本模式ECB、加密块链模式CBC、加密反馈模式CFB、输出反馈模式OFB

522 | *

填充方式有:NoPadding、ZerosPadding、PKCS5Padding

523 | */ 524 | public static String AES_Transformation = "AES/ECB/NoPadding"; 525 | private static final String AES_Algorithm = "AES"; 526 | 527 | 528 | /** 529 | * AES加密后转为Base64编码 530 | * 531 | * @param data 明文 532 | * @param key 16、24、32字节秘钥 533 | * @return Base64密文 534 | */ 535 | public static byte[] encryptAES2Base64(byte[] data, byte[] key) { 536 | return EncodeUtils.base64Encode(encryptAES(data, key)); 537 | } 538 | 539 | /** 540 | * AES加密后转为16进制 541 | * 542 | * @param data 明文 543 | * @param key 16、24、32字节秘钥 544 | * @return 16进制密文 545 | */ 546 | public static String encryptAES2HexString(byte[] data, byte[] key) { 547 | return bytes2HexString(encryptAES(data, key)); 548 | } 549 | 550 | /** 551 | * AES加密 552 | * 553 | * @param data 明文 554 | * @param key 16、24、32字节秘钥 555 | * @return 密文 556 | */ 557 | public static byte[] encryptAES(byte[] data, byte[] key) { 558 | return DESTemplet(data, key, AES_Algorithm, AES_Transformation, true); 559 | } 560 | 561 | /** 562 | * AES解密Base64编码密文 563 | * 564 | * @param data Base64编码密文 565 | * @param key 16、24、32字节秘钥 566 | * @return 明文 567 | */ 568 | public static byte[] decryptBase64AES(byte[] data, byte[] key) { 569 | return decryptAES(EncodeUtils.base64Decode(data), key); 570 | } 571 | 572 | /** 573 | * AES解密16进制密文 574 | * 575 | * @param data 16进制密文 576 | * @param key 16、24、32字节秘钥 577 | * @return 明文 578 | */ 579 | public static byte[] decryptHexStringAES(String data, byte[] key) { 580 | return decryptAES(hexString2Bytes(data), key); 581 | } 582 | 583 | /** 584 | * AES解密 585 | * 586 | * @param data 密文 587 | * @param key 16、24、32字节秘钥 588 | * @return 明文 589 | */ 590 | public static byte[] decryptAES(byte[] data, byte[] key) { 591 | return DESTemplet(data, key, AES_Algorithm, AES_Transformation, false); 592 | } 593 | } --------------------------------------------------------------------------------