├── .idea ├── .name ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── modules.xml ├── runConfigurations.xml ├── compiler.xml ├── gradle.xml └── misc.xml ├── README.md ├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ └── layout │ │ │ │ └── activity_main.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── alenbeyond │ │ │ │ └── androidutils │ │ │ │ ├── MainActivity.java │ │ │ │ └── utils │ │ │ │ ├── OSUtils.java │ │ │ │ ├── StreamUtils.java │ │ │ │ ├── encrypt │ │ │ │ ├── MD5.java │ │ │ │ ├── DES.java │ │ │ │ └── Base64.java │ │ │ │ ├── SDCardUtils.java │ │ │ │ ├── AppInfoUtil.java │ │ │ │ ├── IOUtils.java │ │ │ │ ├── DensityUtil.java │ │ │ │ ├── InputMethodUtils.java │ │ │ │ ├── ByteUtils.java │ │ │ │ ├── WebViewManager.java │ │ │ │ ├── WindowUtils.java │ │ │ │ ├── TimeUtils.java │ │ │ │ ├── ShortCutUtils.java │ │ │ │ ├── SensorsDataUtils.java │ │ │ │ ├── ResourceUtils.java │ │ │ │ ├── PhoneUtil.java │ │ │ │ ├── ToastUtil.java │ │ │ │ ├── RegexUtils.java │ │ │ │ ├── RandomUtils.java │ │ │ │ ├── RegularExpression.java │ │ │ │ ├── AnimationUtils.java │ │ │ │ ├── DeviceStatusUtils.java │ │ │ │ ├── ZipUtil.java │ │ │ │ ├── DateUtil.java │ │ │ │ ├── BadgeUtil.java │ │ │ │ ├── ArrayUtils.java │ │ │ │ ├── ReflectUtils.java │ │ │ │ └── AppUtils.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── alenbeyond │ │ │ └── androidutils │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── alenbeyond │ │ └── androidutils │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── gradle.properties ├── gradlew.bat └── gradlew /.idea/.name: -------------------------------------------------------------------------------- 1 | AndroidUtils -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 收集的安卓工具类 2 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AndroidUtils 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GF-Allen/AndroidUtils/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GF-Allen/AndroidUtils/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GF-Allen/AndroidUtils/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GF-Allen/AndroidUtils/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GF-Allen/AndroidUtils/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GF-Allen/AndroidUtils/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/test/java/com/alenbeyond/androidutils/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | public class MainActivity extends AppCompatActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_main); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/alenbeyond/androidutils/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils; 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 | } -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/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 D:\Dev\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 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "24.0.0" 6 | 7 | defaultConfig { 8 | applicationId "com.alenbeyond.androidutils" 9 | minSdkVersion 15 10 | targetSdkVersion 24 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:24.0.0' 26 | } 27 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/OSUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.os.Build; 4 | import java.io.File; 5 | 6 | /** 7 | * Android系统工具 8 | */ 9 | public class OSUtils { 10 | /** 11 | * 根据/system/bin/或/system/xbin目录下是否存在su文件判断是否已ROOT 12 | * 13 | * @return true:已ROOT 14 | */ 15 | public static boolean isRoot() { 16 | try { 17 | return new File("/system/bin/su").exists() || new File("/system/xbin/su").exists(); 18 | } catch (Exception e) { 19 | return false; 20 | } 21 | } 22 | 23 | /** 24 | * 判断当前系统是否是Android4.0 25 | * 26 | * @return 0:是;小于0:小于4.0;大于0:大于4.0 27 | */ 28 | public static int isAPI14() { 29 | return Build.VERSION.SDK_INT - 14; 30 | } 31 | } -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/StreamUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * 流转换成字符串 8 | */ 9 | public class StreamUtils { 10 | 11 | /** 12 | * @param inputStream inputStream 13 | * @return 字符串转换之后的 14 | */ 15 | public static String streamToString(InputStream inputStream) { 16 | try { 17 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 18 | 19 | byte[] buffer = new byte[1024]; 20 | int len = 0; 21 | while ((len = inputStream.read(buffer)) != -1) { 22 | out.write(buffer, 0, len); 23 | out.flush(); 24 | } 25 | 26 | String result = out.toString(); 27 | out.close(); 28 | inputStream.close(); 29 | return result; 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | return ""; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/encrypt/MD5.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils.encrypt; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.InputStream; 5 | import java.security.MessageDigest; 6 | 7 | import android.text.TextUtils; 8 | 9 | public class MD5 { 10 | private static final char HEX_DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 11 | 'A', 'B', 'C', 'D', 'E', 'F' }; 12 | 13 | public static void main(String[] args) { 14 | System.out.println(md5sum("/init.rc")); 15 | } 16 | 17 | public static String toHexString(byte[] b) { 18 | StringBuilder sb = new StringBuilder(b.length * 2); 19 | for (int i = 0; i < b.length; i++) { 20 | sb.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]); 21 | sb.append(HEX_DIGITS[b[i] & 0x0f]); 22 | } 23 | return sb.toString(); 24 | } 25 | 26 | public static String md5sum(String filename) { 27 | InputStream fis; 28 | byte[] buffer = new byte[1024]; 29 | int numRead = 0; 30 | MessageDigest md5; 31 | try { 32 | fis = new FileInputStream(filename); 33 | md5 = MessageDigest.getInstance("MD5"); 34 | while ((numRead = fis.read(buffer)) > 0) { 35 | md5.update(buffer, 0, numRead); 36 | } 37 | fis.close(); 38 | String md5Str = toHexString(md5.digest()); 39 | return TextUtils.isEmpty(md5Str) ? "" : md5Str; 40 | } catch (Exception e) { 41 | System.out.println("error"); 42 | return ""; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/SDCardUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.os.Environment; 4 | import java.io.File; 5 | 6 | /** 7 | * SD卡工具箱 8 | */ 9 | public class SDCardUtils { 10 | /** 11 | * 获取SD卡的状态 12 | */ 13 | public static String getState() { 14 | return Environment.getExternalStorageState(); 15 | } 16 | 17 | 18 | /** 19 | * SD卡是否可用 20 | * 21 | * @return 只有当SD卡已经安装并且准备好了才返回true 22 | */ 23 | public static boolean isAvailable() { 24 | return getState().equals(Environment.MEDIA_MOUNTED); 25 | } 26 | 27 | 28 | /** 29 | * 获取SD卡的根目录 30 | * 31 | * @return null:不存在SD卡 32 | */ 33 | public static File getRootDirectory() { 34 | return isAvailable() ? Environment.getExternalStorageDirectory() : null; 35 | } 36 | 37 | 38 | /** 39 | * 获取SD卡的根路径 40 | * 41 | * @return null:不存在SD卡 42 | */ 43 | public static String getRootPath() { 44 | File rootDirectory = getRootDirectory(); 45 | return rootDirectory != null ? rootDirectory.getPath() : null; 46 | } 47 | /** 48 | *获取sd卡路径 49 | * @return Stringpath 50 | */ 51 | public static String getSDPath(){ 52 | 53 | File sdDir = null; 54 | boolean sdCardExist = Environment.getExternalStorageState() 55 | .equals(Environment.MEDIA_MOUNTED); //判断sd卡是否存在 56 | if (sdCardExist) 57 | { 58 | sdDir = Environment.getExternalStorageDirectory();//获取跟目录 59 | } 60 | return sdDir.toString(); 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/AppInfoUtil.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.content.pm.ResolveInfo; 7 | 8 | public class AppInfoUtil { 9 | 10 | public static String getLauncherClassName(Context context) { 11 | PackageManager packageManager = context.getPackageManager(); 12 | Intent intent = new Intent(Intent.ACTION_MAIN); 13 | intent.setPackage(context.getPackageName()); 14 | intent.addCategory(Intent.CATEGORY_LAUNCHER); 15 | ResolveInfo info = packageManager 16 | .resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); 17 | if (info == null) { 18 | info = packageManager.resolveActivity(intent, 0); 19 | } 20 | return info.activityInfo.name; 21 | } 22 | 23 | public static boolean checkPermissionGranted(Context context, String permission) { 24 | boolean result = true; 25 | int targetSdkVersion = 0; 26 | try { 27 | PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 28 | targetSdkVersion = info.applicationInfo.targetSdkVersion; 29 | } catch (PackageManager.NameNotFoundException e) { 30 | e.printStackTrace(); 31 | } 32 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 33 | if (targetSdkVersion >= Build.VERSION_CODES.M) { 34 | result = context.checkSelfPermission(permission) 35 | == PackageManager.PERMISSION_GRANTED; 36 | } else { 37 | result = PermissionChecker.checkSelfPermission(context, permission) 38 | == PermissionChecker.PERMISSION_GRANTED; 39 | } 40 | } 41 | return result; 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/IOUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.io.Closeable; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | 8 | /** 9 | * IO utils 10 | */ 11 | 12 | public class IOUtils { 13 | 14 | /** 15 | * 关闭资源对象 16 | * 17 | * @param closeable 18 | */ 19 | public static void close(Closeable closeable) { 20 | if (closeable != null) { 21 | try { 22 | closeable.close(); 23 | } catch (IOException e) { 24 | } 25 | } 26 | } 27 | 28 | 29 | /** 30 | * 保存文本 31 | * 32 | * @param fileName 文件名字 33 | * @param content 内容 34 | * @param append 是否累加 35 | * @return 是否成功 36 | */ 37 | public static boolean saveTextValue(String fileName, String content, boolean append) { 38 | 39 | try { 40 | File textFile = new File(fileName); 41 | if (!append && textFile.exists()) textFile.delete(); 42 | 43 | FileOutputStream os = new FileOutputStream(textFile); 44 | os.write(content.getBytes("UTF-8")); 45 | os.close(); 46 | } catch (Exception ee) { 47 | return false; 48 | } 49 | 50 | return true; 51 | } 52 | 53 | 54 | /** 55 | * 删除目录下所有文件 56 | * 57 | * @param Path 路径 58 | */ 59 | public static void deleteAllFile(String Path) { 60 | 61 | // 删除目录下所有文件 62 | File path = new File(Path); 63 | File files[] = path.listFiles(); 64 | if (files != null) { 65 | for (File tfi : files) { 66 | if (tfi.isDirectory()) { 67 | System.out.println(tfi.getName()); 68 | } else { 69 | tfi.delete(); 70 | } 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/DensityUtil.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.graphics.Point; 7 | import android.os.Build; 8 | import android.util.DisplayMetrics; 9 | import android.view.Display; 10 | import android.view.WindowManager; 11 | 12 | /** 13 | * 设备密度工具类 14 | */ 15 | public class DensityUtil { 16 | 17 | private static int[] deviceWidthHeight = new int[2]; 18 | 19 | public static int[] getDeviceInfo(Context context) { 20 | if ((deviceWidthHeight[0] == 0) && (deviceWidthHeight[1] == 0)) { 21 | DisplayMetrics metrics = new DisplayMetrics(); 22 | ((Activity) context).getWindowManager().getDefaultDisplay() 23 | .getMetrics(metrics); 24 | 25 | deviceWidthHeight[0] = metrics.widthPixels; 26 | deviceWidthHeight[1] = metrics.heightPixels; 27 | } 28 | return deviceWidthHeight; 29 | } 30 | 31 | /** 32 | * @param context 上下文 33 | * @param dpValue dp数值 34 | * @return dp to px 35 | */ 36 | public static int dip2px(Context context, float dpValue) { 37 | final float scale = context.getResources().getDisplayMetrics().density; 38 | return (int) (dpValue * scale + 0.5f); 39 | 40 | } 41 | 42 | /** 43 | * @param context 上下文 44 | * @param pxValue px的数值 45 | * @return px to dp 46 | */ 47 | public static int px2dip(Context context, float pxValue) { 48 | final float scale = context.getResources().getDisplayMetrics().density; 49 | return (int) (pxValue / scale + 0.5f); 50 | } 51 | 52 | /** 53 | * 获取屏幕尺寸 54 | */ 55 | @SuppressWarnings("deprecation") 56 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 57 | public static Point getScreenSize(Context context) { 58 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 59 | Display display = windowManager.getDefaultDisplay(); 60 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) { 61 | return new Point(display.getWidth(), display.getHeight()); 62 | } else { 63 | Point point = new Point(); 64 | display.getSize(point); 65 | return point; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/InputMethodUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.WindowManager; 6 | import android.view.inputmethod.InputMethodManager; 7 | import android.widget.EditText; 8 | 9 | public class InputMethodUtils { 10 | /** 11 | * 为给定的编辑器开启软键盘 12 | * 13 | * @param editText 给定的编辑器 14 | */ 15 | public static void openSoftKeyboard(Context context, EditText editText) { 16 | editText.requestFocus(); 17 | InputMethodManager inputMethodManager 18 | = (InputMethodManager) context.getSystemService( 19 | Context.INPUT_METHOD_SERVICE); 20 | inputMethodManager.showSoftInput(editText, 21 | InputMethodManager.SHOW_IMPLICIT); 22 | ViewUtils.setEditTextSelectionToEnd(editText); 23 | } 24 | 25 | 26 | /** 27 | * 关闭软键盘 28 | */ 29 | public static void closeSoftKeyboard(Activity activity) { 30 | InputMethodManager inputMethodManager 31 | = (InputMethodManager) activity.getSystemService( 32 | Context.INPUT_METHOD_SERVICE); 33 | //如果软键盘已经开启 34 | if (inputMethodManager.isActive()) { 35 | inputMethodManager.hideSoftInputFromWindow( 36 | activity.getCurrentFocus().getWindowToken(), 37 | InputMethodManager.HIDE_NOT_ALWAYS); 38 | } 39 | } 40 | 41 | 42 | /** 43 | * 切换软键盘的状态 44 | */ 45 | public static void toggleSoftKeyboardState(Context context) { 46 | ((InputMethodManager) context.getSystemService( 47 | Context.INPUT_METHOD_SERVICE)).toggleSoftInput( 48 | InputMethodManager.SHOW_IMPLICIT, 49 | InputMethodManager.HIDE_NOT_ALWAYS); 50 | } 51 | 52 | 53 | /** 54 | * 判断隐藏软键盘是否弹出,弹出就隐藏 55 | * @param mActivity 56 | * @return 57 | */ 58 | public boolean keyBoxIsShow(Activity mActivity) { 59 | if (mActivity.getWindow().getAttributes().softInputMode == WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { 60 | //隐藏软键盘 61 | mActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 62 | return true; 63 | } 64 | else { 65 | return false; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/ByteUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | /** 4 | *

字节工具类,提供一些有关字节的便捷方法

5 | * 6 | *
    (01)、位移加密:static void byteJiaMi(byte[] bytes) 7 | *
    (02)、从bytes上截取一段:static byte[] cutOut(byte[] bytes, int off, int length) 8 | */ 9 | public class ByteUtils { 10 | /** 11 | * (01)、位移加密 12 | * @param bytes 13 | */ 14 | public static void byteJiaMi(byte[] bytes){ 15 | for (int w = 0; w < bytes.length; w++){ 16 | int a = bytes[w]; 17 | a = ~a; 18 | bytes[w] = (byte)a; 19 | } 20 | } 21 | 22 | /** 23 | * (02)、从bytes上截取一段 24 | * @param bytes 母体 25 | * @param off 起始 26 | * @param length 个数 27 | * @return byte[] 28 | */ 29 | public static byte[] cutOut(byte[] bytes, int off, int length){ 30 | byte[] bytess = new byte[length]; 31 | System.arraycopy(bytes, off, bytess, 0, length); 32 | return bytess; 33 | } 34 | 35 | /** 36 | * 将字节转换为二进制字符串 37 | * @param bytes 字节数组 38 | * @return 二进制字符串 39 | */ 40 | public static String byteToBit(byte... bytes){ 41 | StringBuffer sb = new StringBuffer(); 42 | int z, len; 43 | String str; 44 | for(int w = 0; w < bytes.length ; w++){ 45 | z = bytes[w]; 46 | z |= 256; 47 | str = Integer.toBinaryString(z); 48 | len = str.length(); 49 | sb.append(str.substring(len-8, len)); 50 | } 51 | return sb.toString(); 52 | } 53 | 54 | 55 | /** 56 | * 字节数组转换成16进制字符串 57 | * @param raw 58 | * @return 59 | */ 60 | public static String getHex(byte [] raw ) { 61 | String HEXES = "0123456789ABCDEF"; 62 | if ( raw == null ) { 63 | return null; 64 | } 65 | final StringBuilder hex = new StringBuilder( 2 * raw.length ); 66 | for ( final byte b : raw ) { 67 | hex.append(HEXES.charAt((b & 0xF0) >> 4)) 68 | .append(HEXES.charAt((b & 0x0F))); 69 | } 70 | return hex.toString(); 71 | } 72 | 73 | /** 74 | * 将一个short转换成字节数组 75 | * @param sh short 76 | * @return 字节数组 77 | */ 78 | public static byte[] valueOf(short sh){ 79 | byte[] shortBuf = new byte[2]; 80 | for(int i=0;i<2;i++) { 81 | int offset = (shortBuf.length - 1 -i)*8; 82 | shortBuf[i] = (byte)((sh>>>offset)&0xff); 83 | } 84 | return shortBuf; 85 | } 86 | 87 | /** 88 | * 将一个int转换成字节数组 89 | * @param in int 90 | * @return 字节数组 91 | */ 92 | public static byte[] valueOf(int in){ 93 | byte[] b = new byte[4]; 94 | for (int i = 0; i < 4; i++) { 95 | int offset = (b.length - 1 - i) * 8; 96 | b[i] = (byte) ((in >>> offset) & 0xFF); 97 | } 98 | return b; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/WebViewManager.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.webkit.WebSettings; 5 | import android.webkit.WebView; 6 | 7 | /** 8 | * WebView管理器,提供常用设置 9 | */ 10 | public class WebViewManager { 11 | private WebView webView; 12 | private WebSettings webSettings; 13 | 14 | public WebViewManager(WebView webView){ 15 | this.webView = webView; 16 | webSettings = webView.getSettings(); 17 | webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); 18 | } 19 | 20 | /** 21 | * 开启自适应功能 22 | */ 23 | public WebViewManager enableAdaptive(){ 24 | webSettings.setUseWideViewPort(true); 25 | webSettings.setLoadWithOverviewMode(true); 26 | return this; 27 | } 28 | 29 | /** 30 | * 禁用自适应功能 31 | */ 32 | public WebViewManager disableAdaptive(){ 33 | webSettings.setUseWideViewPort(true); 34 | webSettings.setLoadWithOverviewMode(true); 35 | return this; 36 | } 37 | 38 | /** 39 | * 开启缩放功能 40 | */ 41 | public WebViewManager enableZoom(){ 42 | webSettings.setSupportZoom(true); 43 | webSettings.setUseWideViewPort(true); 44 | webSettings.setBuiltInZoomControls(true); 45 | return this; 46 | } 47 | 48 | /** 49 | * 禁用缩放功能 50 | */ 51 | public WebViewManager disableZoom(){ 52 | webSettings.setSupportZoom(false); 53 | webSettings.setUseWideViewPort(false); 54 | webSettings.setBuiltInZoomControls(false); 55 | return this; 56 | } 57 | 58 | /** 59 | * 开启JavaScript 60 | */ 61 | @SuppressLint("SetJavaScriptEnabled") 62 | public WebViewManager enableJavaScript(){ 63 | webSettings.setJavaScriptEnabled(true); 64 | return this; 65 | } 66 | 67 | /** 68 | * 禁用JavaScript 69 | */ 70 | public WebViewManager disableJavaScript(){ 71 | webSettings.setJavaScriptEnabled(false); 72 | return this; 73 | } 74 | 75 | /** 76 | * 开启JavaScript自动弹窗 77 | */ 78 | public WebViewManager enableJavaScriptOpenWindowsAutomatically(){ 79 | webSettings.setJavaScriptCanOpenWindowsAutomatically(true); 80 | return this; 81 | } 82 | 83 | /** 84 | * 禁用JavaScript自动弹窗 85 | */ 86 | public WebViewManager disableJavaScriptOpenWindowsAutomatically(){ 87 | webSettings.setJavaScriptCanOpenWindowsAutomatically(false); 88 | return this; 89 | } 90 | 91 | /** 92 | * 返回 93 | * @return true:已经返回,false:到头了没法返回了 94 | */ 95 | public boolean goBack(){ 96 | if(webView.canGoBack()){ 97 | webView.goBack(); 98 | return true; 99 | }else{ 100 | return false; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/WindowUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.content.res.Configuration; 7 | import android.view.Surface; 8 | import android.view.Window; 9 | import android.view.WindowManager; 10 | 11 | /** 12 | * 窗口工具箱 13 | * 14 | */ 15 | public final class WindowUtils { 16 | 17 | /** 18 | * Don't let anyone instantiate this class. 19 | */ 20 | private WindowUtils() { 21 | throw new Error("Do not need instantiate!"); 22 | } 23 | 24 | /** 25 | * 获取当前窗口的旋转角度 26 | * 27 | * @param activity activity 28 | * @return int 29 | */ 30 | public static int getDisplayRotation(Activity activity) { 31 | switch (activity.getWindowManager().getDefaultDisplay().getRotation()) { 32 | case Surface.ROTATION_0: 33 | return 0; 34 | case Surface.ROTATION_90: 35 | return 90; 36 | case Surface.ROTATION_180: 37 | return 180; 38 | case Surface.ROTATION_270: 39 | return 270; 40 | default: 41 | return 0; 42 | } 43 | } 44 | 45 | /** 46 | * 当前是否是横屏 47 | * 48 | * @param context context 49 | * @return boolean 50 | */ 51 | public static final boolean isLandscape(Context context) { 52 | return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; 53 | } 54 | 55 | /** 56 | * 当前是否是竖屏 57 | * 58 | * @param context context 59 | * @return boolean 60 | */ 61 | public static final boolean isPortrait(Context context) { 62 | return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; 63 | } 64 | /** 65 | * 调整窗口的透明度 1.0f,0.5f 变暗 66 | * @param from from>=0&&from<=1.0f 67 | * @param to to>=0&&to<=1.0f 68 | * @param context 当前的activity 69 | */ 70 | public static void dimBackground(final float from, final float to, Activity context) { 71 | final Window window = context.getWindow(); 72 | ValueAnimator valueAnimator = ValueAnimator.ofFloat(from, to); 73 | valueAnimator.setDuration(500); 74 | valueAnimator.addUpdateListener( 75 | new ValueAnimator.AnimatorUpdateListener() { 76 | @Override 77 | public void onAnimationUpdate(ValueAnimator animation) { 78 | WindowManager.LayoutParams params 79 | = window.getAttributes(); 80 | params.alpha = (Float) animation.getAnimatedValue(); 81 | window.setAttributes(params); 82 | } 83 | }); 84 | valueAnimator.start(); 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/TimeUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import java.util.Date; 7 | import java.util.Locale; 8 | 9 | /** 10 | * Created by alenbeyond on 2016/7/12. 11 | */ 12 | public class TimeUtils { 13 | /** 14 | * 格式化yyyy-MM-dd时间成秒 15 | */ 16 | public static String formatTimeMillis(String date) { 17 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); 18 | try { 19 | return sdf.parse(date).getTime() / 1000 + ""; 20 | } catch (ParseException e) { 21 | e.printStackTrace(); 22 | } 23 | return ""; 24 | } 25 | 26 | /** 27 | * 格式化yyyy-MM-dd时间成毫秒 28 | */ 29 | public static long formatTimeMillisl(String date) { 30 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); 31 | try { 32 | return sdf.parse(date).getTime(); 33 | } catch (ParseException e) { 34 | e.printStackTrace(); 35 | } 36 | return 0; 37 | } 38 | 39 | /** 40 | * 格式化yyyy-MM-dd HH:mm:ss时间成毫秒 41 | */ 42 | public static long getTimeMillislByYMDHMS(String date) { 43 | try { 44 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA); 45 | return sdf.parse(date).getTime(); 46 | } catch (Exception e) { 47 | e.printStackTrace(); 48 | return 0; 49 | } 50 | } 51 | 52 | /** 53 | * 传入年月日,返回毫秒数 54 | */ 55 | public static long getTimeMillis(int year, int month, int day) { 56 | Calendar calendar = Calendar.getInstance(); 57 | calendar.set(Calendar.YEAR, year); 58 | calendar.set(Calendar.MONTH, month); 59 | calendar.set(Calendar.DAY_OF_MONTH, day); 60 | calendar.set(Calendar.HOUR_OF_DAY, 0); 61 | calendar.set(Calendar.MINUTE, 0); 62 | calendar.set(Calendar.SECOND, 0); 63 | return calendar.getTimeInMillis(); 64 | } 65 | 66 | /** 67 | * 传入秒,返回yyyy-MM-dd 68 | */ 69 | public static String formatTime(String time) { 70 | Long milliseconds = Long.valueOf(time + "000"); 71 | return new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA).format(new Date(milliseconds)); 72 | } 73 | 74 | /** 75 | * 获取本月后n月的时间 76 | */ 77 | public static String getDate(int offset) { 78 | Calendar calendar = Calendar.getInstance(); 79 | calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + offset); 80 | return new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA).format(calendar.getTime()); 81 | } 82 | 83 | /** 84 | * 获取当月的天数 85 | */ 86 | public static int getCurrentMonthDay(Long time) { 87 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM"); 88 | String data = sdf.format(new Date(time)); 89 | int maxDate = new Date(Integer.valueOf(data.split("-")[0]), Integer.valueOf(data.split("-")[1]), 0).getDate(); 90 | return maxDate; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/ShortCutUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.ContentResolver; 6 | import android.content.Intent; 7 | import android.content.Intent.ShortcutIconResource; 8 | import android.database.Cursor; 9 | import android.net.Uri; 10 | 11 | import com.alenbeyond.androidutils.R; 12 | 13 | /** 14 | * 创建删除快捷图标 15 | * 16 | * 需要权限: com.android.launcher.permission.INSTALL_SHORTCUT com.android.launcher.permission.UNINSTALL_SHORTCUT 17 | */ 18 | public final class ShortCutUtils { 19 | 20 | /** 21 | * 检测是否存在快捷键 22 | * 23 | * @param activity Activity 24 | * @return 是否存在桌面图标 25 | */ 26 | public static boolean hasShortcut(Activity activity) { 27 | boolean isInstallShortcut = false; 28 | final ContentResolver cr = activity.getContentResolver(); 29 | final String AUTHORITY = "com.android.launcher.settings"; 30 | final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY 31 | + "/favorites?notify=true"); 32 | Cursor c = cr.query(CONTENT_URI, 33 | new String[]{"title", "iconResource"}, "title=?", 34 | new String[]{activity.getString(R.string.app_name).trim()}, 35 | null); 36 | if (c != null && c.getCount() > 0) { 37 | isInstallShortcut = true; 38 | } 39 | return isInstallShortcut; 40 | } 41 | 42 | /** 43 | * 为程序创建桌面快捷方式 44 | * 45 | * @param activity Activity 46 | * @param res res 47 | */ 48 | public static void addShortcut(Activity activity, int res) { 49 | 50 | Intent shortcut = new Intent( 51 | "com.android.launcher.action.INSTALL_SHORTCUT"); 52 | // 快捷方式的名称 53 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, 54 | activity.getString(R.string.app_name)); 55 | shortcut.putExtra("duplicate", false); // 不允许重复创建 56 | Intent shortcutIntent = new Intent(Intent.ACTION_MAIN); 57 | shortcutIntent.setClassName(activity, activity.getClass().getName()); 58 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); 59 | // 快捷方式的图标 60 | ShortcutIconResource iconRes = ShortcutIconResource.fromContext( 61 | activity, res); 62 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes); 63 | 64 | activity.sendBroadcast(shortcut); 65 | } 66 | 67 | /** 68 | * 删除程序的快捷方式 69 | * 70 | * @param activity Activity 71 | */ 72 | public static void delShortcut(Activity activity) { 73 | 74 | Intent shortcut = new Intent( 75 | "com.android.launcher.action.UNINSTALL_SHORTCUT"); 76 | // 快捷方式的名称 77 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, 78 | activity.getString(R.string.app_name)); 79 | String appClass = activity.getPackageName() + "." 80 | + activity.getLocalClassName(); 81 | ComponentName comp = new ComponentName(activity.getPackageName(), 82 | appClass); 83 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent( 84 | Intent.ACTION_MAIN).setComponent(comp)); 85 | activity.sendBroadcast(shortcut); 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/encrypt/DES.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils.encrypt; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.SecretKey; 5 | import javax.crypto.SecretKeyFactory; 6 | import javax.crypto.spec.DESKeySpec; 7 | import javax.crypto.spec.IvParameterSpec; 8 | 9 | /** 10 | * 将字符串进行DES加密解密 11 | * 12 | * @version 0.1 20091106 13 | * @author 史先方 14 | */ 15 | public class DES { 16 | 17 | /** 加密KEY */ 18 | private static final byte[] KEY = "7;9Ku7;:84VG*B78".getBytes(); 19 | /** 算法 */ 20 | private static final String ALGORITHM = "DES"; 21 | /** IV */ 22 | private static final byte[] IV = "sHjrydLq".getBytes(); 23 | /** TRANSFORMATION */ 24 | private static final String TRANSFORMATION = "DES/CBC/PKCS5Padding"; 25 | 26 | private int code = 0; 27 | 28 | public DES() { 29 | } 30 | 31 | /** 32 | * 构造函数 33 | * @param code 加密方式:0-“ISO-8859-1”编码,1-base64编码,其它-默认编码(utf-8) 34 | */ 35 | public DES(int code) { 36 | this.code = code; 37 | } 38 | 39 | /** 40 | * 将字符串进行DES加密 41 | * @param source 未加密源字符串 42 | * @return 加密后字符串 43 | */ 44 | public String encrypt(String source) { 45 | byte[] retByte = null; 46 | 47 | // Create SecretKey object 48 | DESKeySpec dks = null; 49 | try { 50 | dks = new DESKeySpec(KEY); 51 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); 52 | SecretKey securekey = keyFactory.generateSecret(dks); 53 | 54 | // Create IvParameterSpec object with initialization vector 55 | IvParameterSpec spec = new IvParameterSpec(IV); 56 | 57 | // Create Cipter object 58 | Cipher cipher = Cipher.getInstance(TRANSFORMATION); 59 | 60 | // Initialize Cipher object 61 | cipher.init(Cipher.ENCRYPT_MODE, securekey, spec); 62 | 63 | // Decrypting data 64 | retByte = cipher.doFinal(source.getBytes()); 65 | 66 | String result = ""; 67 | if (code == 0) { 68 | result = new String(retByte, "ISO-8859-1"); 69 | } else if (code == 1) { 70 | result = Base64.encodeToString(retByte,false); 71 | } else { 72 | result = new String(retByte); 73 | } 74 | return result; 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | } 78 | return null; 79 | 80 | } 81 | 82 | /** 83 | * 将DES加密的字符串解密 84 | * @param encrypted 加密过的字符串 85 | * @return 未加密源字符串 86 | */ 87 | public String decrypt(String encrypted) { 88 | byte[] retByte = null; 89 | 90 | // Create SecretKey object 91 | DESKeySpec dks = null; 92 | try { 93 | dks = new DESKeySpec(KEY); 94 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); 95 | SecretKey securekey = keyFactory.generateSecret(dks); 96 | 97 | // Create IvParameterSpec object with initialization vector 98 | IvParameterSpec spec = new IvParameterSpec(IV); 99 | 100 | // Create Cipter object 101 | Cipher cipher = Cipher.getInstance(TRANSFORMATION); 102 | 103 | // Initialize Cipher object 104 | cipher.init(Cipher.DECRYPT_MODE, securekey, spec); 105 | 106 | if (code == 0) { 107 | retByte = encrypted.getBytes("ISO-8859-1"); 108 | } else if (code == 1) { 109 | retByte = Base64.decode(encrypted); 110 | } else { 111 | retByte = encrypted.getBytes(); 112 | } 113 | 114 | // Decrypting data 115 | retByte = cipher.doFinal(retByte); 116 | return new String(retByte, "utf-8"); 117 | } catch (Exception e) { 118 | e.printStackTrace(); 119 | } 120 | return null; 121 | 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/SensorsDataUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.net.ConnectivityManager; 6 | import android.os.Build; 7 | import android.telephony.TelephonyManager; 8 | import android.text.TextUtils; 9 | 10 | import java.util.Locale; 11 | import java.util.UUID; 12 | 13 | /** 14 | * 传感器工具类 15 | */ 16 | public final class SensorsDataUtils { 17 | 18 | private static SharedPreferences getSharedPreferences(Context context) { 19 | final String sharedPrefsName = SHARED_PREF_EDITS_FILE; 20 | return context.getSharedPreferences(sharedPrefsName, Context.MODE_PRIVATE); 21 | } 22 | 23 | /** 24 | * 获取设备ID 25 | * 26 | * @param context 27 | * @return 28 | */ 29 | public static String getDeviceID(Context context) { 30 | final SharedPreferences preferences = getSharedPreferences(context); 31 | String storedDeviceID = preferences.getString(SHARED_PREF_DEVICE_ID_KEY, null); 32 | 33 | if (storedDeviceID == null) { 34 | storedDeviceID = UUID.randomUUID().toString(); 35 | final SharedPreferences.Editor editor = preferences.edit(); 36 | editor.putString(SHARED_PREF_DEVICE_ID_KEY, storedDeviceID); 37 | editor.apply(); 38 | } 39 | return storedDeviceID; 40 | } 41 | 42 | /** 43 | * 获取IMEI 44 | */ 45 | public static String getIMEI(Context context) { 46 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 47 | String imei = tm.getDeviceId(); 48 | if (!TextUtils.isEmpty(imei)) { 49 | return imei; 50 | } 51 | return ""; 52 | } 53 | 54 | /** 55 | * 判断是否为模拟器 56 | * 57 | * @return 58 | */ 59 | public static boolean isInEmulator() { 60 | if (!Build.HARDWARE.equals("goldfish")) { 61 | return false; 62 | } 63 | 64 | if (!Build.BRAND.startsWith("generic")) { 65 | return false; 66 | } 67 | 68 | if (!Build.DEVICE.startsWith("generic")) { 69 | return false; 70 | } 71 | 72 | if (!Build.PRODUCT.contains("sdk")) { 73 | return false; 74 | } 75 | 76 | if (!Build.MODEL.toLowerCase(Locale.US).contains("sdk")) { 77 | return false; 78 | } 79 | 80 | return true; 81 | } 82 | 83 | /** 84 | * 获取网络类型 85 | * 86 | * @param context 87 | * @return 88 | */ 89 | public static String networkType(Context context) { 90 | // Wifi 91 | ConnectivityManager manager = (ConnectivityManager) 92 | context.getSystemService(context.CONNECTIVITY_SERVICE); 93 | if (manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting()) { 94 | return "WIFI"; 95 | } 96 | 97 | // Mobile network 98 | TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context 99 | .TELEPHONY_SERVICE); 100 | 101 | int networkType = telephonyManager.getNetworkType(); 102 | switch (networkType) { 103 | case TelephonyManager.NETWORK_TYPE_GPRS: 104 | case TelephonyManager.NETWORK_TYPE_EDGE: 105 | case TelephonyManager.NETWORK_TYPE_CDMA: 106 | return "2G"; 107 | case TelephonyManager.NETWORK_TYPE_UMTS: 108 | case TelephonyManager.NETWORK_TYPE_EVDO_0: 109 | case TelephonyManager.NETWORK_TYPE_EVDO_A: 110 | case TelephonyManager.NETWORK_TYPE_HSDPA: 111 | case TelephonyManager.NETWORK_TYPE_HSUPA: 112 | case TelephonyManager.NETWORK_TYPE_HSPA: 113 | case TelephonyManager.NETWORK_TYPE_EVDO_B: 114 | case TelephonyManager.NETWORK_TYPE_EHRPD: 115 | case TelephonyManager.NETWORK_TYPE_HSPAP: 116 | return "3G"; 117 | case TelephonyManager.NETWORK_TYPE_LTE: 118 | return "4G"; 119 | } 120 | 121 | // disconnected to the internet 122 | return "NULL"; 123 | } 124 | 125 | private static final String SHARED_PREF_EDITS_FILE = "sensorsdata"; 126 | private static final String SHARED_PREF_DEVICE_ID_KEY = "sensorsdata.device.id"; 127 | 128 | private static final String LOGTAG = "SA.SensorsDataUtils"; 129 | } 130 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/ResourceUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import android.content.Context; 10 | 11 | /** 12 | * ResourceUtils 13 | * 14 | */ 15 | public class ResourceUtils { 16 | 17 | /** 18 | * get an asset using ACCESS_STREAMING mode. This provides access to files that have been bundled with an 19 | * application as assets -- that is, files placed in to the "assets" directory. 20 | * 21 | * @param context context 22 | * @param fileName The name of the asset to open. This name can be hierarchical. 23 | * @return geFileFromAssets 24 | */ 25 | public static String geFileFromAssets(Context context, String fileName) { 26 | if (context == null || StringUtils.isEmpty(fileName)) { 27 | return null; 28 | } 29 | 30 | StringBuilder s = new StringBuilder(""); 31 | try { 32 | InputStreamReader in = new InputStreamReader(context.getResources().getAssets().open(fileName)); 33 | BufferedReader br = new BufferedReader(in); 34 | String line; 35 | while ((line = br.readLine()) != null) { 36 | s.append(line); 37 | } 38 | return s.toString(); 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | return null; 42 | } 43 | } 44 | 45 | /** 46 | * get content from a raw resource. This can only be used with resources whose value is the name of an asset files 47 | * -- that is, it can be used to open drawable, sound, and raw resources; it will fail on string and color 48 | * resources. 49 | * 50 | * @param context context 51 | * @param resId The resource identifier to open, as generated by the appt tool. 52 | * @return geFileFromRaw 53 | */ 54 | public static String geFileFromRaw(Context context, int resId) { 55 | if (context == null) { 56 | return null; 57 | } 58 | 59 | StringBuilder s = new StringBuilder(); 60 | try { 61 | InputStreamReader in = new InputStreamReader(context.getResources().openRawResource(resId)); 62 | BufferedReader br = new BufferedReader(in); 63 | String line; 64 | while ((line = br.readLine()) != null) { 65 | s.append(line); 66 | } 67 | return s.toString(); 68 | } catch (IOException e) { 69 | e.printStackTrace(); 70 | return null; 71 | } 72 | } 73 | 74 | /** 75 | * 76 | * @param context 上下文 77 | * @param fileName 文件的名字 78 | * @return 返回资源下的文件 79 | */ 80 | public static List geFileToListFromAssets(Context context, String fileName) { 81 | if (context == null || StringUtils.isEmpty(fileName)) { 82 | return null; 83 | } 84 | 85 | List fileContent = new ArrayList(); 86 | try { 87 | InputStreamReader in = new InputStreamReader(context.getResources().getAssets().open(fileName)); 88 | BufferedReader br = new BufferedReader(in); 89 | String line; 90 | while ((line = br.readLine()) != null) { 91 | fileContent.add(line); 92 | } 93 | br.close(); 94 | return fileContent; 95 | } catch (IOException e) { 96 | e.printStackTrace(); 97 | return null; 98 | } 99 | } 100 | 101 | /** 102 | * 103 | * @param context 上下文 104 | * @param resId id 105 | * @return raw下的文件 106 | */ 107 | public static List geFileToListFromRaw(Context context, int resId) { 108 | if (context == null) { 109 | return null; 110 | } 111 | 112 | List fileContent = new ArrayList(); 113 | BufferedReader reader = null; 114 | try { 115 | InputStreamReader in = new InputStreamReader(context.getResources().openRawResource(resId)); 116 | reader = new BufferedReader(in); 117 | String line = null; 118 | while ((line = reader.readLine()) != null) { 119 | fileContent.add(line); 120 | } 121 | reader.close(); 122 | return fileContent; 123 | } catch (IOException e) { 124 | e.printStackTrace(); 125 | return null; 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/PhoneUtil.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.provider.ContactsContract; 9 | import android.provider.MediaStore; 10 | import android.telephony.TelephonyManager; 11 | import java.io.File; 12 | 13 | /** 14 | * 手机组件调用工具类 15 | * 16 | */ 17 | public final class PhoneUtil { 18 | private static long lastClickTime; 19 | 20 | /** 21 | * 调用系统发短信界面 22 | * 23 | * @param activity Activity 24 | * @param phoneNumber 手机号码 25 | * @param smsContent 短信内容 26 | */ 27 | public static void sendMessage(Context activity, String phoneNumber, String smsContent) { 28 | if (phoneNumber == null || phoneNumber.length() < 4) { 29 | return; 30 | } 31 | Uri uri = Uri.parse("smsto:" + phoneNumber); 32 | Intent it = new Intent(Intent.ACTION_SENDTO, uri); 33 | it.putExtra("sms_body", smsContent); 34 | it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 35 | activity.startActivity(it); 36 | } 37 | 38 | /** 39 | * 判断是否为连击 40 | * 41 | * @return boolean 42 | */ 43 | public static boolean isFastDoubleClick() { 44 | long time = System.currentTimeMillis(); 45 | long timeD = time - lastClickTime; 46 | if (0 < timeD && timeD < 500) { 47 | return true; 48 | } 49 | lastClickTime = time; 50 | return false; 51 | } 52 | 53 | /** 54 | * 获取手机型号 55 | * 56 | * @param context 上下文 57 | * @return String 58 | */ 59 | public static String getMobileModel(Context context) { 60 | try { 61 | String model = android.os.Build.MODEL; // 手机型号 62 | return model; 63 | } catch (Exception e) { 64 | return "未知"; 65 | } 66 | } 67 | 68 | /** 69 | * 获取手机品牌 70 | * 71 | * @param context 上下文 72 | * @return String 73 | */ 74 | public static String getMobileBrand(Context context) { 75 | try { 76 | String brand = android.os.Build.BRAND; // android系统版本号 77 | return brand; 78 | } catch (Exception e) { 79 | return "未知"; 80 | } 81 | } 82 | 83 | 84 | /** 85 | *拍照打开照相机! 86 | * @param requestcode 返回值 87 | * @param activity 上下文 88 | * @param fileName 生成的图片文件的路径 89 | */ 90 | public static void toTakePhoto(int requestcode, Activity activity, String fileName) { 91 | Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 92 | intent.putExtra("camerasensortype", 2);// 调用前置摄像头 93 | intent.putExtra("autofocus", true);// 自动对焦 94 | intent.putExtra("fullScreen", false);// 全屏 95 | intent.putExtra("showActionIcons", false); 96 | try {//创建一个当前任务id的文件然后里面存放任务的照片的和路径!这主文件的名字是用uuid到时候在用任务id去查路径! 97 | File file = new File(fileName); 98 | Uri uri = Uri.fromFile(file); 99 | intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); 100 | activity.startActivityForResult(intent, requestcode); 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | } 104 | } 105 | 106 | 107 | /** 108 | *打开相册 109 | * @param requestcode 响应码 110 | * @param activity 上下文 111 | */ 112 | public static void toTakePicture(int requestcode, Activity activity){ 113 | Intent intent = new Intent(Intent.ACTION_PICK, null); 114 | intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 115 | "image/*"); 116 | activity.startActivityForResult(intent, requestcode); 117 | } 118 | 119 | 120 | /** 121 | * 获取所有联系人的姓名和电话号码,需要READ_CONTACTS权限 122 | * @param context 上下文 123 | * @return Cursor。姓名:CommonDataKinds.Phone.DISPLAY_NAME;号码:CommonDataKinds.Phone.NUMBER 124 | */ 125 | public static Cursor getContactsNameAndNumber(Context context){ 126 | return context.getContentResolver().query( 127 | ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] { 128 | ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); 129 | } 130 | 131 | /** 132 | * 获取手机号码 133 | * @param context 上下文 134 | * @return 手机号码,手机号码不一定能获取到 135 | */ 136 | public static String getMobilePhoneNumber(Context context){ 137 | return ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number(); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/ToastUtil.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.widget.LinearLayout; 6 | import android.widget.TextView; 7 | import android.widget.Toast; 8 | 9 | public class ToastUtil { 10 | 11 | private Toast toast; 12 | private LinearLayout toastView; 13 | 14 | /** 15 | * 修改原布局的Toast 16 | */ 17 | public ToastUtil() { 18 | 19 | } 20 | 21 | /** 22 | * 完全自定义布局Toast 23 | * @param context 24 | * @param view 25 | */ 26 | public ToastUtil(Context context, View view,int duration){ 27 | toast=new Toast(context); 28 | toast.setView(view); 29 | toast.setDuration(duration); 30 | } 31 | 32 | /** 33 | * 向Toast中添加自定义view 34 | * @param view 35 | * @param postion 36 | * @return 37 | */ 38 | public ToastUtil addView(View view,int postion) { 39 | toastView = (LinearLayout) toast.getView(); 40 | toastView.addView(view, postion); 41 | 42 | return this; 43 | } 44 | 45 | /** 46 | * 设置Toast字体及背景颜色 47 | * @param messageColor 48 | * @param backgroundColor 49 | * @return 50 | */ 51 | public ToastUtil setToastColor(int messageColor, int backgroundColor) { 52 | View view = toast.getView(); 53 | if(view!=null){ 54 | TextView message=((TextView) view.findViewById(android.R.id.message)); 55 | message.setBackgroundColor(backgroundColor); 56 | message.setTextColor(messageColor); 57 | } 58 | return this; 59 | } 60 | 61 | /** 62 | * 设置Toast字体及背景 63 | * @param messageColor 64 | * @param background 65 | * @return 66 | */ 67 | public ToastUtil setToastBackground(int messageColor, int background) { 68 | View view = toast.getView(); 69 | if(view!=null){ 70 | TextView message=((TextView) view.findViewById(android.R.id.message)); 71 | message.setBackgroundResource(background); 72 | message.setTextColor(messageColor); 73 | } 74 | return this; 75 | } 76 | 77 | /** 78 | * 短时间显示Toast 79 | */ 80 | public ToastUtil Short(Context context, CharSequence message){ 81 | if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){ 82 | toast= Toast.makeText(context, message, Toast.LENGTH_SHORT); 83 | toastView=null; 84 | }else{ 85 | toast.setText(message); 86 | toast.setDuration(Toast.LENGTH_SHORT); 87 | } 88 | return this; 89 | } 90 | 91 | /** 92 | * 短时间显示Toast 93 | */ 94 | public ToastUtil Short(Context context, int message) { 95 | if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){ 96 | toast= Toast.makeText(context, message, Toast.LENGTH_SHORT); 97 | toastView=null; 98 | }else{ 99 | toast.setText(message); 100 | toast.setDuration(Toast.LENGTH_SHORT); 101 | } 102 | return this; 103 | } 104 | 105 | /** 106 | * 长时间显示Toast 107 | */ 108 | public ToastUtil Long(Context context, CharSequence message){ 109 | if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){ 110 | toast= Toast.makeText(context, message, Toast.LENGTH_LONG); 111 | toastView=null; 112 | }else{ 113 | toast.setText(message); 114 | toast.setDuration(Toast.LENGTH_LONG); 115 | } 116 | return this; 117 | } 118 | 119 | /** 120 | * 长时间显示Toast 121 | * 122 | * @param context 123 | * @param message 124 | */ 125 | public ToastUtil Long(Context context, int message) { 126 | if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){ 127 | toast= Toast.makeText(context, message, Toast.LENGTH_LONG); 128 | toastView=null; 129 | }else{ 130 | toast.setText(message); 131 | toast.setDuration(Toast.LENGTH_LONG); 132 | } 133 | return this; 134 | } 135 | 136 | /** 137 | * 自定义显示Toast时间 138 | * 139 | * @param context 140 | * @param message 141 | * @param duration 142 | */ 143 | public ToastUtil Indefinite(Context context, CharSequence message, int duration) { 144 | if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){ 145 | toast= Toast.makeText(context, message,duration); 146 | toastView=null; 147 | }else{ 148 | toast.setText(message); 149 | toast.setDuration(duration); 150 | } 151 | return this; 152 | } 153 | 154 | /** 155 | * 自定义显示Toast时间 156 | * 157 | * @param context 158 | * @param message 159 | * @param duration 160 | */ 161 | public ToastUtil Indefinite(Context context, int message, int duration) { 162 | if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){ 163 | toast= Toast.makeText(context, message,duration); 164 | toastView=null; 165 | }else{ 166 | toast.setText(message); 167 | toast.setDuration(duration); 168 | } 169 | return this; 170 | } 171 | 172 | /** 173 | * 显示Toast 174 | * @return 175 | */ 176 | public ToastUtil show (){ 177 | toast.show(); 178 | 179 | return this; 180 | } 181 | 182 | /** 183 | * 获取Toast 184 | * @return 185 | */ 186 | public Toast getToast(){ 187 | return toast; 188 | } 189 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/RegexUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | *

正则表达式工具类,提供一些常用的正则表达式

8 | */ 9 | public class RegexUtils { 10 | /** 11 | * 匹配全网IP的正则表达式 12 | */ 13 | public static final String IP_REGEX = "^((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))$"; 14 | 15 | /** 16 | * 匹配手机号码的正则表达式 17 | *
支持130——139、150——153、155——159、180、183、185、186、188、189号段 18 | */ 19 | public static final String PHONE_NUMBER_REGEX = "^1{1}(3{1}\\d{1}|5{1}[012356789]{1}|8{1}[035689]{1})\\d{8}$"; 20 | 21 | /** 22 | * 匹配邮箱的正则表达式 23 | *
"www."可省略不写 24 | */ 25 | public static final String EMAIL_REGEX = "^(www\\.)?\\w+@\\w+(\\.\\w+)+$"; 26 | 27 | /** 28 | * 匹配汉子的正则表达式,个数限制为一个或多个 29 | */ 30 | public static final String CHINESE_REGEX = "^[\u4e00-\u9f5a]+$"; 31 | 32 | /** 33 | * 匹配正整数的正则表达式,个数限制为一个或多个 34 | */ 35 | public static final String POSITIVE_INTEGER_REGEX = "^\\d+$"; 36 | 37 | /** 38 | * 匹配身份证号的正则表达式 39 | */ 40 | public static final String ID_CARD = "^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$"; 41 | 42 | /** 43 | * 匹配邮编的正则表达式 44 | */ 45 | public static final String ZIP_CODE = "^\\d{6}$"; 46 | 47 | /** 48 | * 匹配URL的正则表达式 49 | */ 50 | public static final String URL = "^(([hH][tT]{2}[pP][sS]?)|([fF][tT][pP]))\\:\\/\\/[wW]{3}\\.[\\w-]+\\.\\w{2,4}(\\/.*)?$"; 51 | 52 | /** 53 | * 匹配给定的字符串是否是一个邮箱账号,"www."可省略不写 54 | * 55 | * @param string 给定的字符串 56 | * @return true:是 57 | */ 58 | public static boolean isEmail(String string) { 59 | return string.matches(EMAIL_REGEX); 60 | } 61 | 62 | /** 63 | * 匹配给定的字符串是否是一个手机号码,支持130——139、150——153、155——159、180、183、185、186、188、189号段 64 | * 65 | * @param string 给定的字符串 66 | * @return true:是 67 | */ 68 | public static boolean isMobilePhoneNumber(String string) { 69 | return string.matches(PHONE_NUMBER_REGEX); 70 | } 71 | 72 | /** 73 | * 匹配给定的字符串是否是一个全网IP 74 | * 75 | * @param string 给定的字符串 76 | * @return true:是 77 | */ 78 | public static boolean isIp(String string) { 79 | return string.matches(IP_REGEX); 80 | } 81 | 82 | /** 83 | * 匹配给定的字符串是否全部由汉子组成 84 | * 85 | * @param string 给定的字符串 86 | * @return true:是 87 | */ 88 | public static boolean isChinese(String string) { 89 | return string.matches(CHINESE_REGEX); 90 | } 91 | 92 | /** 93 | * 验证给定的字符串是否全部由正整数组成 94 | * 95 | * @param string 给定的字符串 96 | * @return true:是 97 | */ 98 | public static boolean isPositiveInteger(String string) { 99 | return string.matches(POSITIVE_INTEGER_REGEX); 100 | } 101 | 102 | /** 103 | * 验证给定的字符串是否是身份证号 104 | *
105 | *
身份证15位编码规则:dddddd yymmdd xx p 106 | *
dddddd:6位地区编码 107 | *
yymmdd:出生年(两位年)月日,如:910215 108 | *
xx:顺序编码,系统产生,无法确定 109 | *
p:性别,奇数为男,偶数为女 110 | *
111 | *
112 | *
身份证18位编码规则:dddddd yyyymmdd xxx y 113 | *
dddddd:6位地区编码 114 | *
yyyymmdd:出生年(四位年)月日,如:19910215 115 | *
xxx:顺序编码,系统产生,无法确定,奇数为男,偶数为女 116 | *
y:校验码,该位数值可通过前17位计算获得 117 | *
前17位号码加权因子为 Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ] 118 | *
验证位 Y = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ] 119 | *
如果验证码恰好是10,为了保证身份证是十八位,那么第十八位将用X来代替 校验位计算公式:Y_P = mod( ∑(Ai×Wi),11 ) 120 | *
i为身份证号码1...17 位; Y_P为校验码Y所在校验码数组位置 121 | * 122 | * @param string 123 | * @return 124 | */ 125 | public static boolean isIdCard(String string) { 126 | return string.matches(ID_CARD); 127 | } 128 | 129 | /** 130 | * 验证给定的字符串是否是邮编 131 | * 132 | * @param string 133 | * @return 134 | */ 135 | public static boolean isZipCode(String string) { 136 | return string.matches(ZIP_CODE); 137 | } 138 | 139 | /** 140 | * 验证给定的字符串是否是URL,仅支持http、https、ftp 141 | * 142 | * @param string 143 | * @return 144 | */ 145 | public static boolean isURL(String string) { 146 | return string.matches(URL); 147 | } 148 | 149 | 150 | /** 151 | * 验证密码只能输入字母和数字的特殊字符,这个返回的是过滤之后的字符串 152 | */ 153 | public static String checkPasWord(String pro) { 154 | try { 155 | // 只允许字母、数字和汉字 156 | String regEx = "[^a-zA-Z0-9\u4E00-\u9FA5]"; 157 | Pattern p = Pattern.compile(regEx); 158 | Matcher m = p.matcher(pro); 159 | return m.replaceAll("").trim(); 160 | } catch (Exception e) { 161 | } 162 | return ""; 163 | } 164 | 165 | /** 166 | * 只能输入字母和汉字 这个返回的是过滤之后的字符串 167 | */ 168 | public static String checkInputPro(String pro) { 169 | try { 170 | String regEx = "[^a-zA-Z\u4E00-\u9FA5]"; 171 | Pattern p = Pattern.compile(regEx); 172 | Matcher m = p.matcher(pro); 173 | return m.replaceAll("").trim(); 174 | } catch (Exception e) { 175 | 176 | } 177 | return ""; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * 随机工具类 7 | */ 8 | public class RandomUtils { 9 | 10 | public static final String NUMBERS_AND_LETTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 11 | public static final String NUMBERS = "0123456789"; 12 | public static final String LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 13 | public static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 14 | public static final String LOWER_CASE_LETTERS = "abcdefghijklmnopqrstuvwxyz"; 15 | 16 | /** 17 | * 得到一个固定长度的随机字符串,大写,小写字母和数字 18 | * 19 | * @param length length 20 | * @return RandomUtils 21 | */ 22 | public static String getRandomNumbersAndLetters(int length) { 23 | return getRandom(NUMBERS_AND_LETTERS, length); 24 | } 25 | 26 | /** 27 | * 随机获取固定的数字字符串 28 | * 29 | * @param length length 30 | * @return RandomUtils 31 | */ 32 | public static String getRandomNumbers(int length) { 33 | return getRandom(NUMBERS, length); 34 | } 35 | 36 | /** 37 | * 得到一个固定长度的随机字符串,大写和小写字母 38 | * 39 | * @param length length 40 | * @return RandomUtils 41 | */ 42 | public static String getRandomLetters(int length) { 43 | return getRandom(LETTERS, length); 44 | } 45 | 46 | /** 47 | * 得到一个固定长度的随机字符串,大写字母 48 | * 49 | * @param length length 50 | */ 51 | public static String getRandomCapitalLetters(int length) { 52 | return getRandom(CAPITAL_LETTERS, length); 53 | } 54 | 55 | /** 56 | * 小写字母 57 | * 58 | * @param length length 59 | */ 60 | public static String getRandomLowerCaseLetters(int length) { 61 | return getRandom(LOWER_CASE_LETTERS, length); 62 | } 63 | 64 | /** 65 | * 给定的字符串中随机组合 66 | * 67 | * @param source source 68 | * @param length length 69 | */ 70 | public static String getRandom(String source, int length) { 71 | return StringUtils.isEmpty(source) ? null : getRandom(source.toCharArray(), length); 72 | } 73 | 74 | /** 75 | * 给定的字符数组 76 | * 77 | * @param sourceChar sourceChar 78 | * @param length length 79 | */ 80 | public static String getRandom(char[] sourceChar, int length) { 81 | if (sourceChar == null || sourceChar.length == 0 || length < 0) { 82 | return null; 83 | } 84 | 85 | StringBuilder str = new StringBuilder(length); 86 | Random random = new Random(); 87 | for (int i = 0; i < length; i++) { 88 | str.append(sourceChar[random.nextInt(sourceChar.length)]); 89 | } 90 | return str.toString(); 91 | } 92 | 93 | 94 | /** 95 | * @param max 接受的数值 96 | * @return 返回一个随机的数值 97 | */ 98 | public static int getRandom(int max) { 99 | 100 | return getRandom(0, max); 101 | } 102 | 103 | 104 | /** 105 | * @param min 最小 106 | * @param max 最大 107 | * @return 返回一个范围的数值 108 | */ 109 | public static int getRandom(int min, int max) { 110 | 111 | if (min > max) { 112 | return 0; 113 | } 114 | if (min == max) { 115 | return min; 116 | } 117 | return min + new Random().nextInt(max - min); 118 | } 119 | 120 | /** 121 | * 洗牌算法,随机排列指定的数组使用默认的随机性 122 | * 123 | * @param objArray 数组 124 | * @return 从新的数组 125 | */ 126 | public static boolean shuffle(Object[] objArray) { 127 | if (objArray == null) { 128 | return false; 129 | } 130 | 131 | return shuffle(objArray, getRandom(objArray.length)); 132 | } 133 | 134 | /** 135 | * 洗牌算法,随机排列指定的数组,洗多少个 136 | * 137 | * @param objArray 数组 138 | * @param shuffleCount 洗的个数 139 | * @return 是否成功 140 | */ 141 | public static boolean shuffle(Object[] objArray, int shuffleCount) { 142 | int length; 143 | if (objArray == null || shuffleCount < 0 || (length = objArray.length) < shuffleCount) { 144 | return false; 145 | } 146 | 147 | for (int i = 1; i <= shuffleCount; i++) { 148 | int random = getRandom(length - i); 149 | Object temp = objArray[length - i]; 150 | objArray[length - i] = objArray[random]; 151 | objArray[random] = temp; 152 | } 153 | return true; 154 | } 155 | 156 | /** 157 | * 洗牌算法,随机排列指定int数组使用默认的随机性来源 158 | * 159 | * @param intArray 数组 160 | * @return 洗牌之后 161 | */ 162 | public static int[] shuffle(int[] intArray) { 163 | if (intArray == null) { 164 | return null; 165 | } 166 | 167 | return shuffle(intArray, getRandom(intArray.length)); 168 | } 169 | 170 | /** 171 | * 洗牌算法,随机排列指定int数组 172 | * 173 | * @param intArray 数组 174 | * @param shuffleCount 范围 175 | * @return 新的数组 176 | */ 177 | public static int[] shuffle(int[] intArray, int shuffleCount) { 178 | int length; 179 | if (intArray == null || shuffleCount < 0 || (length = intArray.length) < shuffleCount) { 180 | return null; 181 | } 182 | 183 | int[] out = new int[shuffleCount]; 184 | for (int i = 1; i <= shuffleCount; i++) { 185 | int random = getRandom(length - i); 186 | out[i - 1] = intArray[random]; 187 | int temp = intArray[length - i]; 188 | intArray[length - i] = intArray[random]; 189 | intArray[random] = temp; 190 | } 191 | return out; 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Abstraction issuesJava 39 | 40 | 41 | Android Lint 42 | 43 | 44 | Assignment issuesGroovy 45 | 46 | 47 | Assignment issuesJava 48 | 49 | 50 | Bitwise operation issuesJava 51 | 52 | 53 | C/C++ 54 | 55 | 56 | Class structureJava 57 | 58 | 59 | Code style issuesJava 60 | 61 | 62 | Control FlowGroovy 63 | 64 | 65 | Control flow issuesJava 66 | 67 | 68 | Data flow analysisC/C++ 69 | 70 | 71 | GPath inspectionsGroovy 72 | 73 | 74 | General 75 | 76 | 77 | GeneralC/C++ 78 | 79 | 80 | GeneralJava 81 | 82 | 83 | Groovy 84 | 85 | 86 | HTML 87 | 88 | 89 | Initialization issuesJava 90 | 91 | 92 | Internationalization issues 93 | 94 | 95 | Internationalization issuesJava 96 | 97 | 98 | J2ME issuesJava 99 | 100 | 101 | JUnit issues 102 | 103 | 104 | JUnit issuesJava 105 | 106 | 107 | Java 108 | 109 | 110 | Java language level issuesJava 111 | 112 | 113 | Java language level migration aidsJava 114 | 115 | 116 | Javadoc issuesJava 117 | 118 | 119 | Logging issuesJava 120 | 121 | 122 | Memory issuesJava 123 | 124 | 125 | Naming ConventionsGroovy 126 | 127 | 128 | Naming conventionsJava 129 | 130 | 131 | Numeric issuesJava 132 | 133 | 134 | Performance issuesJava 135 | 136 | 137 | Portability issuesJava 138 | 139 | 140 | Potentially confusing code constructsGroovy 141 | 142 | 143 | Probable bugsGroovy 144 | 145 | 146 | Probable bugsJava 147 | 148 | 149 | Properties Files 150 | 151 | 152 | RELAX NG 153 | 154 | 155 | Security issuesJava 156 | 157 | 158 | TestNG 159 | 160 | 161 | Threading issuesJava 162 | 163 | 164 | Visibility issuesJava 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 186 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/RegularExpression.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | * 正则验证相关操作的类. 8 | */ 9 | public class RegularExpression { 10 | 11 | public final static String DESC_NORMALTEXT = "不能包含特殊字符,且不能为空."; 12 | 13 | /** 14 | * 正则验证 15 | * 16 | * @param toCheckStr 待验证的字符串 17 | * @param patternStr 验证格式字符串 18 | * @return 是否通过验证 19 | */ 20 | public static boolean canMatch(String toCheckStr, String patternStr) { 21 | Pattern pattern = Pattern.compile(patternStr); 22 | Matcher matcher = pattern.matcher(toCheckStr); 23 | if (!matcher.matches()) { 24 | return false; 25 | } 26 | return true; 27 | } 28 | 29 | /** 30 | * 验证是否为整数. 31 | * 32 | * @param toCheckStr 待验证的字符串 33 | * @return 是否通过验证 34 | */ 35 | public static boolean isNumeric(String toCheckStr) { 36 | return canMatch(toCheckStr, "[0-9][0-9]*"); 37 | } 38 | 39 | /** 40 | * 验证是否为整数或字母. 41 | * 42 | * @param toCheckStr 待验证的字符串 43 | * @return 是否通过验证 44 | */ 45 | public static boolean isNumOrChar(String toCheckStr) { 46 | return canMatch(toCheckStr, "[a-zA-Z0-9][a-zA-Z0-9]*"); 47 | } 48 | 49 | /** 50 | * 验证是否为身份证号 51 | * 52 | * @param toCheckStr 待验证的字符串 53 | * @return 是否通过验证 54 | */ 55 | public static boolean isIDCard(String toCheckStr) { 56 | // String patternStr = 57 | // "/^((1[1-5])|(2[1-3])|(3[0-7])|(4[1-6])|(5[0-4])|(6[0-9])|(7[12])|(8[0-9])|(9[0-9])|(10[0-9])|(11[0-1])|(12[0-9])|(13[0-3])|(14[0-9]))" 58 | // + "\\d{4}(" 59 | // + "(19\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))" 60 | // + "|(19\\d{2}(0[13578]|1[02])31)" 61 | // + "|(19\\d{2}02(0[1-9]|1\\d|2[0-8]))" 62 | // + "|(19([13579][26]|[2468][048]|0[48])0229)" 63 | // + ")\\d{3}(\\d|X|x)?$/"; 64 | // String patternStr1 = 65 | // "/^((1[1-5])|(2[1-3])|(3[0-7])|(4[1-6])|(5[0-4])|(6[0-9])|(7[0-9])|(8[0-9])|(9[0-1])|(10[0-9])|(11[0-3])|(12[0-9]))" 66 | // + "\\d{4}(" 67 | // + "(16\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))" 68 | // + "|(16\\d{2}(0[13578]|1[02])31)" 69 | // + "|(16\\d{2}02(0[1-9]|1\\d|2[0-8]))" 70 | // + "|(16([13579][26]|[2468][048]|0[48])0229)" 71 | // + ")\\d{3}(\\d|X|x)?$/"; 72 | String isIDCard1 = "^(([0-9]{14}[x0-9]{1})|([0-9]{17}[x0-9]{1}))$"; 73 | // String 74 | // isIDCard2="/^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{4}$/"; 75 | return canMatch(toCheckStr, isIDCard1);// || canMatch(toCheckStr, 76 | // isIDCard2); 77 | } 78 | 79 | /** 80 | * 验证是否为电话号码 81 | * 82 | * @param toCheckStr 待验证的字符串 83 | * @return 是否通过验证 84 | */ 85 | public static boolean isTeleNo(String toCheckStr) { 86 | String patternStr = "(^[0-9]{3,4}\\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\\([0-9]{3,4}\\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$)"; 87 | return canMatch(toCheckStr, patternStr); 88 | } 89 | 90 | /** 91 | * 验证是否为合法的用户名. 用户名只能由汉字、数字、字母、下划线组成,且不能为空. 92 | * 93 | * @param toCheckStr 待验证的字符串 94 | * @return 是否通过验证 95 | */ 96 | public static boolean isUserName(String toCheckStr) { 97 | String patternStr = "^[a-zA-Z0-9_\u4e00-\u9fa5]+$"; 98 | return canMatch(toCheckStr, patternStr); 99 | } 100 | 101 | /** 102 | * 验证是否为汉字. 103 | * 104 | * @param toCheckStr 待验证的字符串 105 | * @return 是否通过验证 106 | */ 107 | public static boolean isCH(String toCheckStr) { 108 | String patternStr = "^[\u4e00-\u9fa5]+$"; 109 | return canMatch(toCheckStr, patternStr); 110 | } 111 | 112 | /** 113 | * 验证是否为正常的文本内容. 内容只能为:汉字、数字、字母、下划线、 中文标点符号 114 | * 英文标点符号,且不能为空. 115 | * 116 | * @param toCheckStr 待验证的字符串 117 | * @return 是否通过验证 118 | */ 119 | public static boolean isNormalText(String toCheckStr) { 120 | String patternStr = "^[a-zA-Z0-9_\u4e00-\u9fa5" // 汉字、数字、字母、下划线 121 | // 中文标点符号(。 ; , : “ ”( ) 、 ! ? 《 》) 122 | + "\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff01\uff1f\u300a\u300b" 123 | // 英文标点符号(. ; , : ' ( ) / ! ? < >) 124 | + "\u002e\u003b\u002c\u003a\u0027\u0028\u0029\u002f\u0021\u003f\u003c\u003e\r\n" 125 | + "]+$"; 126 | return canMatch(toCheckStr, patternStr); 127 | } 128 | 129 | /** 130 | * 验证是否为Url的文本内容. 内容只能为:数字、字母、英文标点符号(. : / ),且不能为空. 131 | * 132 | * @param toCheckStr 待验证的字符串 133 | * @return 是否通过验证 134 | */ 135 | public static boolean isUrlText(String toCheckStr) { 136 | String patternStr = "^[a-zA-Z0-9" // 数字、字母 137 | // 英文标点符号(. : /) 138 | + "\u002e\u003a\u002f" 139 | + "]+$"; 140 | return canMatch(toCheckStr, patternStr); 141 | } 142 | 143 | /** 144 | * 判断房间号是否符合规范:例如102,1202... 先判断3位或者4位的数字 145 | * 146 | * @param roomNumber roomNumber 147 | * @return boolean 148 | */ 149 | public static boolean checkRoomNumber(String roomNumber) { 150 | String regex = "^\\d{3,4}$"; 151 | return Pattern.matches(regex, roomNumber); 152 | } 153 | 154 | /** 155 | * 将身份证后六位隐藏,不显示 156 | * 157 | * @param identityID identityID 158 | * @return String 159 | */ 160 | public static String hideIdentityID(String identityID) { 161 | if (identityID != null && identityID.length() > 6) { 162 | identityID = identityID.substring(0, identityID.length() - 6) 163 | + "******"; 164 | } 165 | return identityID; 166 | } 167 | 168 | /** 169 | * 是否规范的邮编 170 | * 171 | * @param toCheckStr toCheckStr 172 | * @return 是否规范的邮编 173 | */ 174 | public static boolean isPostalCode(String toCheckStr) { 175 | return isNumeric(toCheckStr) && toCheckStr.length() == 6; 176 | } 177 | 178 | /** 179 | * 邮箱验证 180 | * 181 | * @param toCheckStr toCheckStr 182 | * @return 邮箱验证 183 | */ 184 | public static boolean isEmail(String toCheckStr) { 185 | String patternStr = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$"; 186 | return canMatch(toCheckStr, patternStr); 187 | } 188 | 189 | /** 190 | * 办公电话验证 格式:区号(可选)-主机号-分机号(可选) 191 | * 192 | * @param toCheckStr toCheckStr 193 | * @return 办公电话验证 格式:区号(可选)-主机号-分机号(可选) 194 | */ 195 | public static boolean isWorkPhone(String toCheckStr) { 196 | String patternStr = "(^[0-9]{3,4}-[0-9]{7,8}-[0-9]{3,4}$)|(^[0-9]{3,4}-[0-9]{7,8}$)|(^[0-9]{7,8}-[0-9]{3,4}$)|(^[0-9]{7,8}$)"; 197 | return canMatch(toCheckStr, patternStr); 198 | } 199 | 200 | /** 201 | * 常用固定电话验证 格式:区号(可选)-主机号 202 | * 203 | * @param toCheckStr toCheckStr 204 | * @return 常用固定电话验证 格式:区号(可选)-主机号 205 | */ 206 | public static boolean isPhoneNumber(String toCheckStr) { 207 | String patternStr = "(^[0-9]{3,4}-[0-9]{7,8}$)|(^[0-9]{7,8}$)"; 208 | return canMatch(toCheckStr, patternStr); 209 | } 210 | 211 | /** 212 | * 是否为规范的手机电话号码 ,以13/15/18开头 213 | * 214 | * @param toCheckStr toCheckStr 215 | * @return 是否为规范的手机电话号码 ,以13/15/18开头 216 | */ 217 | public static boolean isTelephone(String toCheckStr) { 218 | String patternStr = "(^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$)"; 219 | return canMatch(toCheckStr, patternStr); 220 | } 221 | 222 | public static boolean isDateyyMMddHHmmss(String toCheckStr) { 223 | return canMatch(toCheckStr, "([1-2])([0-9]{3})([0-1])([0-9])([0-3])([0-9])([0-2])([0-9])([0-5])([0-9])([0-5])([0-9])"); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/AnimationUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.view.animation.AlphaAnimation; 4 | import android.view.animation.Animation; 5 | import android.view.animation.Animation.AnimationListener; 6 | import android.view.animation.RotateAnimation; 7 | import android.view.animation.ScaleAnimation; 8 | 9 | /** 10 | * 动画工具类 11 | * 12 | */ 13 | public final class AnimationUtils { 14 | 15 | /** 16 | * 默认动画持续时间 17 | */ 18 | public static final long DEFAULT_ANIMATION_DURATION = 500; 19 | 20 | 21 | /** 22 | * 获取一个旋转动画 23 | * 24 | * @param fromDegrees 开始角度 25 | * @param toDegrees 结束角度 26 | * @param pivotXType 旋转中心点X轴坐标相对类型 27 | * @param pivotXValue 旋转中心点X轴坐标 28 | * @param pivotYType 旋转中心点Y轴坐标相对类型 29 | * @param pivotYValue 旋转中心点Y轴坐标 30 | * @param durationMillis 持续时间 31 | * @param animationListener 动画监听器 32 | * @return 一个旋转动画 33 | */ 34 | public static RotateAnimation getRotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue, long durationMillis, AnimationListener animationListener) { 35 | RotateAnimation rotateAnimation = new RotateAnimation(fromDegrees, 36 | toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue); 37 | rotateAnimation.setDuration(durationMillis); 38 | if (animationListener != null) { 39 | rotateAnimation.setAnimationListener(animationListener); 40 | } 41 | return rotateAnimation; 42 | } 43 | 44 | 45 | /** 46 | * 获取一个根据视图自身中心点旋转的动画 47 | * 48 | * @param durationMillis 动画持续时间 49 | * @param animationListener 动画监听器 50 | * @return 一个根据中心点旋转的动画 51 | */ 52 | public static RotateAnimation getRotateAnimationByCenter(long durationMillis, AnimationListener animationListener) { 53 | return getRotateAnimation(0f, 359f, Animation.RELATIVE_TO_SELF, 0.5f, 54 | Animation.RELATIVE_TO_SELF, 0.5f, durationMillis, 55 | animationListener); 56 | } 57 | 58 | 59 | /** 60 | * 获取一个根据中心点旋转的动画 61 | * 62 | * @param duration 动画持续时间 63 | * @return 一个根据中心点旋转的动画 64 | */ 65 | public static RotateAnimation getRotateAnimationByCenter(long duration) { 66 | return getRotateAnimationByCenter(duration, null); 67 | } 68 | 69 | 70 | /** 71 | * 获取一个根据视图自身中心点旋转的动画 72 | * 73 | * @param animationListener 动画监听器 74 | * @return 一个根据中心点旋转的动画 75 | */ 76 | public static RotateAnimation getRotateAnimationByCenter(AnimationListener animationListener) { 77 | return getRotateAnimationByCenter(DEFAULT_ANIMATION_DURATION, 78 | animationListener); 79 | } 80 | 81 | 82 | /** 83 | * 获取一个根据中心点旋转的动画 84 | * 85 | * @return 一个根据中心点旋转的动画,默认持续时间为DEFAULT_ANIMATION_DURATION 86 | */ 87 | public static RotateAnimation getRotateAnimationByCenter() { 88 | return getRotateAnimationByCenter(DEFAULT_ANIMATION_DURATION, null); 89 | } 90 | 91 | 92 | /** 93 | * 获取一个透明度渐变动画 94 | * 95 | * @param fromAlpha 开始时的透明度 96 | * @param toAlpha 结束时的透明度都 97 | * @param durationMillis 持续时间 98 | * @param animationListener 动画监听器 99 | * @return 一个透明度渐变动画 100 | */ 101 | public static AlphaAnimation getAlphaAnimation(float fromAlpha, float toAlpha, long durationMillis, AnimationListener animationListener) { 102 | AlphaAnimation alphaAnimation = new AlphaAnimation(fromAlpha, toAlpha); 103 | alphaAnimation.setDuration(durationMillis); 104 | if (animationListener != null) { 105 | alphaAnimation.setAnimationListener(animationListener); 106 | } 107 | return alphaAnimation; 108 | } 109 | 110 | 111 | /** 112 | * 获取一个透明度渐变动画 113 | * 114 | * @param fromAlpha 开始时的透明度 115 | * @param toAlpha 结束时的透明度都 116 | * @param durationMillis 持续时间 117 | * @return 一个透明度渐变动画 118 | */ 119 | public static AlphaAnimation getAlphaAnimation(float fromAlpha, float toAlpha, long durationMillis) { 120 | return getAlphaAnimation(fromAlpha, toAlpha, durationMillis, null); 121 | } 122 | 123 | 124 | /** 125 | * 获取一个透明度渐变动画 126 | * 127 | * @param fromAlpha 开始时的透明度 128 | * @param toAlpha 结束时的透明度都 129 | * @param animationListener 动画监听器 130 | * @return 一个透明度渐变动画,默认持续时间为DEFAULT_ANIMATION_DURATION 131 | */ 132 | public static AlphaAnimation getAlphaAnimation(float fromAlpha, float toAlpha, AnimationListener animationListener) { 133 | return getAlphaAnimation(fromAlpha, toAlpha, DEFAULT_ANIMATION_DURATION, 134 | animationListener); 135 | } 136 | 137 | 138 | /** 139 | * 获取一个透明度渐变动画 140 | * 141 | * @param fromAlpha 开始时的透明度 142 | * @param toAlpha 结束时的透明度都 143 | * @return 一个透明度渐变动画,默认持续时间为DEFAULT_ANIMATION_DURATION 144 | */ 145 | public static AlphaAnimation getAlphaAnimation(float fromAlpha, float toAlpha) { 146 | return getAlphaAnimation(fromAlpha, toAlpha, DEFAULT_ANIMATION_DURATION, 147 | null); 148 | } 149 | 150 | 151 | /** 152 | * 获取一个由完全显示变为不可见的透明度渐变动画 153 | * 154 | * @param durationMillis 持续时间 155 | * @param animationListener 动画监听器 156 | * @return 一个由完全显示变为不可见的透明度渐变动画 157 | */ 158 | public static AlphaAnimation getHiddenAlphaAnimation(long durationMillis, AnimationListener animationListener) { 159 | return getAlphaAnimation(1.0f, 0.0f, durationMillis, animationListener); 160 | } 161 | 162 | 163 | /** 164 | * 获取一个由完全显示变为不可见的透明度渐变动画 165 | * 166 | * @param durationMillis 持续时间 167 | * @return 一个由完全显示变为不可见的透明度渐变动画 168 | */ 169 | public static AlphaAnimation getHiddenAlphaAnimation(long durationMillis) { 170 | return getHiddenAlphaAnimation(durationMillis, null); 171 | } 172 | 173 | 174 | /** 175 | * 获取一个由完全显示变为不可见的透明度渐变动画 176 | * 177 | * @param animationListener 动画监听器 178 | * @return 一个由完全显示变为不可见的透明度渐变动画,默认持续时间为DEFAULT_ANIMATION_DURATION 179 | */ 180 | public static AlphaAnimation getHiddenAlphaAnimation(AnimationListener animationListener) { 181 | return getHiddenAlphaAnimation(DEFAULT_ANIMATION_DURATION, 182 | animationListener); 183 | } 184 | 185 | 186 | /** 187 | * 获取一个由完全显示变为不可见的透明度渐变动画 188 | * 189 | * @return 一个由完全显示变为不可见的透明度渐变动画,默认持续时间为DEFAULT_ANIMATION_DURATION 190 | */ 191 | public static AlphaAnimation getHiddenAlphaAnimation() { 192 | return getHiddenAlphaAnimation(DEFAULT_ANIMATION_DURATION, null); 193 | } 194 | 195 | 196 | /** 197 | * 获取一个由不可见变为完全显示的透明度渐变动画 198 | * 199 | * @param durationMillis 持续时间 200 | * @param animationListener 动画监听器 201 | * @return 一个由不可见变为完全显示的透明度渐变动画 202 | */ 203 | public static AlphaAnimation getShowAlphaAnimation(long durationMillis, AnimationListener animationListener) { 204 | return getAlphaAnimation(0.0f, 1.0f, durationMillis, animationListener); 205 | } 206 | 207 | 208 | /** 209 | * 获取一个由不可见变为完全显示的透明度渐变动画 210 | * 211 | * @param durationMillis 持续时间 212 | * @return 一个由不可见变为完全显示的透明度渐变动画 213 | */ 214 | public static AlphaAnimation getShowAlphaAnimation(long durationMillis) { 215 | return getAlphaAnimation(0.0f, 1.0f, durationMillis, null); 216 | } 217 | 218 | 219 | /** 220 | * 获取一个由不可见变为完全显示的透明度渐变动画 221 | * 222 | * @param animationListener 动画监听器 223 | * @return 一个由不可见变为完全显示的透明度渐变动画,默认持续时间为DEFAULT_ANIMATION_DURATION 224 | */ 225 | public static AlphaAnimation getShowAlphaAnimation(AnimationListener animationListener) { 226 | return getAlphaAnimation(0.0f, 1.0f, DEFAULT_ANIMATION_DURATION, 227 | animationListener); 228 | } 229 | 230 | 231 | /** 232 | * 获取一个由不可见变为完全显示的透明度渐变动画 233 | * 234 | * @return 一个由不可见变为完全显示的透明度渐变动画,默认持续时间为DEFAULT_ANIMATION_DURATION 235 | */ 236 | public static AlphaAnimation getShowAlphaAnimation() { 237 | return getAlphaAnimation(0.0f, 1.0f, DEFAULT_ANIMATION_DURATION, null); 238 | } 239 | 240 | 241 | /** 242 | * 获取一个缩小动画 243 | * 244 | * @param durationMillis 时间 245 | * @param animationListener 监听 246 | * @return 一个缩小动画 247 | */ 248 | public static ScaleAnimation getLessenScaleAnimation(long durationMillis, AnimationListener animationListener) { 249 | ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.0f, 1.0f, 250 | 0.0f, ScaleAnimation.RELATIVE_TO_SELF, 251 | ScaleAnimation.RELATIVE_TO_SELF); 252 | scaleAnimation.setDuration(durationMillis); 253 | scaleAnimation.setAnimationListener(animationListener); 254 | 255 | return scaleAnimation; 256 | } 257 | 258 | 259 | /** 260 | * 获取一个缩小动画 261 | * 262 | * @param durationMillis 时间 263 | * @return 一个缩小动画 264 | */ 265 | public static ScaleAnimation getLessenScaleAnimation(long durationMillis) { 266 | return getLessenScaleAnimation(durationMillis, null); 267 | 268 | } 269 | 270 | 271 | /** 272 | * 获取一个缩小动画 273 | * 274 | * @param animationListener 监听 275 | * @return 返回一个缩小的动画 276 | */ 277 | public static ScaleAnimation getLessenScaleAnimation(AnimationListener animationListener) { 278 | return getLessenScaleAnimation(DEFAULT_ANIMATION_DURATION, 279 | animationListener); 280 | 281 | } 282 | 283 | 284 | /** 285 | * 获取一个放大动画 286 | * @param durationMillis 时间 287 | * @param animationListener 监听 288 | * 289 | * @return 返回一个放大的效果 290 | */ 291 | public static ScaleAnimation getAmplificationAnimation(long durationMillis, AnimationListener animationListener) { 292 | ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f, 1.0f, 0.0f, 293 | 1.0f, ScaleAnimation.RELATIVE_TO_SELF, 294 | ScaleAnimation.RELATIVE_TO_SELF); 295 | scaleAnimation.setDuration(durationMillis); 296 | scaleAnimation.setAnimationListener(animationListener); 297 | return scaleAnimation; 298 | } 299 | 300 | 301 | /** 302 | * 获取一个放大动画 303 | * 304 | * @param durationMillis 时间 305 | * 306 | * @return 返回一个放大的效果 307 | */ 308 | public static ScaleAnimation getAmplificationAnimation(long durationMillis) { 309 | return getAmplificationAnimation(durationMillis, null); 310 | 311 | } 312 | 313 | 314 | /** 315 | * 获取一个放大动画 316 | * 317 | * @param animationListener 监听 318 | * @return 返回一个放大的效果 319 | */ 320 | public static ScaleAnimation getAmplificationAnimation(AnimationListener animationListener) { 321 | return getAmplificationAnimation(DEFAULT_ANIMATION_DURATION, 322 | animationListener); 323 | 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/DeviceStatusUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.bluetooth.BluetoothAdapter; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.media.AudioManager; 9 | import android.os.Build; 10 | import android.provider.Settings; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | 14 | /** 15 | * 手机状态工具类 主要包括网络、蓝牙、屏幕亮度、飞行模式、音量等 16 | */ 17 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 18 | public class DeviceStatusUtils { 19 | 20 | /** 21 | * Don't let anyone instantiate this class. 22 | */ 23 | private DeviceStatusUtils() { 24 | throw new Error("Do not need instantiate!"); 25 | } 26 | 27 | /** 28 | * 获取系统屏幕亮度模式的状态,需要WRITE_SETTINGS权限 29 | * 30 | * @param context 上下文 31 | * @return System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC:自动;System. 32 | * SCREEN_BRIGHTNESS_MODE_AUTOMATIC 33 | * :手动;默认:System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC 34 | */ 35 | public static int getScreenBrightnessModeState(Context context) { 36 | return Settings.System.getInt(context.getContentResolver(), 37 | Settings.System.SCREEN_BRIGHTNESS_MODE, 38 | Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); 39 | } 40 | 41 | /** 42 | * 判断系统屏幕亮度模式是否是自动,需要WRITE_SETTINGS权限 43 | * 44 | * @param context 上下文 45 | * @return true:自动;false:手动;默认:true 46 | */ 47 | public static boolean isScreenBrightnessModeAuto(Context context) { 48 | return getScreenBrightnessModeState(context) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC ? true 49 | : false; 50 | } 51 | 52 | /** 53 | * 设置系统屏幕亮度模式,需要WRITE_SETTINGS权限 54 | * 55 | * @param context 上下文 56 | * @param auto 自动 57 | * @return 是否设置成功 58 | */ 59 | public static boolean setScreenBrightnessMode(Context context, boolean auto) { 60 | boolean result = true; 61 | if (isScreenBrightnessModeAuto(context) != auto) { 62 | result = Settings.System.putInt(context.getContentResolver(), 63 | Settings.System.SCREEN_BRIGHTNESS_MODE, 64 | auto ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC 65 | : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); 66 | } 67 | return result; 68 | } 69 | 70 | /** 71 | * 获取系统亮度,需要WRITE_SETTINGS权限 72 | * 73 | * @param context 上下文 74 | * @return 亮度,范围是0-255;默认255 75 | */ 76 | public static int getScreenBrightness(Context context) { 77 | return Settings.System.getInt(context.getContentResolver(), 78 | Settings.System.SCREEN_BRIGHTNESS, 255); 79 | } 80 | 81 | /** 82 | * 设置系统亮度(此方法只是更改了系统的亮度属性,并不能看到效果。要想看到效果可以使用setWindowBrightness()方法设置窗口的亮度), 83 | * 需要WRITE_SETTINGS权限 84 | * 85 | * @param context 上下文 86 | * @param screenBrightness 亮度,范围是0-255 87 | * @return 设置是否成功 88 | */ 89 | public static boolean setScreenBrightness(Context context, 90 | int screenBrightness) { 91 | int brightness = screenBrightness; 92 | if (screenBrightness < 1) { 93 | brightness = 1; 94 | } else if (screenBrightness > 255) { 95 | brightness = screenBrightness % 255; 96 | if (brightness == 0) { 97 | brightness = 255; 98 | } 99 | } 100 | boolean result = Settings.System.putInt(context.getContentResolver(), 101 | Settings.System.SCREEN_BRIGHTNESS, brightness); 102 | return result; 103 | } 104 | 105 | /** 106 | * 设置给定Activity的窗口的亮度(可以看到效果,但系统的亮度属性不会改变) 107 | * 108 | * @param activity 要通过此Activity来设置窗口的亮度 109 | * @param screenBrightness 亮度,范围是0-255 110 | */ 111 | public static void setWindowBrightness(Activity activity, 112 | float screenBrightness) { 113 | float brightness = screenBrightness; 114 | if (screenBrightness < 1) { 115 | brightness = 1; 116 | } else if (screenBrightness > 255) { 117 | brightness = screenBrightness % 255; 118 | if (brightness == 0) { 119 | brightness = 255; 120 | } 121 | } 122 | Window window = activity.getWindow(); 123 | WindowManager.LayoutParams localLayoutParams = window.getAttributes(); 124 | localLayoutParams.screenBrightness = (float) brightness / 255; 125 | window.setAttributes(localLayoutParams); 126 | } 127 | 128 | /** 129 | * 设置系统亮度并实时可以看到效果,需要WRITE_SETTINGS权限 130 | * 131 | * @param activity 要通过此Activity来设置窗口的亮度 132 | * @param screenBrightness 亮度,范围是0-255 133 | * @return 设置是否成功 134 | */ 135 | public static boolean setScreenBrightnessAndApply(Activity activity, 136 | int screenBrightness) { 137 | boolean result = true; 138 | result = setScreenBrightness(activity, screenBrightness); 139 | if (result) { 140 | setWindowBrightness(activity, screenBrightness); 141 | } 142 | return result; 143 | } 144 | 145 | /** 146 | * 获取屏幕休眠时间,需要WRITE_SETTINGS权限 147 | * 148 | * @param context 上下文 149 | * @return 屏幕休眠时间,单位毫秒,默认30000 150 | */ 151 | public static int getScreenDormantTime(Context context) { 152 | return Settings.System.getInt(context.getContentResolver(), 153 | Settings.System.SCREEN_OFF_TIMEOUT, 30000); 154 | } 155 | 156 | /** 157 | * 设置屏幕休眠时间,需要WRITE_SETTINGS权限 158 | * 159 | * @param context 上下文 160 | * @param millis 时间 161 | * @return 设置是否成功 162 | */ 163 | public static boolean setScreenDormantTime(Context context, int millis) { 164 | return Settings.System.putInt(context.getContentResolver(), 165 | Settings.System.SCREEN_OFF_TIMEOUT, millis); 166 | 167 | } 168 | 169 | /** 170 | * 获取飞行模式的状态,需要WRITE_APN_SETTINGS权限 171 | * 172 | * @param context 上下文 173 | * @return 1:打开;0:关闭;默认:关闭 174 | */ 175 | @SuppressWarnings("deprecation") 176 | public static int getAirplaneModeState(Context context) { 177 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 178 | return Settings.System.getInt(context.getContentResolver(), 179 | Settings.System.AIRPLANE_MODE_ON, 0); 180 | } else { 181 | return Settings.Global.getInt(context.getContentResolver(), 182 | Settings.Global.AIRPLANE_MODE_ON, 0); 183 | } 184 | } 185 | 186 | /** 187 | * 判断飞行模式是否打开,需要WRITE_APN_SETTINGS权限 188 | * 189 | * @param context 上下文 190 | * @return true:打开;false:关闭;默认关闭 191 | */ 192 | public static boolean isAirplaneModeOpen(Context context) { 193 | return getAirplaneModeState(context) == 1 ? true : false; 194 | } 195 | 196 | /** 197 | * 设置飞行模式的状态,需要WRITE_APN_SETTINGS权限 198 | * 199 | * @param context 上下文 200 | * @param enable 飞行模式的状态 201 | * @return 设置是否成功 202 | */ 203 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 204 | @SuppressWarnings("deprecation") 205 | public static boolean setAirplaneMode(Context context, boolean enable) { 206 | boolean result = true; 207 | // 如果飞行模式当前的状态与要设置的状态不一样 208 | if (isAirplaneModeOpen(context) != enable) { 209 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 210 | result = Settings.System.putInt(context.getContentResolver(), 211 | Settings.System.AIRPLANE_MODE_ON, enable ? 1 : 0); 212 | } else { 213 | result = Settings.Global.putInt(context.getContentResolver(), 214 | Settings.Global.AIRPLANE_MODE_ON, enable ? 1 : 0); 215 | } 216 | // 发送飞行模式已经改变广播 217 | context.sendBroadcast(new Intent( 218 | Intent.ACTION_AIRPLANE_MODE_CHANGED)); 219 | } 220 | return result; 221 | } 222 | 223 | /** 224 | * 获取蓝牙的状态 225 | * 226 | * @return 取值为BluetoothAdapter的四个静态字段:STATE_OFF, STATE_TURNING_OFF, 227 | * STATE_ON, STATE_TURNING_ON 228 | * @throws Exception 没有找到蓝牙设备 229 | */ 230 | public static int getBluetoothState() throws Exception { 231 | BluetoothAdapter bluetoothAdapter = BluetoothAdapter 232 | .getDefaultAdapter(); 233 | if (bluetoothAdapter == null) { 234 | throw new Exception("bluetooth device not found!"); 235 | } else { 236 | return bluetoothAdapter.getState(); 237 | } 238 | } 239 | 240 | /** 241 | * 判断蓝牙是否打开 242 | * 243 | * @return true:已经打开或者正在打开;false:已经关闭或者正在关闭 244 | * 没有找到蓝牙设备 245 | */ 246 | public static boolean isBluetoothOpen() { 247 | int bluetoothStateCode = 0; 248 | try { 249 | bluetoothStateCode = getBluetoothState(); 250 | return bluetoothStateCode == BluetoothAdapter.STATE_ON 251 | || bluetoothStateCode == BluetoothAdapter.STATE_TURNING_ON ? true 252 | : false; 253 | } catch (Exception e) { 254 | e.printStackTrace(); 255 | } 256 | return false; 257 | } 258 | 259 | /** 260 | * 设置蓝牙状态 261 | * 262 | * @param enable 打开 263 | * 没有找到蓝牙设备 264 | */ 265 | public static void setBluetooth(boolean enable) { 266 | // 如果当前蓝牙的状态与要设置的状态不一样 267 | if (isBluetoothOpen() != enable) { 268 | // 如果是要打开就打开,否则关闭 269 | if (enable) { 270 | BluetoothAdapter.getDefaultAdapter().enable(); 271 | } else { 272 | BluetoothAdapter.getDefaultAdapter().disable(); 273 | } 274 | } 275 | 276 | } 277 | 278 | 279 | /** 280 | * 获取铃声音量,需要WRITE_APN_SETTINGS权限 281 | * 282 | * @param context 上下文 283 | * @return 铃声音量,取值范围为0-7;默认为0 284 | */ 285 | public static int getRingVolume(Context context) { 286 | return ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)).getStreamVolume(AudioManager.STREAM_RING); 287 | } 288 | 289 | /** 290 | * 获取媒体音量 291 | * 292 | * @param context 上下文 293 | * @param ringVloume 音量 294 | */ 295 | public static void setRingVolume(Context context, int ringVloume) { 296 | if (ringVloume < 0) { 297 | ringVloume = 0; 298 | } else if (ringVloume > 7) { 299 | ringVloume = ringVloume % 7; 300 | if (ringVloume == 0) { 301 | ringVloume = 7; 302 | } 303 | } 304 | 305 | ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)).setStreamVolume(AudioManager.STREAM_RING, 306 | ringVloume, AudioManager.FLAG_PLAY_SOUND); 307 | } 308 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/ZipUtil.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.OutputStream; 11 | import java.io.UnsupportedEncodingException; 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | import java.util.Enumeration; 15 | import java.util.zip.ZipEntry; 16 | import java.util.zip.ZipFile; 17 | import java.util.zip.ZipOutputStream; 18 | 19 | /** 20 | * Java utils 实现的Zip工具 21 | * 22 | */ 23 | public class ZipUtil{ 24 | private static final int BUFF_SIZE = 1024 * 1024; // 1M Byte 25 | private static boolean stopZipFlag; 26 | 27 | public static boolean isStopZipFlag() { 28 | return stopZipFlag; 29 | } 30 | 31 | public static void setStopZipFlag(boolean stopZipFlag) { 32 | ZipUtil.stopZipFlag = stopZipFlag; 33 | } 34 | 35 | /** 36 | * 批量压缩文件(夹) 37 | * 38 | * @param resFileList 要压缩的文件(夹)列表 39 | * @param zipFile 生成的压缩文件 40 | * @param zipListener zipListener 41 | */ 42 | public static void zipFiles(Collection resFileList, File zipFile,ZipListener zipListener) { 43 | 44 | ZipOutputStream zipout = null; 45 | try { 46 | zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream( 47 | zipFile), BUFF_SIZE)); 48 | for (File resFile : resFileList) { 49 | if(stopZipFlag){ 50 | break; 51 | } 52 | zipFile(resFile, zipout, "",zipListener); 53 | } 54 | zipout.close(); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | 60 | /** 61 | * 批量压缩文件(夹) 62 | * 63 | * @param resFileList 要压缩的文件(夹)列表 64 | * @param zipFile 生成的压缩文件 65 | * @param comment 压缩文件的注释 66 | * @param zipListener zipListener 67 | */ 68 | public static void zipFiles(Collection resFileList, File zipFile, String comment,ZipListener zipListener) 69 | { 70 | ZipOutputStream zipout = null; 71 | try { 72 | zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile), BUFF_SIZE)); 73 | for (File resFile : resFileList) { 74 | zipFile(resFile, zipout, "",zipListener); 75 | } 76 | zipout.setComment(comment); 77 | zipout.close(); 78 | } catch (Exception e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | 83 | /** 84 | * 解压缩一个文件 85 | * 86 | * @param zipFile 压缩文件 87 | * @param folderPath 解压缩的目标目录 88 | */ 89 | public static void upZipFile(File zipFile, String folderPath) { 90 | File desDir = new File(folderPath); 91 | if (!desDir.exists()) { 92 | desDir.mkdirs(); 93 | } 94 | ZipFile zf = null; 95 | try { 96 | zf = new ZipFile(zipFile); 97 | for (Enumeration entries = zf.entries(); entries.hasMoreElements();) { 98 | ZipEntry entry = ((ZipEntry)entries.nextElement()); 99 | InputStream in = zf.getInputStream(entry); 100 | String str = folderPath + File.separator + entry.getName(); 101 | str = new String(str.getBytes("8859_1"), "GB2312"); 102 | File desFile = new File(str); 103 | if (!desFile.exists()) { 104 | File fileParentDir = desFile.getParentFile(); 105 | if (!fileParentDir.exists()) { 106 | fileParentDir.mkdirs(); 107 | } 108 | desFile.createNewFile(); 109 | } 110 | OutputStream out = new FileOutputStream(desFile); 111 | byte buffer[] = new byte[BUFF_SIZE]; 112 | int realLength; 113 | while ((realLength = in.read(buffer)) > 0) { 114 | out.write(buffer, 0, realLength); 115 | } 116 | in.close(); 117 | out.close(); 118 | } 119 | } catch (Exception e) { 120 | e.printStackTrace(); 121 | } 122 | 123 | } 124 | 125 | /** 126 | * 解压文件名包含传入文字的文件 127 | * 128 | * @param zipFile 压缩文件 129 | * @param folderPath 目标文件夹 130 | * @param nameContains 传入的文件匹配名 131 | * @return 返回的集合 132 | */ 133 | public static ArrayList upZipSelectedFile(File zipFile, String folderPath, 134 | String nameContains) { 135 | 136 | ArrayList fileList = new ArrayList(); 137 | 138 | File desDir = new File(folderPath); 139 | if (!desDir.exists()) { 140 | desDir.mkdir(); 141 | } 142 | 143 | ZipFile zf = null; 144 | try { 145 | zf = new ZipFile(zipFile); 146 | for (Enumeration entries = zf.entries(); entries.hasMoreElements();) { 147 | ZipEntry entry = ((ZipEntry)entries.nextElement()); 148 | if (entry.getName().contains(nameContains)) { 149 | InputStream in = zf.getInputStream(entry); 150 | String str = folderPath + File.separator + entry.getName(); 151 | str = new String(str.getBytes("8859_1"), "GB2312"); 152 | // str.getBytes("GB2312"),"8859_1" 输出 153 | // str.getBytes("8859_1"),"GB2312" 输入 154 | File desFile = new File(str); 155 | if (!desFile.exists()) { 156 | File fileParentDir = desFile.getParentFile(); 157 | if (!fileParentDir.exists()) { 158 | fileParentDir.mkdirs(); 159 | } 160 | desFile.createNewFile(); 161 | } 162 | OutputStream out = new FileOutputStream(desFile); 163 | byte buffer[] = new byte[BUFF_SIZE]; 164 | int realLength; 165 | while ((realLength = in.read(buffer)) > 0) { 166 | out.write(buffer, 0, realLength); 167 | } 168 | in.close(); 169 | out.close(); 170 | fileList.add(desFile); 171 | } 172 | } 173 | return fileList; 174 | } catch (Exception e) { 175 | e.printStackTrace(); 176 | } 177 | return null; 178 | } 179 | 180 | /** 181 | * 获得压缩文件内文件列表 182 | * 183 | * @param zipFile 压缩文件 184 | * @return 压缩文件内文件名称 185 | */ 186 | public static ArrayList getEntriesNames(File zipFile) { 187 | 188 | ArrayList entryNames = new ArrayList(); 189 | Enumeration entries = null; 190 | try { 191 | entries = getEntriesEnumeration(zipFile); 192 | while (entries.hasMoreElements()) { 193 | ZipEntry entry = ((ZipEntry)entries.nextElement()); 194 | entryNames.add(new String(getEntryName(entry).getBytes("GB2312"), "8859_1")); 195 | } 196 | return entryNames; 197 | } catch (IOException e) { 198 | e.printStackTrace(); 199 | } 200 | return null; 201 | } 202 | 203 | /** 204 | * 获得压缩文件内压缩文件对象以取得其属性 205 | * 206 | * @param zipFile 压缩文件 207 | * @return 返回一个压缩文件列表 208 | */ 209 | public static Enumeration getEntriesEnumeration(File zipFile) { 210 | ZipFile zf = null; 211 | try { 212 | zf = new ZipFile(zipFile); 213 | } catch (IOException e) { 214 | e.printStackTrace(); 215 | } 216 | return zf.entries(); 217 | 218 | } 219 | 220 | /** 221 | * 取得压缩文件对象的注释 222 | * 223 | * @param entry 压缩文件对象 224 | * @return 压缩文件对象的注释 225 | */ 226 | public static String getEntryComment(ZipEntry entry) { 227 | try { 228 | return new String(entry.getComment().getBytes("GB2312"), "8859_1"); 229 | } catch (UnsupportedEncodingException e) { 230 | e.printStackTrace(); 231 | } 232 | return null; 233 | } 234 | 235 | /** 236 | * 取得压缩文件对象的名称 237 | * 238 | * @param entry 压缩文件对象 239 | * @return 压缩文件对象的名称 240 | */ 241 | public static String getEntryName(ZipEntry entry) { 242 | try { 243 | return new String(entry.getName().getBytes("GB2312"), "8859_1"); 244 | } catch (UnsupportedEncodingException e) { 245 | e.printStackTrace(); 246 | } 247 | return null; 248 | } 249 | 250 | /** 251 | * 压缩文件 252 | * 253 | * @param resFile 需要压缩的文件(夹) 254 | * @param zipout 压缩的目的文件 255 | * @param rootpath 压缩的文件路径 256 | */ 257 | private static void zipFile(File resFile, ZipOutputStream zipout, String rootpath,ZipListener zipListener) 258 | { 259 | try { 260 | rootpath = rootpath + (rootpath.trim().length() == 0 ? "" : File.separator) 261 | + resFile.getName(); 262 | rootpath = new String(rootpath.getBytes("8859_1"), "GB2312"); 263 | if (resFile.isDirectory()) { 264 | File[] fileList = resFile.listFiles(); 265 | int length=fileList.length; 266 | // Log.e("zipprogress", (int)((1 / (float) (length+1))*100)+"%"); 267 | zipListener.zipProgress((int)((1 / (float) (length+1))*100)); 268 | for (int i=0;i>> 2) & 0x3f]; 64 | bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]; 65 | bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]; 66 | bytes[j + 3] = encodingTable[a3 & 0x3f]; 67 | } 68 | int b1; 69 | int b2; 70 | int b3; 71 | int d1; 72 | int d2; 73 | switch (modulus) { 74 | case 0: /* nothing left to do */ 75 | break; 76 | case 1: 77 | d1 = data[data.length - 1] & 0xff; 78 | b1 = (d1 >>> 2) & 0x3f; 79 | b2 = (d1 << 4) & 0x3f; 80 | bytes[bytes.length - 4] = encodingTable[b1]; 81 | bytes[bytes.length - 3] = encodingTable[b2]; 82 | bytes[bytes.length - 2] = (byte) '='; 83 | bytes[bytes.length - 1] = (byte) '='; 84 | break; 85 | case 2: 86 | d1 = data[data.length - 2] & 0xff; 87 | d2 = data[data.length - 1] & 0xff; 88 | b1 = (d1 >>> 2) & 0x3f; 89 | b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; 90 | b3 = (d2 << 2) & 0x3f; 91 | bytes[bytes.length - 4] = encodingTable[b1]; 92 | bytes[bytes.length - 3] = encodingTable[b2]; 93 | bytes[bytes.length - 2] = encodingTable[b3]; 94 | bytes[bytes.length - 1] = (byte) '='; 95 | break; 96 | } 97 | return bytes; 98 | } 99 | 100 | public static byte[] decode(byte[] data) { 101 | byte[] bytes; 102 | byte b1; 103 | byte b2; 104 | byte b3; 105 | byte b4; 106 | data = discardNonBase64Bytes(data); 107 | if (data[data.length - 2] == '=') { 108 | bytes = new byte[(((data.length / 4) - 1) * 3) + 1]; 109 | } else if (data[data.length - 1] == '=') { 110 | bytes = new byte[(((data.length / 4) - 1) * 3) + 2]; 111 | } else { 112 | bytes = new byte[((data.length / 4) * 3)]; 113 | } 114 | for (int i = 0, j = 0; i < (data.length - 4); i += 4, j += 3) { 115 | b1 = decodingTable[data[i]]; 116 | b2 = decodingTable[data[i + 1]]; 117 | b3 = decodingTable[data[i + 2]]; 118 | b4 = decodingTable[data[i + 3]]; 119 | bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); 120 | bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); 121 | bytes[j + 2] = (byte) ((b3 << 6) | b4); 122 | } 123 | if (data[data.length - 2] == '=') { 124 | b1 = decodingTable[data[data.length - 4]]; 125 | b2 = decodingTable[data[data.length - 3]]; 126 | bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); 127 | } else if (data[data.length - 1] == '=') { 128 | b1 = decodingTable[data[data.length - 4]]; 129 | b2 = decodingTable[data[data.length - 3]]; 130 | b3 = decodingTable[data[data.length - 2]]; 131 | bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); 132 | bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); 133 | } else { 134 | b1 = decodingTable[data[data.length - 4]]; 135 | b2 = decodingTable[data[data.length - 3]]; 136 | b3 = decodingTable[data[data.length - 2]]; 137 | b4 = decodingTable[data[data.length - 1]]; 138 | bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); 139 | bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); 140 | bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); 141 | } 142 | return bytes; 143 | } 144 | 145 | public static byte[] decode(String data) { 146 | byte[] bytes; 147 | byte b1; 148 | byte b2; 149 | byte b3; 150 | byte b4; 151 | data = discardNonBase64Chars(data); 152 | if (data.charAt(data.length() - 2) == '=') { 153 | bytes = new byte[(((data.length() / 4) - 1) * 3) + 1]; 154 | } else if (data.charAt(data.length() - 1) == '=') { 155 | bytes = new byte[(((data.length() / 4) - 1) * 3) + 2]; 156 | } else { 157 | bytes = new byte[((data.length() / 4) * 3)]; 158 | } 159 | for (int i = 0, j = 0; i < (data.length() - 4); i += 4, j += 3) { 160 | b1 = decodingTable[data.charAt(i)]; 161 | b2 = decodingTable[data.charAt(i + 1)]; 162 | b3 = decodingTable[data.charAt(i + 2)]; 163 | b4 = decodingTable[data.charAt(i + 3)]; 164 | bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); 165 | bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); 166 | bytes[j + 2] = (byte) ((b3 << 6) | b4); 167 | } 168 | if (data.charAt(data.length() - 2) == '=') { 169 | b1 = decodingTable[data.charAt(data.length() - 4)]; 170 | b2 = decodingTable[data.charAt(data.length() - 3)]; 171 | bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); 172 | } else if (data.charAt(data.length() - 1) == '=') { 173 | b1 = decodingTable[data.charAt(data.length() - 4)]; 174 | b2 = decodingTable[data.charAt(data.length() - 3)]; 175 | b3 = decodingTable[data.charAt(data.length() - 2)]; 176 | bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); 177 | bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); 178 | } else { 179 | b1 = decodingTable[data.charAt(data.length() - 4)]; 180 | b2 = decodingTable[data.charAt(data.length() - 3)]; 181 | b3 = decodingTable[data.charAt(data.length() - 2)]; 182 | b4 = decodingTable[data.charAt(data.length() - 1)]; 183 | bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); 184 | bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); 185 | bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); 186 | } 187 | return bytes; 188 | } 189 | 190 | private static byte[] discardNonBase64Bytes(byte[] data) { 191 | byte[] temp = new byte[data.length]; 192 | int bytesCopied = 0; 193 | for (int i = 0; i < data.length; i++) { 194 | if (isValidBase64Byte(data[i])) { 195 | temp[bytesCopied++] = data[i]; 196 | } 197 | } 198 | byte[] newData = new byte[bytesCopied]; 199 | System.arraycopy(temp, 0, newData, 0, bytesCopied); 200 | return newData; 201 | } 202 | 203 | private static String discardNonBase64Chars(String data) { 204 | StringBuffer sb = new StringBuffer(); 205 | int length = data.length(); 206 | for (int i = 0; i < length; i++) { 207 | if (isValidBase64Byte((byte) (data.charAt(i)))) { 208 | sb.append(data.charAt(i)); 209 | } 210 | } 211 | return sb.toString(); 212 | } 213 | 214 | private static boolean isValidBase64Byte(byte b) { 215 | if (b == '=') { 216 | return true; 217 | } else if ((b < 0) || (b >= 128)) { 218 | return false; 219 | } else if (decodingTable[b] == -1) { 220 | return false; 221 | } 222 | return true; 223 | } 224 | 225 | /** Encodes a raw byte array into a BASE64 String representation i accordance with RFC 2045. 226 | * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. 227 | * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
228 | * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a 229 | * little faster. 230 | * @return A BASE64 encoded array. Never null. 231 | */ 232 | public final static String encodeToString(byte[] sArr, boolean lineSep) 233 | { 234 | // Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower. 235 | return new String(encodeToChar(sArr, lineSep)); 236 | } 237 | 238 | /** Encodes a raw byte array into a BASE64 char[] representation i accordance with RFC 2045. 239 | * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. 240 | * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
241 | * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a 242 | * little faster. 243 | * @return A BASE64 encoded array. Never null. 244 | */ 245 | public final static char[] encodeToChar(byte[] sArr, boolean lineSep) 246 | { 247 | // Check special case 248 | int sLen = sArr != null ? sArr.length : 0; 249 | if (sLen == 0) 250 | return new char[0]; 251 | 252 | int eLen = (sLen / 3) * 3; // Length of even 24-bits. 253 | int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count 254 | int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array 255 | char[] dArr = new char[dLen]; 256 | 257 | // Encode even 24-bits 258 | for (int s = 0, d = 0, cc = 0; s < eLen;) { 259 | // Copy next three bytes into lower 24 bits of int, paying attension to sign. 260 | int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); 261 | 262 | // Encode the int into four chars 263 | dArr[d++] = CA[(i >>> 18) & 0x3f]; 264 | dArr[d++] = CA[(i >>> 12) & 0x3f]; 265 | dArr[d++] = CA[(i >>> 6) & 0x3f]; 266 | dArr[d++] = CA[i & 0x3f]; 267 | 268 | // Add optional line separator 269 | if (lineSep && ++cc == 19 && d < dLen - 2) { 270 | dArr[d++] = '\r'; 271 | dArr[d++] = '\n'; 272 | cc = 0; 273 | } 274 | } 275 | 276 | // Pad and encode last bits if source isn't even 24 bits. 277 | int left = sLen - eLen; // 0 - 2. 278 | if (left > 0) { 279 | // Prepare the int 280 | int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); 281 | 282 | // Set last four chars 283 | dArr[dLen - 4] = CA[i >> 12]; 284 | dArr[dLen - 3] = CA[(i >>> 6) & 0x3f]; 285 | dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '='; 286 | dArr[dLen - 1] = '='; 287 | } 288 | return dArr; 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/BadgeUtil.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.content.ComponentName; 7 | import android.content.ContentValues; 8 | import android.content.Context; 9 | import android.content.Intent; 10 | import android.net.Uri; 11 | import android.os.Build; 12 | import android.util.Log; 13 | import android.widget.Toast; 14 | 15 | import java.lang.reflect.Field; 16 | import java.lang.reflect.Method; 17 | 18 | public class BadgeUtil { 19 | /** 20 | * 设置Badge 目前支持Launcher: 21 | * MIUI 22 | * Sony 23 | * Samsung 24 | * LG 25 | * HTC 26 | * Nova 需要这些权限 27 | * @param context context 28 | * @param count count 29 | * @param icon icon应用的图标 30 | */ 31 | /* 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | */ 79 | public static void setBadgeCount(Context context, int count,int icon) { 80 | 81 | // TODO 生成器模式重构 82 | if (count <= 0) { 83 | count = 0; 84 | } else { 85 | count = Math.max(0, Math.min(count, 99)); 86 | } 87 | if (Build.MANUFACTURER.equalsIgnoreCase("xiaomi")) { 88 | setBadgeOfMIUI(context, count,icon); 89 | } else if (Build.MANUFACTURER.equalsIgnoreCase("sony")) { 90 | setBadgeOfSony(context, count); 91 | } else if (Build.MANUFACTURER.toLowerCase().contains("samsung") || 92 | Build.MANUFACTURER.toLowerCase().contains("lg")) { 93 | setBadgeOfSumsung(context, count); 94 | } else if (Build.MANUFACTURER.toLowerCase().contains("htc")) { 95 | setBadgeOfHTC(context, count); 96 | } else if (Build.MANUFACTURER.toLowerCase().contains("nova")) { 97 | setBadgeOfNova(context, count); 98 | } else { 99 | Toast.makeText(context, "Not Found Support Launcher", Toast.LENGTH_LONG).show(); 100 | } 101 | } 102 | 103 | /** 104 | * 设置MIUI的Badge 105 | * 106 | * @param context context 107 | * @param count count 108 | * @param icon icon 109 | */ 110 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 111 | private static void setBadgeOfMIUI(Context context, int count, int icon) { 112 | 113 | Log.d("xys", "Launcher : MIUI"); 114 | NotificationManager mNotificationManager = (NotificationManager) context 115 | .getSystemService(Context.NOTIFICATION_SERVICE); 116 | Notification.Builder builder = new Notification.Builder(context) 117 | .setContentTitle("title").setContentText("text").setSmallIcon(icon); 118 | Notification notification = builder.build(); 119 | try { 120 | Field field = notification.getClass().getDeclaredField("extraNotification"); 121 | Object extraNotification = field.get(notification); 122 | Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class); 123 | method.invoke(extraNotification, count); 124 | } catch (Exception e) { 125 | e.printStackTrace(); 126 | } 127 | mNotificationManager.notify(0, notification); 128 | } 129 | 130 | /** 131 | * 设置索尼的Badge 132 | *

133 | * 需添加权限: 134 | * 135 | * @param context context 136 | * @param count count 137 | */ 138 | private static void setBadgeOfSony(Context context, int count) { 139 | String launcherClassName = AppInfoUtil.getLauncherClassName(context); 140 | if (launcherClassName == null) { 141 | return; 142 | } 143 | boolean isShow = true; 144 | if (count == 0) { 145 | isShow = false; 146 | } 147 | Intent localIntent = new Intent(); 148 | localIntent.setAction("com.sonyericsson.home.action.UPDATE_BADGE"); 149 | localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", isShow);//是否显示 150 | localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", launcherClassName);//启动页 151 | localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", String 152 | .valueOf(count));//数字 153 | localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context.getPackageName());//包名 154 | context.sendBroadcast(localIntent); 155 | } 156 | 157 | /** 158 | * 设置三星的Badge\设置LG的Badge 159 | * 160 | * @param context context 161 | * @param count count 162 | */ 163 | private static void setBadgeOfSumsung(Context context, int count) { 164 | String launcherClassName = AppInfoUtil.getLauncherClassName(context); 165 | if (launcherClassName == null) { 166 | return; 167 | } 168 | Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); 169 | intent.putExtra("badge_count", count); 170 | intent.putExtra("badge_count_package_name", context.getPackageName()); 171 | intent.putExtra("badge_count_class_name", launcherClassName); 172 | context.sendBroadcast(intent); 173 | } 174 | 175 | /** 176 | * 设置HTC的Badge 177 | * 178 | * @param context context 179 | * @param count count 180 | */ 181 | private static void setBadgeOfHTC(Context context, int count) { 182 | Intent intentNotification = new Intent("com.htc.launcher.action.SET_NOTIFICATION"); 183 | ComponentName localComponentName = new ComponentName(context.getPackageName(), 184 | AppInfoUtil.getLauncherClassName(context)); 185 | intentNotification.putExtra("com.htc.launcher.extra.COMPONENT", localComponentName.flattenToShortString()); 186 | intentNotification.putExtra("com.htc.launcher.extra.COUNT", count); 187 | context.sendBroadcast(intentNotification); 188 | 189 | Intent intentShortcut = new Intent("com.htc.launcher.action.UPDATE_SHORTCUT"); 190 | intentShortcut.putExtra("packagename", context.getPackageName()); 191 | intentShortcut.putExtra("count", count); 192 | context.sendBroadcast(intentShortcut); 193 | } 194 | 195 | /** 196 | * 设置Nova的Badge 197 | * 198 | * @param context context 199 | * @param count count 200 | */ 201 | private static void setBadgeOfNova(Context context, int count) { 202 | ContentValues contentValues = new ContentValues(); 203 | contentValues.put("tag", context.getPackageName() + "/" + 204 | AppInfoUtil.getLauncherClassName(context)); 205 | contentValues.put("count", count); 206 | context.getContentResolver().insert(Uri.parse("content://com.teslacoilsw.notifier/unread_count"), 207 | contentValues); 208 | } 209 | 210 | public static void setBadgeOfMadMode(Context context, int count, String packageName, String className) { 211 | Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); 212 | intent.putExtra("badge_count", count); 213 | intent.putExtra("badge_count_package_name", packageName); 214 | intent.putExtra("badge_count_class_name", className); 215 | context.sendBroadcast(intent); 216 | } 217 | 218 | /** 219 | * 重置Badge 220 | * 221 | * @param context context 222 | * @param icon icon 223 | */ 224 | public static void resetBadgeCount(Context context,int icon) { 225 | 226 | setBadgeCount(context, 0,icon); 227 | } 228 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Peng fei Pan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.alenbeyond.androidutils.utils; 18 | 19 | import java.util.Stack; 20 | 21 | /** 22 | *

数组工具类,提供一些有关数组的便捷方法

23 | * 24 | *
1、增删移动相关 25 | *
    (1.01)、以无损的方式,将数组objects的元素从索引headIndex处开始到endIndex索引处结束的元素,向后移动number位:static 26 | * void backwardByLossless(Object[] objects, int headIndex, int endIndex, int 27 | * number) 28 | *
    (1.02)、以无损的方式,将数组objects的元素从索引headIndex处开始到endIndex索引处结束的元素,向前移动number位:static 29 | * void forwardByLossless(Object[] objects, int headIndex, int endIndex, int 30 | * number) 31 | *
    (1.03)、以有损的方式,将数组objects的元素从索引headIndex处开始到endIndex索引处结束的元素,向后移动number位:static 32 | * void backwardLoss(Object[] objects, int headIndex, int endIndex, int number) 33 | *
    (1.04)、以有损的方式,将数组objects的元素从索引headIndex处开始到endIndex索引处结束的元素,向前移动number位:static 34 | * void forwardLoss(Object[] objects, int headIndex, int endIndex, int number) 35 | *
    (1.05)、以有损的方式在数组objects的索引insertToIndex处插入元素element:static 36 | * void insert(Object[] objects, int insertToIndex, Object element) 37 | *
    (1.06)、将数组objects中索引removeIndex出的元素删除:static 38 | * Object remove(Object[] objects, int removeIndex) 39 | *
    (1.07)、返回数组objects的字符串表示形式:static String 40 | * toString(Object[] objects) 41 | *
    (1.08)、在数组哦objects中搜索元素element:static int 42 | * search(Object[] objects, Object element) 43 | *
    (1.09)、将数组objects中索引setIndex出的元素用element替换:static 44 | * Object set(Object[] objects, Object element, int setIndex) 45 | *
46 | *
2、Int数组排序相关 47 | *
    (2.01)、使用选择排序法,对数组intArray进行排序:static void 48 | * SortingByChoose(int[] intArray, int type) 49 | *
    (2.02)、使用插入排序法,对数组intArray进行排序:static void 50 | * SortingByInsert(int[] intArray, int type) 51 | *
    (2.03)、使用冒泡排序法,对数组intArray进行排序:static void 52 | * SortingByBubbling(int[] intArray, int type) 53 | *
    (2.04)、使用递归快排法,对数组intArray进行排序:static void 54 | * SortingByFastRecursion(int[] intArray, int start, int end, int type) 55 | *
    (2.05)、使用栈快排法,对数组intArray进行排序:static void 56 | * SortingByFastStack(int[] intArray, int type) 57 | */ 58 | public class ArrayUtils { 59 | 60 | /** 61 | * (1.08)、在数组objects中搜索元素element 62 | * 63 | * @param objects 待操作的数组 64 | * @param element 待匹配的元素 65 | * @return 索引,如不存在,-1 66 | */ 67 | public static int search(Object[] objects, Object element) { 68 | int e = -1; 69 | for (int w = 0; w < objects.length; w++) { 70 | if (!element.equals(objects[w])) { 71 | continue; 72 | } 73 | else { 74 | e = w; 75 | break; 76 | } 77 | } 78 | return e; 79 | } 80 | /* **************************************************************1、增删移动相关over************************************************************ */ 81 | 82 | 83 | 84 | 85 | /* **************************************************************2、Int数组排序相关start************************************************************ */ 86 | 87 | 88 | /** 89 | * (2.01)、使用选择排序法,对数组intArray进行排序 90 | * 91 | * @param intArray 待排序的数组 92 | * @param ascending 升序 93 | */ 94 | public static void sortingByChoose(int[] intArray, boolean ascending) { 95 | for (int cankaozhi = 0; cankaozhi < intArray.length - 1; cankaozhi++) { 96 | int zhongjian = intArray[cankaozhi]; 97 | int zuixiao = 0; 98 | for (int zujian = cankaozhi + 1; 99 | zujian <= intArray.length - 1; 100 | zujian++) { 101 | boolean typee = true; 102 | if (ascending) { 103 | typee = zhongjian > intArray[zujian]; 104 | } 105 | else { 106 | typee = zhongjian < intArray[zujian]; 107 | } 108 | if (typee) { 109 | zhongjian = intArray[zujian]; 110 | zuixiao = zujian; 111 | } 112 | } 113 | 114 | if (zuixiao != 0) { 115 | int f = intArray[zuixiao]; 116 | intArray[zuixiao] = intArray[cankaozhi]; 117 | intArray[cankaozhi] = f; 118 | } 119 | } 120 | } 121 | 122 | 123 | /** 124 | * (2.02)、使用插入排序法,对数组intArray进行排序 125 | * 126 | * @param intArray 待排序的数组 127 | * @param ascending 升序 128 | */ 129 | public static void sortingByInsert(int[] intArray, boolean ascending) { 130 | for (int i = 1; i < intArray.length; i++) { 131 | int t = intArray[i]; 132 | int y = -1; 133 | for (int j = i - 1; j >= 0; j--) { 134 | boolean typee = true; 135 | if (ascending) { 136 | typee = t < intArray[j]; 137 | } 138 | else { 139 | typee = t > intArray[j]; 140 | } 141 | if (!typee) break; 142 | intArray[j + 1] = intArray[j]; 143 | y = j; 144 | } 145 | 146 | if (y > -1) intArray[y] = t; 147 | } 148 | } 149 | 150 | 151 | /** 152 | * (2.03)、使用冒泡排序法,对数组intArray进行排序 153 | * 154 | * @param intArray 待排序的数组 155 | * @param ascending 升序 156 | */ 157 | public static void sortingByBubbling(int[] intArray, boolean ascending) { 158 | for (int e = 0; e < intArray.length - 1; e++) { 159 | for (int r = 0; r < intArray.length - 1; r++) { 160 | boolean typee = true; 161 | if (ascending) { 162 | typee = intArray[r] > intArray[r + 1]; 163 | } 164 | else { 165 | typee = intArray[r] < intArray[r + 1]; 166 | } 167 | if (typee) { 168 | int t = intArray[r]; 169 | intArray[r] = intArray[r + 1]; 170 | intArray[r + 1] = t; 171 | } 172 | } 173 | } 174 | } 175 | 176 | 177 | /** 178 | * (2.04)、使用递归快排法,对数组intArray进行排序 179 | * 180 | * @param intArray 待排序的数组 181 | * @param ascending 排序的方式,用本类中的静态字段指定 182 | */ 183 | public static void sortingByFastRecursion(int[] intArray, int start, int end, boolean ascending) { 184 | int tmp = intArray[start]; 185 | int i = start; 186 | 187 | if (ascending) { 188 | for (int j = end; i < j; ) { 189 | while (intArray[j] > tmp && i < j) { 190 | j--; 191 | } 192 | if (i < j) { 193 | intArray[i] = intArray[j]; 194 | i++; 195 | } 196 | for (; intArray[i] < tmp && i < j; i++) { 197 | ; 198 | } 199 | if (i < j) { 200 | intArray[j] = intArray[i]; 201 | j--; 202 | } 203 | } 204 | } 205 | else { 206 | for (int j = end; i < j; ) { 207 | while (intArray[j] < tmp && i < j) { 208 | j--; 209 | } 210 | if (i < j) { 211 | intArray[i] = intArray[j]; 212 | i++; 213 | } 214 | for (; intArray[i] > tmp && i < j; i++) { 215 | ; 216 | } 217 | if (i < j) { 218 | intArray[j] = intArray[i]; 219 | j--; 220 | } 221 | } 222 | } 223 | 224 | intArray[i] = tmp; 225 | if (start < i - 1) { 226 | sortingByFastRecursion(intArray, start, i - 1, ascending); 227 | } 228 | if (end > i + 1) { 229 | sortingByFastRecursion(intArray, i + 1, end, ascending); 230 | } 231 | } 232 | 233 | 234 | /** 235 | * (2.05)、使用栈快排法,对数组intArray进行排序 236 | * 237 | * @param intArray 待排序的数组 238 | * @param ascending 升序 239 | */ 240 | public static void sortingByFastStack(int[] intArray, boolean ascending) { 241 | Stack sa = new Stack(); 242 | sa.push(0); 243 | sa.push(intArray.length - 1); 244 | while (!sa.isEmpty()) { 245 | int end = ((Integer) sa.pop()).intValue(); 246 | int start = ((Integer) sa.pop()).intValue(); 247 | int i = start; 248 | int j = end; 249 | int tmp = intArray[i]; 250 | if (ascending) { 251 | while (i < j) { 252 | while (intArray[j] > tmp && i < j) { 253 | j--; 254 | } 255 | if (i < j) { 256 | intArray[i] = intArray[j]; 257 | i++; 258 | } 259 | for (; intArray[i] < tmp && i < j; i++) { 260 | ; 261 | } 262 | if (i < j) { 263 | intArray[j] = intArray[i]; 264 | j--; 265 | } 266 | } 267 | } 268 | else { 269 | while (i < j) { 270 | while (intArray[j] < tmp && i < j) { 271 | j--; 272 | } 273 | if (i < j) { 274 | intArray[i] = intArray[j]; 275 | i++; 276 | } 277 | for (; intArray[i] > tmp && i < j; i++) { 278 | ; 279 | } 280 | if (i < j) { 281 | intArray[j] = intArray[i]; 282 | j--; 283 | } 284 | } 285 | } 286 | 287 | intArray[i] = tmp; 288 | if (start < i - 1) { 289 | sa.push(Integer.valueOf(start)); 290 | sa.push(Integer.valueOf(i - 1)); 291 | } 292 | if (end > i + 1) { 293 | sa.push(Integer.valueOf(i + 1)); 294 | sa.push(Integer.valueOf(end)); 295 | } 296 | } 297 | } 298 | /* **************************************************************2、Int数组排序相关over************************************************************ */ 299 | 300 | 301 | /** 302 | * 将数组颠倒 303 | */ 304 | public static Object[] upsideDown(Object[] objects) { 305 | int length = objects.length; 306 | Object tem; 307 | for (int w = 0; w < length / 2; w++) { 308 | tem = objects[w]; 309 | objects[w] = objects[length - 1 - w]; 310 | objects[length - 1 - w] = tem; 311 | tem = null; 312 | } 313 | return objects; 314 | } 315 | 316 | 317 | /** 318 | * Inteher数组转换成int数组 319 | */ 320 | public static int[] integersToInts(Integer[] integers) { 321 | int[] ints = new int[integers.length]; 322 | for (int w = 0; w < integers.length; w++) { 323 | ints[w] = integers[w]; 324 | } 325 | return ints; 326 | } 327 | 328 | 329 | /** 330 | * 将给定的数组转换成字符串 331 | * 332 | * @param integers 给定的数组 333 | * @param startSymbols 开始符号 334 | * @param separator 分隔符 335 | * @param endSymbols 结束符号 336 | * @return 例如开始符号为"{",分隔符为", ",结束符号为"}",那么结果为:{1, 2, 3} 337 | */ 338 | public static String toString(int[] integers, String startSymbols, String separator, String endSymbols) { 339 | boolean addSeparator = false; 340 | StringBuffer sb = new StringBuffer(); 341 | //如果开始符号不为null且不空 342 | if (StringUtils.isNotEmpty(startSymbols)) { 343 | sb.append(startSymbols); 344 | } 345 | 346 | //循环所有的对象 347 | for (int object : integers) { 348 | //如果需要添加分隔符 349 | if (addSeparator) { 350 | sb.append(separator); 351 | addSeparator = false; 352 | } 353 | sb.append(object); 354 | addSeparator = true; 355 | } 356 | 357 | //如果结束符号不为null且不空 358 | if (StringUtils.isNotEmpty(endSymbols)) { 359 | sb.append(endSymbols); 360 | } 361 | return sb.toString(); 362 | } 363 | 364 | 365 | /** 366 | * 将给定的数组转换成字符串 367 | * 368 | * @param integers 给定的数组 369 | * @param separator 分隔符 370 | * @return 例如分隔符为", "那么结果为:1, 2, 3 371 | */ 372 | public static String toString(int[] integers, String separator) { 373 | return toString(integers, null, separator, null); 374 | } 375 | 376 | 377 | /** 378 | * 将给定的数组转换成字符串,默认分隔符为", " 379 | * 380 | * @param integers 给定的数组 381 | * @return 例如:1, 2, 3 382 | */ 383 | public static String toString(int[] integers) { 384 | return toString(integers, null, ", ", null); 385 | } 386 | 387 | 388 | /** 389 | * 将给定的数组转换成字符串 390 | * 391 | * @param objects 给定的数组 392 | * @param startSymbols 开始符号 393 | * @param separator 分隔符 394 | * @param endSymbols 结束符号 395 | * @return 例如开始符号为"{",分隔符为", ",结束符号为"}",那么结果为:{1, 2, 3} 396 | */ 397 | public static String toString(Object[] objects, String startSymbols, String separator, String endSymbols) { 398 | boolean addSeparator = false; 399 | StringBuffer sb = new StringBuffer(); 400 | //如果开始符号不为null且不空 401 | if (StringUtils.isNotEmpty(startSymbols)) { 402 | sb.append(startSymbols); 403 | } 404 | 405 | //循环所有的对象 406 | for (Object object : objects) { 407 | //如果需要添加分隔符 408 | if (addSeparator) { 409 | sb.append(separator); 410 | addSeparator = false; 411 | } 412 | sb.append(object); 413 | addSeparator = true; 414 | } 415 | 416 | //如果结束符号不为null且不空 417 | if (StringUtils.isNotEmpty(endSymbols)) { 418 | sb.append(endSymbols); 419 | } 420 | return sb.toString(); 421 | } 422 | 423 | 424 | /** 425 | * 将给定的数组转换成字符串 426 | * 427 | * @param objects 给定的数组 428 | * @param separator 分隔符 429 | * @return 例如分隔符为", "那么结果为:1, 2, 3 430 | */ 431 | public static String toString(Object[] objects, String separator) { 432 | return toString(objects, null, separator, null); 433 | } 434 | 435 | 436 | /** 437 | * 将给定的数组转换成字符串,默认分隔符为", " 438 | * 439 | * @param objects 给定的数组 440 | * @return 例如:1, 2, 3 441 | */ 442 | public static String toString(Object[] objects) { 443 | return toString(objects, null, ", ", null); 444 | } 445 | } -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/ReflectUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.ParameterizedType; 7 | import java.util.ArrayList; 8 | import java.util.Collection; 9 | import java.util.List; 10 | 11 | /** 12 | * 反射工具类,提供一些Java基本的反射功能 13 | */ 14 | public class ReflectUtils { 15 | public static final Class[] EMPTY_PARAM_TYPES = new Class[0]; 16 | public static final Object[] EMPTY_PARAMS = new Object[0]; 17 | 18 | /* ************************************************** 字段相关的方法 ******************************************************* */ 19 | /** 20 | * 从指定的类中获取指定的字段 21 | * @param sourceClass 指定的类 22 | * @param fieldName 要获取的字段的名字 23 | * @param isFindDeclaredField 是否查找Declared字段 24 | * @param isUpwardFind 是否向上去其父类中寻找 25 | * @return 26 | */ 27 | public static Field getField(Class sourceClass, String fieldName, boolean isFindDeclaredField, boolean isUpwardFind){ 28 | Field field = null; 29 | try { 30 | field = isFindDeclaredField ? sourceClass.getDeclaredField(fieldName) : sourceClass.getField(fieldName); 31 | } catch (NoSuchFieldException e1) { 32 | if(isUpwardFind){ 33 | Class classs = sourceClass.getSuperclass(); 34 | while(field == null && classs != null){ 35 | try { 36 | field = isFindDeclaredField ? classs.getDeclaredField(fieldName) : classs.getField(fieldName); 37 | } catch (NoSuchFieldException e11) { 38 | classs = classs.getSuperclass(); 39 | } 40 | } 41 | } 42 | } 43 | return field; 44 | } 45 | /** 46 | * 从指定的类中获取指定的字段,默认获取Declared类型的字段、向上查找 47 | * @param sourceClass 指定的类 48 | * @param fieldName 要获取的字段的名字 49 | * @return 50 | */ 51 | public static Field getField(Class sourceClass, String fieldName){ 52 | return getField(sourceClass, fieldName, true, true); 53 | } 54 | 55 | /** 56 | * 获取给定类的所有字段 57 | * @param sourceClass 给定的类 58 | * @param isGetDeclaredField 是否需要获取Declared字段 59 | * @param isGetParentField 是否需要把其父类中的字段也取出 60 | * @param isGetAllParentField 是否需要把所有父类中的字段全取出 61 | * @param isDESCGet 在最终获取的列表里,父类的字段是否需要排在子类的前面。只有需要把其父类中的字段也取出时此参数才有效 62 | * @return 给定类的所有字段 63 | */ 64 | public static List getFields(Class sourceClass, boolean isGetDeclaredField, boolean isGetParentField, boolean isGetAllParentField, boolean isDESCGet){ 65 | List fieldList = new ArrayList(); 66 | //如果需要从父类中获取 67 | if(isGetParentField){ 68 | //获取当前类的所有父类 69 | List> classList = null; 70 | if(isGetAllParentField){ 71 | classList = getSuperClasss(sourceClass, true); 72 | }else{ 73 | classList = new ArrayList>(2); 74 | classList.add(sourceClass); 75 | Class superClass = sourceClass.getSuperclass(); 76 | if(superClass != null){ 77 | classList.add(superClass); 78 | } 79 | } 80 | 81 | //如果是降序获取 82 | if(isDESCGet){ 83 | for(int w = classList.size()-1; w > -1; w--){ 84 | for(Field field : isGetDeclaredField ? classList.get(w).getDeclaredFields() : classList.get(w).getFields()){ 85 | fieldList.add(field); 86 | } 87 | } 88 | }else{ 89 | for(int w = 0; w < classList.size(); w++){ 90 | for(Field field : isGetDeclaredField ? classList.get(w).getDeclaredFields() : classList.get(w).getFields()){ 91 | fieldList.add(field); 92 | } 93 | } 94 | } 95 | }else{ 96 | for(Field field : isGetDeclaredField ? sourceClass.getDeclaredFields() : sourceClass.getFields()){ 97 | fieldList.add(field); 98 | } 99 | } 100 | return fieldList; 101 | } 102 | 103 | /** 104 | * 获取给定类的所有字段 105 | * @param sourceClass 给定的类 106 | * @return 给定类的所有字段 107 | */ 108 | public static List getFields(Class sourceClass){ 109 | return getFields(sourceClass, true, true, true, true); 110 | } 111 | 112 | /** 113 | * 设置给定的对象中给定名称的字段的值 114 | * @param object 给定的对象 115 | * @param fieldName 要设置的字段的名称 116 | * @param newValue 要设置的字段的值 117 | * @param isFindDeclaredField 是否查找Declared字段 118 | * @param isUpwardFind 如果在当前类中找不到的话,是否取其父类中查找 119 | * @return 设置是否成功。false:字段不存在或新的值与字段的类型不一样,导致转型失败 120 | */ 121 | public static boolean setField(Object object, String fieldName, Object newValue, boolean isFindDeclaredField, boolean isUpwardFind){ 122 | boolean result = false; 123 | Field field = getField(object.getClass(), fieldName, isFindDeclaredField, isUpwardFind); 124 | if(field != null){ 125 | try { 126 | field.setAccessible(true); 127 | field.set(object, newValue); 128 | result = true; 129 | } catch (IllegalAccessException e) { 130 | e.printStackTrace(); 131 | result = false; 132 | } 133 | } 134 | return result; 135 | } 136 | 137 | 138 | /* ************************************************** 方法相关的方法 ******************************************************* */ 139 | /** 140 | * 从指定的类中获取指定的方法 141 | * @param sourceClass 给定的类 142 | * @param isFindDeclaredMethod 是否查找Declared字段 143 | * @param isUpwardFind 是否向上去其父类中寻找 144 | * @param methodName 要获取的方法的名字 145 | * @param methodParameterTypes 方法参数类型 146 | * @return 给定的类中给定名称以及给定参数类型的方法 147 | */ 148 | public static Method getMethod(Class sourceClass, boolean isFindDeclaredMethod, boolean isUpwardFind, String methodName, Class... methodParameterTypes){ 149 | Method method = null; 150 | try { 151 | method = isFindDeclaredMethod ? sourceClass.getDeclaredMethod(methodName, methodParameterTypes) : sourceClass.getMethod(methodName, methodParameterTypes); 152 | } catch (NoSuchMethodException e1) { 153 | if(isUpwardFind){ 154 | Class classs = sourceClass.getSuperclass(); 155 | while(method == null && classs != null){ 156 | try { 157 | method = isFindDeclaredMethod ? classs.getDeclaredMethod(methodName, methodParameterTypes) : classs.getMethod(methodName, methodParameterTypes); 158 | } catch (NoSuchMethodException e11) { 159 | classs = classs.getSuperclass(); 160 | } 161 | } 162 | } 163 | } 164 | return method; 165 | } 166 | 167 | /** 168 | * 从指定的类中获取指定的方法,默认获取Declared类型的方法、向上查找 169 | * @param sourceClass 指定的类 170 | * @param methodName 方法名 171 | * @param methodParameterTypes 方法参数类型 172 | * @return 173 | */ 174 | public static Method getMethod(Class sourceClass, String methodName, Class... methodParameterTypes){ 175 | return getMethod(sourceClass, true, true, methodName, methodParameterTypes); 176 | } 177 | 178 | /** 179 | * 从指定的类中获取指定名称的不带任何参数的方法,默认获取Declared类型的方法并且向上查找 180 | * @param sourceClass 指定的类 181 | * @param methodName 方法名 182 | * @return 183 | */ 184 | public static Method getMethod(Class sourceClass, String methodName){ 185 | return getMethod(sourceClass, methodName, EMPTY_PARAM_TYPES); 186 | } 187 | 188 | /** 189 | * 获取给定类的所有方法 190 | * @param clas 给定的类 191 | * @param isGetDeclaredMethod 是否需要获取Declared方法 192 | * @param isFromSuperClassGet 是否需要把其父类中的方法也取出 193 | * @param isDESCGet 在最终获取的列表里,父类的方法是否需要排在子类的前面。只有需要把其父类中的方法也取出时此参数才有效 194 | * @return 给定类的所有方法 195 | */ 196 | public static List getMethods(Class clas, boolean isGetDeclaredMethod, boolean isFromSuperClassGet, boolean isDESCGet){ 197 | List methodList = new ArrayList(); 198 | //如果需要从父类中获取 199 | if(isFromSuperClassGet){ 200 | //获取当前类的所有父类 201 | List> classList = getSuperClasss(clas, true); 202 | 203 | //如果是降序获取 204 | if(isDESCGet){ 205 | for(int w = classList.size()-1; w > -1; w--){ 206 | for(Method method : isGetDeclaredMethod ? classList.get(w).getDeclaredMethods() : classList.get(w).getMethods()){ 207 | methodList.add(method); 208 | } 209 | } 210 | }else{ 211 | for(int w = 0; w < classList.size(); w++){ 212 | for(Method method : isGetDeclaredMethod ? classList.get(w).getDeclaredMethods() : classList.get(w).getMethods()){ 213 | methodList.add(method); 214 | } 215 | } 216 | } 217 | }else{ 218 | for(Method method : isGetDeclaredMethod ? clas.getDeclaredMethods() : clas.getMethods()){ 219 | methodList.add(method); 220 | } 221 | } 222 | return methodList; 223 | } 224 | 225 | /** 226 | * 获取给定类的所有方法 227 | * @param sourceClass 给定的类 228 | * @return 给定类的所有方法 229 | */ 230 | public static List getMethods(Class sourceClass){ 231 | return getMethods(sourceClass, true, true, true); 232 | } 233 | 234 | /** 235 | * 获取给定的类中指定参数类型的ValuOf方法 236 | * @param sourceClass 给定的类 237 | * @param methodParameterTypes 方法参数类型 238 | * @return 给定的类中给定名称的字段的GET方法 239 | */ 240 | public static Method getValueOfMethod(Class sourceClass, Class... methodParameterTypes){ 241 | return getMethod(sourceClass, true, true, "valueOf", methodParameterTypes); 242 | } 243 | 244 | /** 245 | * 调用不带参数的方法 246 | * @param method 247 | * @param object 248 | * @return 249 | * @throws Exception 250 | */ 251 | public static Object invokeMethod(Method method, Object object) throws 252 | Exception { 253 | return method.invoke(object, EMPTY_PARAMS); 254 | } 255 | 256 | /* ************************************************** 构造函数相关的方法 ******************************************************* */ 257 | /** 258 | * 获取给定的类中给定参数类型的构造函数 259 | * @param sourceClass 给定的类 260 | * @param isFindDeclaredConstructor 是否查找Declared构造函数 261 | * @param isUpwardFind 是否向上去其父类中寻找 262 | * @param constructorParameterTypes 构造函数的参数类型 263 | * @return 给定的类中给定参数类型的构造函数 264 | */ 265 | public static Constructor getConstructor(Class sourceClass, boolean isFindDeclaredConstructor, boolean isUpwardFind, Class... constructorParameterTypes){ 266 | Constructor method = null; 267 | try { 268 | method = isFindDeclaredConstructor ? sourceClass.getDeclaredConstructor(constructorParameterTypes) : sourceClass.getConstructor(constructorParameterTypes); 269 | } catch (NoSuchMethodException e1) { 270 | if(isUpwardFind){ 271 | Class classs = sourceClass.getSuperclass(); 272 | while(method == null && classs != null){ 273 | try { 274 | method = isFindDeclaredConstructor ? sourceClass.getDeclaredConstructor(constructorParameterTypes) : sourceClass.getConstructor(constructorParameterTypes); 275 | } catch (NoSuchMethodException e11) { 276 | classs = classs.getSuperclass(); 277 | } 278 | } 279 | } 280 | } 281 | return method; 282 | } 283 | 284 | /** 285 | * 获取给定的类中所有的构造函数 286 | * @param sourceClass 给定的类 287 | * @param isFindDeclaredConstructor 是否需要获取Declared构造函数 288 | * @param isFromSuperClassGet 是否需要把其父类中的构造函数也取出 289 | * @param isDESCGet 在最终获取的列表里,父类的构造函数是否需要排在子类的前面。只有需要把其父类中的构造函数也取出时此参数才有效 290 | * @return 给定的类中所有的构造函数 291 | */ 292 | public static List> getConstructors(Class sourceClass, boolean isFindDeclaredConstructor, boolean isFromSuperClassGet, boolean isDESCGet){ 293 | List> constructorList = new ArrayList>(); 294 | //如果需要从父类中获取 295 | if(isFromSuperClassGet){ 296 | //获取当前类的所有父类 297 | List> classList = getSuperClasss(sourceClass, true); 298 | 299 | //如果是降序获取 300 | if(isDESCGet){ 301 | for(int w = classList.size()-1; w > -1; w--){ 302 | for(Constructor constructor : isFindDeclaredConstructor ? classList.get(w).getDeclaredConstructors() : classList.get(w).getConstructors()){ 303 | constructorList.add(constructor); 304 | } 305 | } 306 | }else{ 307 | for(int w = 0; w < classList.size(); w++){ 308 | for(Constructor constructor : isFindDeclaredConstructor ? classList.get(w).getDeclaredConstructors() : classList.get(w).getConstructors()){ 309 | constructorList.add(constructor); 310 | } 311 | } 312 | } 313 | }else{ 314 | for(Constructor constructor : isFindDeclaredConstructor ? sourceClass.getDeclaredConstructors() : sourceClass.getConstructors()){ 315 | constructorList.add(constructor); 316 | } 317 | } 318 | return constructorList; 319 | } 320 | 321 | 322 | /* ************************************************** 父类相关的方法 ******************************************************* */ 323 | /** 324 | * 获取给定的类所有的父类 325 | * @param sourceClass 给定的类 326 | * @param isAddCurrentClass 是否将当年类放在最终返回的父类列表的首位 327 | * @return 给定的类所有的父类 328 | */ 329 | public static List> getSuperClasss(Class sourceClass, boolean isAddCurrentClass){ 330 | List> classList = new ArrayList>(); 331 | Class classs; 332 | if(isAddCurrentClass){ 333 | classs = sourceClass; 334 | }else{ 335 | classs = sourceClass.getSuperclass(); 336 | } 337 | while(classs != null){ 338 | classList.add(classs); 339 | classs = classs.getSuperclass(); 340 | } 341 | return classList; 342 | } 343 | 344 | 345 | /* ************************************************** 其它的辅助方法 ******************************************************* */ 346 | /** 347 | * 获取给定的类的名字 348 | * @param sourceClass 给定的类 349 | * @return 给定的类的名字 350 | */ 351 | public static String getClassName(Class sourceClass){ 352 | String classPath = sourceClass.getName(); 353 | return classPath.substring(classPath.lastIndexOf('.')+1); 354 | } 355 | 356 | @SuppressWarnings("unchecked") 357 | public static T getObjectByFieldName(Object object, String fieldName, Class clas){ 358 | if(object != null && StringUtils.isNotEmpty(fieldName) && clas != null){ 359 | try { 360 | Field field = ReflectUtils.getField(object.getClass(), fieldName, true, true); 361 | if(field != null){ 362 | field.setAccessible(true); 363 | return (T) field.get(object); 364 | }else{ 365 | return null; 366 | } 367 | } catch (Exception e) { 368 | e.printStackTrace(); 369 | return null; 370 | } 371 | }else{ 372 | return null; 373 | } 374 | } 375 | 376 | /** 377 | * 判断给定字段是否是type类型的数组 378 | * @param field 379 | * @param type 380 | * @return 381 | */ 382 | public static final boolean isArrayByType(Field field, Class type){ 383 | Class fieldType = field.getType(); 384 | return fieldType.isArray() && type.isAssignableFrom(fieldType.getComponentType()); 385 | } 386 | 387 | /** 388 | * 判断给定字段是否是type类型的collectionType集合,例如collectionType=List.class,type=Date.class就是要判断给定字段是否是Date类型的List 389 | * @param field 390 | * @param collectionType 391 | * @param type 392 | * @return 393 | */ 394 | @SuppressWarnings("rawtypes") 395 | public static final boolean isCollectionByType(Field field, Class collectionType, Class type){ 396 | Class fieldType = field.getType(); 397 | if(collectionType.isAssignableFrom(fieldType)){ 398 | Class 399 | first = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; 400 | return type.isAssignableFrom(first); 401 | }else{ 402 | return false; 403 | } 404 | } 405 | } 406 | -------------------------------------------------------------------------------- /app/src/main/java/com/alenbeyond/androidutils/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package com.alenbeyond.androidutils.utils; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.File; 5 | 6 | import java.io.FileFilter; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.security.MessageDigest; 10 | import java.security.cert.CertificateException; 11 | import java.security.cert.CertificateFactory; 12 | import java.security.cert.X509Certificate; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.regex.Pattern; 16 | 17 | import android.app.ActivityManager; 18 | import android.app.ActivityManager.MemoryInfo; 19 | import android.app.ActivityManager.RunningAppProcessInfo; 20 | import android.app.ActivityManager.RunningServiceInfo; 21 | import android.app.ActivityManager.RunningTaskInfo; 22 | import android.content.ComponentName; 23 | import android.content.Context; 24 | import android.content.Intent; 25 | import android.content.pm.ApplicationInfo; 26 | import android.content.pm.PackageInfo; 27 | import android.content.pm.PackageManager; 28 | import android.content.pm.PackageManager.NameNotFoundException; 29 | import android.content.pm.Signature; 30 | import android.net.Uri; 31 | import android.text.TextUtils; 32 | 33 | import javax.security.auth.x500.X500Principal; 34 | 35 | /** 36 | * APP工具类 37 | * APP相关信息工具类。获取版本信息 38 | */ 39 | public final class AppUtils { 40 | 41 | /** 42 | * 得到软件版本号 43 | * 44 | * @param context 上下文 45 | * @return 当前版本Code 46 | */ 47 | public static int getVerCode(Context context) { 48 | int verCode = -1; 49 | try { 50 | String packageName = context.getPackageName(); 51 | verCode = context.getPackageManager() 52 | .getPackageInfo(packageName, 0).versionCode; 53 | } catch (NameNotFoundException e) { 54 | e.printStackTrace(); 55 | } 56 | return verCode; 57 | } 58 | 59 | 60 | /** 61 | * 获取应用运行的最大内存 62 | * 63 | * @return 最大内存 64 | */ 65 | public static long getMaxMemory() { 66 | 67 | return Runtime.getRuntime().maxMemory() / 1024; 68 | } 69 | 70 | 71 | /** 72 | * 得到软件显示版本信息 73 | * 74 | * @param context 上下文 75 | * @return 当前版本信息 76 | */ 77 | public static String getVerName(Context context) { 78 | String verName = ""; 79 | try { 80 | String packageName = context.getPackageName(); 81 | verName = context.getPackageManager() 82 | .getPackageInfo(packageName, 0).versionName; 83 | } catch (NameNotFoundException e) { 84 | e.printStackTrace(); 85 | } 86 | return verName; 87 | } 88 | 89 | 90 | /** 91 | * 安装apk 92 | * 93 | * @param context 上下文 94 | * @param file APK文件 95 | */ 96 | public static void installApk(Context context, File file) { 97 | Intent intent = new Intent(); 98 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 99 | intent.setAction(Intent.ACTION_VIEW); 100 | intent.setDataAndType(Uri.fromFile(file), 101 | "application/vnd.android.package-archive"); 102 | context.startActivity(intent); 103 | } 104 | 105 | 106 | /** 107 | * 安装apk 108 | * 109 | * @param context 上下文 110 | * @param file APK文件uri 111 | */ 112 | public static void installApk(Context context, Uri file) { 113 | Intent intent = new Intent(); 114 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 115 | intent.setAction(Intent.ACTION_VIEW); 116 | intent.setDataAndType(file, "application/vnd.android.package-archive"); 117 | context.startActivity(intent); 118 | } 119 | 120 | 121 | /** 122 | * 卸载apk 123 | * 124 | * @param context 上下文 125 | * @param packageName 包名 126 | */ 127 | public static void uninstallApk(Context context, String packageName) { 128 | Intent intent = new Intent(Intent.ACTION_DELETE); 129 | Uri packageURI = Uri.parse("package:" + packageName); 130 | intent.setData(packageURI); 131 | context.startActivity(intent); 132 | } 133 | 134 | 135 | /** 136 | * 检测服务是否运行 137 | * 138 | * @param context 上下文 139 | * @param className 类名 140 | * @return 是否运行的状态 141 | */ 142 | public static boolean isServiceRunning(Context context, String className) { 143 | boolean isRunning = false; 144 | ActivityManager activityManager 145 | = (ActivityManager) context.getSystemService( 146 | Context.ACTIVITY_SERVICE); 147 | List servicesList 148 | = activityManager.getRunningServices(Integer.MAX_VALUE); 149 | for (RunningServiceInfo si : servicesList) { 150 | if (className.equals(si.service.getClassName())) { 151 | isRunning = true; 152 | } 153 | } 154 | return isRunning; 155 | } 156 | 157 | 158 | /** 159 | * 停止运行服务 160 | * 161 | * @param context 上下文 162 | * @param className 类名 163 | * @return 是否执行成功 164 | */ 165 | public static boolean stopRunningService(Context context, String className) { 166 | Intent intent_service = null; 167 | boolean ret = false; 168 | try { 169 | intent_service = new Intent(context, Class.forName(className)); 170 | } catch (Exception e) { 171 | e.printStackTrace(); 172 | } 173 | if (intent_service != null) { 174 | ret = context.stopService(intent_service); 175 | } 176 | return ret; 177 | } 178 | 179 | 180 | /** 181 | * 得到CPU核心数 182 | * 183 | * @return CPU核心数 184 | */ 185 | public static int getNumCores() { 186 | try { 187 | File dir = new File("/sys/devices/system/cpu/"); 188 | File[] files = dir.listFiles(new FileFilter() { 189 | @Override 190 | public boolean accept(File pathname) { 191 | if (Pattern.matches("cpu[0-9]", pathname.getName())) { 192 | return true; 193 | } 194 | return false; 195 | } 196 | }); 197 | return files.length; 198 | } catch (Exception e) { 199 | return 1; 200 | } 201 | } 202 | 203 | 204 | /** 205 | * whether this process is named with processName 206 | * 207 | * @param context 上下文 208 | * @param processName 进程名 209 | * @return 是否含有当前的进程 210 | */ 211 | public static boolean isNamedProcess(Context context, String processName) { 212 | if (context == null || TextUtils.isEmpty(processName)) { 213 | return false; 214 | } 215 | 216 | int pid = android.os.Process.myPid(); 217 | ActivityManager manager = (ActivityManager) context.getSystemService( 218 | Context.ACTIVITY_SERVICE); 219 | List processInfoList 220 | = manager.getRunningAppProcesses(); 221 | if (processInfoList == null) { 222 | return true; 223 | } 224 | 225 | for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { 226 | if (processInfo.pid == pid && 227 | processName.equalsIgnoreCase(processInfo.processName)) { 228 | return true; 229 | } 230 | } 231 | return false; 232 | } 233 | 234 | 235 | /** 236 | * 检测应用是否后台运行 237 | * 权限 android.permission.GET_TASKS 238 | * 239 | * @param context 上下文 240 | */ 241 | public static boolean isApplicationInBackground(Context context) { 242 | ActivityManager am = (ActivityManager) context.getSystemService( 243 | Context.ACTIVITY_SERVICE); 244 | List taskList = am.getRunningTasks(1); 245 | if (taskList != null && !taskList.isEmpty()) { 246 | ComponentName topActivity = taskList.get(0).topActivity; 247 | if (topActivity != null && !topActivity.getPackageName() 248 | .equals(context.getPackageName())) { 249 | return true; 250 | } 251 | } 252 | return false; 253 | } 254 | 255 | 256 | /** 257 | * 获取应用签名 258 | * 259 | * @param context 上下文 260 | * @param pkgName 包名 261 | * @return 返回应用的签名 262 | */ 263 | public static String getSign(Context context, String pkgName) { 264 | try { 265 | PackageInfo pis = context.getPackageManager() 266 | .getPackageInfo(pkgName, 267 | PackageManager.GET_SIGNATURES); 268 | return hexdigest(pis.signatures[0].toByteArray()); 269 | } catch (NameNotFoundException e) { 270 | e.printStackTrace(); 271 | return null; 272 | } 273 | 274 | } 275 | 276 | 277 | /** 278 | * 将签名字符串转换成需要的32位签名 279 | * 280 | * @param paramArrayOfByte 签名byte数组 281 | * @return 32位签名字符串 282 | */ 283 | private static String hexdigest(byte[] paramArrayOfByte) { 284 | final char[] hexDigits = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 285 | 98, 99, 100, 101, 102}; 286 | try { 287 | MessageDigest localMessageDigest = MessageDigest.getInstance("MD5"); 288 | localMessageDigest.update(paramArrayOfByte); 289 | byte[] arrayOfByte = localMessageDigest.digest(); 290 | char[] arrayOfChar = new char[32]; 291 | for (int i = 0, j = 0; ; i++, j++) { 292 | if (i >= 16) { 293 | return new String(arrayOfChar); 294 | } 295 | int k = arrayOfByte[i]; 296 | arrayOfChar[j] = hexDigits[(0xF & k >>> 4)]; 297 | arrayOfChar[++j] = hexDigits[(k & 0xF)]; 298 | } 299 | } catch (Exception e) { 300 | e.printStackTrace(); 301 | } 302 | return ""; 303 | } 304 | 305 | 306 | /** 307 | * 清理后台进程与服务 308 | * 309 | * @param context 应用上下文对象context 310 | * @return 被清理的数量 311 | */ 312 | public static int gc(Context context) { 313 | long i = getDeviceUsableMemory(context); 314 | int count = 0; // 清理掉的进程数 315 | ActivityManager am = (ActivityManager) context.getSystemService( 316 | Context.ACTIVITY_SERVICE); 317 | // 获取正在运行的service列表 318 | List serviceList = am.getRunningServices(100); 319 | if (serviceList != null) { 320 | for (RunningServiceInfo service : serviceList) { 321 | if (service.pid == android.os.Process.myPid()) continue; 322 | try { 323 | android.os.Process.killProcess(service.pid); 324 | count++; 325 | } catch (Exception e) { 326 | e.getStackTrace(); 327 | } 328 | } 329 | } 330 | 331 | // 获取正在运行的进程列表 332 | List processList = am.getRunningAppProcesses(); 333 | if (processList != null) { 334 | for (RunningAppProcessInfo process : processList) { 335 | // 一般数值大于RunningAppProcessInfo.IMPORTANCE_SERVICE的进程都长时间没用或者空进程了 336 | // 一般数值大于RunningAppProcessInfo.IMPORTANCE_VISIBLE的进程都是非可见进程,也就是在后台运行着 337 | if (process.importance > 338 | RunningAppProcessInfo.IMPORTANCE_VISIBLE) { 339 | // pkgList 得到该进程下运行的包名 340 | String[] pkgList = process.pkgList; 341 | for (String pkgName : pkgList) { 342 | try { 343 | am.killBackgroundProcesses(pkgName); 344 | count++; 345 | } catch (Exception e) { // 防止意外发生 346 | e.getStackTrace(); 347 | } 348 | } 349 | } 350 | } 351 | } 352 | return count; 353 | } 354 | 355 | 356 | /** 357 | * 获取设备的可用内存大小 358 | * 359 | * @param context 应用上下文对象context 360 | * @return 当前内存大小 361 | */ 362 | public static int getDeviceUsableMemory(Context context) { 363 | ActivityManager am = (ActivityManager) context.getSystemService( 364 | Context.ACTIVITY_SERVICE); 365 | MemoryInfo mi = new MemoryInfo(); 366 | am.getMemoryInfo(mi); 367 | // 返回当前系统的可用内存 368 | return (int) (mi.availMem / (1024 * 1024)); 369 | } 370 | 371 | 372 | /** 373 | * 获取系统中所有的应用 374 | * 375 | * @param context 上下文 376 | * @return 应用信息List 377 | */ 378 | public static List getAllApps(Context context) { 379 | 380 | List apps = new ArrayList(); 381 | PackageManager pManager = context.getPackageManager(); 382 | List paklist = pManager.getInstalledPackages(0); 383 | for (int i = 0; i < paklist.size(); i++) { 384 | PackageInfo pak = paklist.get(i); 385 | if ((pak.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 386 | 0) { 387 | // customs applications 388 | apps.add(pak); 389 | } 390 | } 391 | return apps; 392 | } 393 | 394 | 395 | /** 396 | * 获取手机系统SDK版本 397 | * 398 | * @return 如API 17 则返回 17 399 | */ 400 | public static int getSDKVersion() { 401 | return android.os.Build.VERSION.SDK_INT; 402 | } 403 | 404 | 405 | /** 406 | * 是否Dalvik模式 407 | * 408 | * @return 结果 409 | */ 410 | public static boolean isDalvik() { 411 | return "Dalvik".equals(getCurrentRuntimeValue()); 412 | } 413 | 414 | 415 | /** 416 | * 是否ART模式 417 | * 418 | * @return 结果 419 | */ 420 | public static boolean isART() { 421 | String currentRuntime = getCurrentRuntimeValue(); 422 | return "ART".equals(currentRuntime) || 423 | "ART debug build".equals(currentRuntime); 424 | } 425 | 426 | 427 | /** 428 | * 获取手机当前的Runtime 429 | * 430 | * @return 正常情况下可能取值Dalvik, ART, ART debug build; 431 | */ 432 | public static String getCurrentRuntimeValue() { 433 | try { 434 | Class systemProperties = Class.forName( 435 | "android.os.SystemProperties"); 436 | try { 437 | Method get = systemProperties.getMethod("get", String.class, 438 | String.class); 439 | if (get == null) { 440 | return "WTF?!"; 441 | } 442 | try { 443 | final String value = (String) get.invoke(systemProperties, 444 | "persist.sys.dalvik.vm.lib", 445 | /* Assuming default is */"Dalvik"); 446 | if ("libdvm.so".equals(value)) { 447 | return "Dalvik"; 448 | } else if ("libart.so".equals(value)) { 449 | return "ART"; 450 | } else if ("libartd.so".equals(value)) { 451 | return "ART debug build"; 452 | } 453 | 454 | return value; 455 | } catch (IllegalAccessException e) { 456 | return "IllegalAccessException"; 457 | } catch (IllegalArgumentException e) { 458 | return "IllegalArgumentException"; 459 | } catch (InvocationTargetException e) { 460 | return "InvocationTargetException"; 461 | } 462 | } catch (NoSuchMethodException e) { 463 | return "SystemProperties.get(String key, String def) method is not found"; 464 | } 465 | } catch (ClassNotFoundException e) { 466 | return "SystemProperties class is not found"; 467 | } 468 | } 469 | 470 | 471 | private final static X500Principal DEBUG_DN = new X500Principal( 472 | "CN=Android Debug,O=Android,C=US"); 473 | 474 | 475 | /** 476 | * 检测当前应用是否是Debug版本 477 | * 478 | * @param ctx 上下文 479 | * @return 是否是Debug版本 480 | */ 481 | public static boolean isDebuggable(Context ctx) { 482 | boolean debuggable = false; 483 | try { 484 | PackageInfo pinfo = ctx.getPackageManager() 485 | .getPackageInfo(ctx.getPackageName(), 486 | PackageManager.GET_SIGNATURES); 487 | Signature signatures[] = pinfo.signatures; 488 | for (int i = 0; i < signatures.length; i++) { 489 | CertificateFactory cf = CertificateFactory.getInstance("X.509"); 490 | ByteArrayInputStream stream = new ByteArrayInputStream( 491 | signatures[i].toByteArray()); 492 | X509Certificate cert = (X509Certificate) cf.generateCertificate( 493 | stream); 494 | debuggable = cert.getSubjectX500Principal().equals(DEBUG_DN); 495 | if (debuggable) break; 496 | } 497 | } catch (NameNotFoundException e) { 498 | } catch (CertificateException e) { 499 | } 500 | return debuggable; 501 | } 502 | 503 | 504 | /** 505 | * 比较版本号的大小,前者大则返回一个正数,后者大返回一个负数,相等则返回0 支持4.1.2,4.1.23.4.1.rc111这种形式 506 | * 507 | * @param version1 508 | * @param version2 509 | * @return 510 | */ 511 | public static int compareVersion(String version1, String version2) throws Exception { 512 | if (version1 == null || version2 == null) { 513 | throw new Exception("compareVersion error:illegal params."); 514 | } 515 | String[] versionArray1 = version1.split("\\.");//注意此处为正则匹配,不能用"."; 516 | String[] versionArray2 = version2.split("\\."); 517 | int idx = 0; 518 | int minLength = Math.min(versionArray1.length, versionArray2.length);//取最小长度值 519 | int diff = 0; 520 | while (idx < minLength 521 | && (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0//先比较长度 522 | && (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {//再比较字符 523 | ++idx; 524 | } 525 | //如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大; 526 | diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length; 527 | return diff; 528 | } 529 | 530 | } --------------------------------------------------------------------------------