Commit 7ab02daa95f3da691b6f0c538f5ab2dd09bab98b

Authored by 韩亚云
2 parents f761e5b0 ee599ef7

Merge branch 'master' of bj.gitlab.cnlive.com:cnlive-team/newModuleStrike

Showing 42 changed files with 10322 additions and 442 deletions
app/strike/build.gradle
... ... @@ -107,7 +107,7 @@ android {
107 107 zipAlignEnabled true // 是否支持zip
108 108 // shrinkResources true // 移除无用的resource文件
109 109 minifyEnabled false // 是否对代码进行混淆,true表示混淆
110   - debuggable false //是否支持调试
  110 + debuggable true //是否支持调试
111 111 // proguardFiles getDefaultProguardFile('proguard-android.txt'),
112 112 // 'proguard-rules.pro'
113 113  
... ...
app/strike/src/main/AndroidManifest.xml
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:tools="http://schemas.android.com/tools"
3 4 package="com.cnlive.strike">
4 5  
5 6 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
6 7 <uses-permission android:name="android.permission.INTERNET" />
7 8 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
8 9 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
9   -
10 10 <application
11 11 android:name=".MyApp"
12 12 android:allowBackup="true"
... ... @@ -16,6 +16,7 @@
16 16 android:roundIcon="@mipmap/ic_launcher_round"
17 17 android:supportsRtl="true"
18 18 android:theme="@style/AppTheme">
  19 +
19 20 <activity android:name=".demo.activity.DemoActivity" />
20 21 <activity android:name=".MyActivity"></activity>
21 22 <activity android:name=".imgutil.ImgActivity" />
... ...
app/strike/src/main/java/com/cnlive/strike/MyActivity.java
1 1 package com.cnlive.strike;
2 2  
3 3  
4   -import android.content.Intent;
5 4 import android.text.TextUtils;
6 5 import android.view.View;
7 6  
8 7 import com.alibaba.android.arouter.facade.annotation.Route;
9 8 import com.cnlive.core.libs.base.frame.activity.BaseActivity;
10   -import com.cnlive.core.network.HttpConn;
11   -import com.cnlive.core.network.NetCallBack;
12   -import com.cnlive.core.network.model.BaseResult;
13   -import com.cnlive.libs.wjjpay.model.GroupBalanceInfo;
14   -import com.cnlive.libs.wjjpay.pay.WjjPay;
  9 +import com.cnlive.core.libs.base.util.NetworkUtil;
15 10 import com.cnlive.moudle.pedometer.commonInfo.CommonInfo;
16   -import com.cnlive.moudle.pedometer.ui.activity.RunLineActivity;
17 11 import com.cnlive.strike.databinding.ActivityMyBinding;
18 12 import com.cnlive.strike.user.auth.UserService;
19 13 import com.cnlive.strike.xiaojiaspeaker.commonInfo.XiaoJIaCommInfo;
20   -import com.cnlive.strike.xiaojiaspeaker.ui.activity.AllDeviceActivity;
21   -import com.cnlive.strike.xiaojiaspeaker.util.QMUITipDialogUtil;
22 14  
23 15 @Route(path = "/strick/MyActivity")
24 16 public class MyActivity extends BaseActivity {
... ... @@ -44,7 +36,10 @@ public class MyActivity extends BaseActivity {
44 36 binding.btnChange.setOnClickListener(new View.OnClickListener() {
45 37 @Override
46 38 public void onClick(View v) {
47   - startActivity(new Intent(MyActivity.this, RunLineActivity.class));
  39 +// Bitmap bitmap=ImageUtils.drawable2Bitmap(getResources().getDrawable(R.mipmap.timg));
  40 + binding.btnChange.setText(NetworkUtil.getNetWorkType(me) + "");
  41 + binding.ivImg.setImageBitmap(screenShot());
  42 +// startActivity(new Intent(MyActivity.this, RunLineActivity.class));
48 43  
49 44 // WjjPay.passwordIsExisting(UserService.getUid(me), new NetCallBack<BaseResult<GroupBalanceInfo>>() {
50 45 // @Override
... ...
app/strike/src/main/res/layout/activity_my.xml
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <layout>
3 3  
4   - <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4 + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
5 5 xmlns:app="http://schemas.android.com/apk/res-auto"
6 6 xmlns:tools="http://schemas.android.com/tools"
7 7 android:layout_width="match_parent"
8 8 android:layout_height="match_parent"
9 9 tools:context="com.cnlive.strike.MyActivity">
10 10  
11   - <RelativeLayout
  11 + <LinearLayout
12 12 android:id="@+id/fragment_container"
13 13 android:layout_width="match_parent"
14   - android:layout_height="match_parent">
  14 + android:layout_height="match_parent"
  15 + android:orientation="vertical">
15 16  
16 17 <TextView
17 18 android:layout_width="wrap_content"
... ... @@ -23,6 +24,11 @@
23 24 android:layout_width="wrap_content"
24 25 android:layout_height="wrap_content"
25 26 android:text="修改支付密码" />
26   - </RelativeLayout>
27   - </RelativeLayout>
  27 +
  28 + <ImageView
  29 + android:id="@+id/iv_img"
  30 + android:layout_width="100dp"
  31 + android:layout_height="100dp" />
  32 + </LinearLayout>
  33 + </LinearLayout>
28 34 </layout>
29 35 \ No newline at end of file
... ...
build.gradle
... ... @@ -29,22 +29,10 @@ allprojects {
29 29 }
30 30 }
31 31  
32   -////配置全局变量
33   -//ext {
34   -// def versionMajor = 1
35   -// def versionMinor = 5
36   -// def versionPatch = 6
37   -// def versionBuild = 0
38   -// // module依赖库公共版本号
39   -// versionCode = versionMajor * 1000 + versionMinor * 100 + versionPatch * 10 + versionBuild
40   -// versionName = "${versionMajor}.${versionMinor}.${versionPatch}.${versionBuild}"
41   -//
42   -// compileSdkVersion = 29
43   -// buildToolsVersion = "29.0.2"
44   -// minSdkVersion = 19
45   -// targetSdkVersion = 29
46   -//}
47 32 allprojects {
  33 +// configurations.all {
  34 +////// resolutionStrategy.force 'androidx.appcompat:appcompat:1.1.0'
  35 +// }
48 36 afterEvaluate {
49 37 if (project.parent == null || project.parent == rootProject) return
50 38  
... ... @@ -69,7 +57,21 @@ allprojects {
69 57 ]
70 58 }
71 59 }
72   -
  60 + //解决引用glide-transformations冲突问题
  61 + packagingOptions {
  62 + exclude "lib/armeabi-v7a/libRSSupport.so"
  63 + exclude "lib/arm64-v8a/librsjni.so"
  64 + exclude "lib/arm64-v8a/libRSSupport.so"
  65 + exclude "lib/x86_64/libRSSupport.so"
  66 + exclude "lib/x86/librsjni.so"
  67 + exclude "lib/x86_64/librsjni.so"
  68 + exclude "lib/armeabi-v7a/librsjni.so"
  69 + exclude "lib/x86/libRSSupport.so"
  70 + exclude "lib/x86_64/librsjni_androidx.so"
  71 + exclude "lib/x86/librsjni_androidx.so"
  72 + exclude "lib/arm64-v8a/librsjni_androidx.so"
  73 + exclude "lib/armeabi-v7a/librsjni_androidx.so"
  74 + }
73 75 ndk {
74 76 abiFilters(
75 77 "armeabi-v7a"
... ...
cloud/user/src/main/java/com/cnlive/strike/user/auth/UserAccountAuthenticator.java
... ... @@ -8,8 +8,7 @@ import android.accounts.NetworkErrorException;
8 8 import android.content.Context;
9 9 import android.content.Intent;
10 10 import android.os.Bundle;
11   -
12   -import com.cnlive.core.libs.base.util.LogUtil;
  11 +import android.util.Log;
13 12  
14 13  
15 14 public class UserAccountAuthenticator extends AbstractAccountAuthenticator {
... ... @@ -22,7 +21,7 @@ public class UserAccountAuthenticator extends AbstractAccountAuthenticator {
22 21 }
23 22  
24 23 public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) {
25   - LogUtil.d(_tag, accountType + " - " + authTokenType);
  24 + Log.d(_tag, accountType + " - " + authTokenType);
26 25 Bundle ret = new Bundle();
27 26 try {
28 27 Class<?> clazz = Class.forName("com.cnlive.strike.moudle.user.ui.activity.LoginActivity");
... ... @@ -38,42 +37,42 @@ public class UserAccountAuthenticator extends AbstractAccountAuthenticator {
38 37  
39 38 @Override
40 39 public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) {
41   - LogUtil.d(_tag, ".confirmCredentials");
  40 + Log.d(_tag, ".confirmCredentials");
42 41 return null;
43 42 }
44 43  
45 44  
46 45 @Override
47 46 public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
48   - LogUtil.d(_tag, ".editProperties");
  47 + Log.d(_tag, ".editProperties");
49 48 return null;
50 49 }
51 50  
52 51  
53 52 @Override
54 53 public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws NetworkErrorException {
55   - LogUtil.d(_tag, ".getAuthToken");
  54 + Log.d(_tag, ".getAuthToken");
56 55 return null;
57 56 }
58 57  
59 58  
60 59 @Override
61 60 public String getAuthTokenLabel(String authTokenType) {
62   - LogUtil.d(_tag, ".getAuthTokenLabel");
  61 + Log.d(_tag, ".getAuthTokenLabel");
63 62 return null;
64 63 }
65 64  
66 65  
67 66 @Override
68 67 public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
69   - LogUtil.d(_tag, ".hasFeatures");
  68 + Log.d(_tag, ".hasFeatures");
70 69 return null;
71 70 }
72 71  
73 72  
74 73 @Override
75 74 public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) {
76   - LogUtil.d(_tag, ".updateCredentials");
  75 + Log.d(_tag, ".updateCredentials");
77 76 return null;
78 77 }
79 78  
... ...
cloud/user/src/main/java/com/cnlive/strike/user/frame/presenter/QuickLoginPresenter.java
... ... @@ -9,7 +9,7 @@ import com.cnlive.core.libs.base.frame.presenter.BasePresenter;
9 9 import com.cnlive.core.network.model.BaseResult;
10 10 import com.cnlive.core.network.HttpConn;
11 11 import com.cnlive.core.network.NetCallBack;
12   -import com.cnlive.core.libs.base.util.TimerUtil;
  12 +import com.cnlive.core.libs.base.util.TimerWaitUtil;
13 13 import com.cnlive.strike.user.R;
14 14 import com.cnlive.strike.user.UserUtilAction;
15 15 import com.cnlive.strike.user.auth.UserService;
... ... @@ -34,7 +34,7 @@ import io.reactivex.disposables.Disposable;
34 34 */
35 35  
36 36 public class QuickLoginPresenter extends BasePresenter<QuickLoginView> {
37   - private TimerUtil timerUtil; //计时工具类
  37 + private TimerWaitUtil timerUtil; //计时工具类
38 38  
39 39 private Disposable event;
40 40 private Disposable sendMsgBefQuickLogin;
... ... @@ -69,11 +69,11 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; {
69 69 private void startTimer() {
70 70 if (timerUtil != null) timerUtil.cancel();
71 71  
72   - timerUtil = new TimerUtil();
  72 + timerUtil = new TimerWaitUtil();
73 73 timerUtil.setTotalTime(60_000);//设置毫秒数
74 74 timerUtil.setIntervalTime(500);//设置间隔数
75 75 timerUtil.start();
76   - timerUtil.setTimerLiener(new TimerUtil.TimeListener() {
  76 + timerUtil.setTimerLiener(new TimerWaitUtil.TimeListener() {
77 77 @Override
78 78 public void onFinish() {
79 79 ifViewAttached(view -> view.onTimerFinish());
... ...
cloud/user/src/main/java/com/cnlive/strike/user/ui/activity/FirstLoginActivity.java
1 1 package com.cnlive.strike.user.ui.activity;
2 2  
3   -import android.content.Intent;
4 3 import android.os.Bundle;
5 4 import android.text.TextUtils;
6 5  
7   -import androidx.annotation.NonNull;
8   -import androidx.fragment.app.FragmentManager;
9   -
10 6 import com.cnlive.core.libs.base.frame.activity.BaseActivity;
11 7 import com.cnlive.core.libs.base.util.AlertUtil;
12 8 import com.cnlive.core.libs.base.util.DoublePressed;
13   -import com.cnlive.core.libs.base.util.FragmentUtil;
14 9 import com.cnlive.strike.user.R;
15 10 import com.cnlive.strike.user.ui.fragment.FirstLoginFragment;
16 11  
... ...
cloud/user/src/main/java/com/cnlive/strike/user/ui/activity/LoginActivity.java
... ... @@ -6,17 +6,11 @@ import android.content.Intent;
6 6 import android.net.Uri;
7 7  
8 8 import androidx.annotation.NonNull;
9   -import androidx.fragment.app.Fragment;
10   -import androidx.fragment.app.FragmentManager;
11 9  
12 10 import com.alibaba.android.arouter.facade.annotation.Route;
13 11 import com.cnlive.core.libs.base.frame.activity.BaseActivity;
14 12 import com.cnlive.core.libs.base.frame.fragment.BaseFragment;
15   -import com.cnlive.core.libs.base.util.FragmentUtil;
16   -import com.cnlive.strike.user.R;
17 13 import com.cnlive.strike.user.ui.fragment.QuickLoginFragment;
18   -import com.me.yokeyword.fragmentation.anim.DefaultHorizontalAnimator;
19   -import com.me.yokeyword.fragmentation.anim.FragmentAnimator;
20 14  
21 15 /**
22 16 * @author Lynn
... ...
config.gradle
... ... @@ -20,7 +20,7 @@ ext {
20 20 //用户
21 21 core_network: project(':core:network'),
22 22 //基础库
23   - core_base: project(':core:base')
  23 + core_base : project(':core:base')
24 24  
25 25 ]
26 26  
... ... @@ -34,11 +34,15 @@ ext {
34 34 api : 'com.alibaba:arouter-api:1.5.0',
35 35 compiler: 'com.alibaba:arouter-compiler:1.2.2'
36 36 ]
  37 +
37 38 //图片加载库Glide
38 39 glide = [
39   - api : 'com.github.bumptech.glide:glide:4.10.0',
40   - transformations: 'jp.wasabeef:glide-transformations:3.0.1',
41   - compiler : 'com.github.bumptech.glide:compiler:4.10.0'
  40 + api : 'com.github.bumptech.glide:glide:4.10.0',
  41 + compiler : 'com.github.bumptech.glide:compiler:4.10.0',
  42 + //图片加载特效
  43 + transformations : 'jp.wasabeef:glide-transformations:4.1.0',
  44 + //图片滤镜
  45 + transformations_gpuimage: 'jp.co.cyberagent.android:gpuimage:2.0.4'
42 46 ]
43 47 test = [
44 48 junit : 'junit:junit:4.12',
... ... @@ -46,7 +50,7 @@ ext {
46 50 espresso: 'androidx.test.espresso:espresso-core:3.2.0'
47 51 ]
48 52  
49   - //Maven Base库配置
  53 +//Maven Base库配置
50 54 moudle_cnlive_base = [
51 55 //编译方式
52 56 debug : false,
... ... @@ -113,7 +117,9 @@ ext {
113 117 cardviewV7 : 'com.android.support:cardview-v7:28.0.0',
114 118 dataBinding : 'com.android.databinding.library:3.5.1'
115 119 ]
116   - //基础三方库
  120 +
  121 +
  122 +//基础三方库
117 123 base_librarys = [
118 124 library.logger,
119 125 //视讯云加密库
... ... @@ -137,6 +143,7 @@ ext {
137 143 //图片加载Glide
138 144 glide.api,
139 145 glide.transformations,
  146 + glide.transformations_gpuimage,
140 147 //使用androidx
141 148 androidx.appcompat,
142 149 androidx.constraintlayout,
... ... @@ -164,7 +171,8 @@ ext {
164 171 router.compiler
165 172 ]
166 173  
167   - //正式签名配置
  174 +
  175 +//正式签名配置
168 176 Properties properties = new Properties()
169 177 properties.load(project.rootProject.file('local.properties').newDataInputStream())
170 178  
... ...
core/base/src/main/java/com/cnlive/core/libs/base/frame/activity/BaseActivity.java
... ... @@ -7,6 +7,9 @@ import android.content.DialogInterface;
7 7 import android.content.Intent;
8 8 import android.content.pm.ActivityInfo;
9 9 import android.content.pm.PackageManager;
  10 +import android.content.res.Configuration;
  11 +import android.content.res.Resources;
  12 +import android.graphics.Bitmap;
10 13 import android.graphics.Point;
11 14 import android.net.Uri;
12 15 import android.os.Build;
... ... @@ -24,6 +27,7 @@ import android.view.inputmethod.InputMethodManager;
24 27 import androidx.annotation.ColorInt;
25 28 import androidx.annotation.ColorRes;
26 29 import androidx.annotation.DrawableRes;
  30 +import androidx.annotation.IntDef;
27 31 import androidx.annotation.IntRange;
28 32 import androidx.annotation.NonNull;
29 33 import androidx.annotation.Nullable;
... ... @@ -59,6 +63,10 @@ import com.me.yokeyword.fragmentation_swipeback.core.ISwipeBackActivity;
59 63 import com.me.yokeyword.fragmentation_swipeback.core.SwipeBackActivityDelegate;
60 64 import com.orhanobut.logger.Logger;
61 65  
  66 +import java.lang.annotation.ElementType;
  67 +import java.lang.annotation.Retention;
  68 +import java.lang.annotation.RetentionPolicy;
  69 +import java.lang.annotation.Target;
62 70 import java.lang.reflect.Field;
63 71 import java.util.ArrayList;
64 72 import java.util.List;
... ... @@ -214,6 +222,94 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
214 222 isAllowScreenRoate = allowScreenRoate;
215 223 }
216 224  
  225 +
  226 + /**
  227 + * 设置屏幕为横屏
  228 + * Set the screen to landscape.
  229 + */
  230 + public void setLandscape() {
  231 + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
  232 + }
  233 +
  234 + /**
  235 + * 设置屏幕为竖屏
  236 + * Set the screen to portrait.
  237 + */
  238 + public void setPortrait() {
  239 + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  240 + }
  241 +
  242 +
  243 + /**
  244 + * 是否横屏
  245 + * Return whether screen is landscape.
  246 + *
  247 + * @return {@code true}: yes<br>{@code false}: no
  248 + */
  249 + public boolean isLandscape() {
  250 + return getResources().getConfiguration().orientation
  251 + == Configuration.ORIENTATION_LANDSCAPE;
  252 + }
  253 +
  254 + /**
  255 + * 是否竖屏
  256 + * Return whether screen is portrait.
  257 + *
  258 + * @return {@code true}: yes<br>{@code false}: no
  259 + */
  260 + public boolean isPortrait() {
  261 + return getResources().getConfiguration().orientation
  262 + == Configuration.ORIENTATION_PORTRAIT;
  263 + }
  264 +
  265 + /**
  266 + * 截屏
  267 + * Return the bitmap of screen.
  268 + *
  269 + * @return the bitmap of screen
  270 + */
  271 + public Bitmap screenShot() {
  272 + return screenShot(this, false);
  273 + }
  274 +
  275 + public Bitmap screenShot(boolean isDeleteStatusBar) {
  276 + return screenShot(this, isDeleteStatusBar);
  277 + }
  278 +
  279 + /**
  280 + * Return the bitmap of screen.
  281 + *
  282 + * @param activity The activity.
  283 + * @param isDeleteStatusBar True to delete status bar, false otherwise.
  284 + * @return the bitmap of screen
  285 + */
  286 + private Bitmap screenShot(@NonNull final Activity activity, boolean isDeleteStatusBar) {
  287 + View decorView = activity.getWindow().getDecorView();
  288 + decorView.setDrawingCacheEnabled(true);
  289 + decorView.setWillNotCacheDrawing(false);
  290 + Bitmap bmp = decorView.getDrawingCache();
  291 + if (bmp == null) return null;
  292 + DisplayMetrics dm = new DisplayMetrics();
  293 + activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
  294 + Bitmap ret;
  295 + if (isDeleteStatusBar) {
  296 + Resources resources = activity.getResources();
  297 + int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
  298 + int statusBarHeight = resources.getDimensionPixelSize(resourceId);
  299 + ret = Bitmap.createBitmap(
  300 + bmp,
  301 + 0,
  302 + statusBarHeight,
  303 + dm.widthPixels,
  304 + dm.heightPixels - statusBarHeight
  305 + );
  306 + } else {
  307 + ret = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels);
  308 + }
  309 + decorView.destroyDrawingCache();
  310 + return ret;
  311 + }
  312 +
217 313 /**
218 314 * 保证同一按钮在1秒内只会响应一次点击事件
219 315 */
... ... @@ -235,18 +331,6 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
235 331 }
236 332  
237 333 /**
238   - * 同一按钮在短时间内可重复响应点击事件
239   - */
240   - public abstract class OnMultiClickListener implements View.OnClickListener {
241   - public abstract void onMultiClick(View view);
242   -
243   - @Override
244   - public void onClick(View v) {
245   - onMultiClick(v);
246   - }
247   - }
248   -
249   - /**
250 334 * 隐藏软键盘
251 335 */
252 336 public void hideSoftInput() {
... ... @@ -270,7 +354,6 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
270 354 * 显示软键盘
271 355 */
272 356 public void showSoftInput(View view) {
273   - // InputMethodManager.SHOW_FORCED);
274 357 InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
275 358 imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
276 359 }
... ... @@ -339,7 +422,8 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
339 422 /**
340 423 * 设置状态栏字体颜色
341 424 */
342   - public void setStatusBarTextColor(int type) {
  425 + // 定义适用于参数的注解,限定取值范围为{STATUS_OPEN, STATUS_CLOSE}
  426 + public void setStatusBarTextColor(@StatusBarConfig.Unit final int type) {
343 427 if (type == StatusBarConfig.BLACK) {
344 428 StatusBarUtil.setStatusBarWrite(this);
345 429 } else if (type == StatusBarConfig.WHITE) {
... ... @@ -366,7 +450,6 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
366 450 return view;
367 451 }
368 452  
369   - // protected abstract int getLayoutId();
370 453 protected int getBindLayoutId() {
371 454 return 0;
372 455 }
... ...
core/base/src/main/java/com/cnlive/core/libs/base/frame/fragment/BaseFragment.java
... ... @@ -2,13 +2,12 @@ package com.cnlive.core.libs.base.frame.fragment;
2 2  
3 3 import android.app.Activity;
4 4 import android.content.Intent;
5   -import android.content.pm.ActivityInfo;
  5 +import android.graphics.Bitmap;
6 6 import android.os.Bundle;
7 7 import android.view.LayoutInflater;
8 8 import android.view.View;
9 9 import android.view.ViewGroup;
10 10 import android.view.animation.Animation;
11   -import android.view.inputmethod.InputMethodManager;
12 11  
13 12 import androidx.annotation.ColorInt;
14 13 import androidx.annotation.ColorRes;
... ... @@ -17,7 +16,6 @@ import androidx.annotation.IntRange;
17 16 import androidx.annotation.NonNull;
18 17 import androidx.annotation.Nullable;
19 18 import androidx.annotation.StringRes;
20   -import androidx.core.content.ContextCompat;
21 19 import androidx.databinding.DataBindingUtil;
22 20 import androidx.databinding.ViewDataBinding;
23 21  
... ... @@ -26,11 +24,9 @@ import com.cnlive.core.libs.base.frame.activity.BaseActivity;
26 24 import com.cnlive.core.libs.base.frame.presenter.BasePresenter;
27 25 import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener;
28 26 import com.cnlive.core.libs.base.network.manager.SubscriptionManager;
29   -import com.cnlive.core.libs.base.util.ParameterCache;
30 27 import com.cnlive.core.libs.base.util.ReflectUtil;
31 28 import com.cnlive.core.libs.base.frame.view.BaseView;
32 29 import com.cnlive.core.libs.base.util.StatusBarConfig;
33   -import com.cnlive.core.libs.base.util.StatusBarUtil;
34 30 import com.me.yokeyword.fragmentation.ExtraTransaction;
35 31 import com.me.yokeyword.fragmentation.ISupportFragment;
36 32 import com.me.yokeyword.fragmentation.SupportFragmentDelegate;
... ... @@ -41,9 +37,6 @@ import com.me.yokeyword.fragmentation_swipeback.core.ISwipeBackFragment;
41 37 import com.me.yokeyword.fragmentation_swipeback.core.SwipeBackFragmentDelegate;
42 38 import com.orhanobut.logger.Logger;
43 39  
44   -
45   -import static android.content.Context.INPUT_METHOD_SERVICE;
46   -
47 40 /**
48 41 * 基类fragment
49 42 *
... ... @@ -232,7 +225,7 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V
232 225 /**
233 226 * 设置状态栏字体颜色
234 227 */
235   - public void setStatusBarTextColor(int type) {
  228 + public void setStatusBarTextColor(@StatusBarConfig.Unit int type) {
236 229 me.setStatusBarTextColor(type);
237 230 }
238 231  
... ... @@ -244,13 +237,56 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V
244 237 me.showSoftInput();
245 238 }
246 239  
247   -// /**
248   -// * 显示软键盘
249   -// */
250   -// public void showSoftInput(View view) {
251   -// me.showSoftInput(view);
252   -// }
  240 + /**
  241 + * 设置屏幕为横屏
  242 + * Set the screen to landscape.
  243 + */
  244 + public void setLandscape() {
  245 + me.setLandscape();
  246 + }
  247 +
  248 + /**
  249 + * 设置屏幕为竖屏
  250 + * Set the screen to portrait.
  251 + */
  252 + public void setPortrait() {
  253 + me.setPortrait();
  254 + }
  255 +
  256 +
  257 + /**
  258 + * 是否横屏
  259 + * Return whether screen is landscape.
  260 + *
  261 + * @return {@code true}: yes<br>{@code false}: no
  262 + */
  263 + public boolean isLandscape() {
  264 + return me.isLandscape();
  265 + }
  266 +
  267 + /**
  268 + * 是否竖屏
  269 + * Return whether screen is portrait.
  270 + *
  271 + * @return {@code true}: yes<br>{@code false}: no
  272 + */
  273 + public boolean isPortrait() {
  274 + return me.isPortrait();
  275 + }
253 276  
  277 + /**
  278 + * 截屏
  279 + * Return the bitmap of screen.
  280 + *
  281 + * @return the bitmap of screen
  282 + */
  283 + public Bitmap screenShot() {
  284 + return me.screenShot();
  285 + }
  286 +
  287 + public Bitmap screenShot(boolean isDeleteStatusBar) {
  288 + return me.screenShot(isDeleteStatusBar);
  289 + }
254 290  
255 291 /*********************************************************/
256 292 //用于进行dip和px转换
... ...
core/base/src/main/java/com/cnlive/core/libs/base/network/manager/SubscriptionManager.java
... ... @@ -15,16 +15,16 @@ import io.reactivex.disposables.Disposable;
15 15 * @author ys
16 16 */
17 17 public class SubscriptionManager {
18   - public static SubscriptionManager instance;
19   - public HashMap<String, CompositeDisposable> hashDisposable;//所有订阅关系
20   - public HashMap<Integer, String> hashTag;//当前activity
21   - public HashMap<String, Integer> hashTagIndex;//当前activity
  18 + private static SubscriptionManager instance;
  19 + private HashMap<String, CompositeDisposable> hashDisposable;//所有订阅关系
  20 + private HashMap<Integer, String> hashTag;//当前activity
  21 + private HashMap<String, Integer> hashTagIndex;//当前activity
22 22 private String currentClassName;
23 23  
24 24 /**
25 25 * 构造函数 new CompositeDisposable对象
26 26 */
27   - public SubscriptionManager() {
  27 + public SubscriptionManager() {
28 28 if (null == hashDisposable) {
29 29 hashDisposable = new HashMap<>();
30 30 }
... ... @@ -59,7 +59,7 @@ public class SubscriptionManager {
59 59 //存放当前class映射
60 60 hashTag.put(hashDisposable.size() - 1, TAG);
61 61 hashTagIndex.put(TAG, hashTag.size() - 1);
62   - Log.e(TAG, "初始化: ");
  62 + Log.d(TAG, "初始化: ");
63 63 }
64 64 }
65 65  
... ... @@ -89,7 +89,7 @@ public class SubscriptionManager {
89 89 hashTagIndex.remove(TAG);
90 90 }
91 91 } catch (Exception e) {
92   - Log.e(TAG, "cancel: " + e.getMessage());
  92 + Log.d(TAG, "cancel: " + e.getMessage());
93 93 }
94 94 }
95 95  
... ... @@ -99,16 +99,20 @@ public class SubscriptionManager {
99 99 * @param disposable 订阅事件
100 100 */
101 101 public synchronized void add(Disposable disposable) {
102   - if (disposable == null) return;
103   - //每次去除最新的activity进行存放
104   - if (null != hashDisposable && hashDisposable.size() > 0) {
105   - if (!TextUtils.isEmpty(currentClassName)) {
106   - if (null != hashDisposable.get(currentClassName)) {
107   - //存放当前activity对应的订阅
108   - hashDisposable.get(currentClassName).add(disposable);
109   - Log.e(currentClassName, "add: 添加订阅关系" + hashDisposable.size());
  102 + try {
  103 + if (disposable == null) return;
  104 + //每次去除最新的activity进行存放
  105 + if (null != hashDisposable && hashDisposable.size() > 0) {
  106 + if (!TextUtils.isEmpty(currentClassName)) {
  107 + if (null != hashDisposable.get(currentClassName)) {
  108 + //存放当前activity对应的订阅
  109 + hashDisposable.get(currentClassName).add(disposable);
  110 + Log.d(currentClassName, "add: 添加订阅关系" + hashDisposable.size());
  111 + }
110 112 }
111 113 }
  114 + } catch (Exception e) {
  115 + Log.e("SubscriptionManager", "cancel: " + e.getMessage());
112 116 }
113 117 }
114 118  
... ... @@ -127,20 +131,24 @@ public class SubscriptionManager {
127 131 * 清除容器所有
128 132 */
129 133 public synchronized void cancelAll() {
130   - //解除所有订阅
131   - if (null != hashDisposable && hashDisposable.size() > 0) {
132   - if (null != hashTag && hashTag.size() > 0) {
133   - for (int i = 0; i < hashTag.size(); i++) {
134   - if (null != hashTag.get(i)) {
135   - if (null != hashDisposable.get(hashTag.get(i))) {
136   - hashDisposable.get(hashTag.get(i)).clear();
  134 + try {
  135 + //解除所有订阅
  136 + if (null != hashDisposable && hashDisposable.size() > 0) {
  137 + if (null != hashTag && hashTag.size() > 0) {
  138 + for (int i = 0; i < hashTag.size(); i++) {
  139 + if (null != hashTag.get(i)) {
  140 + if (null != hashDisposable.get(hashTag.get(i))) {
  141 + hashDisposable.get(hashTag.get(i)).clear();
  142 + }
137 143 }
138 144 }
139 145 }
140 146 }
  147 + hashDisposable.clear();
  148 + hashTag.clear();
  149 + hashTagIndex.clear();
  150 + } catch (Exception e) {
  151 + Log.e("SubscriptionManager", "cancelAll: " + e.getMessage());
141 152 }
142   - hashDisposable.clear();
143   - hashTag.clear();
144   - hashTagIndex.clear();
145 153 }
146 154 }
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/ArrayUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import java.lang.reflect.Array;
  4 +import java.util.ArrayList;
  5 +import java.util.Arrays;
  6 +import java.util.Collections;
  7 +import java.util.Comparator;
  8 +import java.util.LinkedList;
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * <pre>
  13 + * author: blankj
  14 + * blog : http://blankj.com
  15 + * time : 2019/08/10
  16 + * desc : utils about array
  17 + * </pre>
  18 + * newArray : 新建数组
  19 + * newLongArray : 新建长整型数组
  20 + * newIntArray : 新建整型数组
  21 + * newShortArray : 新建 short 数组
  22 + * newCharArray : 新建字符数组
  23 + * newByteArray : 新建字节数组
  24 + * newDoubleArray : 新建双精度数组
  25 + * newFloatArray : 新建浮点数数组
  26 + * newBooleanArray : 新建 boolean 数组
  27 + * isEmpty : 判断数组是否为空
  28 + * getLength : 获取数组长度
  29 + * isSameLength : 判断两数组长度是否相等
  30 + * get : 获取数组的索引值
  31 + * set : 设置数组的索引值
  32 + * equals : 判断数组是否相等
  33 + * reverse : 逆序数组
  34 + * copy : 拷贝数组
  35 + * subArray : 截取数组
  36 + * add : 增加数组
  37 + * remove : 移除指定的索引
  38 + * removeElement : 移除指定的元素
  39 + * indexOf : 查找第一个元素的索引
  40 + * lastIndexOf : 查找最后一个元素的索引
  41 + * contains : 判断是否包含该元素
  42 + * toPrimitive : 装箱数组转基本类型数组
  43 + * toObject : 基本类型数组转装箱数组
  44 + * asList : 转为链表
  45 + * asUnmodifiableList: 转为不可变链表
  46 + * asArrayList : 转为数组链表
  47 + * asLinkedList : 转为双向链表
  48 + * sort : 排序
  49 + * forAllDo : 对所有元素做操作
  50 + * toString : 数组转为字符串
  51 + */
  52 +public class ArrayUtils {
  53 +
  54 + public static final int INDEX_NOT_FOUND = -1;
  55 +
  56 + private ArrayUtils() {
  57 + throw new UnsupportedOperationException("u can't instantiate me...");
  58 + }
  59 +
  60 + /**
  61 + * 新建数组
  62 + * Returns a new array only of those given elements.
  63 + *
  64 + * @param array The array.
  65 + * @return a new array only of those given elements.
  66 + */
  67 + @SafeVarargs
  68 + public static <T> T[] newArray(T... array) {
  69 + return array;
  70 + }
  71 +
  72 + /**
  73 + * 新建长整型数组
  74 + *
  75 + * @param array
  76 + * @return
  77 + */
  78 + public static long[] newLongArray(long... array) {
  79 + return array;
  80 + }
  81 +
  82 + /**
  83 + * 新建整型数组
  84 + *
  85 + * @param array
  86 + * @return
  87 + */
  88 + public static int[] newIntArray(int... array) {
  89 + return array;
  90 + }
  91 +
  92 + /**
  93 + * 新建 short 数组
  94 + *
  95 + * @param array
  96 + * @return
  97 + */
  98 + public static short[] newShortArray(short... array) {
  99 + return array;
  100 + }
  101 +
  102 + /**
  103 + * 新建字符数组
  104 + *
  105 + * @param array
  106 + * @return
  107 + */
  108 + public static char[] newCharArray(char... array) {
  109 + return array;
  110 + }
  111 +
  112 + /**
  113 + * 新建字节数组
  114 + *
  115 + * @param array
  116 + * @return
  117 + */
  118 + public static byte[] newByteArray(byte... array) {
  119 + return array;
  120 + }
  121 +
  122 + /**
  123 + * 新建双精度数组
  124 + *
  125 + * @param array
  126 + * @return
  127 + */
  128 + public static double[] newDoubleArray(double... array) {
  129 + return array;
  130 + }
  131 +
  132 + /**
  133 + * 新建浮点数数组
  134 + *
  135 + * @param array
  136 + * @return
  137 + */
  138 + public static float[] newFloatArray(float... array) {
  139 + return array;
  140 + }
  141 +
  142 + /**
  143 + * 新建 boolean 数组
  144 + *
  145 + * @param array
  146 + * @return
  147 + */
  148 + public static boolean[] newBooleanArray(boolean... array) {
  149 + return array;
  150 + }
  151 +
  152 + /**
  153 + * 判断数组是否为空
  154 + * Return the array is empty.
  155 + *
  156 + * @param array The array.
  157 + * @return {@code true}: yes<br>{@code false}: no
  158 + */
  159 + public static boolean isEmpty(Object array) {
  160 + return getLength(array) == 0;
  161 + }
  162 +
  163 + /**
  164 + * 获取数组长度
  165 + * Return the size of array.
  166 + *
  167 + * @param array The array.
  168 + * @return the size of array
  169 + */
  170 + public static int getLength(Object array) {
  171 + if (array == null) return 0;
  172 + return Array.getLength(array);
  173 + }
  174 +
  175 + /**
  176 + * 判断两数组长度是否相等
  177 + *
  178 + * @param array1
  179 + * @param array2
  180 + * @return
  181 + */
  182 + public static boolean isSameLength(Object array1, Object array2) {
  183 + return getLength(array1) == getLength(array2);
  184 + }
  185 +
  186 + /**
  187 + * 获取数组的索引值
  188 + * Get the value of the specified index of the array.
  189 + *
  190 + * @param array The array.
  191 + * @param index The index into the array.
  192 + * @return the value of the specified index of the array
  193 + */
  194 + public static Object get(Object array, int index) {
  195 + return get(array, index, null);
  196 + }
  197 +
  198 + /**
  199 + * 取数组的索引值,带有默认值
  200 + * Get the value of the specified index of the array.
  201 + *
  202 + * @param array The array.
  203 + * @param index The index into the array.
  204 + * @param defaultValue The default value.
  205 + * @return the value of the specified index of the array
  206 + */
  207 + public static Object get(Object array, int index, Object defaultValue) {
  208 + if (array == null) return defaultValue;
  209 + try {
  210 + return Array.get(array, index);
  211 + } catch (Exception ignore) {
  212 + return defaultValue;
  213 + }
  214 + }
  215 +
  216 + /**
  217 + * 设置数组的索引值
  218 + * Set the value of the specified index of the array.
  219 + *
  220 + * @param array The array.
  221 + * @param index The index into the array.
  222 + * @param value The new value of the indexed component.
  223 + */
  224 + public static void set(Object array, int index, Object value) {
  225 + if (array == null) return;
  226 + Array.set(array, index, value);
  227 + }
  228 +
  229 + /**
  230 + * 判断数组是否相等
  231 + * Return whether the two arrays are equals.
  232 + *
  233 + * @param a One array.
  234 + * @param a2 The other array.
  235 + * @return {@code true}: yes<br>{@code false}: no
  236 + */
  237 + public static boolean equals(Object[] a, Object[] a2) {
  238 + return Arrays.deepEquals(a, a2);
  239 + }
  240 +
  241 + public static boolean equals(boolean[] a, boolean[] a2) {
  242 + return Arrays.equals(a, a2);
  243 + }
  244 +
  245 + public static boolean equals(byte[] a, byte[] a2) {
  246 + return Arrays.equals(a, a2);
  247 + }
  248 +
  249 + public static boolean equals(char[] a, char[] a2) {
  250 + return Arrays.equals(a, a2);
  251 + }
  252 +
  253 + public static boolean equals(double[] a, double[] a2) {
  254 + return Arrays.equals(a, a2);
  255 + }
  256 +
  257 + public static boolean equals(float[] a, float[] a2) {
  258 + return Arrays.equals(a, a2);
  259 + }
  260 +
  261 + public static boolean equals(int[] a, int[] a2) {
  262 + return Arrays.equals(a, a2);
  263 + }
  264 +
  265 + public static boolean equals(short[] a, short[] a2) {
  266 + return Arrays.equals(a, a2);
  267 + }
  268 +
  269 + ///////////////////////////////////////////////////////////////////////////
  270 + // reverse
  271 + ///////////////////////////////////////////////////////////////////////////
  272 +
  273 + /**
  274 + * 逆序数组
  275 + * <p>Reverses the order of the given array.</p>
  276 + *
  277 + * <p>There is no special handling for multi-dimensional arrays.</p>
  278 + *
  279 + * <p>This method does nothing for a <code>null</code> input array.</p>
  280 + *
  281 + * @param array the array to reverse, may be <code>null</code>
  282 + */
  283 + public static <T> void reverse(T[] array) {
  284 + if (array == null) {
  285 + return;
  286 + }
  287 + int i = 0;
  288 + int j = array.length - 1;
  289 + T tmp;
  290 + while (j > i) {
  291 + tmp = array[j];
  292 + array[j] = array[i];
  293 + array[i] = tmp;
  294 + j--;
  295 + i++;
  296 + }
  297 + }
  298 +
  299 + public static void reverse(long[] array) {
  300 + if (array == null) {
  301 + return;
  302 + }
  303 + int i = 0;
  304 + int j = array.length - 1;
  305 + long tmp;
  306 + while (j > i) {
  307 + tmp = array[j];
  308 + array[j] = array[i];
  309 + array[i] = tmp;
  310 + j--;
  311 + i++;
  312 + }
  313 + }
  314 +
  315 + public static void reverse(int[] array) {
  316 + if (array == null) {
  317 + return;
  318 + }
  319 + int i = 0;
  320 + int j = array.length - 1;
  321 + int tmp;
  322 + while (j > i) {
  323 + tmp = array[j];
  324 + array[j] = array[i];
  325 + array[i] = tmp;
  326 + j--;
  327 + i++;
  328 + }
  329 + }
  330 +
  331 + public static void reverse(short[] array) {
  332 + if (array == null) {
  333 + return;
  334 + }
  335 + int i = 0;
  336 + int j = array.length - 1;
  337 + short tmp;
  338 + while (j > i) {
  339 + tmp = array[j];
  340 + array[j] = array[i];
  341 + array[i] = tmp;
  342 + j--;
  343 + i++;
  344 + }
  345 + }
  346 +
  347 + public static void reverse(char[] array) {
  348 + if (array == null) {
  349 + return;
  350 + }
  351 + int i = 0;
  352 + int j = array.length - 1;
  353 + char tmp;
  354 + while (j > i) {
  355 + tmp = array[j];
  356 + array[j] = array[i];
  357 + array[i] = tmp;
  358 + j--;
  359 + i++;
  360 + }
  361 + }
  362 +
  363 + public static void reverse(byte[] array) {
  364 + if (array == null) {
  365 + return;
  366 + }
  367 + int i = 0;
  368 + int j = array.length - 1;
  369 + byte tmp;
  370 + while (j > i) {
  371 + tmp = array[j];
  372 + array[j] = array[i];
  373 + array[i] = tmp;
  374 + j--;
  375 + i++;
  376 + }
  377 + }
  378 +
  379 + public static void reverse(double[] array) {
  380 + if (array == null) {
  381 + return;
  382 + }
  383 + int i = 0;
  384 + int j = array.length - 1;
  385 + double tmp;
  386 + while (j > i) {
  387 + tmp = array[j];
  388 + array[j] = array[i];
  389 + array[i] = tmp;
  390 + j--;
  391 + i++;
  392 + }
  393 + }
  394 +
  395 + public static void reverse(float[] array) {
  396 + if (array == null) {
  397 + return;
  398 + }
  399 + int i = 0;
  400 + int j = array.length - 1;
  401 + float tmp;
  402 + while (j > i) {
  403 + tmp = array[j];
  404 + array[j] = array[i];
  405 + array[i] = tmp;
  406 + j--;
  407 + i++;
  408 + }
  409 + }
  410 +
  411 + public static void reverse(boolean[] array) {
  412 + if (array == null) {
  413 + return;
  414 + }
  415 + int i = 0;
  416 + int j = array.length - 1;
  417 + boolean tmp;
  418 + while (j > i) {
  419 + tmp = array[j];
  420 + array[j] = array[i];
  421 + array[i] = tmp;
  422 + j--;
  423 + i++;
  424 + }
  425 + }
  426 +
  427 + ///////////////////////////////////////////////////////////////////////////
  428 + // copy
  429 + ///////////////////////////////////////////////////////////////////////////
  430 +
  431 + /**
  432 + * 拷贝数组
  433 + * <p>Copies the specified array and handling
  434 + * <code>null</code>.</p>
  435 + *
  436 + * <p>The objects in the array are not cloned, thus there is no special
  437 + * handling for multi-dimensional arrays.</p>
  438 + *
  439 + * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
  440 + *
  441 + * @param array the array to shallow clone, may be <code>null</code>
  442 + * @return the cloned array, <code>null</code> if <code>null</code> input
  443 + */
  444 + public static <T> T[] copy(T[] array) {
  445 + if (array == null) return null;
  446 + return subArray(array, 0, array.length);
  447 + }
  448 +
  449 + public static long[] copy(long[] array) {
  450 + if (array == null) return null;
  451 + return subArray(array, 0, array.length);
  452 + }
  453 +
  454 + public static int[] copy(int[] array) {
  455 + if (array == null) return null;
  456 + return subArray(array, 0, array.length);
  457 + }
  458 +
  459 + public static short[] copy(short[] array) {
  460 + if (array == null) return null;
  461 + return subArray(array, 0, array.length);
  462 + }
  463 +
  464 + public static char[] copy(char[] array) {
  465 + if (array == null) return null;
  466 + return subArray(array, 0, array.length);
  467 + }
  468 +
  469 + public static byte[] copy(byte[] array) {
  470 + if (array == null) return null;
  471 + return subArray(array, 0, array.length);
  472 + }
  473 +
  474 + public static double[] copy(double[] array) {
  475 + if (array == null) return null;
  476 + return subArray(array, 0, array.length);
  477 + }
  478 +
  479 + public static float[] copy(float[] array) {
  480 + if (array == null) return null;
  481 + return subArray(array, 0, array.length);
  482 + }
  483 +
  484 + public static boolean[] copy(boolean[] array) {
  485 + if (array == null) return null;
  486 + return subArray(array, 0, array.length);
  487 + }
  488 +
  489 + private static Object realCopy(Object array) {
  490 + if (array == null) return null;
  491 + return realSubArray(array, 0, getLength(array));
  492 + }
  493 +
  494 + ///////////////////////////////////////////////////////////////////////////
  495 + // subArray
  496 + ///////////////////////////////////////////////////////////////////////////
  497 +
  498 + /**
  499 + * 截取数组
  500 + *
  501 + * @param array
  502 + * @param startIndexInclusive
  503 + * @param endIndexExclusive
  504 + * @param <T>
  505 + * @return
  506 + */
  507 + public static <T> T[] subArray(T[] array, int startIndexInclusive, int endIndexExclusive) {
  508 + //noinspection unchecked
  509 + return (T[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  510 + }
  511 +
  512 + public static long[] subArray(long[] array, int startIndexInclusive, int endIndexExclusive) {
  513 + return (long[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  514 + }
  515 +
  516 + public static int[] subArray(int[] array, int startIndexInclusive, int endIndexExclusive) {
  517 + return (int[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  518 + }
  519 +
  520 + public static short[] subArray(short[] array, int startIndexInclusive, int endIndexExclusive) {
  521 + return (short[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  522 + }
  523 +
  524 + public static char[] subArray(char[] array, int startIndexInclusive, int endIndexExclusive) {
  525 + return (char[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  526 + }
  527 +
  528 + public static byte[] subArray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
  529 + return (byte[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  530 + }
  531 +
  532 + public static double[] subArray(double[] array, int startIndexInclusive, int endIndexExclusive) {
  533 + return (double[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  534 + }
  535 +
  536 + public static float[] subArray(float[] array, int startIndexInclusive, int endIndexExclusive) {
  537 + return (float[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  538 + }
  539 +
  540 + public static boolean[] subArray(boolean[] array, int startIndexInclusive, int endIndexExclusive) {
  541 + return (boolean[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
  542 + }
  543 +
  544 + private static Object realSubArray(Object array, int startIndexInclusive, int endIndexExclusive) {
  545 + if (array == null) {
  546 + return null;
  547 + }
  548 + if (startIndexInclusive < 0) {
  549 + startIndexInclusive = 0;
  550 + }
  551 + int length = getLength(array);
  552 + if (endIndexExclusive > length) {
  553 + endIndexExclusive = length;
  554 + }
  555 + int newSize = endIndexExclusive - startIndexInclusive;
  556 + Class type = array.getClass().getComponentType();
  557 + if (newSize <= 0) {
  558 + return Array.newInstance(type, 0);
  559 + }
  560 + Object subArray = Array.newInstance(type, newSize);
  561 + System.arraycopy(array, startIndexInclusive, subArray, 0, newSize);
  562 + return subArray;
  563 + }
  564 +
  565 + ///////////////////////////////////////////////////////////////////////////
  566 + // add
  567 + ///////////////////////////////////////////////////////////////////////////
  568 +
  569 + /**
  570 + * 增加数组
  571 + * <p>Copies the given array and adds the given element at the end of the new array.</p>
  572 + *
  573 + * <p>The new array contains the same elements of the input
  574 + * array plus the given element in the last position. The component type of
  575 + * the new array is the same as that of the input array.</p>
  576 + *
  577 + * <p>If the input array is <code>null</code>, a new one element array is returned
  578 + * whose component type is the same as the element.</p>
  579 + *
  580 + * <pre>
  581 + * ArrayUtils.realAdd(null, null) = [null]
  582 + * ArrayUtils.realAdd(null, "a") = ["a"]
  583 + * ArrayUtils.realAdd(["a"], null) = ["a", null]
  584 + * ArrayUtils.realAdd(["a"], "b") = ["a", "b"]
  585 + * ArrayUtils.realAdd(["a", "b"], "c") = ["a", "b", "c"]
  586 + * </pre>
  587 + *
  588 + * @param array the array to "realAdd" the element to, may be <code>null</code>
  589 + * @param element the object to realAdd
  590 + * @return A new array containing the existing elements plus the new element
  591 + */
  592 + public static <T> T[] add(T[] array, T element) {
  593 + Class type = array != null ? array.getClass() : (element != null ? element.getClass() : Object.class);
  594 + return (T[]) realAddOne(array, element, type);
  595 + }
  596 +
  597 + public static boolean[] add(boolean[] array, boolean element) {
  598 + return (boolean[]) realAddOne(array, element, Boolean.TYPE);
  599 + }
  600 +
  601 + public static byte[] add(byte[] array, byte element) {
  602 + return (byte[]) realAddOne(array, element, Byte.TYPE);
  603 + }
  604 +
  605 + public static char[] add(char[] array, char element) {
  606 + return (char[]) realAddOne(array, element, Character.TYPE);
  607 + }
  608 +
  609 + public static double[] add(double[] array, double element) {
  610 + return (double[]) realAddOne(array, element, Double.TYPE);
  611 + }
  612 +
  613 + public static float[] add(float[] array, float element) {
  614 + return (float[]) realAddOne(array, element, Float.TYPE);
  615 + }
  616 +
  617 + public static int[] add(int[] array, int element) {
  618 + return (int[]) realAddOne(array, element, Integer.TYPE);
  619 + }
  620 +
  621 + public static long[] add(long[] array, long element) {
  622 + return (long[]) realAddOne(array, element, Long.TYPE);
  623 + }
  624 +
  625 + public static short[] add(short[] array, short element) {
  626 + return (short[]) realAddOne(array, element, Short.TYPE);
  627 + }
  628 +
  629 + private static Object realAddOne(Object array, Object element, Class newArrayComponentType) {
  630 + Object newArray;
  631 + int arrayLength = 0;
  632 + if (array != null) {
  633 + arrayLength = getLength(array);
  634 + newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
  635 + System.arraycopy(array, 0, newArray, 0, arrayLength);
  636 + } else {
  637 + newArray = Array.newInstance(newArrayComponentType, 1);
  638 + }
  639 + Array.set(newArray, arrayLength, element);
  640 + return newArray;
  641 + }
  642 +
  643 + /**
  644 + * <p>Adds all the elements of the given arrays into a new array.</p>
  645 + * <p>The new array contains all of the element of <code>array1</code> followed
  646 + * by all of the elements <code>array2</code>. When an array is returned, it is always
  647 + * a new array.</p>
  648 + *
  649 + * <pre>
  650 + * ArrayUtils.add(null, null) = null
  651 + * ArrayUtils.add(array1, null) = copy of array1
  652 + * ArrayUtils.add(null, array2) = copy of array2
  653 + * ArrayUtils.add([], []) = []
  654 + * ArrayUtils.add([null], [null]) = [null, null]
  655 + * ArrayUtils.add(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
  656 + * </pre>
  657 + *
  658 + * @param array1 the first array whose elements are added to the new array, may be <code>null</code>
  659 + * @param array2 the second array whose elements are added to the new array, may be <code>null</code>
  660 + * @return The new array, <code>null</code> if <code>null</code> array inputs.
  661 + * The type of the new array is the type of the first array.
  662 + */
  663 + public static <T> T[] add(T[] array1, T[] array2) {
  664 + return (T[]) realAddArr(array1, array2);
  665 + }
  666 +
  667 + public static boolean[] add(boolean[] array1, boolean[] array2) {
  668 + return (boolean[]) realAddArr(array1, array2);
  669 + }
  670 +
  671 + public static char[] add(char[] array1, char[] array2) {
  672 + return (char[]) realAddArr(array1, array2);
  673 + }
  674 +
  675 + public static byte[] add(byte[] array1, byte[] array2) {
  676 + return (byte[]) realAddArr(array1, array2);
  677 + }
  678 +
  679 + public static short[] add(short[] array1, short[] array2) {
  680 + return (short[]) realAddArr(array1, array2);
  681 + }
  682 +
  683 + public static int[] add(int[] array1, int[] array2) {
  684 + return (int[]) realAddArr(array1, array2);
  685 + }
  686 +
  687 + public static long[] add(long[] array1, long[] array2) {
  688 + return (long[]) realAddArr(array1, array2);
  689 + }
  690 +
  691 + public static float[] add(float[] array1, float[] array2) {
  692 + return (float[]) realAddArr(array1, array2);
  693 + }
  694 +
  695 + public static double[] add(double[] array1, double[] array2) {
  696 + return (double[]) realAddArr(array1, array2);
  697 + }
  698 +
  699 + private static Object realAddArr(Object array1, Object array2) {
  700 + if (array1 == null && array2 == null) return null;
  701 + if (array1 == null) {
  702 + return realCopy(array2);
  703 + }
  704 + if (array2 == null) {
  705 + return realCopy(array1);
  706 + }
  707 + int len1 = getLength(array1);
  708 + int len2 = getLength(array2);
  709 + Object joinedArray = Array.newInstance(array1.getClass().getComponentType(), len1 + len2);
  710 + System.arraycopy(array1, 0, joinedArray, 0, len1);
  711 + System.arraycopy(array2, 0, joinedArray, len1, len2);
  712 + return joinedArray;
  713 + }
  714 +
  715 + /**
  716 + * <p>Inserts the specified element at the specified position in the array.
  717 + * Shifts the element currently at that position (if any) and any subsequent
  718 + * elements to the right (adds one to their indices).</p>
  719 + *
  720 + * <p>This method returns a new array with the same elements of the input
  721 + * array plus the given element on the specified position. The component
  722 + * type of the returned array is always the same as that of the input
  723 + * array.</p>
  724 + *
  725 + * <p>If the input array is <code>null</code>, a new one element array is returned
  726 + * whose component type is the same as the element.</p>
  727 + *
  728 + * <pre>
  729 + * ArrayUtils.add(null, 0, null) = [null]
  730 + * ArrayUtils.add(null, 0, "a") = ["a"]
  731 + * ArrayUtils.add(["a"], 1, null) = ["a", null]
  732 + * ArrayUtils.add(["a"], 1, "b") = ["a", "b"]
  733 + * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
  734 + * </pre>
  735 + *
  736 + * @param array1 the array to realAdd the element to, may be <code>null</code>
  737 + * @param index the position of the new object
  738 + * @param array2 the array to realAdd
  739 + * @return A new array containing the existing elements and the new element
  740 + * @throws IndexOutOfBoundsException if the index is out of range
  741 + * (index < 0 || index > array.length).
  742 + */
  743 + public static <T> T[] add(T[] array1, int index, T[] array2) {
  744 + Class clss;
  745 + if (array1 != null) {
  746 + clss = array1.getClass().getComponentType();
  747 + } else if (array2 != null) {
  748 + clss = array2.getClass().getComponentType();
  749 + } else {
  750 + return (T[]) new Object[]{null};
  751 + }
  752 + return (T[]) realAddArr(array1, index, array2, clss);
  753 + }
  754 +
  755 + public static boolean[] add(boolean[] array1, int index, boolean[] array2) {
  756 + return (boolean[]) realAddArr(array1, index, array2, Boolean.TYPE);
  757 + }
  758 +
  759 + public static char[] add(char[] array1, int index, char[] array2) {
  760 + return (char[]) realAddArr(array1, index, array2, Character.TYPE);
  761 + }
  762 +
  763 + public static byte[] add(byte[] array1, int index, byte[] array2) {
  764 + return (byte[]) realAddArr(array1, index, array2, Byte.TYPE);
  765 + }
  766 +
  767 + public static short[] add(short[] array1, int index, short[] array2) {
  768 + return (short[]) realAddArr(array1, index, array2, Short.TYPE);
  769 + }
  770 +
  771 + public static int[] add(int[] array1, int index, int[] array2) {
  772 + return (int[]) realAddArr(array1, index, array2, Integer.TYPE);
  773 + }
  774 +
  775 + public static long[] add(long[] array1, int index, long[] array2) {
  776 + return (long[]) realAddArr(array1, index, array2, Long.TYPE);
  777 + }
  778 +
  779 + public static float[] add(float[] array1, int index, float[] array2) {
  780 + return (float[]) realAddArr(array1, index, array2, Float.TYPE);
  781 + }
  782 +
  783 + public static double[] add(double[] array1, int index, double[] array2) {
  784 + return (double[]) realAddArr(array1, index, array2, Double.TYPE);
  785 + }
  786 +
  787 + private static Object realAddArr(Object array1, int index, Object array2, Class clss) {
  788 + if (array1 == null && array2 == null) return null;
  789 + int len1 = getLength(array1);
  790 + int len2 = getLength(array2);
  791 + if (len1 == 0) {
  792 + if (index != 0) {
  793 + throw new IndexOutOfBoundsException("Index: " + index + ", array1 Length: 0");
  794 + }
  795 + return realCopy(array2);
  796 + }
  797 + if (len2 == 0) {
  798 + return realCopy(array1);
  799 + }
  800 + if (index > len1 || index < 0) {
  801 + throw new IndexOutOfBoundsException("Index: " + index + ", array1 Length: " + len1);
  802 + }
  803 + Object joinedArray = Array.newInstance(array1.getClass().getComponentType(), len1 + len2);
  804 + if (index == len1) {
  805 + System.arraycopy(array1, 0, joinedArray, 0, len1);
  806 + System.arraycopy(array2, 0, joinedArray, len1, len2);
  807 + } else if (index == 0) {
  808 + System.arraycopy(array2, 0, joinedArray, 0, len2);
  809 + System.arraycopy(array1, 0, joinedArray, len2, len1);
  810 + } else {
  811 + System.arraycopy(array1, 0, joinedArray, 0, index);
  812 + System.arraycopy(array2, 0, joinedArray, index, len2);
  813 + System.arraycopy(array1, index, joinedArray, index + len2, len1 - index);
  814 + }
  815 + return joinedArray;
  816 + }
  817 +
  818 + /**
  819 + * <p>Inserts the specified element at the specified position in the array.
  820 + * Shifts the element currently at that position (if any) and any subsequent
  821 + * elements to the right (adds one to their indices).</p>
  822 + *
  823 + * <p>This method returns a new array with the same elements of the input
  824 + * array plus the given element on the specified position. The component
  825 + * type of the returned array is always the same as that of the input
  826 + * array.</p>
  827 + *
  828 + * <p>If the input array is <code>null</code>, a new one element array is returned
  829 + * whose component type is the same as the element.</p>
  830 + *
  831 + * <pre>
  832 + * ArrayUtils.add(null, 0, null) = [null]
  833 + * ArrayUtils.add(null, 0, "a") = ["a"]
  834 + * ArrayUtils.add(["a"], 1, null) = ["a", null]
  835 + * ArrayUtils.add(["a"], 1, "b") = ["a", "b"]
  836 + * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
  837 + * </pre>
  838 + *
  839 + * @param array the array to realAdd the element to, may be <code>null</code>
  840 + * @param index the position of the new object
  841 + * @param element the object to realAdd
  842 + * @return A new array containing the existing elements and the new element
  843 + * @throws IndexOutOfBoundsException if the index is out of range
  844 + * (index < 0 || index > array.length).
  845 + */
  846 + public static <T> T[] add(T[] array, int index, T element) {
  847 + Class clss;
  848 + if (array != null) {
  849 + clss = array.getClass().getComponentType();
  850 + } else if (element != null) {
  851 + clss = element.getClass();
  852 + } else {
  853 + return (T[]) new Object[]{null};
  854 + }
  855 + return (T[]) realAdd(array, index, element, clss);
  856 + }
  857 +
  858 + public static boolean[] add(boolean[] array, int index, boolean element) {
  859 + return (boolean[]) realAdd(array, index, element, Boolean.TYPE);
  860 + }
  861 +
  862 + public static char[] add(char[] array, int index, char element) {
  863 + return (char[]) realAdd(array, index, element, Character.TYPE);
  864 + }
  865 +
  866 + public static byte[] add(byte[] array, int index, byte element) {
  867 + return (byte[]) realAdd(array, index, element, Byte.TYPE);
  868 + }
  869 +
  870 + public static short[] add(short[] array, int index, short element) {
  871 + return (short[]) realAdd(array, index, element, Short.TYPE);
  872 + }
  873 +
  874 + public static int[] add(int[] array, int index, int element) {
  875 + return (int[]) realAdd(array, index, element, Integer.TYPE);
  876 + }
  877 +
  878 + public static long[] add(long[] array, int index, long element) {
  879 + return (long[]) realAdd(array, index, element, Long.TYPE);
  880 + }
  881 +
  882 + public static float[] add(float[] array, int index, float element) {
  883 + return (float[]) realAdd(array, index, element, Float.TYPE);
  884 + }
  885 +
  886 + public static double[] add(double[] array, int index, double element) {
  887 + return (double[]) realAdd(array, index, element, Double.TYPE);
  888 + }
  889 +
  890 + private static Object realAdd(Object array, int index, Object element, Class clss) {
  891 + if (array == null) {
  892 + if (index != 0) {
  893 + throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
  894 + }
  895 + Object joinedArray = Array.newInstance(clss, 1);
  896 + Array.set(joinedArray, 0, element);
  897 + return joinedArray;
  898 + }
  899 + int length = Array.getLength(array);
  900 + if (index > length || index < 0) {
  901 + throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
  902 + }
  903 + Object result = Array.newInstance(clss, length + 1);
  904 + System.arraycopy(array, 0, result, 0, index);
  905 + Array.set(result, index, element);
  906 + if (index < length) {
  907 + System.arraycopy(array, index, result, index + 1, length - index);
  908 + }
  909 + return result;
  910 + }
  911 +
  912 + ///////////////////////////////////////////////////////////////////////////
  913 + // remove
  914 + ///////////////////////////////////////////////////////////////////////////
  915 +
  916 + /**
  917 + * 移除指定的索引
  918 + * <p>Removes the element at the specified position from the specified array.
  919 + * All subsequent elements are shifted to the left (substracts one from
  920 + * their indices).</p>
  921 + *
  922 + * <p>This method returns a new array with the same elements of the input
  923 + * array except the element on the specified position. The component
  924 + * type of the returned array is always the same as that of the input
  925 + * array.</p>
  926 + *
  927 + * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
  928 + * will be thrown, because in that case no valid index can be specified.</p>
  929 + *
  930 + * <pre>
  931 + * ArrayUtils.remove(["a"], 0) = []
  932 + * ArrayUtils.remove(["a", "b"], 0) = ["b"]
  933 + * ArrayUtils.remove(["a", "b"], 1) = ["a"]
  934 + * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
  935 + * </pre>
  936 + *
  937 + * @param array the array to remove the element from, may not be <code>null</code>
  938 + * @param index the position of the element to be removed
  939 + * @return A new array containing the existing elements except the element
  940 + * at the specified position.
  941 + * @throws IndexOutOfBoundsException if the index is out of range
  942 + * (index < 0 || index >= array.length), or if the array is <code>null</code>.
  943 + * @since 2.1
  944 + */
  945 + public static Object[] remove(Object[] array, int index) {
  946 + return (Object[]) remove((Object) array, index);
  947 + }
  948 +
  949 + /**
  950 + * 移除指定的元素
  951 + * <p>Removes the first occurrence of the specified element from the
  952 + * specified array. All subsequent elements are shifted to the left
  953 + * (substracts one from their indices). If the array doesn't contains
  954 + * such an element, no elements are removed from the array.</p>
  955 + *
  956 + * <p>This method returns a new array with the same elements of the input
  957 + * array except the first occurrence of the specified element. The component
  958 + * type of the returned array is always the same as that of the input
  959 + * array.</p>
  960 + *
  961 + * <pre>
  962 + * ArrayUtils.removeElement(null, "a") = null
  963 + * ArrayUtils.removeElement([], "a") = []
  964 + * ArrayUtils.removeElement(["a"], "b") = ["a"]
  965 + * ArrayUtils.removeElement(["a", "b"], "a") = ["b"]
  966 + * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
  967 + * </pre>
  968 + *
  969 + * @param array the array to remove the element from, may be <code>null</code>
  970 + * @param element the element to be removed
  971 + * @return A new array containing the existing elements except the first
  972 + * occurrence of the specified element.
  973 + * @since 2.1
  974 + */
  975 + public static Object[] removeElement(Object[] array, Object element) {
  976 + int index = indexOf(array, element);
  977 + if (index == INDEX_NOT_FOUND) {
  978 + return copy(array);
  979 + }
  980 + return remove(array, index);
  981 + }
  982 +
  983 + public static boolean[] remove(boolean[] array, int index) {
  984 + return (boolean[]) remove((Object) array, index);
  985 + }
  986 +
  987 + public static boolean[] removeElement(boolean[] array, boolean element) {
  988 + int index = indexOf(array, element);
  989 + if (index == INDEX_NOT_FOUND) {
  990 + return copy(array);
  991 + }
  992 + return remove(array, index);
  993 + }
  994 +
  995 + public static byte[] remove(byte[] array, int index) {
  996 + return (byte[]) remove((Object) array, index);
  997 + }
  998 +
  999 + public static byte[] removeElement(byte[] array, byte element) {
  1000 + int index = indexOf(array, element);
  1001 + if (index == INDEX_NOT_FOUND) {
  1002 + return copy(array);
  1003 + }
  1004 + return remove(array, index);
  1005 + }
  1006 +
  1007 + public static char[] remove(char[] array, int index) {
  1008 + return (char[]) remove((Object) array, index);
  1009 + }
  1010 +
  1011 + public static char[] removeElement(char[] array, char element) {
  1012 + int index = indexOf(array, element);
  1013 + if (index == INDEX_NOT_FOUND) {
  1014 + return copy(array);
  1015 + }
  1016 + return remove(array, index);
  1017 + }
  1018 +
  1019 + public static double[] remove(double[] array, int index) {
  1020 + return (double[]) remove((Object) array, index);
  1021 + }
  1022 +
  1023 + public static double[] removeElement(double[] array, double element) {
  1024 + int index = indexOf(array, element);
  1025 + if (index == INDEX_NOT_FOUND) {
  1026 + return copy(array);
  1027 + }
  1028 + return remove(array, index);
  1029 + }
  1030 +
  1031 + public static float[] remove(float[] array, int index) {
  1032 + return (float[]) remove((Object) array, index);
  1033 + }
  1034 +
  1035 + public static float[] removeElement(float[] array, float element) {
  1036 + int index = indexOf(array, element);
  1037 + if (index == INDEX_NOT_FOUND) {
  1038 + return copy(array);
  1039 + }
  1040 + return remove(array, index);
  1041 + }
  1042 +
  1043 + public static int[] remove(int[] array, int index) {
  1044 + return (int[]) remove((Object) array, index);
  1045 + }
  1046 +
  1047 + public static int[] removeElement(int[] array, int element) {
  1048 + int index = indexOf(array, element);
  1049 + if (index == INDEX_NOT_FOUND) {
  1050 + return copy(array);
  1051 + }
  1052 + return remove(array, index);
  1053 + }
  1054 +
  1055 + public static long[] remove(long[] array, int index) {
  1056 + return (long[]) remove((Object) array, index);
  1057 + }
  1058 +
  1059 + public static long[] removeElement(long[] array, long element) {
  1060 + int index = indexOf(array, element);
  1061 + if (index == INDEX_NOT_FOUND) {
  1062 + return copy(array);
  1063 + }
  1064 + return remove(array, index);
  1065 + }
  1066 +
  1067 + public static short[] remove(short[] array, int index) {
  1068 + return (short[]) remove((Object) array, index);
  1069 + }
  1070 +
  1071 + public static short[] removeElement(short[] array, short element) {
  1072 + int index = indexOf(array, element);
  1073 + if (index == INDEX_NOT_FOUND) {
  1074 + return copy(array);
  1075 + }
  1076 + return remove(array, index);
  1077 + }
  1078 +
  1079 + private static Object remove(Object array, int index) {
  1080 + int length = getLength(array);
  1081 + if (index < 0 || index >= length) {
  1082 + throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
  1083 + }
  1084 +
  1085 + Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
  1086 + System.arraycopy(array, 0, result, 0, index);
  1087 + if (index < length - 1) {
  1088 + System.arraycopy(array, index + 1, result, index, length - index - 1);
  1089 + }
  1090 +
  1091 + return result;
  1092 + }
  1093 +
  1094 + ///////////////////////////////////////////////////////////////////////////
  1095 + // object indexOf
  1096 + ///////////////////////////////////////////////////////////////////////////
  1097 +
  1098 + /**
  1099 + * 查找第一个元素的索引
  1100 + *
  1101 + * @param array
  1102 + * @param objectToFind
  1103 + * @return
  1104 + */
  1105 + public static int indexOf(Object[] array, Object objectToFind) {
  1106 + return indexOf(array, objectToFind, 0);
  1107 + }
  1108 +
  1109 + public static int indexOf(Object[] array, final Object objectToFind, int startIndex) {
  1110 + if (array == null) {
  1111 + return INDEX_NOT_FOUND;
  1112 + }
  1113 + if (startIndex < 0) {
  1114 + startIndex = 0;
  1115 + }
  1116 + if (objectToFind == null) {
  1117 + for (int i = startIndex; i < array.length; i++) {
  1118 + if (array[i] == null) {
  1119 + return i;
  1120 + }
  1121 + }
  1122 + } else {
  1123 + for (int i = startIndex; i < array.length; i++) {
  1124 + if (objectToFind.equals(array[i])) {
  1125 + return i;
  1126 + }
  1127 + }
  1128 + }
  1129 + return INDEX_NOT_FOUND;
  1130 + }
  1131 +
  1132 + /**
  1133 + * 查找最后一个元素的索引
  1134 + *
  1135 + * @param array
  1136 + * @param objectToFind
  1137 + * @return
  1138 + */
  1139 + public static int lastIndexOf(Object[] array, Object objectToFind) {
  1140 + return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
  1141 + }
  1142 +
  1143 + public static int lastIndexOf(Object[] array, Object objectToFind, int startIndex) {
  1144 + if (array == null) {
  1145 + return INDEX_NOT_FOUND;
  1146 + }
  1147 + if (startIndex < 0) {
  1148 + return INDEX_NOT_FOUND;
  1149 + } else if (startIndex >= array.length) {
  1150 + startIndex = array.length - 1;
  1151 + }
  1152 + if (objectToFind == null) {
  1153 + for (int i = startIndex; i >= 0; i--) {
  1154 + if (array[i] == null) {
  1155 + return i;
  1156 + }
  1157 + }
  1158 + } else {
  1159 + for (int i = startIndex; i >= 0; i--) {
  1160 + if (objectToFind.equals(array[i])) {
  1161 + return i;
  1162 + }
  1163 + }
  1164 + }
  1165 + return INDEX_NOT_FOUND;
  1166 + }
  1167 +
  1168 + /**
  1169 + * 判断是否包含该元素
  1170 + *
  1171 + * @param array
  1172 + * @param objectToFind
  1173 + * @return
  1174 + */
  1175 + public static boolean contains(Object[] array, Object objectToFind) {
  1176 + return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
  1177 + }
  1178 +
  1179 + ///////////////////////////////////////////////////////////////////////////
  1180 + // long indexOf
  1181 + ///////////////////////////////////////////////////////////////////////////
  1182 +
  1183 + public static int indexOf(long[] array, long valueToFind) {
  1184 + return indexOf(array, valueToFind, 0);
  1185 + }
  1186 +
  1187 + public static int indexOf(long[] array, long valueToFind, int startIndex) {
  1188 + if (array == null) {
  1189 + return INDEX_NOT_FOUND;
  1190 + }
  1191 + if (startIndex < 0) {
  1192 + startIndex = 0;
  1193 + }
  1194 + for (int i = startIndex; i < array.length; i++) {
  1195 + if (valueToFind == array[i]) {
  1196 + return i;
  1197 + }
  1198 + }
  1199 + return INDEX_NOT_FOUND;
  1200 + }
  1201 +
  1202 + public static int lastIndexOf(long[] array, long valueToFind) {
  1203 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1204 + }
  1205 +
  1206 + public static int lastIndexOf(long[] array, long valueToFind, int startIndex) {
  1207 + if (array == null) {
  1208 + return INDEX_NOT_FOUND;
  1209 + }
  1210 + if (startIndex < 0) {
  1211 + return INDEX_NOT_FOUND;
  1212 + } else if (startIndex >= array.length) {
  1213 + startIndex = array.length - 1;
  1214 + }
  1215 + for (int i = startIndex; i >= 0; i--) {
  1216 + if (valueToFind == array[i]) {
  1217 + return i;
  1218 + }
  1219 + }
  1220 + return INDEX_NOT_FOUND;
  1221 + }
  1222 +
  1223 + public static boolean contains(long[] array, long valueToFind) {
  1224 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1225 + }
  1226 +
  1227 + ///////////////////////////////////////////////////////////////////////////
  1228 + // int indexOf
  1229 + ///////////////////////////////////////////////////////////////////////////
  1230 +
  1231 + public static int indexOf(int[] array, int valueToFind) {
  1232 + return indexOf(array, valueToFind, 0);
  1233 + }
  1234 +
  1235 + public static int indexOf(int[] array, int valueToFind, int startIndex) {
  1236 + if (array == null) {
  1237 + return INDEX_NOT_FOUND;
  1238 + }
  1239 + if (startIndex < 0) {
  1240 + startIndex = 0;
  1241 + }
  1242 + for (int i = startIndex; i < array.length; i++) {
  1243 + if (valueToFind == array[i]) {
  1244 + return i;
  1245 + }
  1246 + }
  1247 + return INDEX_NOT_FOUND;
  1248 + }
  1249 +
  1250 + public static int lastIndexOf(int[] array, int valueToFind) {
  1251 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1252 + }
  1253 +
  1254 + public static int lastIndexOf(int[] array, int valueToFind, int startIndex) {
  1255 + if (array == null) {
  1256 + return INDEX_NOT_FOUND;
  1257 + }
  1258 + if (startIndex < 0) {
  1259 + return INDEX_NOT_FOUND;
  1260 + } else if (startIndex >= array.length) {
  1261 + startIndex = array.length - 1;
  1262 + }
  1263 + for (int i = startIndex; i >= 0; i--) {
  1264 + if (valueToFind == array[i]) {
  1265 + return i;
  1266 + }
  1267 + }
  1268 + return INDEX_NOT_FOUND;
  1269 + }
  1270 +
  1271 + public static boolean contains(int[] array, int valueToFind) {
  1272 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1273 + }
  1274 +
  1275 + ///////////////////////////////////////////////////////////////////////////
  1276 + // short indexOf
  1277 + ///////////////////////////////////////////////////////////////////////////
  1278 +
  1279 + public static int indexOf(short[] array, short valueToFind) {
  1280 + return indexOf(array, valueToFind, 0);
  1281 + }
  1282 +
  1283 + public static int indexOf(short[] array, short valueToFind, int startIndex) {
  1284 + if (array == null) {
  1285 + return INDEX_NOT_FOUND;
  1286 + }
  1287 + if (startIndex < 0) {
  1288 + startIndex = 0;
  1289 + }
  1290 + for (int i = startIndex; i < array.length; i++) {
  1291 + if (valueToFind == array[i]) {
  1292 + return i;
  1293 + }
  1294 + }
  1295 + return INDEX_NOT_FOUND;
  1296 + }
  1297 +
  1298 + public static int lastIndexOf(short[] array, short valueToFind) {
  1299 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1300 + }
  1301 +
  1302 + public static int lastIndexOf(short[] array, short valueToFind, int startIndex) {
  1303 + if (array == null) {
  1304 + return INDEX_NOT_FOUND;
  1305 + }
  1306 + if (startIndex < 0) {
  1307 + return INDEX_NOT_FOUND;
  1308 + } else if (startIndex >= array.length) {
  1309 + startIndex = array.length - 1;
  1310 + }
  1311 + for (int i = startIndex; i >= 0; i--) {
  1312 + if (valueToFind == array[i]) {
  1313 + return i;
  1314 + }
  1315 + }
  1316 + return INDEX_NOT_FOUND;
  1317 + }
  1318 +
  1319 + public static boolean contains(short[] array, short valueToFind) {
  1320 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1321 + }
  1322 +
  1323 + ///////////////////////////////////////////////////////////////////////////
  1324 + // char indexOf
  1325 + ///////////////////////////////////////////////////////////////////////////
  1326 +
  1327 + public static int indexOf(char[] array, char valueToFind) {
  1328 + return indexOf(array, valueToFind, 0);
  1329 + }
  1330 +
  1331 + public static int indexOf(char[] array, char valueToFind, int startIndex) {
  1332 + if (array == null) {
  1333 + return INDEX_NOT_FOUND;
  1334 + }
  1335 + if (startIndex < 0) {
  1336 + startIndex = 0;
  1337 + }
  1338 + for (int i = startIndex; i < array.length; i++) {
  1339 + if (valueToFind == array[i]) {
  1340 + return i;
  1341 + }
  1342 + }
  1343 + return INDEX_NOT_FOUND;
  1344 + }
  1345 +
  1346 + public static int lastIndexOf(char[] array, char valueToFind) {
  1347 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1348 + }
  1349 +
  1350 + public static int lastIndexOf(char[] array, char valueToFind, int startIndex) {
  1351 + if (array == null) {
  1352 + return INDEX_NOT_FOUND;
  1353 + }
  1354 + if (startIndex < 0) {
  1355 + return INDEX_NOT_FOUND;
  1356 + } else if (startIndex >= array.length) {
  1357 + startIndex = array.length - 1;
  1358 + }
  1359 + for (int i = startIndex; i >= 0; i--) {
  1360 + if (valueToFind == array[i]) {
  1361 + return i;
  1362 + }
  1363 + }
  1364 + return INDEX_NOT_FOUND;
  1365 + }
  1366 +
  1367 + public static boolean contains(char[] array, char valueToFind) {
  1368 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1369 + }
  1370 +
  1371 + ///////////////////////////////////////////////////////////////////////////
  1372 + // byte indexOf
  1373 + ///////////////////////////////////////////////////////////////////////////
  1374 +
  1375 + public static int indexOf(byte[] array, byte valueToFind) {
  1376 + return indexOf(array, valueToFind, 0);
  1377 + }
  1378 +
  1379 + public static int indexOf(byte[] array, byte valueToFind, int startIndex) {
  1380 + if (array == null) {
  1381 + return INDEX_NOT_FOUND;
  1382 + }
  1383 + if (startIndex < 0) {
  1384 + startIndex = 0;
  1385 + }
  1386 + for (int i = startIndex; i < array.length; i++) {
  1387 + if (valueToFind == array[i]) {
  1388 + return i;
  1389 + }
  1390 + }
  1391 + return INDEX_NOT_FOUND;
  1392 + }
  1393 +
  1394 + public static int lastIndexOf(byte[] array, byte valueToFind) {
  1395 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1396 + }
  1397 +
  1398 + public static int lastIndexOf(byte[] array, byte valueToFind, int startIndex) {
  1399 + if (array == null) {
  1400 + return INDEX_NOT_FOUND;
  1401 + }
  1402 + if (startIndex < 0) {
  1403 + return INDEX_NOT_FOUND;
  1404 + } else if (startIndex >= array.length) {
  1405 + startIndex = array.length - 1;
  1406 + }
  1407 + for (int i = startIndex; i >= 0; i--) {
  1408 + if (valueToFind == array[i]) {
  1409 + return i;
  1410 + }
  1411 + }
  1412 + return INDEX_NOT_FOUND;
  1413 + }
  1414 +
  1415 + public static boolean contains(byte[] array, byte valueToFind) {
  1416 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1417 + }
  1418 +
  1419 + ///////////////////////////////////////////////////////////////////////////
  1420 + // double indexOf
  1421 + ///////////////////////////////////////////////////////////////////////////
  1422 +
  1423 + public static int indexOf(double[] array, double valueToFind) {
  1424 + return indexOf(array, valueToFind, 0);
  1425 + }
  1426 +
  1427 + public static int indexOf(double[] array, double valueToFind, double tolerance) {
  1428 + return indexOf(array, valueToFind, 0, tolerance);
  1429 + }
  1430 +
  1431 + public static int indexOf(double[] array, double valueToFind, int startIndex) {
  1432 + if (ArrayUtils.isEmpty(array)) {
  1433 + return INDEX_NOT_FOUND;
  1434 + }
  1435 + if (startIndex < 0) {
  1436 + startIndex = 0;
  1437 + }
  1438 + for (int i = startIndex; i < array.length; i++) {
  1439 + if (valueToFind == array[i]) {
  1440 + return i;
  1441 + }
  1442 + }
  1443 + return INDEX_NOT_FOUND;
  1444 + }
  1445 +
  1446 + public static int indexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
  1447 + if (ArrayUtils.isEmpty(array)) {
  1448 + return INDEX_NOT_FOUND;
  1449 + }
  1450 + if (startIndex < 0) {
  1451 + startIndex = 0;
  1452 + }
  1453 + double min = valueToFind - tolerance;
  1454 + double max = valueToFind + tolerance;
  1455 + for (int i = startIndex; i < array.length; i++) {
  1456 + if (array[i] >= min && array[i] <= max) {
  1457 + return i;
  1458 + }
  1459 + }
  1460 + return INDEX_NOT_FOUND;
  1461 + }
  1462 +
  1463 + public static int lastIndexOf(double[] array, double valueToFind) {
  1464 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1465 + }
  1466 +
  1467 + public static int lastIndexOf(double[] array, double valueToFind, double tolerance) {
  1468 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
  1469 + }
  1470 +
  1471 + public static int lastIndexOf(double[] array, double valueToFind, int startIndex) {
  1472 + if (ArrayUtils.isEmpty(array)) {
  1473 + return INDEX_NOT_FOUND;
  1474 + }
  1475 + if (startIndex < 0) {
  1476 + return INDEX_NOT_FOUND;
  1477 + } else if (startIndex >= array.length) {
  1478 + startIndex = array.length - 1;
  1479 + }
  1480 + for (int i = startIndex; i >= 0; i--) {
  1481 + if (valueToFind == array[i]) {
  1482 + return i;
  1483 + }
  1484 + }
  1485 + return INDEX_NOT_FOUND;
  1486 + }
  1487 +
  1488 + public static int lastIndexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
  1489 + if (ArrayUtils.isEmpty(array)) {
  1490 + return INDEX_NOT_FOUND;
  1491 + }
  1492 + if (startIndex < 0) {
  1493 + return INDEX_NOT_FOUND;
  1494 + } else if (startIndex >= array.length) {
  1495 + startIndex = array.length - 1;
  1496 + }
  1497 + double min = valueToFind - tolerance;
  1498 + double max = valueToFind + tolerance;
  1499 + for (int i = startIndex; i >= 0; i--) {
  1500 + if (array[i] >= min && array[i] <= max) {
  1501 + return i;
  1502 + }
  1503 + }
  1504 + return INDEX_NOT_FOUND;
  1505 + }
  1506 +
  1507 + public static boolean contains(double[] array, double valueToFind) {
  1508 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1509 + }
  1510 +
  1511 + public static boolean contains(double[] array, double valueToFind, double tolerance) {
  1512 + return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
  1513 + }
  1514 +
  1515 + ///////////////////////////////////////////////////////////////////////////
  1516 + // float indexOf
  1517 + ///////////////////////////////////////////////////////////////////////////
  1518 +
  1519 + public static int indexOf(float[] array, float valueToFind) {
  1520 + return indexOf(array, valueToFind, 0);
  1521 + }
  1522 +
  1523 + public static int indexOf(float[] array, float valueToFind, int startIndex) {
  1524 + if (ArrayUtils.isEmpty(array)) {
  1525 + return INDEX_NOT_FOUND;
  1526 + }
  1527 + if (startIndex < 0) {
  1528 + startIndex = 0;
  1529 + }
  1530 + for (int i = startIndex; i < array.length; i++) {
  1531 + if (valueToFind == array[i]) {
  1532 + return i;
  1533 + }
  1534 + }
  1535 + return INDEX_NOT_FOUND;
  1536 + }
  1537 +
  1538 + public static int lastIndexOf(float[] array, float valueToFind) {
  1539 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1540 + }
  1541 +
  1542 + public static int lastIndexOf(float[] array, float valueToFind, int startIndex) {
  1543 + if (ArrayUtils.isEmpty(array)) {
  1544 + return INDEX_NOT_FOUND;
  1545 + }
  1546 + if (startIndex < 0) {
  1547 + return INDEX_NOT_FOUND;
  1548 + } else if (startIndex >= array.length) {
  1549 + startIndex = array.length - 1;
  1550 + }
  1551 + for (int i = startIndex; i >= 0; i--) {
  1552 + if (valueToFind == array[i]) {
  1553 + return i;
  1554 + }
  1555 + }
  1556 + return INDEX_NOT_FOUND;
  1557 + }
  1558 +
  1559 + public static boolean contains(float[] array, float valueToFind) {
  1560 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1561 + }
  1562 +
  1563 + ///////////////////////////////////////////////////////////////////////////
  1564 + // bool indexOf
  1565 + ///////////////////////////////////////////////////////////////////////////
  1566 +
  1567 + public static int indexOf(boolean[] array, boolean valueToFind) {
  1568 + return indexOf(array, valueToFind, 0);
  1569 + }
  1570 +
  1571 + public static int indexOf(boolean[] array, boolean valueToFind, int startIndex) {
  1572 + if (ArrayUtils.isEmpty(array)) {
  1573 + return INDEX_NOT_FOUND;
  1574 + }
  1575 + if (startIndex < 0) {
  1576 + startIndex = 0;
  1577 + }
  1578 + for (int i = startIndex; i < array.length; i++) {
  1579 + if (valueToFind == array[i]) {
  1580 + return i;
  1581 + }
  1582 + }
  1583 + return INDEX_NOT_FOUND;
  1584 + }
  1585 +
  1586 + public static int lastIndexOf(boolean[] array, boolean valueToFind) {
  1587 + return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
  1588 + }
  1589 +
  1590 + public static int lastIndexOf(boolean[] array, boolean valueToFind, int startIndex) {
  1591 + if (ArrayUtils.isEmpty(array)) {
  1592 + return INDEX_NOT_FOUND;
  1593 + }
  1594 + if (startIndex < 0) {
  1595 + return INDEX_NOT_FOUND;
  1596 + } else if (startIndex >= array.length) {
  1597 + startIndex = array.length - 1;
  1598 + }
  1599 + for (int i = startIndex; i >= 0; i--) {
  1600 + if (valueToFind == array[i]) {
  1601 + return i;
  1602 + }
  1603 + }
  1604 + return INDEX_NOT_FOUND;
  1605 + }
  1606 +
  1607 + public static boolean contains(boolean[] array, boolean valueToFind) {
  1608 + return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
  1609 + }
  1610 +
  1611 + ///////////////////////////////////////////////////////////////////////////
  1612 + // char converters
  1613 + ///////////////////////////////////////////////////////////////////////////
  1614 +
  1615 + /**
  1616 + * 装箱数组转基本类型数组
  1617 + *
  1618 + * @param array
  1619 + * @return
  1620 + */
  1621 + public static char[] toPrimitive(Character[] array) {
  1622 + if (array == null) {
  1623 + return null;
  1624 + } else if (array.length == 0) {
  1625 + return new char[0];
  1626 + }
  1627 + final char[] result = new char[array.length];
  1628 + for (int i = 0; i < array.length; i++) {
  1629 + result[i] = array[i].charValue();
  1630 + }
  1631 + return result;
  1632 + }
  1633 +
  1634 + public static char[] toPrimitive(Character[] array, char valueForNull) {
  1635 + if (array == null) {
  1636 + return null;
  1637 + } else if (array.length == 0) {
  1638 + return new char[0];
  1639 + }
  1640 + final char[] result = new char[array.length];
  1641 + for (int i = 0; i < array.length; i++) {
  1642 + Character b = array[i];
  1643 + result[i] = (b == null ? valueForNull : b.charValue());
  1644 + }
  1645 + return result;
  1646 + }
  1647 +
  1648 + /**
  1649 + * 基本类型数组转装箱数组
  1650 + *
  1651 + * @param array
  1652 + * @return
  1653 + */
  1654 + public static Character[] toObject(char[] array) {
  1655 + if (array == null) {
  1656 + return null;
  1657 + } else if (array.length == 0) {
  1658 + return new Character[0];
  1659 + }
  1660 + final Character[] result = new Character[array.length];
  1661 + for (int i = 0; i < array.length; i++) {
  1662 + result[i] = new Character(array[i]);
  1663 + }
  1664 + return result;
  1665 + }
  1666 +
  1667 + ///////////////////////////////////////////////////////////////////////////
  1668 + // long converters
  1669 + ///////////////////////////////////////////////////////////////////////////
  1670 +
  1671 + public static long[] toPrimitive(Long[] array) {
  1672 + if (array == null) {
  1673 + return null;
  1674 + } else if (array.length == 0) {
  1675 + return new long[0];
  1676 + }
  1677 + final long[] result = new long[array.length];
  1678 + for (int i = 0; i < array.length; i++) {
  1679 + result[i] = array[i].longValue();
  1680 + }
  1681 + return result;
  1682 + }
  1683 +
  1684 + public static long[] toPrimitive(Long[] array, long valueForNull) {
  1685 + if (array == null) {
  1686 + return null;
  1687 + } else if (array.length == 0) {
  1688 + return new long[0];
  1689 + }
  1690 + final long[] result = new long[array.length];
  1691 + for (int i = 0; i < array.length; i++) {
  1692 + Long b = array[i];
  1693 + result[i] = (b == null ? valueForNull : b.longValue());
  1694 + }
  1695 + return result;
  1696 + }
  1697 +
  1698 + public static Long[] toObject(long[] array) {
  1699 + if (array == null) {
  1700 + return null;
  1701 + } else if (array.length == 0) {
  1702 + return new Long[0];
  1703 + }
  1704 + final Long[] result = new Long[array.length];
  1705 + for (int i = 0; i < array.length; i++) {
  1706 + result[i] = new Long(array[i]);
  1707 + }
  1708 + return result;
  1709 + }
  1710 +
  1711 + ///////////////////////////////////////////////////////////////////////////
  1712 + // int converters
  1713 + ///////////////////////////////////////////////////////////////////////////
  1714 +
  1715 + public static int[] toPrimitive(Integer[] array) {
  1716 + if (array == null) {
  1717 + return null;
  1718 + } else if (array.length == 0) {
  1719 + return new int[0];
  1720 + }
  1721 + final int[] result = new int[array.length];
  1722 + for (int i = 0; i < array.length; i++) {
  1723 + result[i] = array[i].intValue();
  1724 + }
  1725 + return result;
  1726 + }
  1727 +
  1728 + public static int[] toPrimitive(Integer[] array, int valueForNull) {
  1729 + if (array == null) {
  1730 + return null;
  1731 + } else if (array.length == 0) {
  1732 + return new int[0];
  1733 + }
  1734 + final int[] result = new int[array.length];
  1735 + for (int i = 0; i < array.length; i++) {
  1736 + Integer b = array[i];
  1737 + result[i] = (b == null ? valueForNull : b.intValue());
  1738 + }
  1739 + return result;
  1740 + }
  1741 +
  1742 + public static Integer[] toObject(int[] array) {
  1743 + if (array == null) {
  1744 + return null;
  1745 + } else if (array.length == 0) {
  1746 + return new Integer[0];
  1747 + }
  1748 + final Integer[] result = new Integer[array.length];
  1749 + for (int i = 0; i < array.length; i++) {
  1750 + result[i] = new Integer(array[i]);
  1751 + }
  1752 + return result;
  1753 + }
  1754 +
  1755 + ///////////////////////////////////////////////////////////////////////////
  1756 + // short converters
  1757 + ///////////////////////////////////////////////////////////////////////////
  1758 +
  1759 + public static short[] toPrimitive(Short[] array) {
  1760 + if (array == null) {
  1761 + return null;
  1762 + } else if (array.length == 0) {
  1763 + return new short[0];
  1764 + }
  1765 + final short[] result = new short[array.length];
  1766 + for (int i = 0; i < array.length; i++) {
  1767 + result[i] = array[i].shortValue();
  1768 + }
  1769 + return result;
  1770 + }
  1771 +
  1772 + public static short[] toPrimitive(Short[] array, short valueForNull) {
  1773 + if (array == null) {
  1774 + return null;
  1775 + } else if (array.length == 0) {
  1776 + return new short[0];
  1777 + }
  1778 + final short[] result = new short[array.length];
  1779 + for (int i = 0; i < array.length; i++) {
  1780 + Short b = array[i];
  1781 + result[i] = (b == null ? valueForNull : b.shortValue());
  1782 + }
  1783 + return result;
  1784 + }
  1785 +
  1786 + public static Short[] toObject(short[] array) {
  1787 + if (array == null) {
  1788 + return null;
  1789 + } else if (array.length == 0) {
  1790 + return new Short[0];
  1791 + }
  1792 + final Short[] result = new Short[array.length];
  1793 + for (int i = 0; i < array.length; i++) {
  1794 + result[i] = new Short(array[i]);
  1795 + }
  1796 + return result;
  1797 + }
  1798 +
  1799 + ///////////////////////////////////////////////////////////////////////////
  1800 + // byte converters
  1801 + ///////////////////////////////////////////////////////////////////////////
  1802 +
  1803 + public static byte[] toPrimitive(Byte[] array) {
  1804 + if (array == null) {
  1805 + return null;
  1806 + } else if (array.length == 0) {
  1807 + return new byte[0];
  1808 + }
  1809 + final byte[] result = new byte[array.length];
  1810 + for (int i = 0; i < array.length; i++) {
  1811 + result[i] = array[i].byteValue();
  1812 + }
  1813 + return result;
  1814 + }
  1815 +
  1816 + public static byte[] toPrimitive(Byte[] array, byte valueForNull) {
  1817 + if (array == null) {
  1818 + return null;
  1819 + } else if (array.length == 0) {
  1820 + return new byte[0];
  1821 + }
  1822 + final byte[] result = new byte[array.length];
  1823 + for (int i = 0; i < array.length; i++) {
  1824 + Byte b = array[i];
  1825 + result[i] = (b == null ? valueForNull : b.byteValue());
  1826 + }
  1827 + return result;
  1828 + }
  1829 +
  1830 + public static Byte[] toObject(byte[] array) {
  1831 + if (array == null) {
  1832 + return null;
  1833 + } else if (array.length == 0) {
  1834 + return new Byte[0];
  1835 + }
  1836 + final Byte[] result = new Byte[array.length];
  1837 + for (int i = 0; i < array.length; i++) {
  1838 + result[i] = new Byte(array[i]);
  1839 + }
  1840 + return result;
  1841 + }
  1842 +
  1843 + ///////////////////////////////////////////////////////////////////////////
  1844 + // double converters
  1845 + ///////////////////////////////////////////////////////////////////////////
  1846 +
  1847 + public static double[] toPrimitive(Double[] array) {
  1848 + if (array == null) {
  1849 + return null;
  1850 + } else if (array.length == 0) {
  1851 + return new double[0];
  1852 + }
  1853 + final double[] result = new double[array.length];
  1854 + for (int i = 0; i < array.length; i++) {
  1855 + result[i] = array[i].doubleValue();
  1856 + }
  1857 + return result;
  1858 + }
  1859 +
  1860 + public static double[] toPrimitive(Double[] array, double valueForNull) {
  1861 + if (array == null) {
  1862 + return null;
  1863 + } else if (array.length == 0) {
  1864 + return new double[0];
  1865 + }
  1866 + final double[] result = new double[array.length];
  1867 + for (int i = 0; i < array.length; i++) {
  1868 + Double b = array[i];
  1869 + result[i] = (b == null ? valueForNull : b.doubleValue());
  1870 + }
  1871 + return result;
  1872 + }
  1873 +
  1874 + public static Double[] toObject(double[] array) {
  1875 + if (array == null) {
  1876 + return null;
  1877 + } else if (array.length == 0) {
  1878 + return new Double[0];
  1879 + }
  1880 + final Double[] result = new Double[array.length];
  1881 + for (int i = 0; i < array.length; i++) {
  1882 + result[i] = new Double(array[i]);
  1883 + }
  1884 + return result;
  1885 + }
  1886 +
  1887 + ///////////////////////////////////////////////////////////////////////////
  1888 + // float converters
  1889 + ///////////////////////////////////////////////////////////////////////////
  1890 +
  1891 + public static float[] toPrimitive(Float[] array) {
  1892 + if (array == null) {
  1893 + return null;
  1894 + } else if (array.length == 0) {
  1895 + return new float[0];
  1896 + }
  1897 + final float[] result = new float[array.length];
  1898 + for (int i = 0; i < array.length; i++) {
  1899 + result[i] = array[i].floatValue();
  1900 + }
  1901 + return result;
  1902 + }
  1903 +
  1904 + public static float[] toPrimitive(Float[] array, float valueForNull) {
  1905 + if (array == null) {
  1906 + return null;
  1907 + } else if (array.length == 0) {
  1908 + return new float[0];
  1909 + }
  1910 + final float[] result = new float[array.length];
  1911 + for (int i = 0; i < array.length; i++) {
  1912 + Float b = array[i];
  1913 + result[i] = (b == null ? valueForNull : b.floatValue());
  1914 + }
  1915 + return result;
  1916 + }
  1917 +
  1918 + public static Float[] toObject(float[] array) {
  1919 + if (array == null) {
  1920 + return null;
  1921 + } else if (array.length == 0) {
  1922 + return new Float[0];
  1923 + }
  1924 + final Float[] result = new Float[array.length];
  1925 + for (int i = 0; i < array.length; i++) {
  1926 + result[i] = new Float(array[i]);
  1927 + }
  1928 + return result;
  1929 + }
  1930 +
  1931 + ///////////////////////////////////////////////////////////////////////////
  1932 + // boolean converters
  1933 + ///////////////////////////////////////////////////////////////////////////
  1934 +
  1935 + public static boolean[] toPrimitive(Boolean[] array) {
  1936 + if (array == null) {
  1937 + return null;
  1938 + } else if (array.length == 0) {
  1939 + return new boolean[0];
  1940 + }
  1941 + final boolean[] result = new boolean[array.length];
  1942 + for (int i = 0; i < array.length; i++) {
  1943 + result[i] = array[i].booleanValue();
  1944 + }
  1945 + return result;
  1946 + }
  1947 +
  1948 + public static boolean[] toPrimitive(Boolean[] array, boolean valueForNull) {
  1949 + if (array == null) {
  1950 + return null;
  1951 + } else if (array.length == 0) {
  1952 + return new boolean[0];
  1953 + }
  1954 + final boolean[] result = new boolean[array.length];
  1955 + for (int i = 0; i < array.length; i++) {
  1956 + Boolean b = array[i];
  1957 + result[i] = (b == null ? valueForNull : b.booleanValue());
  1958 + }
  1959 + return result;
  1960 + }
  1961 +
  1962 + public static Boolean[] toObject(boolean[] array) {
  1963 + if (array == null) {
  1964 + return null;
  1965 + } else if (array.length == 0) {
  1966 + return new Boolean[0];
  1967 + }
  1968 + final Boolean[] result = new Boolean[array.length];
  1969 + for (int i = 0; i < array.length; i++) {
  1970 + result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
  1971 + }
  1972 + return result;
  1973 + }
  1974 +
  1975 + /**
  1976 + * 转为链表
  1977 + *
  1978 + * @param array
  1979 + * @param <T>
  1980 + * @return
  1981 + */
  1982 + public static <T> List<T> asList(T... array) {
  1983 + if (array == null || array.length == 0) {
  1984 + return Collections.emptyList();
  1985 + }
  1986 + return Arrays.asList(array);
  1987 + }
  1988 +
  1989 + /**
  1990 + * 转为不可变链表
  1991 + *
  1992 + * @param array
  1993 + * @param <T>
  1994 + * @return
  1995 + */
  1996 + public static <T> List<T> asUnmodifiableList(T... array) {
  1997 + return Collections.unmodifiableList(asList(array));
  1998 + }
  1999 +
  2000 + /**
  2001 + * 转为数组链表
  2002 + *
  2003 + * @param array
  2004 + * @param <T>
  2005 + * @return
  2006 + */
  2007 + public static <T> List<T> asArrayList(T... array) {
  2008 + List<T> list = new ArrayList<>();
  2009 + if (array == null || array.length == 0) return list;
  2010 + list.addAll(Arrays.asList(array));
  2011 + return list;
  2012 + }
  2013 +
  2014 + /**
  2015 + * 转为双向链表
  2016 + *
  2017 + * @param array
  2018 + * @param <T>
  2019 + * @return
  2020 + */
  2021 + public static <T> List<T> asLinkedList(T... array) {
  2022 + List<T> list = new LinkedList<>();
  2023 + if (array == null || array.length == 0) return list;
  2024 + list.addAll(Arrays.asList(array));
  2025 + return list;
  2026 + }
  2027 +
  2028 + /**
  2029 + * 排序
  2030 + *
  2031 + * @param array
  2032 + * @param c
  2033 + * @param <T>
  2034 + */
  2035 + public static <T> void sort(T[] array, Comparator<? super T> c) {
  2036 + if (array == null || array.length < 2) return;
  2037 + Arrays.sort(array, c);
  2038 + }
  2039 +
  2040 + public static void sort(byte[] array) {
  2041 + if (array == null || array.length < 2) return;
  2042 + Arrays.sort(array);
  2043 + }
  2044 +
  2045 + public static void sort(char[] array) {
  2046 + if (array == null || array.length < 2) return;
  2047 + Arrays.sort(array);
  2048 + }
  2049 +
  2050 + public static void sort(double[] array) {
  2051 + if (array == null || array.length < 2) return;
  2052 + Arrays.sort(array);
  2053 + }
  2054 +
  2055 + public static void sort(float[] array) {
  2056 + if (array == null || array.length < 2) return;
  2057 + Arrays.sort(array);
  2058 + }
  2059 +
  2060 + public static void sort(int[] array) {
  2061 + if (array == null || array.length < 2) return;
  2062 + Arrays.sort(array);
  2063 + }
  2064 +
  2065 + public static void sort(long[] array) {
  2066 + if (array == null || array.length < 2) return;
  2067 + Arrays.sort(array);
  2068 + }
  2069 +
  2070 + public static void sort(short[] array) {
  2071 + if (array == null || array.length < 2) return;
  2072 + Arrays.sort(array);
  2073 + }
  2074 +
  2075 + /**
  2076 + * 对所有元素做操作
  2077 + * Executes the given closure on each element in the array.
  2078 + * <p>
  2079 + * If the input array or closure is null, there is no change made.
  2080 + *
  2081 + * @param array The array.
  2082 + * @param closure the closure to perform, may be null
  2083 + */
  2084 + public static <E> void forAllDo(Object array, Closure<E> closure) {
  2085 + if (array == null || closure == null) return;
  2086 + if (array instanceof Object[]) {
  2087 + Object[] objects = (Object[]) array;
  2088 + for (int i = 0, length = objects.length; i < length; i++) {
  2089 + Object ele = objects[i];
  2090 + closure.execute(i, (E) ele);
  2091 + }
  2092 + } else if (array instanceof boolean[]) {
  2093 + boolean[] booleans = (boolean[]) array;
  2094 + for (int i = 0, length = booleans.length; i < length; i++) {
  2095 + boolean ele = booleans[i];
  2096 + closure.execute(i, (E) (ele ? Boolean.TRUE : Boolean.FALSE));
  2097 + }
  2098 + } else if (array instanceof byte[]) {
  2099 + byte[] bytes = (byte[]) array;
  2100 + for (int i = 0, length = bytes.length; i < length; i++) {
  2101 + byte ele = bytes[i];
  2102 + closure.execute(i, (E) Byte.valueOf(ele));
  2103 + }
  2104 + } else if (array instanceof char[]) {
  2105 + char[] chars = (char[]) array;
  2106 + for (int i = 0, length = chars.length; i < length; i++) {
  2107 + char ele = chars[i];
  2108 + closure.execute(i, (E) Character.valueOf(ele));
  2109 + }
  2110 + } else if (array instanceof short[]) {
  2111 + short[] shorts = (short[]) array;
  2112 + for (int i = 0, length = shorts.length; i < length; i++) {
  2113 + short ele = shorts[i];
  2114 + closure.execute(i, (E) Short.valueOf(ele));
  2115 + }
  2116 + } else if (array instanceof int[]) {
  2117 + int[] ints = (int[]) array;
  2118 + for (int i = 0, length = ints.length; i < length; i++) {
  2119 + int ele = ints[i];
  2120 + closure.execute(i, (E) Integer.valueOf(ele));
  2121 + }
  2122 + } else if (array instanceof long[]) {
  2123 + long[] longs = (long[]) array;
  2124 + for (int i = 0, length = longs.length; i < length; i++) {
  2125 + long ele = longs[i];
  2126 + closure.execute(i, (E) Long.valueOf(ele));
  2127 + }
  2128 + } else if (array instanceof float[]) {
  2129 + float[] floats = (float[]) array;
  2130 + for (int i = 0, length = floats.length; i < length; i++) {
  2131 + float ele = floats[i];
  2132 + closure.execute(i, (E) Float.valueOf(ele));
  2133 + }
  2134 + } else if (array instanceof double[]) {
  2135 + double[] doubles = (double[]) array;
  2136 + for (int i = 0, length = doubles.length; i < length; i++) {
  2137 + double ele = doubles[i];
  2138 + closure.execute(i, (E) Double.valueOf(ele));
  2139 + }
  2140 + } else {
  2141 + throw new IllegalArgumentException("Not an array: " + array.getClass());
  2142 + }
  2143 + }
  2144 +
  2145 + /**
  2146 + * 数组转为字符串
  2147 + * Return the string of array.
  2148 + *
  2149 + * @param array The array.
  2150 + * @return the string of array
  2151 + */
  2152 + public static String toString(Object array) {
  2153 + if (array == null) return "null";
  2154 + if (array instanceof Object[]) {
  2155 + return Arrays.deepToString((Object[]) array);
  2156 + } else if (array instanceof boolean[]) {
  2157 + return Arrays.toString((boolean[]) array);
  2158 + } else if (array instanceof byte[]) {
  2159 + return Arrays.toString((byte[]) array);
  2160 + } else if (array instanceof char[]) {
  2161 + return Arrays.toString((char[]) array);
  2162 + } else if (array instanceof double[]) {
  2163 + return Arrays.toString((double[]) array);
  2164 + } else if (array instanceof float[]) {
  2165 + return Arrays.toString((float[]) array);
  2166 + } else if (array instanceof int[]) {
  2167 + return Arrays.toString((int[]) array);
  2168 + } else if (array instanceof long[]) {
  2169 + return Arrays.toString((long[]) array);
  2170 + } else if (array instanceof short[]) {
  2171 + return Arrays.toString((short[]) array);
  2172 + }
  2173 + throw new IllegalArgumentException("Array has incompatible type: " + array.getClass());
  2174 + }
  2175 +
  2176 + public interface Closure<E> {
  2177 + void execute(int index, E item);
  2178 + }
  2179 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/CollectionUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import java.lang.reflect.Array;
  4 +import java.util.ArrayList;
  5 +import java.util.Arrays;
  6 +import java.util.Collection;
  7 +import java.util.Collections;
  8 +import java.util.Comparator;
  9 +import java.util.Enumeration;
  10 +import java.util.HashMap;
  11 +import java.util.HashSet;
  12 +import java.util.Iterator;
  13 +import java.util.LinkedList;
  14 +import java.util.List;
  15 +import java.util.ListIterator;
  16 +import java.util.Map;
  17 +import java.util.Set;
  18 +import java.util.TreeSet;
  19 +
  20 +/**
  21 + * <pre>
  22 + * author: blankj
  23 + * blog : http://blankj.com
  24 + * time : 2019/07/26
  25 + * desc : utils about collection
  26 + * </pre>
  27 + * newUnmodifiableList[NotNull]: 新建只读[非空]链表
  28 + * newArrayList[NotNull] : 新建数组型[非空]链表
  29 + * newLinkedList[NotNull] : 新建指针型[非空]链表
  30 + * newHashSet[NotNull] : 新建哈希[非空]集合
  31 + * newTreeSet[NotNull] : 新建有序[非空]集合
  32 + * newSynchronizedCollection : 新建同步集合
  33 + * newUnmodifiableCollection : 新建只读集合
  34 + * union : 获取并集
  35 + * intersection : 获取交集
  36 + * disjunction : 获取并集减交集
  37 + * subtract : 获取差集
  38 + * containsAny : 判断是否有交集
  39 + * getCardinalityMap : 获取集合中所有元素的基数
  40 + * isSubCollection : 是否子集
  41 + * isProperSubCollection : 是否真子集
  42 + * isEqualCollection : 判断集合是否相等
  43 + * cardinality : 获取集合中元素的基数
  44 + * find : 查找第一个符合条件的元素
  45 + * forAllDo : 对所有元素做操作
  46 + * filter : 删除原集合中不符合条件的元素
  47 + * select : 查找出所有符合条件的元素并返回新集合
  48 + * selectRejected : 查找出所有不符合条件的元素并返回新集合
  49 + * transform : 对原集合进行转变
  50 + * collect : 转变为新的集合
  51 + * countMatches : 查找到匹配的元素个数
  52 + * exists : 判断集合是否存在符合条件的元素
  53 + * addIgnoreNull : 新增元素如果不为空
  54 + * addAll : 新增多个元素
  55 + * get : 获取集合元素
  56 + * size : 获取集合个数
  57 + * sizeIsEmpty : 判断个数是否为零
  58 + * isEmpty : 判断是否为空
  59 + * isNotEmpty : 判断是否非空
  60 + * retainAll : 保留元素
  61 + * removeAll : 删除下来
  62 + * toString : 集合转为字符串
  63 + */
  64 +public final class CollectionUtils {
  65 +
  66 + private CollectionUtils() {
  67 + throw new UnsupportedOperationException("u can't instantiate me...");
  68 + }
  69 +
  70 + ///////////////////////////////////////////////////////////////////////////
  71 + // listOf
  72 + ///////////////////////////////////////////////////////////////////////////
  73 +
  74 + /**
  75 + * 新建只读[非空]链表
  76 + * Returns a new read-only list of given elements.
  77 + *
  78 + * @param array The array.
  79 + * @return a new read-only list of given elements
  80 + */
  81 + @SafeVarargs
  82 + public static <E> List<E> newUnmodifiableList(E... array) {
  83 + return Collections.unmodifiableList(newArrayList(array));
  84 + }
  85 +
  86 + /**
  87 + * Returns a new read-only list only of those given elements, that are not null.
  88 + *
  89 + * @param array The array.
  90 + * @return a new read-only list only of those given elements, that are not null
  91 + */
  92 + @SafeVarargs
  93 + public static <E> List<E> newUnmodifiableListNotNull(E... array) {
  94 + return Collections.unmodifiableList(newArrayListNotNull(array));
  95 + }
  96 +
  97 + /**
  98 + * 新建数组型[非空]链表
  99 + *
  100 + * @param array
  101 + * @param <E>
  102 + * @return
  103 + */
  104 + @SafeVarargs
  105 + public static <E> ArrayList<E> newArrayList(E... array) {
  106 + ArrayList<E> list = new ArrayList<>();
  107 + if (array == null || array.length == 0) return list;
  108 + for (E e : array) {
  109 + list.add(e);
  110 + }
  111 + return list;
  112 + }
  113 +
  114 + @SafeVarargs
  115 + public static <E> ArrayList<E> newArrayListNotNull(E... array) {
  116 + ArrayList<E> list = new ArrayList<>();
  117 + if (array == null || array.length == 0) return list;
  118 + for (E e : array) {
  119 + if (e == null) continue;
  120 + list.add(e);
  121 + }
  122 + return list;
  123 + }
  124 +
  125 + /**
  126 + * 新建指针型[非空]链表
  127 + *
  128 + * @param array
  129 + * @param <E>
  130 + * @return
  131 + */
  132 + @SafeVarargs
  133 + public static <E> List<E> newLinkedList(E... array) {
  134 + LinkedList<E> list = new LinkedList<>();
  135 + if (array == null || array.length == 0) return list;
  136 + for (E e : array) {
  137 + list.add(e);
  138 + }
  139 + return list;
  140 + }
  141 +
  142 + @SafeVarargs
  143 + public static <E> List<E> newLinkedListNotNull(E... array) {
  144 + LinkedList<E> list = new LinkedList<>();
  145 + if (array == null || array.length == 0) return list;
  146 + for (E e : array) {
  147 + if (e == null) continue;
  148 + list.add(e);
  149 + }
  150 + return list;
  151 + }
  152 +
  153 + /**
  154 + * 新建哈希[非空]集合
  155 + *
  156 + * @param array
  157 + * @param <E>
  158 + * @return
  159 + */
  160 + @SafeVarargs
  161 + public static <E> HashSet<E> newHashSet(E... array) {
  162 + HashSet<E> set = new HashSet<>();
  163 + if (array == null || array.length == 0) return set;
  164 + for (E e : array) {
  165 + set.add(e);
  166 + }
  167 + return set;
  168 + }
  169 +
  170 + @SafeVarargs
  171 + public static <E> HashSet<E> newHashSetNotNull(E... array) {
  172 + HashSet<E> set = new HashSet<>();
  173 + if (array == null || array.length == 0) return set;
  174 + for (E e : array) {
  175 + if (e == null) continue;
  176 + set.add(e);
  177 + }
  178 + return set;
  179 + }
  180 +
  181 + /**
  182 + * 新建有序[非空]集合
  183 + *
  184 + * @param comparator
  185 + * @param array
  186 + * @param <E>
  187 + * @return
  188 + */
  189 + @SafeVarargs
  190 + public static <E> TreeSet<E> newTreeSet(Comparator<E> comparator, E... array) {
  191 + TreeSet<E> set = new TreeSet<>(comparator);
  192 + if (array == null || array.length == 0) return set;
  193 + for (E e : array) {
  194 + set.add(e);
  195 + }
  196 + return set;
  197 + }
  198 +
  199 + @SafeVarargs
  200 + public static <E> TreeSet<E> newTreeSetNotNull(Comparator<E> comparator, E... array) {
  201 + TreeSet<E> set = new TreeSet<>(comparator);
  202 + if (array == null || array.length == 0) return set;
  203 + for (E e : array) {
  204 + if (e == null) continue;
  205 + set.add(e);
  206 + }
  207 + return set;
  208 + }
  209 +
  210 + /**
  211 + * 新建同步集合
  212 + *
  213 + * @param collection
  214 + * @return
  215 + */
  216 + public static Collection newSynchronizedCollection(Collection collection) {
  217 + return Collections.synchronizedCollection(collection);
  218 + }
  219 +
  220 + /**
  221 + * 新建只读集合
  222 + *
  223 + * @param collection
  224 + * @return
  225 + */
  226 + public static Collection newUnmodifiableCollection(Collection collection) {
  227 + return Collections.unmodifiableCollection(collection);
  228 + }
  229 +
  230 + /**
  231 + * 获取并集
  232 + * Returns a {@link Collection} containing the union
  233 + * of the given {@link Collection}s.
  234 + * <p>
  235 + * The cardinality of each element in the returned {@link Collection}
  236 + * will be equal to the maximum of the cardinality of that element
  237 + * in the two given {@link Collection}s.
  238 + *
  239 + * @param a the first collection
  240 + * @param b the second collection
  241 + * @return the union of the two collections
  242 + * @see Collection#addAll
  243 + */
  244 + public static Collection union(final Collection a, final Collection b) {
  245 + if (a == null && b == null) return new ArrayList();
  246 + if (a == null) return new ArrayList<Object>(b);
  247 + if (b == null) return new ArrayList<Object>(a);
  248 + ArrayList<Object> list = new ArrayList<>();
  249 + Map<Object, Integer> mapA = getCardinalityMap(a);
  250 + Map<Object, Integer> mapB = getCardinalityMap(b);
  251 + Set<Object> elts = new HashSet<Object>(a);
  252 + elts.addAll(b);
  253 + for (Object obj : elts) {
  254 + for (int i = 0, m = Math.max(getFreq(obj, mapA), getFreq(obj, mapB)); i < m; i++) {
  255 + list.add(obj);
  256 + }
  257 + }
  258 + return list;
  259 + }
  260 +
  261 + /**
  262 + * 获取交集
  263 + * Returns a {@link Collection} containing the intersection
  264 + * of the given {@link Collection}s.
  265 + * <p>
  266 + * The cardinality of each element in the returned {@link Collection}
  267 + * will be equal to the minimum of the cardinality of that element
  268 + * in the two given {@link Collection}s.
  269 + *
  270 + * @param a the first collection
  271 + * @param b the second collection
  272 + * @return the intersection of the two collections
  273 + * @see Collection#retainAll
  274 + */
  275 + public static Collection intersection(final Collection a, final Collection b) {
  276 + if (a == null || b == null) return new ArrayList();
  277 + ArrayList<Object> list = new ArrayList<>();
  278 + Map mapA = getCardinalityMap(a);
  279 + Map mapB = getCardinalityMap(b);
  280 + Set<Object> elts = new HashSet<Object>(a);
  281 + elts.addAll(b);
  282 + for (Object obj : elts) {
  283 + for (int i = 0, m = Math.min(getFreq(obj, mapA), getFreq(obj, mapB)); i < m; i++) {
  284 + list.add(obj);
  285 + }
  286 + }
  287 + return list;
  288 + }
  289 +
  290 + private static int getFreq(final Object obj, final Map freqMap) {
  291 + Integer count = (Integer) freqMap.get(obj);
  292 + if (count != null) {
  293 + return count;
  294 + }
  295 + return 0;
  296 + }
  297 +
  298 + /**
  299 + * 获取并集减交集
  300 + * Returns a {@link Collection} containing the exclusive disjunction
  301 + * (symmetric difference) of the given {@link Collection}s.
  302 + * <p>
  303 + * The cardinality of each element <i>e</i> in the returned {@link Collection}
  304 + * will be equal to
  305 + * <tt>max(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>)) - min(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>))</tt>.
  306 + * <p>
  307 + * This is equivalent to
  308 + * <tt>{@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)})</tt>
  309 + * or
  310 + * <tt>{@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)})</tt>.
  311 + *
  312 + * @param a the first collection
  313 + * @param b the second collection
  314 + * @return the symmetric difference of the two collections
  315 + */
  316 + public static Collection disjunction(final Collection a, final Collection b) {
  317 + if (a == null && b == null) return new ArrayList();
  318 + if (a == null) return new ArrayList<Object>(b);
  319 + if (b == null) return new ArrayList<Object>(a);
  320 + ArrayList<Object> list = new ArrayList<>();
  321 + Map mapA = getCardinalityMap(a);
  322 + Map mapB = getCardinalityMap(b);
  323 + Set<Object> elts = new HashSet<Object>(a);
  324 + elts.addAll(b);
  325 + for (Object obj : elts) {
  326 + for (int i = 0, m = ((Math.max(getFreq(obj, mapA), getFreq(obj, mapB)))
  327 + - (Math.min(getFreq(obj, mapA), getFreq(obj, mapB)))); i < m; i++) {
  328 + list.add(obj);
  329 + }
  330 + }
  331 + return list;
  332 + }
  333 +
  334 + /**
  335 + * 获取差集
  336 + * Returns a new {@link Collection} containing <tt><i>a</i> - <i>b</i></tt>.
  337 + * The cardinality of each element <i>e</i> in the returned {@link Collection}
  338 + * will be the cardinality of <i>e</i> in <i>a</i> minus the cardinality
  339 + * of <i>e</i> in <i>b</i>, or zero, whichever is greater.
  340 + *
  341 + * @param a the collection to subtract from
  342 + * @param b the collection to subtract
  343 + * @return a new collection with the results
  344 + * @see Collection#removeAll
  345 + */
  346 + public static Collection subtract(final Collection a, final Collection b) {
  347 + if (a == null) return new ArrayList();
  348 + if (b == null) return new ArrayList<Object>(a);
  349 + ArrayList<Object> list = new ArrayList<Object>(a);
  350 + for (Object o : b) {
  351 + list.remove(o);
  352 + }
  353 + return list;
  354 + }
  355 +
  356 + /**
  357 + * 判断是否有交集
  358 + * Returns <code>true</code> iff at least one element is in both collections.
  359 + * <p>
  360 + * In other words, this method returns <code>true</code> iff the
  361 + * {@link #intersection} of <i>coll1</i> and <i>coll2</i> is not empty.
  362 + *
  363 + * @param coll1 the first collection
  364 + * @param coll2 the first collection
  365 + * @return <code>true</code> iff the intersection of the collections is non-empty
  366 + * @see #intersection
  367 + */
  368 + public static boolean containsAny(final Collection coll1, final Collection coll2) {
  369 + if (coll1 == null || coll2 == null) return false;
  370 + if (coll1.size() < coll2.size()) {
  371 + for (Object o : coll1) {
  372 + if (coll2.contains(o)) {
  373 + return true;
  374 + }
  375 + }
  376 + } else {
  377 + for (Object o : coll2) {
  378 + if (coll1.contains(o)) {
  379 + return true;
  380 + }
  381 + }
  382 + }
  383 + return false;
  384 + }
  385 +
  386 +
  387 + /**
  388 + * 获取集合中所有元素的基数
  389 + * Returns a {@link Map} mapping each unique element in the given
  390 + * {@link Collection} to an {@link Integer} representing the number
  391 + * of occurrences of that element in the {@link Collection}.
  392 + * <p>
  393 + * Only those elements present in the collection will appear as
  394 + * keys in the map.
  395 + *
  396 + * @param coll the collection to get the cardinality map for, must not be null
  397 + * @return the populated cardinality map
  398 + */
  399 + public static Map<Object, Integer> getCardinalityMap(final Collection coll) {
  400 + Map<Object, Integer> count = new HashMap<>();
  401 + if (coll == null) return count;
  402 + for (Object obj : coll) {
  403 + Integer c = count.get(obj);
  404 + if (c == null) {
  405 + count.put(obj, 1);
  406 + } else {
  407 + count.put(obj, c + 1);
  408 + }
  409 + }
  410 + return count;
  411 + }
  412 +
  413 + /**
  414 + * 是否子集
  415 + * Returns <tt>true</tt> iff <i>a</i> is a sub-collection of <i>b</i>,
  416 + * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
  417 + * than or equal to the cardinality of <i>e</i> in <i>b</i>,
  418 + * for each element <i>e</i> in <i>a</i>.
  419 + *
  420 + * @param a the first (sub?) collection
  421 + * @param b the second (super?) collection
  422 + * @return <code>true</code> iff <i>a</i> is a sub-collection of <i>b</i>
  423 + * @see #isProperSubCollection
  424 + * @see Collection#containsAll
  425 + */
  426 + public static boolean isSubCollection(final Collection a, final Collection b) {
  427 + if (a == null || b == null) return false;
  428 + Map mapA = getCardinalityMap(a);
  429 + Map mapB = getCardinalityMap(b);
  430 + for (Object obj : a) {
  431 + if (getFreq(obj, mapA) > getFreq(obj, mapB)) {
  432 + return false;
  433 + }
  434 + }
  435 + return true;
  436 + }
  437 +
  438 + /**
  439 + * 是否真子集
  440 + * Returns <tt>true</tt> iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>,
  441 + * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
  442 + * than or equal to the cardinality of <i>e</i> in <i>b</i>,
  443 + * for each element <i>e</i> in <i>a</i>, and there is at least one
  444 + * element <i>f</i> such that the cardinality of <i>f</i> in <i>b</i>
  445 + * is strictly greater than the cardinality of <i>f</i> in <i>a</i>.
  446 + * <p>
  447 + * The implementation assumes
  448 + * <ul>
  449 + * <li><code>a.size()</code> and <code>b.size()</code> represent the
  450 + * total cardinality of <i>a</i> and <i>b</i>, resp. </li>
  451 + * <li><code>a.size() < Integer.MAXVALUE</code></li>
  452 + * </ul>
  453 + *
  454 + * @param a the first (sub?) collection
  455 + * @param b the second (super?) collection
  456 + * @return <code>true</code> iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>
  457 + * @see #isSubCollection
  458 + * @see Collection#containsAll
  459 + */
  460 + public static boolean isProperSubCollection(final Collection a, final Collection b) {
  461 + if (a == null || b == null) return false;
  462 + return a.size() < b.size() && CollectionUtils.isSubCollection(a, b);
  463 + }
  464 +
  465 + /**
  466 + * 判断集合是否相等
  467 + * Returns <tt>true</tt> iff the given {@link Collection}s contain
  468 + * exactly the same elements with exactly the same cardinalities.
  469 + * <p>
  470 + * That is, iff the cardinality of <i>e</i> in <i>a</i> is
  471 + * equal to the cardinality of <i>e</i> in <i>b</i>,
  472 + * for each element <i>e</i> in <i>a</i> or <i>b</i>.
  473 + *
  474 + * @param a the first collection
  475 + * @param b the second collection
  476 + * @return <code>true</code> iff the collections contain the same elements with the same cardinalities.
  477 + */
  478 + public static boolean isEqualCollection(final Collection a, final Collection b) {
  479 + if (a == null || b == null) return false;
  480 + if (a.size() != b.size()) {
  481 + return false;
  482 + } else {
  483 + Map mapA = getCardinalityMap(a);
  484 + Map mapB = getCardinalityMap(b);
  485 + if (mapA.size() != mapB.size()) {
  486 + return false;
  487 + } else {
  488 + for (Object obj : mapA.keySet()) {
  489 + if (getFreq(obj, mapA) != getFreq(obj, mapB)) {
  490 + return false;
  491 + }
  492 + }
  493 + return true;
  494 + }
  495 + }
  496 + }
  497 +
  498 + /**
  499 + * 获取集合中元素的基数
  500 + * Returns the number of occurrences of <i>obj</i> in <i>coll</i>.
  501 + *
  502 + * @param obj the object to find the cardinality of
  503 + * @param coll the collection to search
  504 + * @return the the number of occurrences of obj in coll
  505 + */
  506 + public static <E> int cardinality(E obj, final Collection<E> coll) {
  507 + if (coll == null) return 0;
  508 + if (coll instanceof Set) {
  509 + return (coll.contains(obj) ? 1 : 0);
  510 + }
  511 + int count = 0;
  512 + if (obj == null) {
  513 + for (E e : coll) {
  514 + if (e == null) {
  515 + count++;
  516 + }
  517 + }
  518 + } else {
  519 + for (E e : coll) {
  520 + if (obj.equals(e)) {
  521 + count++;
  522 + }
  523 + }
  524 + }
  525 + return count;
  526 + }
  527 +
  528 + /**
  529 + * 查找第一个符合条件的元素
  530 + * Finds the first element in the given collection which matches the given predicate.
  531 + * <p>
  532 + * If the input collection or predicate is null, or no element of the collection
  533 + * matches the predicate, null is returned.
  534 + *
  535 + * @param collection the collection to search, may be null
  536 + * @param predicate the predicate to use, may be null
  537 + * @return the first element of the collection which matches the predicate or null if none could be found
  538 + */
  539 + public static <E> E find(Collection<E> collection, Predicate<E> predicate) {
  540 + if (collection == null || predicate == null) return null;
  541 + for (E item : collection) {
  542 + if (predicate.evaluate(item)) {
  543 + return item;
  544 + }
  545 + }
  546 + return null;
  547 + }
  548 +
  549 + /**
  550 + * 对所有元素做操作
  551 + * Executes the given closure on each element in the collection.
  552 + * <p>
  553 + * If the input collection or closure is null, there is no change made.
  554 + *
  555 + * @param collection the collection to get the input from, may be null
  556 + * @param closure the closure to perform, may be null
  557 + */
  558 + public static <E> void forAllDo(Collection<E> collection, Closure<E> closure) {
  559 + if (collection == null || closure == null) return;
  560 + int index = 0;
  561 + for (E e : collection) {
  562 + closure.execute(index++, e);
  563 + }
  564 + }
  565 +
  566 + /**
  567 + * 删除原集合中不符合条件的元素
  568 + * Filter the collection by applying a Predicate to each element. If the
  569 + * predicate returns false, remove the element.
  570 + * <p>
  571 + * If the input collection or predicate is null, there is no change made.
  572 + *
  573 + * @param collection the collection to get the input from, may be null
  574 + * @param predicate the predicate to use as a filter, may be null
  575 + */
  576 + public static <E> void filter(Collection<E> collection, Predicate<E> predicate) {
  577 + if (collection == null || predicate == null) return;
  578 + for (Iterator it = collection.iterator(); it.hasNext(); ) {
  579 + if (!predicate.evaluate((E) it.next())) {
  580 + it.remove();
  581 + }
  582 + }
  583 + }
  584 +
  585 + /**
  586 + * 查找出所有符合条件的元素并返回新集合
  587 + * Selects all elements from input collection which match the given predicate
  588 + * into an output collection.
  589 + * <p>
  590 + * A <code>null</code> predicate matches no elements.
  591 + *
  592 + * @param inputCollection the collection to get the input from, may not be null
  593 + * @param predicate the predicate to use, may be null
  594 + * @return the elements matching the predicate (new list)
  595 + * @throws NullPointerException if the input collection is null
  596 + */
  597 + public static <E> Collection<E> select(Collection<E> inputCollection, Predicate<E> predicate) {
  598 + if (inputCollection == null || predicate == null) return new ArrayList<>();
  599 + ArrayList<E> answer = new ArrayList<>(inputCollection.size());
  600 + for (E o : inputCollection) {
  601 + if (predicate.evaluate(o)) {
  602 + answer.add(o);
  603 + }
  604 + }
  605 + return answer;
  606 + }
  607 +
  608 + /**
  609 + * 查找出所有不符合条件的元素并返回新集合
  610 + * Selects all elements from inputCollection which don't match the given predicate
  611 + * into an output collection.
  612 + * <p>
  613 + * If the input predicate is <code>null</code>, the result is an empty list.
  614 + *
  615 + * @param inputCollection the collection to get the input from, may not be null
  616 + * @param predicate the predicate to use, may be null
  617 + * @return the elements <b>not</b> matching the predicate (new list)
  618 + * @throws NullPointerException if the input collection is null
  619 + */
  620 + public static <E> Collection<E> selectRejected(Collection<E> inputCollection, Predicate<E> predicate) {
  621 + if (inputCollection == null || predicate == null) return new ArrayList<>();
  622 + ArrayList<E> answer = new ArrayList<>(inputCollection.size());
  623 + for (E o : inputCollection) {
  624 + if (!predicate.evaluate(o)) {
  625 + answer.add(o);
  626 + }
  627 + }
  628 + return answer;
  629 + }
  630 +
  631 + /**
  632 + * 对原集合进行转变
  633 + * Transform the collection by applying a Transformer to each element.
  634 + * <p>
  635 + * If the input collection or transformer is null, there is no change made.
  636 + * <p>
  637 + * This routine is best for Lists, for which set() is used to do the
  638 + * transformations "in place." For other Collections, clear() and addAll()
  639 + * are used to replace elements.
  640 + * <p>
  641 + * If the input collection controls its input, such as a Set, and the
  642 + * Transformer creates duplicates (or are otherwise invalid), the
  643 + * collection may reduce in size due to calling this method.
  644 + *
  645 + * @param collection the collection to get the input from, may be null
  646 + * @param transformer the transformer to perform, may be null
  647 + */
  648 + public static <E1, E2> void transform(Collection<E1> collection, Transformer<E1, E2> transformer) {
  649 + if (collection == null || transformer == null) return;
  650 + if (collection instanceof List) {
  651 + List list = (List) collection;
  652 + for (ListIterator it = list.listIterator(); it.hasNext(); ) {
  653 + it.set(transformer.transform((E1) it.next()));
  654 + }
  655 + } else {
  656 + Collection resultCollection = collect(collection, transformer);
  657 + collection.clear();
  658 + collection.addAll(resultCollection);
  659 + }
  660 + }
  661 +
  662 +
  663 + /**
  664 + * 转变为新的集合
  665 + * Returns a new Collection consisting of the elements of inputCollection transformed
  666 + * by the given transformer.
  667 + * <p>
  668 + * If the input transformer is null, the result is an empty list.
  669 + *
  670 + * @param inputCollection the collection to get the input from, may be null
  671 + * @param transformer the transformer to use, may be null
  672 + * @return the transformed result (new list)
  673 + */
  674 + public static <E1, E2> Collection<E2> collect(final Collection<E1> inputCollection,
  675 + final Transformer<E1, E2> transformer) {
  676 + List<E2> answer = new ArrayList<>();
  677 + if (inputCollection == null || transformer == null) return answer;
  678 + for (E1 e1 : inputCollection) {
  679 + answer.add(transformer.transform(e1));
  680 + }
  681 + return answer;
  682 + }
  683 +
  684 + /**
  685 + * 查找到匹配的元素个数
  686 + * Counts the number of elements in the input collection that match the predicate.
  687 + * <p>
  688 + * A <code>null</code> collection or predicate matches no elements.
  689 + *
  690 + * @param collection the collection to get the input from, may be null
  691 + * @param predicate the predicate to use, may be null
  692 + * @return the number of matches for the predicate in the collection
  693 + */
  694 + public static <E> int countMatches(Collection<E> collection, Predicate<E> predicate) {
  695 + if (collection == null || predicate == null) return 0;
  696 + int count = 0;
  697 + for (E o : collection) {
  698 + if (predicate.evaluate(o)) {
  699 + count++;
  700 + }
  701 + }
  702 + return count;
  703 + }
  704 +
  705 + /**
  706 + * 判断集合是否存在符合条件的元素
  707 + * Answers true if a predicate is true for at least one element of a collection.
  708 + * <p>
  709 + * A <code>null</code> collection or predicate returns false.
  710 + *
  711 + * @param collection the collection to get the input from, may be null
  712 + * @param predicate the predicate to use, may be null
  713 + * @return true if at least one element of the collection matches the predicate
  714 + */
  715 + public static <E> boolean exists(Collection<E> collection, Predicate<E> predicate) {
  716 + if (collection == null || predicate == null) return false;
  717 + for (E o : collection) {
  718 + if (predicate.evaluate(o)) {
  719 + return true;
  720 + }
  721 + }
  722 + return false;
  723 + }
  724 +
  725 + /**
  726 + * 新增元素如果不为空
  727 + * Adds an element to the collection unless the element is null.
  728 + *
  729 + * @param collection the collection to add to, may be null
  730 + * @param object the object to add, if null it will not be added
  731 + * @return true if the collection changed
  732 + */
  733 + public static <E> boolean addIgnoreNull(Collection<E> collection, E object) {
  734 + if (collection == null) return false;
  735 + return (object != null && collection.add(object));
  736 + }
  737 +
  738 + /**
  739 + * 新增多个元素
  740 + * Adds all elements in the iteration to the given collection.
  741 + *
  742 + * @param collection the collection to add to, may be null
  743 + * @param iterator the iterator of elements to add, may be null
  744 + */
  745 + public static <E> void addAll(Collection<E> collection, Iterator<E> iterator) {
  746 + if (collection == null || iterator == null) return;
  747 + while (iterator.hasNext()) {
  748 + collection.add(iterator.next());
  749 + }
  750 + }
  751 +
  752 + /**
  753 + * Adds all elements in the enumeration to the given collection.
  754 + *
  755 + * @param collection the collection to add to, may be null
  756 + * @param enumeration the enumeration of elements to add, may be null
  757 + */
  758 + public static <E> void addAll(Collection<E> collection, Enumeration<E> enumeration) {
  759 + if (collection == null || enumeration == null) return;
  760 + while (enumeration.hasMoreElements()) {
  761 + collection.add(enumeration.nextElement());
  762 + }
  763 + }
  764 +
  765 + /**
  766 + * Adds all elements in the array to the given collection.
  767 + *
  768 + * @param collection the collection to add to, may be null
  769 + * @param elements the array of elements to add, may be null
  770 + */
  771 + public static <E> void addAll(Collection<E> collection, E[] elements) {
  772 + if (collection == null || elements == null || elements.length == 0) return;
  773 + collection.addAll(Arrays.asList(elements));
  774 + }
  775 +
  776 + /**
  777 + * 获取集合元素
  778 + * Returns the <code>index</code>-th value in <code>object</code>, throwing
  779 + * <code>IndexOutOfBoundsException</code> if there is no such element or
  780 + * <code>IllegalArgumentException</code> if <code>object</code> is not an
  781 + * instance of one of the supported types.
  782 + * <p>
  783 + * The supported types, and associated semantics are:
  784 + * <ul>
  785 + * <li> Map -- the value returned is the <code>Map.Entry</code> in position
  786 + * <code>index</code> in the map's <code>entrySet</code> iterator,
  787 + * if there is such an entry.</li>
  788 + * <li> List -- this method is equivalent to the list's get method.</li>
  789 + * <li> Array -- the <code>index</code>-th array entry is returned,
  790 + * if there is such an entry; otherwise an <code>IndexOutOfBoundsException</code>
  791 + * is thrown.</li>
  792 + * <li> Collection -- the value returned is the <code>index</code>-th object
  793 + * returned by the collection's default iterator, if there is such an element.</li>
  794 + * <li> Iterator or Enumeration -- the value returned is the
  795 + * <code>index</code>-th object in the Iterator/Enumeration, if there
  796 + * is such an element. The Iterator/Enumeration is advanced to
  797 + * <code>index</code> (or to the end, if <code>index</code> exceeds the
  798 + * number of entries) as a side effect of this method.</li>
  799 + * </ul>
  800 + *
  801 + * @param object the object to get a value from
  802 + * @param index the index to get
  803 + * @return the object at the specified index
  804 + * @throws IndexOutOfBoundsException if the index is invalid
  805 + * @throws IllegalArgumentException if the object type is invalid
  806 + */
  807 + public static Object get(Object object, int index) {
  808 + if (object == null) return null;
  809 + if (index < 0) {
  810 + throw new IndexOutOfBoundsException("Index cannot be negative: " + index);
  811 + }
  812 + if (object instanceof Map) {
  813 + Map map = (Map) object;
  814 + Iterator iterator = map.entrySet().iterator();
  815 + return get(iterator, index);
  816 + } else if (object instanceof List) {
  817 + return ((List) object).get(index);
  818 + } else if (object instanceof Object[]) {
  819 + return ((Object[]) object)[index];
  820 + } else if (object instanceof Iterator) {
  821 + Iterator it = (Iterator) object;
  822 + while (it.hasNext()) {
  823 + index--;
  824 + if (index == -1) {
  825 + return it.next();
  826 + } else {
  827 + it.next();
  828 + }
  829 + }
  830 + throw new IndexOutOfBoundsException("Entry does not exist: " + index);
  831 + } else if (object instanceof Collection) {
  832 + Iterator iterator = ((Collection) object).iterator();
  833 + return get(iterator, index);
  834 + } else if (object instanceof Enumeration) {
  835 + Enumeration it = (Enumeration) object;
  836 + while (it.hasMoreElements()) {
  837 + index--;
  838 + if (index == -1) {
  839 + return it.nextElement();
  840 + } else {
  841 + it.nextElement();
  842 + }
  843 + }
  844 + throw new IndexOutOfBoundsException("Entry does not exist: " + index);
  845 + } else {
  846 + try {
  847 + return Array.get(object, index);
  848 + } catch (IllegalArgumentException ex) {
  849 + throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
  850 + }
  851 + }
  852 + }
  853 +
  854 + /**
  855 + * 获取集合个数
  856 + * Gets the size of the collection/iterator specified.
  857 + * <p>
  858 + * This method can handles objects as follows
  859 + * <ul>
  860 + * <li>Collection - the collection size
  861 + * <li>Map - the map size
  862 + * <li>Array - the array size
  863 + * <li>Iterator - the number of elements remaining in the iterator
  864 + * <li>Enumeration - the number of elements remaining in the enumeration
  865 + * </ul>
  866 + *
  867 + * @param object the object to get the size of
  868 + * @return the size of the specified collection
  869 + * @throws IllegalArgumentException thrown if object is not recognised or null
  870 + */
  871 + public static int size(Object object) {
  872 + if (object == null) return 0;
  873 + int total = 0;
  874 + if (object instanceof Map) {
  875 + total = ((Map) object).size();
  876 + } else if (object instanceof Collection) {
  877 + total = ((Collection) object).size();
  878 + } else if (object instanceof Object[]) {
  879 + total = ((Object[]) object).length;
  880 + } else if (object instanceof Iterator) {
  881 + Iterator it = (Iterator) object;
  882 + while (it.hasNext()) {
  883 + total++;
  884 + it.next();
  885 + }
  886 + } else if (object instanceof Enumeration) {
  887 + Enumeration it = (Enumeration) object;
  888 + while (it.hasMoreElements()) {
  889 + total++;
  890 + it.nextElement();
  891 + }
  892 + } else {
  893 + try {
  894 + total = Array.getLength(object);
  895 + } catch (IllegalArgumentException ex) {
  896 + throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
  897 + }
  898 + }
  899 + return total;
  900 + }
  901 +
  902 + /**
  903 + * 判断个数是否为零
  904 + * Checks if the specified collection/array/iterator is empty.
  905 + * <p>
  906 + * This method can handles objects as follows
  907 + * <ul>
  908 + * <li>Collection - via collection isEmpty
  909 + * <li>Map - via map isEmpty
  910 + * <li>Array - using array size
  911 + * <li>Iterator - via hasNext
  912 + * <li>Enumeration - via hasMoreElements
  913 + * </ul>
  914 + * <p>
  915 + * Note: This method is named to avoid clashing with
  916 + * {@link #isEmpty(Collection)}.
  917 + *
  918 + * @param object the object to get the size of, not null
  919 + * @return true if empty
  920 + * @throws IllegalArgumentException thrown if object is not recognised or null
  921 + */
  922 + public static boolean sizeIsEmpty(Object object) {
  923 + if (object == null) return true;
  924 + if (object instanceof Collection) {
  925 + return ((Collection) object).isEmpty();
  926 + } else if (object instanceof Map) {
  927 + return ((Map) object).isEmpty();
  928 + } else if (object instanceof Object[]) {
  929 + return ((Object[]) object).length == 0;
  930 + } else if (object instanceof Iterator) {
  931 + return !((Iterator) object).hasNext();
  932 + } else if (object instanceof Enumeration) {
  933 + return !((Enumeration) object).hasMoreElements();
  934 + } else {
  935 + try {
  936 + return Array.getLength(object) == 0;
  937 + } catch (IllegalArgumentException ex) {
  938 + throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
  939 + }
  940 + }
  941 + }
  942 +
  943 + /**
  944 + * 判断是否为空
  945 + * Null-safe check if the specified collection is empty.
  946 + * <p>
  947 + * Null returns true.
  948 + *
  949 + * @param coll the collection to check, may be null
  950 + * @return true if empty or null
  951 + */
  952 + public static boolean isEmpty(Collection coll) {
  953 + return coll == null || coll.size() == 0;
  954 + }
  955 +
  956 + /**
  957 + * 判断是否非空
  958 + * Null-safe check if the specified collection is not empty.
  959 + * <p>
  960 + * Null returns false.
  961 + *
  962 + * @param coll the collection to check, may be null
  963 + * @return true if non-null and non-empty
  964 + */
  965 + public static boolean isNotEmpty(Collection coll) {
  966 + return !isEmpty(coll);
  967 + }
  968 +
  969 +
  970 + /**
  971 + * 保留元素
  972 + * Returns a collection containing all the elements in <code>collection</code>
  973 + * that are also in <code>retain</code>. The cardinality of an element <code>e</code>
  974 + * in the returned collection is the same as the cardinality of <code>e</code>
  975 + * in <code>collection</code> unless <code>retain</code> does not contain <code>e</code>, in which
  976 + * case the cardinality is zero. This method is useful if you do not wish to modify
  977 + * the collection <code>c</code> and thus cannot call <code>c.retainAll(retain);</code>.
  978 + *
  979 + * @param collection the collection whose contents are the target of the #retailAll operation
  980 + * @param retain the collection containing the elements to be retained in the returned collection
  981 + * @return a <code>Collection</code> containing all the elements of <code>collection</code>
  982 + * that occur at least once in <code>retain</code>.
  983 + */
  984 + public static <E> Collection<E> retainAll(Collection<E> collection, Collection<E> retain) {
  985 + if (collection == null || retain == null) return new ArrayList<>();
  986 + List<E> list = new ArrayList<>();
  987 + for (E item : collection) {
  988 + if (retain.contains(item)) {
  989 + list.add(item);
  990 + }
  991 + }
  992 + return list;
  993 + }
  994 +
  995 + /**
  996 + * 删除下来
  997 + * Removes the elements in <code>remove</code> from <code>collection</code>. That is, this
  998 + * method returns a collection containing all the elements in <code>c</code>
  999 + * that are not in <code>remove</code>. The cardinality of an element <code>e</code>
  1000 + * in the returned collection is the same as the cardinality of <code>e</code>
  1001 + * in <code>collection</code> unless <code>remove</code> contains <code>e</code>, in which
  1002 + * case the cardinality is zero. This method is useful if you do not wish to modify
  1003 + * the collection <code>c</code> and thus cannot call <code>collection.removeAll(remove);</code>.
  1004 + *
  1005 + * @param collection the collection from which items are removed (in the returned collection)
  1006 + * @param remove the items to be removed from the returned <code>collection</code>
  1007 + * @return a <code>Collection</code> containing all the elements of <code>collection</code> except
  1008 + * any elements that also occur in <code>remove</code>.
  1009 + */
  1010 + public static <E> Collection<E> removeAll(Collection<E> collection, Collection<E> remove) {
  1011 + if (collection == null) return new ArrayList<>();
  1012 + if (remove == null) return new ArrayList<>(collection);
  1013 + List<E> list = new ArrayList<>();
  1014 + for (E obj : collection) {
  1015 + if (!remove.contains(obj)) {
  1016 + list.add(obj);
  1017 + }
  1018 + }
  1019 + return list;
  1020 + }
  1021 +
  1022 + /**
  1023 + * Randomly permutes the specified list using a default source of randomness.
  1024 + *
  1025 + * @param list the list to be shuffled.
  1026 + * @throws UnsupportedOperationException if the specified list or
  1027 + * its list-iterator does not support the <tt>set</tt> operation.
  1028 + */
  1029 + public static <T> void shuffle(List<T> list) {
  1030 + Collections.shuffle(list);
  1031 + }
  1032 +
  1033 + /**
  1034 + * 集合转为字符串
  1035 + * Return the string of collection.
  1036 + *
  1037 + * @param collection The collection.
  1038 + * @return the string of collection
  1039 + */
  1040 + public static String toString(Collection collection) {
  1041 + if (collection == null) return "null";
  1042 + return collection.toString();
  1043 + }
  1044 +
  1045 + public interface Closure<E> {
  1046 + void execute(int index, E item);
  1047 + }
  1048 +
  1049 + public interface Transformer<E1, E2> {
  1050 + E2 transform(E1 input);
  1051 + }
  1052 +
  1053 + public interface Predicate<E> {
  1054 + boolean evaluate(E item);
  1055 + }
  1056 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/ColorUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Color;
  5 +
  6 +import androidx.annotation.ColorInt;
  7 +import androidx.annotation.ColorRes;
  8 +import androidx.annotation.FloatRange;
  9 +import androidx.annotation.IntRange;
  10 +import androidx.annotation.NonNull;
  11 +import androidx.core.content.ContextCompat;
  12 +
  13 +/**
  14 + * <pre>
  15 + * author: Blankj
  16 + * blog : http://blankj.com
  17 + * time : 2019/01/15
  18 + * desc : utils about color
  19 + * </pre>
  20 + * getColor : 获取颜色
  21 + * setAlphaComponent: 设置颜色透明度值
  22 + * setRedComponent : 设置颜色红色值
  23 + * setGreenComponent: 设置颜色绿色值
  24 + * setBlueComponent : 设置颜色蓝色值
  25 + * string2Int : 颜色串转颜色值
  26 + * int2RgbString : 颜色值转 RGB 串
  27 + * int2ArgbString : 颜色值转 ARGB 串
  28 + * getRandomColor : 获取随机色
  29 + */
  30 +public final class ColorUtils {
  31 +
  32 + private ColorUtils() {
  33 + throw new UnsupportedOperationException("u can't instantiate me...");
  34 + }
  35 +
  36 + /**
  37 + * 获取颜色
  38 + * Returns a color associated with a particular resource ID.
  39 + *
  40 + * @param id The desired resource identifier.
  41 + * @return a color associated with a particular resource ID
  42 + */
  43 + public static int getColor(Context context, @ColorRes int id) {
  44 + return ContextCompat.getColor(context, id);
  45 + }
  46 +
  47 + /**
  48 + * 设置颜色透明度值
  49 + * Set the alpha component of {@code color} to be {@code alpha}.
  50 + *
  51 + * @param color The color.
  52 + * @param alpha Alpha component \([0..255]\) of the color.
  53 + * @return the {@code color} with {@code alpha} component
  54 + */
  55 + public static int setAlphaComponent(@ColorInt final int color,
  56 + @IntRange(from = 0x0, to = 0xFF) int alpha) {
  57 + return (color & 0x00ffffff) | (alpha << 24);
  58 + }
  59 +
  60 + /**
  61 + * Set the alpha component of {@code color} to be {@code alpha}.
  62 + *
  63 + * @param color The color.
  64 + * @param alpha Alpha component \([0..1]\) of the color.
  65 + * @return the {@code color} with {@code alpha} component
  66 + */
  67 + public static int setAlphaComponent(@ColorInt int color,
  68 + @FloatRange(from = 0, to = 1) float alpha) {
  69 + return (color & 0x00ffffff) | ((int) (alpha * 255.0f + 0.5f) << 24);
  70 + }
  71 +
  72 + /**
  73 + * 设置颜色红色值
  74 + * Set the red component of {@code color} to be {@code red}.
  75 + *
  76 + * @param color The color.
  77 + * @param red Red component \([0..255]\) of the color.
  78 + * @return the {@code color} with {@code red} component
  79 + */
  80 + public static int setRedComponent(@ColorInt int color,
  81 + @IntRange(from = 0x0, to = 0xFF) int red) {
  82 + return (color & 0xff00ffff) | (red << 16);
  83 + }
  84 +
  85 + /**
  86 + * Set the red component of {@code color} to be {@code red}.
  87 + *
  88 + * @param color The color.
  89 + * @param red Red component \([0..1]\) of the color.
  90 + * @return the {@code color} with {@code red} component
  91 + */
  92 + public static int setRedComponent(@ColorInt int color,
  93 + @FloatRange(from = 0, to = 1) float red) {
  94 + return (color & 0xff00ffff) | ((int) (red * 255.0f + 0.5f) << 16);
  95 + }
  96 +
  97 + /**
  98 + * 设置颜色绿色值
  99 + * Set the green component of {@code color} to be {@code green}.
  100 + *
  101 + * @param color The color.
  102 + * @param green Green component \([0..255]\) of the color.
  103 + * @return the {@code color} with {@code green} component
  104 + */
  105 + public static int setGreenComponent(@ColorInt int color,
  106 + @IntRange(from = 0x0, to = 0xFF) int green) {
  107 + return (color & 0xffff00ff) | (green << 8);
  108 + }
  109 +
  110 + /**
  111 + * Set the green component of {@code color} to be {@code green}.
  112 + *
  113 + * @param color The color.
  114 + * @param green Green component \([0..1]\) of the color.
  115 + * @return the {@code color} with {@code green} component
  116 + */
  117 + public static int setGreenComponent(@ColorInt int color,
  118 + @FloatRange(from = 0, to = 1) float green) {
  119 + return (color & 0xffff00ff) | ((int) (green * 255.0f + 0.5f) << 8);
  120 + }
  121 +
  122 + /**
  123 + * 设置颜色蓝色值
  124 + * Set the blue component of {@code color} to be {@code blue}.
  125 + *
  126 + * @param color The color.
  127 + * @param blue Blue component \([0..255]\) of the color.
  128 + * @return the {@code color} with {@code blue} component
  129 + */
  130 + public static int setBlueComponent(@ColorInt int color,
  131 + @IntRange(from = 0x0, to = 0xFF) int blue) {
  132 + return (color & 0xffffff00) | blue;
  133 + }
  134 +
  135 + /**
  136 + * Set the blue component of {@code color} to be {@code blue}.
  137 + *
  138 + * @param color The color.
  139 + * @param blue Blue component \([0..1]\) of the color.
  140 + * @return the {@code color} with {@code blue} component
  141 + */
  142 + public static int setBlueComponent(@ColorInt int color,
  143 + @FloatRange(from = 0, to = 1) float blue) {
  144 + return (color & 0xffffff00) | (int) (blue * 255.0f + 0.5f);
  145 + }
  146 +
  147 + /**
  148 + * 颜色串转颜色值
  149 + * Color-string to color-int.
  150 + * <p>Supported formats are:</p>
  151 + *
  152 + * <ul>
  153 + * <li><code>#RRGGBB</code></li>
  154 + * <li><code>#AARRGGBB</code></li>
  155 + * </ul>
  156 + *
  157 + * <p>The following names are also accepted: <code>red</code>, <code>blue</code>,
  158 + * <code>green</code>, <code>black</code>, <code>white</code>, <code>gray</code>,
  159 + * <code>cyan</code>, <code>magenta</code>, <code>yellow</code>, <code>lightgray</code>,
  160 + * <code>darkgray</code>, <code>grey</code>, <code>lightgrey</code>, <code>darkgrey</code>,
  161 + * <code>aqua</code>, <code>fuchsia</code>, <code>lime</code>, <code>maroon</code>,
  162 + * <code>navy</code>, <code>olive</code>, <code>purple</code>, <code>silver</code>,
  163 + * and <code>teal</code>.</p>
  164 + *
  165 + * @param colorString The color-string.
  166 + * @return color-int
  167 + * @throws IllegalArgumentException The string cannot be parsed.
  168 + */
  169 + public static int string2Int(@NonNull String colorString) {
  170 + return Color.parseColor(colorString);
  171 + }
  172 +
  173 + /**
  174 + * 颜色值转 RGB 串
  175 + * Color-int to color-string.
  176 + *
  177 + * @param colorInt The color-int.
  178 + * @return color-string
  179 + */
  180 + public static String int2RgbString(@ColorInt int colorInt) {
  181 + colorInt = colorInt & 0x00ffffff;
  182 + String color = Integer.toHexString(colorInt);
  183 + while (color.length() < 6) {
  184 + color = "0" + color;
  185 + }
  186 + return "#" + color;
  187 + }
  188 +
  189 + /**
  190 + * 颜色值转 ARGB 串
  191 + * Color-int to color-string.
  192 + *
  193 + * @param colorInt The color-int.
  194 + * @return color-string
  195 + */
  196 + public static String int2ArgbString(@ColorInt final int colorInt) {
  197 + String color = Integer.toHexString(colorInt);
  198 + while (color.length() < 6) {
  199 + color = "0" + color;
  200 + }
  201 + while (color.length() < 8) {
  202 + color = "f" + color;
  203 + }
  204 + return "#" + color;
  205 + }
  206 +
  207 + /**
  208 + * 获取随机色
  209 + * Return the random color.
  210 + *
  211 + * @return the random color
  212 + */
  213 + public static int getRandomColor() {
  214 + return getRandomColor(true);
  215 + }
  216 +
  217 + /**
  218 + * Return the random color.
  219 + *
  220 + * @param supportAlpha True to support alpha, false otherwise.
  221 + * @return the random color
  222 + */
  223 + public static int getRandomColor(final boolean supportAlpha) {
  224 + int high = supportAlpha ? (int) (Math.random() * 0x100) << 24 : 0xFF000000;
  225 + return high | (int) (Math.random() * 0x1000000);
  226 + }
  227 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/EncodeUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import android.os.Build;
  4 +import android.text.Html;
  5 +import android.util.Base64;
  6 +
  7 +import java.io.UnsupportedEncodingException;
  8 +import java.net.URLDecoder;
  9 +import java.net.URLEncoder;
  10 +
  11 +/**
  12 + * <pre>
  13 + * author: Blankj
  14 + * blog : http://blankj.com
  15 + * time : 2016/08/07
  16 + * desc : utils about encode
  17 + * </pre>
  18 + */
  19 +public final class EncodeUtils {
  20 +
  21 + private EncodeUtils() {
  22 + throw new UnsupportedOperationException("u can't instantiate me...");
  23 + }
  24 +
  25 + /**
  26 + * URL 编码
  27 + * Return the urlencoded string.
  28 + *
  29 + * @param input The input.
  30 + * @return the urlencoded string
  31 + */
  32 + public static String urlEncode(final String input) {
  33 + return urlEncode(input, "UTF-8");
  34 + }
  35 +
  36 + /**
  37 + * URL 解码
  38 + * Return the urlencoded string.
  39 + *
  40 + * @param input The input.
  41 + * @param charsetName The name of charset.
  42 + * @return the urlencoded string
  43 + */
  44 + public static String urlEncode(final String input, final String charsetName) {
  45 + if (input == null || input.length() == 0) return "";
  46 + try {
  47 + return URLEncoder.encode(input, charsetName);
  48 + } catch (UnsupportedEncodingException e) {
  49 + throw new AssertionError(e);
  50 + }
  51 + }
  52 +
  53 + /**
  54 + * Return the string of decode urlencoded string.
  55 + *
  56 + * @param input The input.
  57 + * @return the string of decode urlencoded string
  58 + */
  59 + public static String urlDecode(final String input) {
  60 + return urlDecode(input, "UTF-8");
  61 + }
  62 +
  63 + /**
  64 + * Return the string of decode urlencoded string.
  65 + *
  66 + * @param input The input.
  67 + * @param charsetName The name of charset.
  68 + * @return the string of decode urlencoded string
  69 + */
  70 + public static String urlDecode(final String input, final String charsetName) {
  71 + if (input == null || input.length() == 0) return "";
  72 + try {
  73 + return URLDecoder.decode(input, charsetName);
  74 + } catch (UnsupportedEncodingException e) {
  75 + throw new AssertionError(e);
  76 + }
  77 + }
  78 +
  79 + /**
  80 + * Base64 编码
  81 + * Return Base64-encode bytes.
  82 + *
  83 + * @param input The input.
  84 + * @return Base64-encode bytes
  85 + */
  86 + public static byte[] base64Encode(final String input) {
  87 + return base64Encode(input.getBytes());
  88 + }
  89 +
  90 + /**
  91 + * Return Base64-encode bytes.
  92 + *
  93 + * @param input The input.
  94 + * @return Base64-encode bytes
  95 + */
  96 + public static byte[] base64Encode(final byte[] input) {
  97 + if (input == null || input.length == 0) return new byte[0];
  98 + return Base64.encode(input, Base64.NO_WRAP);
  99 + }
  100 +
  101 + /**
  102 + * Return Base64-encode string.
  103 + *
  104 + * @param input The input.
  105 + * @return Base64-encode string
  106 + */
  107 + public static String base64Encode2String(final byte[] input) {
  108 + if (input == null || input.length == 0) return "";
  109 + return Base64.encodeToString(input, Base64.NO_WRAP);
  110 + }
  111 +
  112 + /**
  113 + * Base64 解码
  114 + * Return the bytes of decode Base64-encode string.
  115 + *
  116 + * @param input The input.
  117 + * @return the string of decode Base64-encode string
  118 + */
  119 + public static byte[] base64Decode(final String input) {
  120 + if (input == null || input.length() == 0) return new byte[0];
  121 + return Base64.decode(input, Base64.NO_WRAP);
  122 + }
  123 +
  124 + /**
  125 + * Return the bytes of decode Base64-encode bytes.
  126 + *
  127 + * @param input The input.
  128 + * @return the bytes of decode Base64-encode bytes
  129 + */
  130 + public static byte[] base64Decode(final byte[] input) {
  131 + if (input == null || input.length == 0) return new byte[0];
  132 + return Base64.decode(input, Base64.NO_WRAP);
  133 + }
  134 +
  135 + /**
  136 + * Html 编码
  137 + * Return html-encode string.
  138 + *
  139 + * @param input The input.
  140 + * @return html-encode string
  141 + */
  142 + public static String htmlEncode(final CharSequence input) {
  143 + if (input == null || input.length() == 0) return "";
  144 + StringBuilder sb = new StringBuilder();
  145 + char c;
  146 + for (int i = 0, len = input.length(); i < len; i++) {
  147 + c = input.charAt(i);
  148 + switch (c) {
  149 + case '<':
  150 + sb.append("&lt;"); //$NON-NLS-1$
  151 + break;
  152 + case '>':
  153 + sb.append("&gt;"); //$NON-NLS-1$
  154 + break;
  155 + case '&':
  156 + sb.append("&amp;"); //$NON-NLS-1$
  157 + break;
  158 + case '\'':
  159 + //http://www.w3.org/TR/xhtml1
  160 + // The named character reference &apos; (the apostrophe, U+0027) was
  161 + // introduced in XML 1.0 but does not appear in HTML. Authors should
  162 + // therefore use &#39; instead of &apos; to work as expected in HTML 4
  163 + // user agents.
  164 + sb.append("&#39;"); //$NON-NLS-1$
  165 + break;
  166 + case '"':
  167 + sb.append("&quot;"); //$NON-NLS-1$
  168 + break;
  169 + default:
  170 + sb.append(c);
  171 + }
  172 + }
  173 + return sb.toString();
  174 + }
  175 +
  176 + /**
  177 + * Html 解码
  178 + * Return the string of decode html-encode string.
  179 + *
  180 + * @param input The input.
  181 + * @return the string of decode html-encode string
  182 + */
  183 + @SuppressWarnings("deprecation")
  184 + public static CharSequence htmlDecode(final String input) {
  185 + if (input == null || input.length() == 0) return "";
  186 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
  187 + return Html.fromHtml(input, Html.FROM_HTML_MODE_LEGACY);
  188 + } else {
  189 + return Html.fromHtml(input);
  190 + }
  191 + }
  192 +
  193 + /**
  194 + * Return the binary encoded string padded with one space
  195 + *
  196 + * @param input
  197 + * @return binary string
  198 + */
  199 + public static String binEncode(final String input) {
  200 + StringBuilder stringBuilder = new StringBuilder();
  201 + for (char i : input.toCharArray()) {
  202 + stringBuilder.append(Integer.toBinaryString(i));
  203 + stringBuilder.append(' ');
  204 + }
  205 + return stringBuilder.toString();
  206 + }
  207 +
  208 + /**
  209 + * 编码解码相关
  210 + * Return UTF-8 String from binary
  211 + *
  212 + * @param input binary string
  213 + * @return UTF-8 String
  214 + * urlEncode : URL 编码
  215 + * urlDecode : URL 解码
  216 + * base64Encode : Base64 编码
  217 + * base64Encode2String: Base64 编码
  218 + * base64Decode : Base64 解码
  219 + * htmlEncode : Html 编码
  220 + * htmlDecode : Html 解码
  221 + */
  222 + public static String binDecode(final String input) {
  223 + String[] splitted = input.split(" ");
  224 + StringBuilder sb = new StringBuilder();
  225 + for (String i : splitted) {
  226 + sb.append(((char) Integer.parseInt(i.replace(" ", ""), 2)));
  227 + }
  228 + return sb.toString();
  229 + }
  230 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/EncryptUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import android.util.Base64;
  4 +
  5 +import java.io.File;
  6 +import java.io.FileInputStream;
  7 +import java.io.IOException;
  8 +import java.security.DigestInputStream;
  9 +import java.security.InvalidKeyException;
  10 +import java.security.Key;
  11 +import java.security.KeyFactory;
  12 +import java.security.MessageDigest;
  13 +import java.security.NoSuchAlgorithmException;
  14 +import java.security.spec.AlgorithmParameterSpec;
  15 +import java.security.spec.InvalidKeySpecException;
  16 +import java.security.spec.PKCS8EncodedKeySpec;
  17 +import java.security.spec.X509EncodedKeySpec;
  18 +
  19 +import javax.crypto.BadPaddingException;
  20 +import javax.crypto.Cipher;
  21 +import javax.crypto.IllegalBlockSizeException;
  22 +import javax.crypto.Mac;
  23 +import javax.crypto.NoSuchPaddingException;
  24 +import javax.crypto.SecretKey;
  25 +import javax.crypto.SecretKeyFactory;
  26 +import javax.crypto.spec.DESKeySpec;
  27 +import javax.crypto.spec.IvParameterSpec;
  28 +import javax.crypto.spec.SecretKeySpec;
  29 +
  30 +/**
  31 + * 加密解密相关
  32 + * <pre>
  33 + * author: Blankj
  34 + * blog : http://blankj.com
  35 + * time : 2016/08/02
  36 + * desc : utils about encrypt
  37 + * </pre>
  38 + * encryptMD2, encryptMD2ToString : MD2 加密
  39 + * encryptMD5, encryptMD5ToString : MD5 加密
  40 + * encryptMD5File, encryptMD5File2String : MD5 加密文件
  41 + * encryptSHA1, encryptSHA1ToString : SHA1 加密
  42 + * encryptSHA224, encryptSHA224ToString : SHA224 加密
  43 + * encryptSHA256, encryptSHA256ToString : SHA256 加密
  44 + * encryptSHA384, encryptSHA384ToString : SHA384 加密
  45 + * encryptSHA512, encryptSHA512ToString : SHA512 加密
  46 + * encryptHmacMD5, encryptHmacMD5ToString : HmacMD5 加密
  47 + * encryptHmacSHA1, encryptHmacSHA1ToString : HmacSHA1 加密
  48 + * encryptHmacSHA224, encryptHmacSHA224ToString : HmacSHA224 加密
  49 + * encryptHmacSHA256, encryptHmacSHA256ToString : HmacSHA256 加密
  50 + * encryptHmacSHA384, encryptHmacSHA384ToString : HmacSHA384 加密
  51 + * encryptHmacSHA512, encryptHmacSHA512ToString : HmacSHA512 加密
  52 + * encryptDES, encryptDES2HexString, encryptDES2Base64 : DES 加密
  53 + * decryptDES, decryptHexStringDES, decryptBase64DES : DES 解密
  54 + * encrypt3DES, encrypt3DES2HexString, encrypt3DES2Base64: 3DES 加密
  55 + * decrypt3DES, decryptHexString3DES, decryptBase64_3DES : 3DES 解密
  56 + * encryptAES, encryptAES2HexString, encryptAES2Base64 : AES 加密
  57 + * decryptAES, decryptHexStringAES, decryptBase64AES : AES 解密
  58 + * encryptRSA, encryptRSA2HexString, encryptRSA2Base64 : RSA 加密
  59 + * decryptRSA, decryptHexStringRSA, decryptBase64RSA : RSA 解密
  60 + */
  61 +public final class EncryptUtils {
  62 +
  63 + private EncryptUtils() {
  64 + throw new UnsupportedOperationException("u can't instantiate me...");
  65 + }
  66 +
  67 + ///////////////////////////////////////////////////////////////////////////
  68 + // hash encryption
  69 + ///////////////////////////////////////////////////////////////////////////
  70 +
  71 + /**
  72 + * Return the hex string of MD2 encryption.
  73 + *
  74 + * @param data The data.
  75 + * @return the hex string of MD2 encryption
  76 + */
  77 + public static String encryptMD2ToString(final String data) {
  78 + if (data == null || data.length() == 0) return "";
  79 + return encryptMD2ToString(data.getBytes());
  80 + }
  81 +
  82 + /**
  83 + * Return the hex string of MD2 encryption.
  84 + *
  85 + * @param data The data.
  86 + * @return the hex string of MD2 encryption
  87 + */
  88 + public static String encryptMD2ToString(final byte[] data) {
  89 + return bytes2HexString(encryptMD2(data));
  90 + }
  91 +
  92 + /**
  93 + * MD2 加密
  94 + * Return the bytes of MD2 encryption.
  95 + *
  96 + * @param data The data.
  97 + * @return the bytes of MD2 encryption
  98 + */
  99 + public static byte[] encryptMD2(final byte[] data) {
  100 + return hashTemplate(data, "MD2");
  101 + }
  102 +
  103 + /**
  104 + * Return the hex string of MD5 encryption.
  105 + *
  106 + * @param data The data.
  107 + * @return the hex string of MD5 encryption
  108 + */
  109 + public static String encryptMD5ToString(final String data) {
  110 + if (data == null || data.length() == 0) return "";
  111 + return encryptMD5ToString(data.getBytes());
  112 + }
  113 +
  114 + /**
  115 + * Return the hex string of MD5 encryption.
  116 + *
  117 + * @param data The data.
  118 + * @param salt The salt.
  119 + * @return the hex string of MD5 encryption
  120 + */
  121 + public static String encryptMD5ToString(final String data, final String salt) {
  122 + if (data == null && salt == null) return "";
  123 + if (salt == null) return bytes2HexString(encryptMD5(data.getBytes()));
  124 + if (data == null) return bytes2HexString(encryptMD5(salt.getBytes()));
  125 + return bytes2HexString(encryptMD5((data + salt).getBytes()));
  126 + }
  127 +
  128 + /**
  129 + * Return the hex string of MD5 encryption.
  130 + *
  131 + * @param data The data.
  132 + * @return the hex string of MD5 encryption
  133 + */
  134 + public static String encryptMD5ToString(final byte[] data) {
  135 + return bytes2HexString(encryptMD5(data));
  136 + }
  137 +
  138 + /**
  139 + * Return the hex string of MD5 encryption.
  140 + *
  141 + * @param data The data.
  142 + * @param salt The salt.
  143 + * @return the hex string of MD5 encryption
  144 + */
  145 + public static String encryptMD5ToString(final byte[] data, final byte[] salt) {
  146 + if (data == null && salt == null) return "";
  147 + if (salt == null) return bytes2HexString(encryptMD5(data));
  148 + if (data == null) return bytes2HexString(encryptMD5(salt));
  149 + byte[] dataSalt = new byte[data.length + salt.length];
  150 + System.arraycopy(data, 0, dataSalt, 0, data.length);
  151 + System.arraycopy(salt, 0, dataSalt, data.length, salt.length);
  152 + return bytes2HexString(encryptMD5(dataSalt));
  153 + }
  154 +
  155 + /**
  156 + * MD5 加密
  157 + * Return the bytes of MD5 encryption.
  158 + *
  159 + * @param data The data.
  160 + * @return the bytes of MD5 encryption
  161 + */
  162 + public static byte[] encryptMD5(final byte[] data) {
  163 + return hashTemplate(data, "MD5");
  164 + }
  165 +
  166 + /**
  167 + * MD5 加密文件
  168 + * Return the hex string of file's MD5 encryption.
  169 + *
  170 + * @param filePath The path of file.
  171 + * @return the hex string of file's MD5 encryption
  172 + */
  173 + public static String encryptMD5File2String(final String filePath) {
  174 + File file = isSpace(filePath) ? null : new File(filePath);
  175 + return encryptMD5File2String(file);
  176 + }
  177 +
  178 + /**
  179 + * Return the bytes of file's MD5 encryption.
  180 + *
  181 + * @param filePath The path of file.
  182 + * @return the bytes of file's MD5 encryption
  183 + */
  184 + public static byte[] encryptMD5File(final String filePath) {
  185 + File file = isSpace(filePath) ? null : new File(filePath);
  186 + return encryptMD5File(file);
  187 + }
  188 +
  189 + /**
  190 + * Return the hex string of file's MD5 encryption.
  191 + *
  192 + * @param file The file.
  193 + * @return the hex string of file's MD5 encryption
  194 + */
  195 + public static String encryptMD5File2String(final File file) {
  196 + return bytes2HexString(encryptMD5File(file));
  197 + }
  198 +
  199 + /**
  200 + * Return the bytes of file's MD5 encryption.
  201 + *
  202 + * @param file The file.
  203 + * @return the bytes of file's MD5 encryption
  204 + */
  205 + public static byte[] encryptMD5File(final File file) {
  206 + if (file == null) return null;
  207 + FileInputStream fis = null;
  208 + DigestInputStream digestInputStream;
  209 + try {
  210 + fis = new FileInputStream(file);
  211 + MessageDigest md = MessageDigest.getInstance("MD5");
  212 + digestInputStream = new DigestInputStream(fis, md);
  213 + byte[] buffer = new byte[256 * 1024];
  214 + while (true) {
  215 + if (!(digestInputStream.read(buffer) > 0)) break;
  216 + }
  217 + md = digestInputStream.getMessageDigest();
  218 + return md.digest();
  219 + } catch (NoSuchAlgorithmException | IOException e) {
  220 + e.printStackTrace();
  221 + return null;
  222 + } finally {
  223 + try {
  224 + if (fis != null) {
  225 + fis.close();
  226 + }
  227 + } catch (IOException e) {
  228 + e.printStackTrace();
  229 + }
  230 + }
  231 + }
  232 +
  233 + /**
  234 + * Return the hex string of SHA1 encryption.
  235 + *
  236 + * @param data The data.
  237 + * @return the hex string of SHA1 encryption
  238 + */
  239 + public static String encryptSHA1ToString(final String data) {
  240 + if (data == null || data.length() == 0) return "";
  241 + return encryptSHA1ToString(data.getBytes());
  242 + }
  243 +
  244 + /**
  245 + * Return the hex string of SHA1 encryption.
  246 + *
  247 + * @param data The data.
  248 + * @return the hex string of SHA1 encryption
  249 + */
  250 + public static String encryptSHA1ToString(final byte[] data) {
  251 + return bytes2HexString(encryptSHA1(data));
  252 + }
  253 +
  254 + /**
  255 + * SHA1 加密
  256 + * Return the bytes of SHA1 encryption.
  257 + *
  258 + * @param data The data.
  259 + * @return the bytes of SHA1 encryption
  260 + */
  261 + public static byte[] encryptSHA1(final byte[] data) {
  262 + return hashTemplate(data, "SHA-1");
  263 + }
  264 +
  265 + /**
  266 + * Return the hex string of SHA224 encryption.
  267 + *
  268 + * @param data The data.
  269 + * @return the hex string of SHA224 encryption
  270 + */
  271 + public static String encryptSHA224ToString(final String data) {
  272 + if (data == null || data.length() == 0) return "";
  273 + return encryptSHA224ToString(data.getBytes());
  274 + }
  275 +
  276 + /**
  277 + * Return the hex string of SHA224 encryption.
  278 + *
  279 + * @param data The data.
  280 + * @return the hex string of SHA224 encryption
  281 + */
  282 + public static String encryptSHA224ToString(final byte[] data) {
  283 + return bytes2HexString(encryptSHA224(data));
  284 + }
  285 +
  286 + /**
  287 + * SHA224 加密
  288 + * Return the bytes of SHA224 encryption.
  289 + *
  290 + * @param data The data.
  291 + * @return the bytes of SHA224 encryption
  292 + */
  293 + public static byte[] encryptSHA224(final byte[] data) {
  294 + return hashTemplate(data, "SHA224");
  295 + }
  296 +
  297 + /**
  298 + * Return the hex string of SHA256 encryption.
  299 + *
  300 + * @param data The data.
  301 + * @return the hex string of SHA256 encryption
  302 + */
  303 + public static String encryptSHA256ToString(final String data) {
  304 + if (data == null || data.length() == 0) return "";
  305 + return encryptSHA256ToString(data.getBytes());
  306 + }
  307 +
  308 + /**
  309 + * Return the hex string of SHA256 encryption.
  310 + *
  311 + * @param data The data.
  312 + * @return the hex string of SHA256 encryption
  313 + */
  314 + public static String encryptSHA256ToString(final byte[] data) {
  315 + return bytes2HexString(encryptSHA256(data));
  316 + }
  317 +
  318 + /**
  319 + * SHA256 加密
  320 + * Return the bytes of SHA256 encryption.
  321 + *
  322 + * @param data The data.
  323 + * @return the bytes of SHA256 encryption
  324 + */
  325 + public static byte[] encryptSHA256(final byte[] data) {
  326 + return hashTemplate(data, "SHA-256");
  327 + }
  328 +
  329 + /**
  330 + * Return the hex string of SHA384 encryption.
  331 + *
  332 + * @param data The data.
  333 + * @return the hex string of SHA384 encryption
  334 + */
  335 + public static String encryptSHA384ToString(final String data) {
  336 + if (data == null || data.length() == 0) return "";
  337 + return encryptSHA384ToString(data.getBytes());
  338 + }
  339 +
  340 + /**
  341 + * Return the hex string of SHA384 encryption.
  342 + *
  343 + * @param data The data.
  344 + * @return the hex string of SHA384 encryption
  345 + */
  346 + public static String encryptSHA384ToString(final byte[] data) {
  347 + return bytes2HexString(encryptSHA384(data));
  348 + }
  349 +
  350 + /**
  351 + * SHA384 加密
  352 + * Return the bytes of SHA384 encryption.
  353 + *
  354 + * @param data The data.
  355 + * @return the bytes of SHA384 encryption
  356 + */
  357 + public static byte[] encryptSHA384(final byte[] data) {
  358 + return hashTemplate(data, "SHA-384");
  359 + }
  360 +
  361 + /**
  362 + * Return the hex string of SHA512 encryption.
  363 + *
  364 + * @param data The data.
  365 + * @return the hex string of SHA512 encryption
  366 + */
  367 + public static String encryptSHA512ToString(final String data) {
  368 + if (data == null || data.length() == 0) return "";
  369 + return encryptSHA512ToString(data.getBytes());
  370 + }
  371 +
  372 + /**
  373 + * Return the hex string of SHA512 encryption.
  374 + *
  375 + * @param data The data.
  376 + * @return the hex string of SHA512 encryption
  377 + */
  378 + public static String encryptSHA512ToString(final byte[] data) {
  379 + return bytes2HexString(encryptSHA512(data));
  380 + }
  381 +
  382 + /**
  383 + * SHA512 加密
  384 + * Return the bytes of SHA512 encryption.
  385 + *
  386 + * @param data The data.
  387 + * @return the bytes of SHA512 encryption
  388 + */
  389 + public static byte[] encryptSHA512(final byte[] data) {
  390 + return hashTemplate(data, "SHA-512");
  391 + }
  392 +
  393 + /**
  394 + * Return the bytes of hash encryption.
  395 + *
  396 + * @param data The data.
  397 + * @param algorithm The name of hash encryption.
  398 + * @return the bytes of hash encryption
  399 + */
  400 + private static byte[] hashTemplate(final byte[] data, final String algorithm) {
  401 + if (data == null || data.length <= 0) return null;
  402 + try {
  403 + MessageDigest md = MessageDigest.getInstance(algorithm);
  404 + md.update(data);
  405 + return md.digest();
  406 + } catch (NoSuchAlgorithmException e) {
  407 + e.printStackTrace();
  408 + return null;
  409 + }
  410 + }
  411 +
  412 + ///////////////////////////////////////////////////////////////////////////
  413 + // hmac encryption
  414 + ///////////////////////////////////////////////////////////////////////////
  415 +
  416 + /**
  417 + * Return the hex string of HmacMD5 encryption.
  418 + *
  419 + * @param data The data.
  420 + * @param key The key.
  421 + * @return the hex string of HmacMD5 encryption
  422 + */
  423 + public static String encryptHmacMD5ToString(final String data, final String key) {
  424 + if (data == null || data.length() == 0 || key == null || key.length() == 0) return "";
  425 + return encryptHmacMD5ToString(data.getBytes(), key.getBytes());
  426 + }
  427 +
  428 + /**
  429 + * Return the hex string of HmacMD5 encryption.
  430 + *
  431 + * @param data The data.
  432 + * @param key The key.
  433 + * @return the hex string of HmacMD5 encryption
  434 + */
  435 + public static String encryptHmacMD5ToString(final byte[] data, final byte[] key) {
  436 + return bytes2HexString(encryptHmacMD5(data, key));
  437 + }
  438 +
  439 + /**
  440 + * HmacMD5 加密
  441 + * Return the bytes of HmacMD5 encryption.
  442 + *
  443 + * @param data The data.
  444 + * @param key The key.
  445 + * @return the bytes of HmacMD5 encryption
  446 + */
  447 + public static byte[] encryptHmacMD5(final byte[] data, final byte[] key) {
  448 + return hmacTemplate(data, key, "HmacMD5");
  449 + }
  450 +
  451 + /**
  452 + * Return the hex string of HmacSHA1 encryption.
  453 + *
  454 + * @param data The data.
  455 + * @param key The key.
  456 + * @return the hex string of HmacSHA1 encryption
  457 + */
  458 + public static String encryptHmacSHA1ToString(final String data, final String key) {
  459 + if (data == null || data.length() == 0 || key == null || key.length() == 0) return "";
  460 + return encryptHmacSHA1ToString(data.getBytes(), key.getBytes());
  461 + }
  462 +
  463 + /**
  464 + * Return the hex string of HmacSHA1 encryption.
  465 + *
  466 + * @param data The data.
  467 + * @param key The key.
  468 + * @return the hex string of HmacSHA1 encryption
  469 + */
  470 + public static String encryptHmacSHA1ToString(final byte[] data, final byte[] key) {
  471 + return bytes2HexString(encryptHmacSHA1(data, key));
  472 + }
  473 +
  474 + /**
  475 + * HmacSHA1 加密
  476 + * Return the bytes of HmacSHA1 encryption.
  477 + *
  478 + * @param data The data.
  479 + * @param key The key.
  480 + * @return the bytes of HmacSHA1 encryption
  481 + */
  482 + public static byte[] encryptHmacSHA1(final byte[] data, final byte[] key) {
  483 + return hmacTemplate(data, key, "HmacSHA1");
  484 + }
  485 +
  486 + /**
  487 + * Return the hex string of HmacSHA224 encryption.
  488 + *
  489 + * @param data The data.
  490 + * @param key The key.
  491 + * @return the hex string of HmacSHA224 encryption
  492 + */
  493 + public static String encryptHmacSHA224ToString(final String data, final String key) {
  494 + if (data == null || data.length() == 0 || key == null || key.length() == 0) return "";
  495 + return encryptHmacSHA224ToString(data.getBytes(), key.getBytes());
  496 + }
  497 +
  498 + /**
  499 + * Return the hex string of HmacSHA224 encryption.
  500 + *
  501 + * @param data The data.
  502 + * @param key The key.
  503 + * @return the hex string of HmacSHA224 encryption
  504 + */
  505 + public static String encryptHmacSHA224ToString(final byte[] data, final byte[] key) {
  506 + return bytes2HexString(encryptHmacSHA224(data, key));
  507 + }
  508 +
  509 + /**
  510 + * HmacSHA224 加密
  511 + * Return the bytes of HmacSHA224 encryption.
  512 + *
  513 + * @param data The data.
  514 + * @param key The key.
  515 + * @return the bytes of HmacSHA224 encryption
  516 + */
  517 + public static byte[] encryptHmacSHA224(final byte[] data, final byte[] key) {
  518 + return hmacTemplate(data, key, "HmacSHA224");
  519 + }
  520 +
  521 + /**
  522 + * Return the hex string of HmacSHA256 encryption.
  523 + *
  524 + * @param data The data.
  525 + * @param key The key.
  526 + * @return the hex string of HmacSHA256 encryption
  527 + */
  528 + public static String encryptHmacSHA256ToString(final String data, final String key) {
  529 + if (data == null || data.length() == 0 || key == null || key.length() == 0) return "";
  530 + return encryptHmacSHA256ToString(data.getBytes(), key.getBytes());
  531 + }
  532 +
  533 + /**
  534 + * Return the hex string of HmacSHA256 encryption.
  535 + *
  536 + * @param data The data.
  537 + * @param key The key.
  538 + * @return the hex string of HmacSHA256 encryption
  539 + */
  540 + public static String encryptHmacSHA256ToString(final byte[] data, final byte[] key) {
  541 + return bytes2HexString(encryptHmacSHA256(data, key));
  542 + }
  543 +
  544 + /**
  545 + * HmacSHA256 加密
  546 + * Return the bytes of HmacSHA256 encryption.
  547 + *
  548 + * @param data The data.
  549 + * @param key The key.
  550 + * @return the bytes of HmacSHA256 encryption
  551 + */
  552 + public static byte[] encryptHmacSHA256(final byte[] data, final byte[] key) {
  553 + return hmacTemplate(data, key, "HmacSHA256");
  554 + }
  555 +
  556 + /**
  557 + * Return the hex string of HmacSHA384 encryption.
  558 + *
  559 + * @param data The data.
  560 + * @param key The key.
  561 + * @return the hex string of HmacSHA384 encryption
  562 + */
  563 + public static String encryptHmacSHA384ToString(final String data, final String key) {
  564 + if (data == null || data.length() == 0 || key == null || key.length() == 0) return "";
  565 + return encryptHmacSHA384ToString(data.getBytes(), key.getBytes());
  566 + }
  567 +
  568 + /**
  569 + * Return the hex string of HmacSHA384 encryption.
  570 + *
  571 + * @param data The data.
  572 + * @param key The key.
  573 + * @return the hex string of HmacSHA384 encryption
  574 + */
  575 + public static String encryptHmacSHA384ToString(final byte[] data, final byte[] key) {
  576 + return bytes2HexString(encryptHmacSHA384(data, key));
  577 + }
  578 +
  579 + /**
  580 + * HmacSHA384 加密
  581 + * Return the bytes of HmacSHA384 encryption.
  582 + *
  583 + * @param data The data.
  584 + * @param key The key.
  585 + * @return the bytes of HmacSHA384 encryption
  586 + */
  587 + public static byte[] encryptHmacSHA384(final byte[] data, final byte[] key) {
  588 + return hmacTemplate(data, key, "HmacSHA384");
  589 + }
  590 +
  591 + /**
  592 + * Return the hex string of HmacSHA512 encryption.
  593 + *
  594 + * @param data The data.
  595 + * @param key The key.
  596 + * @return the hex string of HmacSHA512 encryption
  597 + */
  598 + public static String encryptHmacSHA512ToString(final String data, final String key) {
  599 + if (data == null || data.length() == 0 || key == null || key.length() == 0) return "";
  600 + return encryptHmacSHA512ToString(data.getBytes(), key.getBytes());
  601 + }
  602 +
  603 + /**
  604 + * Return the hex string of HmacSHA512 encryption.
  605 + *
  606 + * @param data The data.
  607 + * @param key The key.
  608 + * @return the hex string of HmacSHA512 encryption
  609 + */
  610 + public static String encryptHmacSHA512ToString(final byte[] data, final byte[] key) {
  611 + return bytes2HexString(encryptHmacSHA512(data, key));
  612 + }
  613 +
  614 + /**
  615 + * HmacSHA512 加密
  616 + * Return the bytes of HmacSHA512 encryption.
  617 + *
  618 + * @param data The data.
  619 + * @param key The key.
  620 + * @return the bytes of HmacSHA512 encryption
  621 + */
  622 + public static byte[] encryptHmacSHA512(final byte[] data, final byte[] key) {
  623 + return hmacTemplate(data, key, "HmacSHA512");
  624 + }
  625 +
  626 + /**
  627 + * Return the bytes of hmac encryption.
  628 + *
  629 + * @param data The data.
  630 + * @param key The key.
  631 + * @param algorithm The name of hmac encryption.
  632 + * @return the bytes of hmac encryption
  633 + */
  634 + private static byte[] hmacTemplate(final byte[] data,
  635 + final byte[] key,
  636 + final String algorithm) {
  637 + if (data == null || data.length == 0 || key == null || key.length == 0) return null;
  638 + try {
  639 + SecretKeySpec secretKey = new SecretKeySpec(key, algorithm);
  640 + Mac mac = Mac.getInstance(algorithm);
  641 + mac.init(secretKey);
  642 + return mac.doFinal(data);
  643 + } catch (InvalidKeyException | NoSuchAlgorithmException e) {
  644 + e.printStackTrace();
  645 + return null;
  646 + }
  647 + }
  648 +
  649 + ///////////////////////////////////////////////////////////////////////////
  650 + // DES encryption
  651 + ///////////////////////////////////////////////////////////////////////////
  652 +
  653 + /**
  654 + * Return the Base64-encode bytes of DES encryption.
  655 + *
  656 + * @param data The data.
  657 + * @param key The key.
  658 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  659 + * @param iv The buffer with the IV. The contents of the
  660 + * buffer are copied to protect against subsequent modification.
  661 + * @return the Base64-encode bytes of DES encryption
  662 + */
  663 + public static byte[] encryptDES2Base64(final byte[] data,
  664 + final byte[] key,
  665 + final String transformation,
  666 + final byte[] iv) {
  667 + return base64Encode(encryptDES(data, key, transformation, iv));
  668 + }
  669 +
  670 + /**
  671 + * Return the hex string of DES encryption.
  672 + *
  673 + * @param data The data.
  674 + * @param key The key.
  675 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  676 + * @param iv The buffer with the IV. The contents of the
  677 + * buffer are copied to protect against subsequent modification.
  678 + * @return the hex string of DES encryption
  679 + */
  680 + public static String encryptDES2HexString(final byte[] data,
  681 + final byte[] key,
  682 + final String transformation,
  683 + final byte[] iv) {
  684 + return bytes2HexString(encryptDES(data, key, transformation, iv));
  685 + }
  686 +
  687 + /**
  688 + * DES 加密
  689 + * Return the bytes of DES encryption.
  690 + *
  691 + * @param data The data.
  692 + * @param key The key.
  693 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  694 + * @param iv The buffer with the IV. The contents of the
  695 + * buffer are copied to protect against subsequent modification.
  696 + * @return the bytes of DES encryption
  697 + */
  698 + public static byte[] encryptDES(final byte[] data,
  699 + final byte[] key,
  700 + final String transformation,
  701 + final byte[] iv) {
  702 + return symmetricTemplate(data, key, "DES", transformation, iv, true);
  703 + }
  704 +
  705 + /**
  706 + * Return the bytes of DES decryption for Base64-encode bytes.
  707 + *
  708 + * @param data The data.
  709 + * @param key The key.
  710 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  711 + * @param iv The buffer with the IV. The contents of the
  712 + * buffer are copied to protect against subsequent modification.
  713 + * @return the bytes of DES decryption for Base64-encode bytes
  714 + */
  715 + public static byte[] decryptBase64DES(final byte[] data,
  716 + final byte[] key,
  717 + final String transformation,
  718 + final byte[] iv) {
  719 + return decryptDES(base64Decode(data), key, transformation, iv);
  720 + }
  721 +
  722 + /**
  723 + * Return the bytes of DES decryption for hex string.
  724 + *
  725 + * @param data The data.
  726 + * @param key The key.
  727 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  728 + * @param iv The buffer with the IV. The contents of the
  729 + * buffer are copied to protect against subsequent modification.
  730 + * @return the bytes of DES decryption for hex string
  731 + */
  732 + public static byte[] decryptHexStringDES(final String data,
  733 + final byte[] key,
  734 + final String transformation,
  735 + final byte[] iv) {
  736 + return decryptDES(hexString2Bytes(data), key, transformation, iv);
  737 + }
  738 +
  739 + /**
  740 + * DES 解密
  741 + * Return the bytes of DES decryption.
  742 + *
  743 + * @param data The data.
  744 + * @param key The key.
  745 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  746 + * @param iv The buffer with the IV. The contents of the
  747 + * buffer are copied to protect against subsequent modification.
  748 + * @return the bytes of DES decryption
  749 + */
  750 + public static byte[] decryptDES(final byte[] data,
  751 + final byte[] key,
  752 + final String transformation,
  753 + final byte[] iv) {
  754 + return symmetricTemplate(data, key, "DES", transformation, iv, false);
  755 + }
  756 +
  757 + ///////////////////////////////////////////////////////////////////////////
  758 + // 3DES encryption
  759 + ///////////////////////////////////////////////////////////////////////////
  760 +
  761 + /**
  762 + * Return the Base64-encode bytes of 3DES encryption.
  763 + *
  764 + * @param data The data.
  765 + * @param key The key.
  766 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  767 + * @param iv The buffer with the IV. The contents of the
  768 + * buffer are copied to protect against subsequent modification.
  769 + * @return the Base64-encode bytes of 3DES encryption
  770 + */
  771 + public static byte[] encrypt3DES2Base64(final byte[] data,
  772 + final byte[] key,
  773 + final String transformation,
  774 + final byte[] iv) {
  775 + return base64Encode(encrypt3DES(data, key, transformation, iv));
  776 + }
  777 +
  778 + /**
  779 + * Return the hex string of 3DES encryption.
  780 + *
  781 + * @param data The data.
  782 + * @param key The key.
  783 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  784 + * @param iv The buffer with the IV. The contents of the
  785 + * buffer are copied to protect against subsequent modification.
  786 + * @return the hex string of 3DES encryption
  787 + */
  788 + public static String encrypt3DES2HexString(final byte[] data,
  789 + final byte[] key,
  790 + final String transformation,
  791 + final byte[] iv) {
  792 + return bytes2HexString(encrypt3DES(data, key, transformation, iv));
  793 + }
  794 +
  795 + /**
  796 + * 3DES 加密
  797 + * Return the bytes of 3DES encryption.
  798 + *
  799 + * @param data The data.
  800 + * @param key The key.
  801 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  802 + * @param iv The buffer with the IV. The contents of the
  803 + * buffer are copied to protect against subsequent modification.
  804 + * @return the bytes of 3DES encryption
  805 + */
  806 + public static byte[] encrypt3DES(final byte[] data,
  807 + final byte[] key,
  808 + final String transformation,
  809 + final byte[] iv) {
  810 + return symmetricTemplate(data, key, "DESede", transformation, iv, true);
  811 + }
  812 +
  813 + /**
  814 + * Return the bytes of 3DES decryption for Base64-encode bytes.
  815 + *
  816 + * @param data The data.
  817 + * @param key The key.
  818 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  819 + * @param iv The buffer with the IV. The contents of the
  820 + * buffer are copied to protect against subsequent modification.
  821 + * @return the bytes of 3DES decryption for Base64-encode bytes
  822 + */
  823 + public static byte[] decryptBase64_3DES(final byte[] data,
  824 + final byte[] key,
  825 + final String transformation,
  826 + final byte[] iv) {
  827 + return decrypt3DES(base64Decode(data), key, transformation, iv);
  828 + }
  829 +
  830 + /**
  831 + * Return the bytes of 3DES decryption for hex string.
  832 + *
  833 + * @param data The data.
  834 + * @param key The key.
  835 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  836 + * @param iv The buffer with the IV. The contents of the
  837 + * buffer are copied to protect against subsequent modification.
  838 + * @return the bytes of 3DES decryption for hex string
  839 + */
  840 + public static byte[] decryptHexString3DES(final String data,
  841 + final byte[] key,
  842 + final String transformation,
  843 + final byte[] iv) {
  844 + return decrypt3DES(hexString2Bytes(data), key, transformation, iv);
  845 + }
  846 +
  847 + /**
  848 + * 3DES 解密
  849 + * Return the bytes of 3DES decryption.
  850 + *
  851 + * @param data The data.
  852 + * @param key The key.
  853 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  854 + * @param iv The buffer with the IV. The contents of the
  855 + * buffer are copied to protect against subsequent modification.
  856 + * @return the bytes of 3DES decryption
  857 + */
  858 + public static byte[] decrypt3DES(final byte[] data,
  859 + final byte[] key,
  860 + final String transformation,
  861 + final byte[] iv) {
  862 + return symmetricTemplate(data, key, "DESede", transformation, iv, false);
  863 + }
  864 +
  865 + ///////////////////////////////////////////////////////////////////////////
  866 + // AES encryption
  867 + ///////////////////////////////////////////////////////////////////////////
  868 +
  869 + /**
  870 + * Return the Base64-encode bytes of AES encryption.
  871 + *
  872 + * @param data The data.
  873 + * @param key The key.
  874 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  875 + * @param iv The buffer with the IV. The contents of the
  876 + * buffer are copied to protect against subsequent modification.
  877 + * @return the Base64-encode bytes of AES encryption
  878 + */
  879 + public static byte[] encryptAES2Base64(final byte[] data,
  880 + final byte[] key,
  881 + final String transformation,
  882 + final byte[] iv) {
  883 + return base64Encode(encryptAES(data, key, transformation, iv));
  884 + }
  885 +
  886 + /**
  887 + * Return the hex string of AES encryption.
  888 + *
  889 + * @param data The data.
  890 + * @param key The key.
  891 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  892 + * @param iv The buffer with the IV. The contents of the
  893 + * buffer are copied to protect against subsequent modification.
  894 + * @return the hex string of AES encryption
  895 + */
  896 + public static String encryptAES2HexString(final byte[] data,
  897 + final byte[] key,
  898 + final String transformation,
  899 + final byte[] iv) {
  900 + return bytes2HexString(encryptAES(data, key, transformation, iv));
  901 + }
  902 +
  903 + /**
  904 + * AES 加密
  905 + * Return the bytes of AES encryption.
  906 + *
  907 + * @param data The data.
  908 + * @param key The key.
  909 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  910 + * @param iv The buffer with the IV. The contents of the
  911 + * buffer are copied to protect against subsequent modification.
  912 + * @return the bytes of AES encryption
  913 + */
  914 + public static byte[] encryptAES(final byte[] data,
  915 + final byte[] key,
  916 + final String transformation,
  917 + final byte[] iv) {
  918 + return symmetricTemplate(data, key, "AES", transformation, iv, true);
  919 + }
  920 +
  921 + /**
  922 + * Return the bytes of AES decryption for Base64-encode bytes.
  923 + *
  924 + * @param data The data.
  925 + * @param key The key.
  926 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  927 + * @param iv The buffer with the IV. The contents of the
  928 + * buffer are copied to protect against subsequent modification.
  929 + * @return the bytes of AES decryption for Base64-encode bytes
  930 + */
  931 + public static byte[] decryptBase64AES(final byte[] data,
  932 + final byte[] key,
  933 + final String transformation,
  934 + final byte[] iv) {
  935 + return decryptAES(base64Decode(data), key, transformation, iv);
  936 + }
  937 +
  938 + /**
  939 + * Return the bytes of AES decryption for hex string.
  940 + *
  941 + * @param data The data.
  942 + * @param key The key.
  943 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  944 + * @param iv The buffer with the IV. The contents of the
  945 + * buffer are copied to protect against subsequent modification.
  946 + * @return the bytes of AES decryption for hex string
  947 + */
  948 + public static byte[] decryptHexStringAES(final String data,
  949 + final byte[] key,
  950 + final String transformation,
  951 + final byte[] iv) {
  952 + return decryptAES(hexString2Bytes(data), key, transformation, iv);
  953 + }
  954 +
  955 + /**
  956 + * AES 解密
  957 + * Return the bytes of AES decryption.
  958 + *
  959 + * @param data The data.
  960 + * @param key The key.
  961 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  962 + * @param iv The buffer with the IV. The contents of the
  963 + * buffer are copied to protect against subsequent modification.
  964 + * @return the bytes of AES decryption
  965 + */
  966 + public static byte[] decryptAES(final byte[] data,
  967 + final byte[] key,
  968 + final String transformation,
  969 + final byte[] iv) {
  970 + return symmetricTemplate(data, key, "AES", transformation, iv, false);
  971 + }
  972 +
  973 + /**
  974 + * Return the bytes of symmetric encryption or decryption.
  975 + *
  976 + * @param data The data.
  977 + * @param key The key.
  978 + * @param algorithm The name of algorithm.
  979 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
  980 + * @param isEncrypt True to encrypt, false otherwise.
  981 + * @return the bytes of symmetric encryption or decryption
  982 + */
  983 + private static byte[] symmetricTemplate(final byte[] data,
  984 + final byte[] key,
  985 + final String algorithm,
  986 + final String transformation,
  987 + final byte[] iv,
  988 + final boolean isEncrypt) {
  989 + if (data == null || data.length == 0 || key == null || key.length == 0) return null;
  990 + try {
  991 + SecretKey secretKey;
  992 + if ("DES".equals(algorithm)) {
  993 + DESKeySpec desKey = new DESKeySpec(key);
  994 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
  995 + secretKey = keyFactory.generateSecret(desKey);
  996 + } else {
  997 + secretKey = new SecretKeySpec(key, algorithm);
  998 + }
  999 + Cipher cipher = Cipher.getInstance(transformation);
  1000 + if (iv == null || iv.length == 0) {
  1001 + cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey);
  1002 + } else {
  1003 + AlgorithmParameterSpec params = new IvParameterSpec(iv);
  1004 + cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey, params);
  1005 + }
  1006 + return cipher.doFinal(data);
  1007 + } catch (Throwable e) {
  1008 + e.printStackTrace();
  1009 + return null;
  1010 + }
  1011 + }
  1012 +
  1013 + ///////////////////////////////////////////////////////////////////////////
  1014 + // RSA encryption
  1015 + ///////////////////////////////////////////////////////////////////////////
  1016 +
  1017 + /**
  1018 + * Return the Base64-encode bytes of RSA encryption.
  1019 + *
  1020 + * @param data The data.
  1021 + * @param publicKey The public key.
  1022 + * @param keySize The size of key, e.g. 1024, 2048...
  1023 + * @param transformation The name of the transformation, e.g., <i>RSA/CBC/PKCS1Padding</i>.
  1024 + * @return the Base64-encode bytes of RSA encryption
  1025 + */
  1026 + public static byte[] encryptRSA2Base64(final byte[] data,
  1027 + final byte[] publicKey,
  1028 + final int keySize,
  1029 + final String transformation) {
  1030 + return base64Encode(encryptRSA(data, publicKey, keySize, transformation));
  1031 + }
  1032 +
  1033 + /**
  1034 + * Return the hex string of RSA encryption.
  1035 + *
  1036 + * @param data The data.
  1037 + * @param publicKey The public key.
  1038 + * @param keySize The size of key, e.g. 1024, 2048...
  1039 + * @param transformation The name of the transformation, e.g., <i>RSA/CBC/PKCS1Padding</i>.
  1040 + * @return the hex string of RSA encryption
  1041 + */
  1042 + public static String encryptRSA2HexString(final byte[] data,
  1043 + final byte[] publicKey,
  1044 + final int keySize,
  1045 + final String transformation) {
  1046 + return bytes2HexString(encryptRSA(data, publicKey, keySize, transformation));
  1047 + }
  1048 +
  1049 + /**
  1050 + * RSA 加密
  1051 + * Return the bytes of RSA encryption.
  1052 + *
  1053 + * @param data The data.
  1054 + * @param publicKey The public key.
  1055 + * @param keySize The size of key, e.g. 1024, 2048...
  1056 + * @param transformation The name of the transformation, e.g., <i>RSA/CBC/PKCS1Padding</i>.
  1057 + * @return the bytes of RSA encryption
  1058 + */
  1059 + public static byte[] encryptRSA(final byte[] data,
  1060 + final byte[] publicKey,
  1061 + final int keySize,
  1062 + final String transformation) {
  1063 + return rsaTemplate(data, publicKey, keySize, transformation, true);
  1064 + }
  1065 +
  1066 + /**
  1067 + * Return the bytes of RSA decryption for Base64-encode bytes.
  1068 + *
  1069 + * @param data The data.
  1070 + * @param privateKey The private key.
  1071 + * @param keySize The size of key, e.g. 1024, 2048...
  1072 + * @param transformation The name of the transformation, e.g., <i>RSA/CBC/PKCS1Padding</i>.
  1073 + * @return the bytes of RSA decryption for Base64-encode bytes
  1074 + */
  1075 + public static byte[] decryptBase64RSA(final byte[] data,
  1076 + final byte[] privateKey,
  1077 + final int keySize,
  1078 + final String transformation) {
  1079 + return decryptRSA(base64Decode(data), privateKey, keySize, transformation);
  1080 + }
  1081 +
  1082 + /**
  1083 + * Return the bytes of RSA decryption for hex string.
  1084 + *
  1085 + * @param data The data.
  1086 + * @param privateKey The private key.
  1087 + * @param keySize The size of key, e.g. 1024, 2048...
  1088 + * @param transformation The name of the transformation, e.g., <i>RSA/CBC/PKCS1Padding</i>.
  1089 + * @return the bytes of RSA decryption for hex string
  1090 + */
  1091 + public static byte[] decryptHexStringRSA(final String data,
  1092 + final byte[] privateKey,
  1093 + final int keySize,
  1094 + final String transformation) {
  1095 + return decryptRSA(hexString2Bytes(data), privateKey, keySize, transformation);
  1096 + }
  1097 +
  1098 + /**
  1099 + * RSA 解密
  1100 + * Return the bytes of RSA decryption.
  1101 + *
  1102 + * @param data The data.
  1103 + * @param privateKey The private key.
  1104 + * @param keySize The size of key, e.g. 1024, 2048...
  1105 + * @param transformation The name of the transformation, e.g., <i>RSA/CBC/PKCS1Padding</i>.
  1106 + * @return the bytes of RSA decryption
  1107 + */
  1108 + public static byte[] decryptRSA(final byte[] data,
  1109 + final byte[] privateKey,
  1110 + final int keySize,
  1111 + final String transformation) {
  1112 + return rsaTemplate(data, privateKey, keySize, transformation, false);
  1113 + }
  1114 +
  1115 + /**
  1116 + * Return the bytes of RSA encryption or decryption.
  1117 + *
  1118 + * @param data The data.
  1119 + * @param key The key.
  1120 + * @param keySize The size of key, e.g. 1024, 2048...
  1121 + * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS1Padding</i>.
  1122 + * @param isEncrypt True to encrypt, false otherwise.
  1123 + * @return the bytes of RSA encryption or decryption
  1124 + */
  1125 + private static byte[] rsaTemplate(final byte[] data,
  1126 + final byte[] key,
  1127 + final int keySize,
  1128 + final String transformation,
  1129 + final boolean isEncrypt) {
  1130 + if (data == null || data.length == 0 || key == null || key.length == 0) {
  1131 + return null;
  1132 + }
  1133 + try {
  1134 + Key rsaKey;
  1135 + if (isEncrypt) {
  1136 + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
  1137 + rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec);
  1138 + } else {
  1139 + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key);
  1140 + rsaKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
  1141 + }
  1142 + if (rsaKey == null) return null;
  1143 + Cipher cipher = Cipher.getInstance(transformation);
  1144 + cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, rsaKey);
  1145 + int len = data.length;
  1146 + int maxLen = keySize / 8;
  1147 + if (isEncrypt) {
  1148 + String lowerTrans = transformation.toLowerCase();
  1149 + if (lowerTrans.endsWith("pkcs1padding")) {
  1150 + maxLen -= 11;
  1151 + }
  1152 + }
  1153 + int count = len / maxLen;
  1154 + if (count > 0) {
  1155 + byte[] ret = new byte[0];
  1156 + byte[] buff = new byte[maxLen];
  1157 + int index = 0;
  1158 + for (int i = 0; i < count; i++) {
  1159 + System.arraycopy(data, index, buff, 0, maxLen);
  1160 + ret = joins(ret, cipher.doFinal(buff));
  1161 + index += maxLen;
  1162 + }
  1163 + if (index != len) {
  1164 + int restLen = len - index;
  1165 + buff = new byte[restLen];
  1166 + System.arraycopy(data, index, buff, 0, restLen);
  1167 + ret = joins(ret, cipher.doFinal(buff));
  1168 + }
  1169 + return ret;
  1170 + } else {
  1171 + return cipher.doFinal(data);
  1172 + }
  1173 + } catch (NoSuchAlgorithmException e) {
  1174 + e.printStackTrace();
  1175 + } catch (NoSuchPaddingException e) {
  1176 + e.printStackTrace();
  1177 + } catch (InvalidKeyException e) {
  1178 + e.printStackTrace();
  1179 + } catch (BadPaddingException e) {
  1180 + e.printStackTrace();
  1181 + } catch (IllegalBlockSizeException e) {
  1182 + e.printStackTrace();
  1183 + } catch (InvalidKeySpecException e) {
  1184 + e.printStackTrace();
  1185 + }
  1186 + return null;
  1187 + }
  1188 +
  1189 + ///////////////////////////////////////////////////////////////////////////
  1190 + // other utils methods
  1191 + ///////////////////////////////////////////////////////////////////////////
  1192 +
  1193 + private static byte[] joins(final byte[] prefix, final byte[] suffix) {
  1194 + byte[] ret = new byte[prefix.length + suffix.length];
  1195 + System.arraycopy(prefix, 0, ret, 0, prefix.length);
  1196 + System.arraycopy(suffix, 0, ret, prefix.length, suffix.length);
  1197 + return ret;
  1198 + }
  1199 +
  1200 + private static final char[] HEX_DIGITS =
  1201 + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  1202 +
  1203 + private static String bytes2HexString(final byte[] bytes) {
  1204 + if (bytes == null) return "";
  1205 + int len = bytes.length;
  1206 + if (len <= 0) return "";
  1207 + char[] ret = new char[len << 1];
  1208 + for (int i = 0, j = 0; i < len; i++) {
  1209 + ret[j++] = HEX_DIGITS[bytes[i] >> 4 & 0x0f];
  1210 + ret[j++] = HEX_DIGITS[bytes[i] & 0x0f];
  1211 + }
  1212 + return new String(ret);
  1213 + }
  1214 +
  1215 + private static byte[] hexString2Bytes(String hexString) {
  1216 + if (isSpace(hexString)) return null;
  1217 + int len = hexString.length();
  1218 + if (len % 2 != 0) {
  1219 + hexString = "0" + hexString;
  1220 + len = len + 1;
  1221 + }
  1222 + char[] hexBytes = hexString.toUpperCase().toCharArray();
  1223 + byte[] ret = new byte[len >> 1];
  1224 + for (int i = 0; i < len; i += 2) {
  1225 + ret[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1]));
  1226 + }
  1227 + return ret;
  1228 + }
  1229 +
  1230 + private static int hex2Dec(final char hexChar) {
  1231 + if (hexChar >= '0' && hexChar <= '9') {
  1232 + return hexChar - '0';
  1233 + } else if (hexChar >= 'A' && hexChar <= 'F') {
  1234 + return hexChar - 'A' + 10;
  1235 + } else {
  1236 + throw new IllegalArgumentException();
  1237 + }
  1238 + }
  1239 +
  1240 + private static byte[] base64Encode(final byte[] input) {
  1241 + return Base64.encode(input, Base64.NO_WRAP);
  1242 + }
  1243 +
  1244 + private static byte[] base64Decode(final byte[] input) {
  1245 + return Base64.decode(input, Base64.NO_WRAP);
  1246 + }
  1247 +
  1248 + private static boolean isSpace(final String s) {
  1249 + if (s == null) return true;
  1250 + for (int i = 0, len = s.length(); i < len; ++i) {
  1251 + if (!Character.isWhitespace(s.charAt(i))) {
  1252 + return false;
  1253 + }
  1254 + }
  1255 + return true;
  1256 + }
  1257 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/FragmentUtil.java deleted 100644 → 0
1   -package com.cnlive.core.libs.base.util;
2   -
3   -import androidx.fragment.app.Fragment;
4   -import androidx.fragment.app.FragmentManager;
5   -import androidx.fragment.app.FragmentTransaction;
6   -
7   -public class FragmentUtil {
8   -
9   - private int content_id;
10   -
11   - public FragmentUtil(int content_id) {
12   - this.content_id = content_id;
13   - }
14   -
15   - public void initFragment(Fragment fragment, FragmentManager fragmentManager) {
16   - if (fragmentManager.findFragmentById(content_id) != null) return;
17   - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
18   - fragmentTransaction.add(content_id, fragment);
19   - fragmentTransaction.commit();
20   - }
21   -
22   - public void changeFragment(Fragment fragment, FragmentManager fragmentManager) {
23   - Fragment find_fragment = fragmentManager.findFragmentById(content_id);
24   - if (find_fragment != null && find_fragment.equals(fragment)) return;
25   - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
26   - if (find_fragment != null) fragmentTransaction.remove(find_fragment);
27   - fragmentTransaction.add(content_id, fragment);
28   - fragmentTransaction.commitAllowingStateLoss();
29   - }
30   -}
31 0 \ No newline at end of file
core/base/src/main/java/com/cnlive/core/libs/base/util/ImageUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.Resources;
  5 +import android.graphics.Bitmap;
  6 +import android.graphics.Bitmap.CompressFormat;
  7 +import android.graphics.BitmapFactory;
  8 +import android.graphics.BitmapShader;
  9 +import android.graphics.Canvas;
  10 +import android.graphics.Color;
  11 +import android.graphics.ColorMatrix;
  12 +import android.graphics.ColorMatrixColorFilter;
  13 +import android.graphics.LinearGradient;
  14 +import android.graphics.Matrix;
  15 +import android.graphics.Paint;
  16 +import android.graphics.PixelFormat;
  17 +import android.graphics.PorterDuff;
  18 +import android.graphics.PorterDuffColorFilter;
  19 +import android.graphics.PorterDuffXfermode;
  20 +import android.graphics.Rect;
  21 +import android.graphics.RectF;
  22 +import android.graphics.Shader;
  23 +import android.graphics.drawable.BitmapDrawable;
  24 +import android.graphics.drawable.Drawable;
  25 +import android.media.ExifInterface;
  26 +import android.os.Build;
  27 +import android.renderscript.Allocation;
  28 +import android.renderscript.Element;
  29 +import android.renderscript.RenderScript;
  30 +import android.renderscript.ScriptIntrinsicBlur;
  31 +import android.view.View;
  32 +
  33 +import androidx.annotation.ColorInt;
  34 +import androidx.annotation.DrawableRes;
  35 +import androidx.annotation.FloatRange;
  36 +import androidx.annotation.IntRange;
  37 +import androidx.annotation.NonNull;
  38 +import androidx.annotation.RequiresApi;
  39 +import androidx.core.content.ContextCompat;
  40 +
  41 +import java.io.BufferedOutputStream;
  42 +import java.io.ByteArrayOutputStream;
  43 +import java.io.File;
  44 +import java.io.FileDescriptor;
  45 +import java.io.FileInputStream;
  46 +import java.io.FileOutputStream;
  47 +import java.io.IOException;
  48 +import java.io.InputStream;
  49 +import java.io.OutputStream;
  50 +
  51 +/**
  52 + * 图片相关
  53 + * <pre>
  54 + * author: Blankj
  55 + * blog : http://blankj.com
  56 + * time : 2016/08/12
  57 + * desc : utils about image
  58 + * </pre>
  59 + * bitmap2Bytes, bytes2Bitmap : bitmap 与 bytes 互转
  60 + * drawable2Bitmap, bitmap2Drawable: drawable 与 bitmap 互转
  61 + * drawable2Bytes, bytes2Drawable : drawable 与 bytes 互转
  62 + * view2Bitmap : view 转 bitmap
  63 + * getBitmap : 获取 bitmap
  64 + * scale : 缩放图片
  65 + * clip : 裁剪图片
  66 + * skew : 倾斜图片
  67 + * rotate : 旋转图片
  68 + * getRotateDegree : 获取图片旋转角度
  69 + * toRound : 转为圆形图片
  70 + * toRoundCorner : 转为圆角图片
  71 + * addCornerBorder : 添加圆角边框
  72 + * addCircleBorder : 添加圆形边框
  73 + * addReflection : 添加倒影
  74 + * addTextWatermark : 添加文字水印
  75 + * addImageWatermark : 添加图片水印
  76 + * toAlpha : 转为 alpha 位图
  77 + * toGray : 转为灰度图片
  78 + * fastBlur : 快速模糊
  79 + * renderScriptBlur : renderScript 模糊图片
  80 + * stackBlur : stack 模糊图片
  81 + * save : 保存图片
  82 + * isImage : 根据文件名判断文件是否为图片
  83 + * getImageType : 获取图片类型
  84 + * compressByScale : 按缩放压缩
  85 + * compressByQuality : 按质量压缩
  86 + * compressBySampleSize : 按采样大小压缩
  87 + * getSize : 获取图片尺寸
  88 + */
  89 +public final class ImageUtils {
  90 +
  91 + private ImageUtils() {
  92 + throw new UnsupportedOperationException("u can't instantiate me...");
  93 + }
  94 +
  95 + /**
  96 + * Bitmap to bytes.
  97 + *
  98 + * @param bitmap The bitmap.
  99 + * @param format The format of bitmap.
  100 + * @return bytes
  101 + */
  102 + public static byte[] bitmap2Bytes(final Bitmap bitmap, final CompressFormat format) {
  103 + if (bitmap == null) return null;
  104 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  105 + bitmap.compress(format, 100, baos);
  106 + return baos.toByteArray();
  107 + }
  108 +
  109 + /**
  110 + * Bytes to bitmap.
  111 + *
  112 + * @param bytes The bytes.
  113 + * @return bitmap
  114 + */
  115 + public static Bitmap bytes2Bitmap(final byte[] bytes) {
  116 + return (bytes == null || bytes.length == 0)
  117 + ? null
  118 + : BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
  119 + }
  120 +
  121 + /**
  122 + * Drawable to bitmap.
  123 + *
  124 + * @param drawable The drawable.
  125 + * @return bitmap
  126 + */
  127 + public static Bitmap drawable2Bitmap(final Drawable drawable) {
  128 + if (drawable instanceof BitmapDrawable) {
  129 + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
  130 + if (bitmapDrawable.getBitmap() != null) {
  131 + return bitmapDrawable.getBitmap();
  132 + }
  133 + }
  134 + Bitmap bitmap;
  135 + if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
  136 + bitmap = Bitmap.createBitmap(1, 1,
  137 + drawable.getOpacity() != PixelFormat.OPAQUE
  138 + ? Bitmap.Config.ARGB_8888
  139 + : Bitmap.Config.RGB_565);
  140 + } else {
  141 + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
  142 + drawable.getIntrinsicHeight(),
  143 + drawable.getOpacity() != PixelFormat.OPAQUE
  144 + ? Bitmap.Config.ARGB_8888
  145 + : Bitmap.Config.RGB_565);
  146 + }
  147 + Canvas canvas = new Canvas(bitmap);
  148 + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
  149 + drawable.draw(canvas);
  150 + return bitmap;
  151 + }
  152 +
  153 + /**
  154 + * Bitmap to drawable.
  155 + *
  156 + * @param bitmap The bitmap.
  157 + * @return drawable
  158 + */
  159 + public static Drawable bitmap2Drawable(Context context, final Bitmap bitmap) {
  160 + return bitmap == null ? null : new BitmapDrawable(context.getResources(), bitmap);
  161 + }
  162 +
  163 + /**
  164 + * Drawable to bytes.
  165 + *
  166 + * @param drawable The drawable.
  167 + * @param format The format of bitmap.
  168 + * @return bytes
  169 + */
  170 + public static byte[] drawable2Bytes(final Drawable drawable, final CompressFormat format) {
  171 + return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format);
  172 + }
  173 +
  174 + /**
  175 + * Bytes to drawable.
  176 + *
  177 + * @param bytes The bytes.
  178 + * @return drawable
  179 + */
  180 + public static Drawable bytes2Drawable(Context context, final byte[] bytes) {
  181 + return bitmap2Drawable(context, bytes2Bitmap(bytes));
  182 + }
  183 +
  184 + /**
  185 + * view 转 bitmap
  186 + * View to bitmap.
  187 + *
  188 + * @param view The view.
  189 + * @return bitmap
  190 + */
  191 + public static Bitmap view2Bitmap(final View view) {
  192 + if (view == null) return null;
  193 + Bitmap ret = Bitmap.createBitmap(view.getWidth(),
  194 + view.getHeight(),
  195 + Bitmap.Config.ARGB_8888);
  196 + Canvas canvas = new Canvas(ret);
  197 + Drawable bgDrawable = view.getBackground();
  198 + if (bgDrawable != null) {
  199 + bgDrawable.draw(canvas);
  200 + } else {
  201 + canvas.drawColor(Color.WHITE);
  202 + }
  203 + view.draw(canvas);
  204 + return ret;
  205 + }
  206 +
  207 +// /**获取 bitmap,//todo android Q改
  208 +// * Return bitmap.
  209 +// *
  210 +// * @param file The file.
  211 +// * @return bitmap
  212 +// */
  213 +// public static Bitmap getBitmap(final File file) {
  214 +// if (file == null) return null;
  215 +// return BitmapFactory.decodeFile(file.getAbsolutePath());
  216 +// }
  217 +
  218 + /**
  219 + * Return bitmap.
  220 + *
  221 + * @param file The file.
  222 + * @param maxWidth The maximum width.
  223 + * @param maxHeight The maximum height.
  224 + * @return bitmap
  225 + */
  226 + public static Bitmap getBitmap(final File file, final int maxWidth, final int maxHeight) {
  227 + if (file == null) return null;
  228 + BitmapFactory.Options options = new BitmapFactory.Options();
  229 + options.inJustDecodeBounds = true;
  230 + BitmapFactory.decodeFile(file.getAbsolutePath(), options);
  231 + options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
  232 + options.inJustDecodeBounds = false;
  233 + return BitmapFactory.decodeFile(file.getAbsolutePath(), options);
  234 + }
  235 +
  236 + /**
  237 + * Return bitmap.
  238 + *
  239 + * @param filePath The path of file.
  240 + * @return bitmap
  241 + */
  242 + public static Bitmap getBitmap(final String filePath) {
  243 + if (isSpace(filePath)) return null;
  244 + return BitmapFactory.decodeFile(filePath);
  245 + }
  246 +
  247 + /**
  248 + * Return bitmap.
  249 + *
  250 + * @param filePath The path of file.
  251 + * @param maxWidth The maximum width.
  252 + * @param maxHeight The maximum height.
  253 + * @return bitmap
  254 + */
  255 + public static Bitmap getBitmap(final String filePath, final int maxWidth, final int maxHeight) {
  256 + if (isSpace(filePath)) return null;
  257 + BitmapFactory.Options options = new BitmapFactory.Options();
  258 + options.inJustDecodeBounds = true;
  259 + BitmapFactory.decodeFile(filePath, options);
  260 + options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
  261 + options.inJustDecodeBounds = false;
  262 + return BitmapFactory.decodeFile(filePath, options);
  263 + }
  264 +
  265 + /**
  266 + * Return bitmap.
  267 + *
  268 + * @param is The input stream.
  269 + * @return bitmap
  270 + */
  271 + public static Bitmap getBitmap(final InputStream is) {
  272 + if (is == null) return null;
  273 + return BitmapFactory.decodeStream(is);
  274 + }
  275 +
  276 + /**
  277 + * Return bitmap.
  278 + *
  279 + * @param is The input stream.
  280 + * @param maxWidth The maximum width.
  281 + * @param maxHeight The maximum height.
  282 + * @return bitmap
  283 + */
  284 + public static Bitmap getBitmap(final InputStream is, final int maxWidth, final int maxHeight) {
  285 + if (is == null) return null;
  286 + byte[] bytes = input2Byte(is);
  287 + return getBitmap(bytes, 0, maxWidth, maxHeight);
  288 + }
  289 +
  290 + /**
  291 + * Return bitmap.
  292 + *
  293 + * @param data The data.
  294 + * @param offset The offset.
  295 + * @return bitmap
  296 + */
  297 + public static Bitmap getBitmap(final byte[] data, final int offset) {
  298 + if (data.length == 0) return null;
  299 + return BitmapFactory.decodeByteArray(data, offset, data.length);
  300 + }
  301 +
  302 + /**
  303 + * Return bitmap.
  304 + *
  305 + * @param data The data.
  306 + * @param offset The offset.
  307 + * @param maxWidth The maximum width.
  308 + * @param maxHeight The maximum height.
  309 + * @return bitmap
  310 + */
  311 + public static Bitmap getBitmap(final byte[] data,
  312 + final int offset,
  313 + final int maxWidth,
  314 + final int maxHeight) {
  315 + if (data.length == 0) return null;
  316 + BitmapFactory.Options options = new BitmapFactory.Options();
  317 + options.inJustDecodeBounds = true;
  318 + BitmapFactory.decodeByteArray(data, offset, data.length, options);
  319 + options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
  320 + options.inJustDecodeBounds = false;
  321 + return BitmapFactory.decodeByteArray(data, offset, data.length, options);
  322 + }
  323 +
  324 + /**
  325 + * Return bitmap.
  326 + *
  327 + * @param resId The resource id.
  328 + * @return bitmap
  329 + */
  330 + public static Bitmap getBitmap(Context context, @DrawableRes final int resId) {
  331 + Drawable drawable = ContextCompat.getDrawable(context, resId);
  332 + Canvas canvas = new Canvas();
  333 + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
  334 + drawable.getIntrinsicHeight(),
  335 + Bitmap.Config.ARGB_8888);
  336 + canvas.setBitmap(bitmap);
  337 + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
  338 + drawable.draw(canvas);
  339 + return bitmap;
  340 + }
  341 +
  342 + /**
  343 + * Return bitmap.
  344 + *
  345 + * @param resId The resource id.
  346 + * @param maxWidth The maximum width.
  347 + * @param maxHeight The maximum height.
  348 + * @return bitmap
  349 + */
  350 + public static Bitmap getBitmap(Context context, @DrawableRes final int resId,
  351 + final int maxWidth,
  352 + final int maxHeight) {
  353 + BitmapFactory.Options options = new BitmapFactory.Options();
  354 + final Resources resources = context.getResources();
  355 + options.inJustDecodeBounds = true;
  356 + BitmapFactory.decodeResource(resources, resId, options);
  357 + options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
  358 + options.inJustDecodeBounds = false;
  359 + return BitmapFactory.decodeResource(resources, resId, options);
  360 + }
  361 +
  362 + /**
  363 + * Return bitmap.
  364 + *
  365 + * @param fd The file descriptor.
  366 + * @return bitmap
  367 + */
  368 + public static Bitmap getBitmap(final FileDescriptor fd) {
  369 + if (fd == null) return null;
  370 + return BitmapFactory.decodeFileDescriptor(fd);
  371 + }
  372 +
  373 + /**
  374 + * Return bitmap.
  375 + *
  376 + * @param fd The file descriptor
  377 + * @param maxWidth The maximum width.
  378 + * @param maxHeight The maximum height.
  379 + * @return bitmap
  380 + */
  381 + public static Bitmap getBitmap(final FileDescriptor fd,
  382 + final int maxWidth,
  383 + final int maxHeight) {
  384 + if (fd == null) return null;
  385 + BitmapFactory.Options options = new BitmapFactory.Options();
  386 + options.inJustDecodeBounds = true;
  387 + BitmapFactory.decodeFileDescriptor(fd, null, options);
  388 + options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
  389 + options.inJustDecodeBounds = false;
  390 + return BitmapFactory.decodeFileDescriptor(fd, null, options);
  391 + }
  392 +
  393 + /**
  394 + * Return the bitmap with the specified color.
  395 + *
  396 + * @param src The source of bitmap.
  397 + * @param color The color.
  398 + * @return the bitmap with the specified color
  399 + */
  400 + public static Bitmap drawColor(@NonNull final Bitmap src, @ColorInt final int color) {
  401 + return drawColor(src, color, false);
  402 + }
  403 +
  404 + /**
  405 + * Return the bitmap with the specified color.
  406 + *
  407 + * @param src The source of bitmap.
  408 + * @param color The color.
  409 + * @param recycle True to recycle the source of bitmap, false otherwise.
  410 + * @return the bitmap with the specified color
  411 + */
  412 + public static Bitmap drawColor(@NonNull final Bitmap src,
  413 + @ColorInt final int color,
  414 + final boolean recycle) {
  415 + if (isEmptyBitmap(src)) return null;
  416 + Bitmap ret = recycle ? src : src.copy(src.getConfig(), true);
  417 + Canvas canvas = new Canvas(ret);
  418 + canvas.drawColor(color, PorterDuff.Mode.DARKEN);
  419 + return ret;
  420 + }
  421 +
  422 + /**
  423 + * 缩放图片
  424 + * Return the scaled bitmap.
  425 + *
  426 + * @param src The source of bitmap.
  427 + * @param newWidth The new width.
  428 + * @param newHeight The new height.
  429 + * @return the scaled bitmap
  430 + */
  431 + public static Bitmap scale(final Bitmap src, final int newWidth, final int newHeight) {
  432 + return scale(src, newWidth, newHeight, false);
  433 + }
  434 +
  435 + /**
  436 + * Return the scaled bitmap.
  437 + *
  438 + * @param src The source of bitmap.
  439 + * @param newWidth The new width.
  440 + * @param newHeight The new height.
  441 + * @param recycle True to recycle the source of bitmap, false otherwise.
  442 + * @return the scaled bitmap
  443 + */
  444 + public static Bitmap scale(final Bitmap src,
  445 + final int newWidth,
  446 + final int newHeight,
  447 + final boolean recycle) {
  448 + if (isEmptyBitmap(src)) return null;
  449 + Bitmap ret = Bitmap.createScaledBitmap(src, newWidth, newHeight, true);
  450 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  451 + return ret;
  452 + }
  453 +
  454 + /**
  455 + * Return the scaled bitmap
  456 + *
  457 + * @param src The source of bitmap.
  458 + * @param scaleWidth The scale of width.
  459 + * @param scaleHeight The scale of height.
  460 + * @return the scaled bitmap
  461 + */
  462 + public static Bitmap scale(final Bitmap src, final float scaleWidth, final float scaleHeight) {
  463 + return scale(src, scaleWidth, scaleHeight, false);
  464 + }
  465 +
  466 + /**
  467 + * Return the scaled bitmap
  468 + *
  469 + * @param src The source of bitmap.
  470 + * @param scaleWidth The scale of width.
  471 + * @param scaleHeight The scale of height.
  472 + * @param recycle True to recycle the source of bitmap, false otherwise.
  473 + * @return the scaled bitmap
  474 + */
  475 + public static Bitmap scale(final Bitmap src,
  476 + final float scaleWidth,
  477 + final float scaleHeight,
  478 + final boolean recycle) {
  479 + if (isEmptyBitmap(src)) return null;
  480 + Matrix matrix = new Matrix();
  481 + matrix.setScale(scaleWidth, scaleHeight);
  482 + Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
  483 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  484 + return ret;
  485 + }
  486 +
  487 + /**
  488 + * 裁剪图片
  489 + * Return the clipped bitmap.
  490 + *
  491 + * @param src The source of bitmap.
  492 + * @param x The x coordinate of the first pixel.
  493 + * @param y The y coordinate of the first pixel.
  494 + * @param width The width.
  495 + * @param height The height.
  496 + * @return the clipped bitmap
  497 + */
  498 + public static Bitmap clip(final Bitmap src,
  499 + final int x,
  500 + final int y,
  501 + final int width,
  502 + final int height) {
  503 + return clip(src, x, y, width, height, false);
  504 + }
  505 +
  506 + /**
  507 + * Return the clipped bitmap.
  508 + *
  509 + * @param src The source of bitmap.
  510 + * @param x The x coordinate of the first pixel.
  511 + * @param y The y coordinate of the first pixel.
  512 + * @param width The width.
  513 + * @param height The height.
  514 + * @param recycle True to recycle the source of bitmap, false otherwise.
  515 + * @return the clipped bitmap
  516 + */
  517 + public static Bitmap clip(final Bitmap src,
  518 + final int x,
  519 + final int y,
  520 + final int width,
  521 + final int height,
  522 + final boolean recycle) {
  523 + if (isEmptyBitmap(src)) return null;
  524 + Bitmap ret = Bitmap.createBitmap(src, x, y, width, height);
  525 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  526 + return ret;
  527 + }
  528 +
  529 + /**
  530 + * 倾斜图片
  531 + * Return the skewed bitmap.
  532 + *
  533 + * @param src The source of bitmap.
  534 + * @param kx The skew factor of x.
  535 + * @param ky The skew factor of y.
  536 + * @return the skewed bitmap
  537 + */
  538 + public static Bitmap skew(final Bitmap src, final float kx, final float ky) {
  539 + return skew(src, kx, ky, 0, 0, false);
  540 + }
  541 +
  542 + /**
  543 + * Return the skewed bitmap.
  544 + *
  545 + * @param src The source of bitmap.
  546 + * @param kx The skew factor of x.
  547 + * @param ky The skew factor of y.
  548 + * @param recycle True to recycle the source of bitmap, false otherwise.
  549 + * @return the skewed bitmap
  550 + */
  551 + public static Bitmap skew(final Bitmap src,
  552 + final float kx,
  553 + final float ky,
  554 + final boolean recycle) {
  555 + return skew(src, kx, ky, 0, 0, recycle);
  556 + }
  557 +
  558 + /**
  559 + * Return the skewed bitmap.
  560 + *
  561 + * @param src The source of bitmap.
  562 + * @param kx The skew factor of x.
  563 + * @param ky The skew factor of y.
  564 + * @param px The x coordinate of the pivot point.
  565 + * @param py The y coordinate of the pivot point.
  566 + * @return the skewed bitmap
  567 + */
  568 + public static Bitmap skew(final Bitmap src,
  569 + final float kx,
  570 + final float ky,
  571 + final float px,
  572 + final float py) {
  573 + return skew(src, kx, ky, px, py, false);
  574 + }
  575 +
  576 + /**
  577 + * Return the skewed bitmap.
  578 + *
  579 + * @param src The source of bitmap.
  580 + * @param kx The skew factor of x.
  581 + * @param ky The skew factor of y.
  582 + * @param px The x coordinate of the pivot point.
  583 + * @param py The y coordinate of the pivot point.
  584 + * @param recycle True to recycle the source of bitmap, false otherwise.
  585 + * @return the skewed bitmap
  586 + */
  587 + public static Bitmap skew(final Bitmap src,
  588 + final float kx,
  589 + final float ky,
  590 + final float px,
  591 + final float py,
  592 + final boolean recycle) {
  593 + if (isEmptyBitmap(src)) return null;
  594 + Matrix matrix = new Matrix();
  595 + matrix.setSkew(kx, ky, px, py);
  596 + Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
  597 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  598 + return ret;
  599 + }
  600 +
  601 + /**
  602 + * 旋转图片
  603 + * Return the rotated bitmap.
  604 + *
  605 + * @param src The source of bitmap.
  606 + * @param degrees The number of degrees.
  607 + * @param px The x coordinate of the pivot point.
  608 + * @param py The y coordinate of the pivot point.
  609 + * @return the rotated bitmap
  610 + */
  611 + public static Bitmap rotate(final Bitmap src,
  612 + final int degrees,
  613 + final float px,
  614 + final float py) {
  615 + return rotate(src, degrees, px, py, false);
  616 + }
  617 +
  618 + /**
  619 + * Return the rotated bitmap.
  620 + *
  621 + * @param src The source of bitmap.
  622 + * @param degrees The number of degrees.
  623 + * @param px The x coordinate of the pivot point.
  624 + * @param py The y coordinate of the pivot point.
  625 + * @param recycle True to recycle the source of bitmap, false otherwise.
  626 + * @return the rotated bitmap
  627 + */
  628 + public static Bitmap rotate(final Bitmap src,
  629 + final int degrees,
  630 + final float px,
  631 + final float py,
  632 + final boolean recycle) {
  633 + if (isEmptyBitmap(src)) return null;
  634 + if (degrees == 0) return src;
  635 + Matrix matrix = new Matrix();
  636 + matrix.setRotate(degrees, px, py);
  637 + Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
  638 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  639 + return ret;
  640 + }
  641 +
  642 + /**
  643 + * 获取图片旋转角度
  644 + * Return the rotated degree.
  645 + *
  646 + * @param filePath The path of file.
  647 + * @return the rotated degree
  648 + */
  649 + public static int getRotateDegree(final String filePath) {
  650 + try {
  651 + ExifInterface exifInterface = new ExifInterface(filePath);
  652 + int orientation = exifInterface.getAttributeInt(
  653 + ExifInterface.TAG_ORIENTATION,
  654 + ExifInterface.ORIENTATION_NORMAL
  655 + );
  656 + switch (orientation) {
  657 + case ExifInterface.ORIENTATION_ROTATE_90:
  658 + return 90;
  659 + case ExifInterface.ORIENTATION_ROTATE_180:
  660 + return 180;
  661 + case ExifInterface.ORIENTATION_ROTATE_270:
  662 + return 270;
  663 + default:
  664 + return 0;
  665 + }
  666 + } catch (IOException e) {
  667 + e.printStackTrace();
  668 + return -1;
  669 + }
  670 + }
  671 +
  672 + /**
  673 + * 转为圆形图片
  674 + * Return the round bitmap.
  675 + *
  676 + * @param src The source of bitmap.
  677 + * @return the round bitmap
  678 + */
  679 + public static Bitmap toRound(final Bitmap src) {
  680 + return toRound(src, 0, 0, false);
  681 + }
  682 +
  683 + /**
  684 + * Return the round bitmap.
  685 + *
  686 + * @param src The source of bitmap.
  687 + * @param recycle True to recycle the source of bitmap, false otherwise.
  688 + * @return the round bitmap
  689 + */
  690 + public static Bitmap toRound(final Bitmap src, final boolean recycle) {
  691 + return toRound(src, 0, 0, recycle);
  692 + }
  693 +
  694 + /**
  695 + * Return the round bitmap.
  696 + *
  697 + * @param src The source of bitmap.
  698 + * @param borderSize The size of border.
  699 + * @param borderColor The color of border.
  700 + * @return the round bitmap
  701 + */
  702 + public static Bitmap toRound(final Bitmap src,
  703 + @IntRange(from = 0) int borderSize,
  704 + @ColorInt int borderColor) {
  705 + return toRound(src, borderSize, borderColor, false);
  706 + }
  707 +
  708 + /**
  709 + * Return the round bitmap.
  710 + *
  711 + * @param src The source of bitmap.
  712 + * @param recycle True to recycle the source of bitmap, false otherwise.
  713 + * @param borderSize The size of border.
  714 + * @param borderColor The color of border.
  715 + * @return the round bitmap
  716 + */
  717 + public static Bitmap toRound(final Bitmap src,
  718 + @IntRange(from = 0) int borderSize,
  719 + @ColorInt int borderColor,
  720 + final boolean recycle) {
  721 + if (isEmptyBitmap(src)) return null;
  722 + int width = src.getWidth();
  723 + int height = src.getHeight();
  724 + int size = Math.min(width, height);
  725 + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  726 + Bitmap ret = Bitmap.createBitmap(width, height, src.getConfig());
  727 + float center = size / 2f;
  728 + RectF rectF = new RectF(0, 0, width, height);
  729 + rectF.inset((width - size) / 2f, (height - size) / 2f);
  730 + Matrix matrix = new Matrix();
  731 + matrix.setTranslate(rectF.left, rectF.top);
  732 + if (width != height) {
  733 + matrix.preScale((float) size / width, (float) size / height);
  734 + }
  735 + BitmapShader shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  736 + shader.setLocalMatrix(matrix);
  737 + paint.setShader(shader);
  738 + Canvas canvas = new Canvas(ret);
  739 + canvas.drawRoundRect(rectF, center, center, paint);
  740 + if (borderSize > 0) {
  741 + paint.setShader(null);
  742 + paint.setColor(borderColor);
  743 + paint.setStyle(Paint.Style.STROKE);
  744 + paint.setStrokeWidth(borderSize);
  745 + float radius = center - borderSize / 2f;
  746 + canvas.drawCircle(width / 2f, height / 2f, radius, paint);
  747 + }
  748 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  749 + return ret;
  750 + }
  751 +
  752 + /**
  753 + * 转为圆角图片
  754 + * Return the round corner bitmap.
  755 + *
  756 + * @param src The source of bitmap.
  757 + * @param radius The radius of corner.
  758 + * @return the round corner bitmap
  759 + */
  760 + public static Bitmap toRoundCorner(final Bitmap src, final float radius) {
  761 + return toRoundCorner(src, radius, 0, 0, false);
  762 + }
  763 +
  764 + /**
  765 + * Return the round corner bitmap.
  766 + *
  767 + * @param src The source of bitmap.
  768 + * @param radius The radius of corner.
  769 + * @param recycle True to recycle the source of bitmap, false otherwise.
  770 + * @return the round corner bitmap
  771 + */
  772 + public static Bitmap toRoundCorner(final Bitmap src,
  773 + final float radius,
  774 + final boolean recycle) {
  775 + return toRoundCorner(src, radius, 0, 0, recycle);
  776 + }
  777 +
  778 + /**
  779 + * Return the round corner bitmap.
  780 + *
  781 + * @param src The source of bitmap.
  782 + * @param radius The radius of corner.
  783 + * @param borderSize The size of border.
  784 + * @param borderColor The color of border.
  785 + * @return the round corner bitmap
  786 + */
  787 + public static Bitmap toRoundCorner(final Bitmap src,
  788 + final float radius,
  789 + @IntRange(from = 0) int borderSize,
  790 + @ColorInt int borderColor) {
  791 + return toRoundCorner(src, radius, borderSize, borderColor, false);
  792 + }
  793 +
  794 + /**
  795 + * Return the round corner bitmap.
  796 + *
  797 + * @param src The source of bitmap.
  798 + * @param radius The radius of corner.
  799 + * @param borderSize The size of border.
  800 + * @param borderColor The color of border.
  801 + * @param recycle True to recycle the source of bitmap, false otherwise.
  802 + * @return the round corner bitmap
  803 + */
  804 + public static Bitmap toRoundCorner(final Bitmap src,
  805 + final float radius,
  806 + @IntRange(from = 0) int borderSize,
  807 + @ColorInt int borderColor,
  808 + final boolean recycle) {
  809 + if (isEmptyBitmap(src)) return null;
  810 + int width = src.getWidth();
  811 + int height = src.getHeight();
  812 + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  813 + Bitmap ret = Bitmap.createBitmap(width, height, src.getConfig());
  814 + BitmapShader shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  815 + paint.setShader(shader);
  816 + Canvas canvas = new Canvas(ret);
  817 + RectF rectF = new RectF(0, 0, width, height);
  818 + float halfBorderSize = borderSize / 2f;
  819 + rectF.inset(halfBorderSize, halfBorderSize);
  820 + canvas.drawRoundRect(rectF, radius, radius, paint);
  821 + if (borderSize > 0) {
  822 + paint.setShader(null);
  823 + paint.setColor(borderColor);
  824 + paint.setStyle(Paint.Style.STROKE);
  825 + paint.setStrokeWidth(borderSize);
  826 + paint.setStrokeCap(Paint.Cap.ROUND);
  827 + canvas.drawRoundRect(rectF, radius, radius, paint);
  828 + }
  829 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  830 + return ret;
  831 + }
  832 +
  833 + /**
  834 + * 添加圆角边框
  835 + * Return the round corner bitmap with border.
  836 + *
  837 + * @param src The source of bitmap.
  838 + * @param borderSize The size of border.
  839 + * @param color The color of border.
  840 + * @param cornerRadius The radius of corner.
  841 + * @return the round corner bitmap with border
  842 + */
  843 + public static Bitmap addCornerBorder(final Bitmap src,
  844 + @IntRange(from = 1) final int borderSize,
  845 + @ColorInt final int color,
  846 + @FloatRange(from = 0) final float cornerRadius) {
  847 + return addBorder(src, borderSize, color, false, cornerRadius, false);
  848 + }
  849 +
  850 + /**
  851 + * Return the round corner bitmap with border.
  852 + *
  853 + * @param src The source of bitmap.
  854 + * @param borderSize The size of border.
  855 + * @param color The color of border.
  856 + * @param cornerRadius The radius of corner.
  857 + * @param recycle True to recycle the source of bitmap, false otherwise.
  858 + * @return the round corner bitmap with border
  859 + */
  860 + public static Bitmap addCornerBorder(final Bitmap src,
  861 + @IntRange(from = 1) final int borderSize,
  862 + @ColorInt final int color,
  863 + @FloatRange(from = 0) final float cornerRadius,
  864 + final boolean recycle) {
  865 + return addBorder(src, borderSize, color, false, cornerRadius, recycle);
  866 + }
  867 +
  868 + /**
  869 + * 添加圆形边框
  870 + * Return the round bitmap with border.
  871 + *
  872 + * @param src The source of bitmap.
  873 + * @param borderSize The size of border.
  874 + * @param color The color of border.
  875 + * @return the round bitmap with border
  876 + */
  877 + public static Bitmap addCircleBorder(final Bitmap src,
  878 + @IntRange(from = 1) final int borderSize,
  879 + @ColorInt final int color) {
  880 + return addBorder(src, borderSize, color, true, 0, false);
  881 + }
  882 +
  883 + /**
  884 + * Return the round bitmap with border.
  885 + *
  886 + * @param src The source of bitmap.
  887 + * @param borderSize The size of border.
  888 + * @param color The color of border.
  889 + * @param recycle True to recycle the source of bitmap, false otherwise.
  890 + * @return the round bitmap with border
  891 + */
  892 + public static Bitmap addCircleBorder(final Bitmap src,
  893 + @IntRange(from = 1) final int borderSize,
  894 + @ColorInt final int color,
  895 + final boolean recycle) {
  896 + return addBorder(src, borderSize, color, true, 0, recycle);
  897 + }
  898 +
  899 + /**
  900 + * Return the bitmap with border.
  901 + *
  902 + * @param src The source of bitmap.
  903 + * @param borderSize The size of border.
  904 + * @param color The color of border.
  905 + * @param isCircle True to draw circle, false to draw corner.
  906 + * @param cornerRadius The radius of corner.
  907 + * @param recycle True to recycle the source of bitmap, false otherwise.
  908 + * @return the bitmap with border
  909 + */
  910 + private static Bitmap addBorder(final Bitmap src,
  911 + @IntRange(from = 1) final int borderSize,
  912 + @ColorInt final int color,
  913 + final boolean isCircle,
  914 + final float cornerRadius,
  915 + final boolean recycle) {
  916 + if (isEmptyBitmap(src)) return null;
  917 + Bitmap ret = recycle ? src : src.copy(src.getConfig(), true);
  918 + int width = ret.getWidth();
  919 + int height = ret.getHeight();
  920 + Canvas canvas = new Canvas(ret);
  921 + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  922 + paint.setColor(color);
  923 + paint.setStyle(Paint.Style.STROKE);
  924 + paint.setStrokeWidth(borderSize);
  925 + if (isCircle) {
  926 + float radius = Math.min(width, height) / 2f - borderSize / 2f;
  927 + canvas.drawCircle(width / 2f, height / 2f, radius, paint);
  928 + } else {
  929 + int halfBorderSize = borderSize >> 1;
  930 + RectF rectF = new RectF(halfBorderSize, halfBorderSize,
  931 + width - halfBorderSize, height - halfBorderSize);
  932 + canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, paint);
  933 + }
  934 + return ret;
  935 + }
  936 +
  937 + /**
  938 + * 添加倒影
  939 + * Return the bitmap with reflection.
  940 + *
  941 + * @param src The source of bitmap.
  942 + * @param reflectionHeight The height of reflection.
  943 + * @return the bitmap with reflection
  944 + */
  945 + public static Bitmap addReflection(final Bitmap src, final int reflectionHeight) {
  946 + return addReflection(src, reflectionHeight, false);
  947 + }
  948 +
  949 + /**
  950 + * Return the bitmap with reflection.
  951 + *
  952 + * @param src The source of bitmap.
  953 + * @param reflectionHeight The height of reflection.
  954 + * @param recycle True to recycle the source of bitmap, false otherwise.
  955 + * @return the bitmap with reflection
  956 + */
  957 + public static Bitmap addReflection(final Bitmap src,
  958 + final int reflectionHeight,
  959 + final boolean recycle) {
  960 + if (isEmptyBitmap(src)) return null;
  961 + final int REFLECTION_GAP = 0;
  962 + int srcWidth = src.getWidth();
  963 + int srcHeight = src.getHeight();
  964 + Matrix matrix = new Matrix();
  965 + matrix.preScale(1, -1);
  966 + Bitmap reflectionBitmap = Bitmap.createBitmap(src, 0, srcHeight - reflectionHeight,
  967 + srcWidth, reflectionHeight, matrix, false);
  968 + Bitmap ret = Bitmap.createBitmap(srcWidth, srcHeight + reflectionHeight, src.getConfig());
  969 + Canvas canvas = new Canvas(ret);
  970 + canvas.drawBitmap(src, 0, 0, null);
  971 + canvas.drawBitmap(reflectionBitmap, 0, srcHeight + REFLECTION_GAP, null);
  972 + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  973 + LinearGradient shader = new LinearGradient(
  974 + 0, srcHeight,
  975 + 0, ret.getHeight() + REFLECTION_GAP,
  976 + 0x70FFFFFF,
  977 + 0x00FFFFFF,
  978 + Shader.TileMode.MIRROR);
  979 + paint.setShader(shader);
  980 + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
  981 + canvas.drawRect(0, srcHeight + REFLECTION_GAP, srcWidth, ret.getHeight(), paint);
  982 + if (!reflectionBitmap.isRecycled()) reflectionBitmap.recycle();
  983 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  984 + return ret;
  985 + }
  986 +
  987 + /**
  988 + * 添加文字水印
  989 + * Return the bitmap with text watermarking.
  990 + *
  991 + * @param src The source of bitmap.
  992 + * @param content The content of text.
  993 + * @param textSize The size of text.
  994 + * @param color The color of text.
  995 + * @param x The x coordinate of the first pixel.
  996 + * @param y The y coordinate of the first pixel.
  997 + * @return the bitmap with text watermarking
  998 + */
  999 + public static Bitmap addTextWatermark(final Bitmap src,
  1000 + final String content,
  1001 + final int textSize,
  1002 + @ColorInt final int color,
  1003 + final float x,
  1004 + final float y) {
  1005 + return addTextWatermark(src, content, textSize, color, x, y, false);
  1006 + }
  1007 +
  1008 + /**
  1009 + * Return the bitmap with text watermarking.
  1010 + *
  1011 + * @param src The source of bitmap.
  1012 + * @param content The content of text.
  1013 + * @param textSize The size of text.
  1014 + * @param color The color of text.
  1015 + * @param x The x coordinate of the first pixel.
  1016 + * @param y The y coordinate of the first pixel.
  1017 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1018 + * @return the bitmap with text watermarking
  1019 + */
  1020 + public static Bitmap addTextWatermark(final Bitmap src,
  1021 + final String content,
  1022 + final float textSize,
  1023 + @ColorInt final int color,
  1024 + final float x,
  1025 + final float y,
  1026 + final boolean recycle) {
  1027 + if (isEmptyBitmap(src) || content == null) return null;
  1028 + Bitmap ret = src.copy(src.getConfig(), true);
  1029 + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  1030 + Canvas canvas = new Canvas(ret);
  1031 + paint.setColor(color);
  1032 + paint.setTextSize(textSize);
  1033 + Rect bounds = new Rect();
  1034 + paint.getTextBounds(content, 0, content.length(), bounds);
  1035 + canvas.drawText(content, x, y + textSize, paint);
  1036 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  1037 + return ret;
  1038 + }
  1039 +
  1040 + /**
  1041 + * 添加图片水印
  1042 + * Return the bitmap with image watermarking.
  1043 + *
  1044 + * @param src The source of bitmap.
  1045 + * @param watermark The image watermarking.
  1046 + * @param x The x coordinate of the first pixel.
  1047 + * @param y The y coordinate of the first pixel.
  1048 + * @param alpha The alpha of watermark.
  1049 + * @return the bitmap with image watermarking
  1050 + */
  1051 + public static Bitmap addImageWatermark(final Bitmap src,
  1052 + final Bitmap watermark,
  1053 + final int x, final int y,
  1054 + final int alpha) {
  1055 + return addImageWatermark(src, watermark, x, y, alpha, false);
  1056 + }
  1057 +
  1058 + /**
  1059 + * Return the bitmap with image watermarking.
  1060 + *
  1061 + * @param src The source of bitmap.
  1062 + * @param watermark The image watermarking.
  1063 + * @param x The x coordinate of the first pixel.
  1064 + * @param y The y coordinate of the first pixel.
  1065 + * @param alpha The alpha of watermark.
  1066 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1067 + * @return the bitmap with image watermarking
  1068 + */
  1069 + public static Bitmap addImageWatermark(final Bitmap src,
  1070 + final Bitmap watermark,
  1071 + final int x,
  1072 + final int y,
  1073 + final int alpha,
  1074 + final boolean recycle) {
  1075 + if (isEmptyBitmap(src)) return null;
  1076 + Bitmap ret = src.copy(src.getConfig(), true);
  1077 + if (!isEmptyBitmap(watermark)) {
  1078 + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  1079 + Canvas canvas = new Canvas(ret);
  1080 + paint.setAlpha(alpha);
  1081 + canvas.drawBitmap(watermark, x, y, paint);
  1082 + }
  1083 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  1084 + return ret;
  1085 + }
  1086 +
  1087 + /**
  1088 + * 转为 alpha 位图
  1089 + * Return the alpha bitmap.
  1090 + *
  1091 + * @param src The source of bitmap.
  1092 + * @return the alpha bitmap
  1093 + */
  1094 + public static Bitmap toAlpha(final Bitmap src) {
  1095 + return toAlpha(src, false);
  1096 + }
  1097 +
  1098 + /**
  1099 + * Return the alpha bitmap.
  1100 + *
  1101 + * @param src The source of bitmap.
  1102 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1103 + * @return the alpha bitmap
  1104 + */
  1105 + public static Bitmap toAlpha(final Bitmap src, final Boolean recycle) {
  1106 + if (isEmptyBitmap(src)) return null;
  1107 + Bitmap ret = src.extractAlpha();
  1108 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  1109 + return ret;
  1110 + }
  1111 +
  1112 + /**
  1113 + * 转为灰度图片
  1114 + * Return the gray bitmap.
  1115 + *
  1116 + * @param src The source of bitmap.
  1117 + * @return the gray bitmap
  1118 + */
  1119 + public static Bitmap toGray(final Bitmap src) {
  1120 + return toGray(src, false);
  1121 + }
  1122 +
  1123 + /**
  1124 + * Return the gray bitmap.
  1125 + *
  1126 + * @param src The source of bitmap.
  1127 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1128 + * @return the gray bitmap
  1129 + */
  1130 + public static Bitmap toGray(final Bitmap src, final boolean recycle) {
  1131 + if (isEmptyBitmap(src)) return null;
  1132 + Bitmap ret = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
  1133 + Canvas canvas = new Canvas(ret);
  1134 + Paint paint = new Paint();
  1135 + ColorMatrix colorMatrix = new ColorMatrix();
  1136 + colorMatrix.setSaturation(0);
  1137 + ColorMatrixColorFilter colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
  1138 + paint.setColorFilter(colorMatrixColorFilter);
  1139 + canvas.drawBitmap(src, 0, 0, paint);
  1140 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  1141 + return ret;
  1142 + }
  1143 +
  1144 + /**
  1145 + * 快速模糊
  1146 + * Return the blur bitmap fast.
  1147 + * <p>zoom out, blur, zoom in</p>
  1148 + *
  1149 + * @param src The source of bitmap.
  1150 + * @param scale The scale(0...1).
  1151 + * @param radius The radius(0...25).
  1152 + * @return the blur bitmap
  1153 + */
  1154 + public static Bitmap fastBlur(Context context, final Bitmap src,
  1155 + @FloatRange(
  1156 + from = 0, to = 1, fromInclusive = false
  1157 + ) final float scale,
  1158 + @FloatRange(
  1159 + from = 0, to = 25, fromInclusive = false
  1160 + ) final float radius) {
  1161 + return fastBlur(context, src, scale, radius, false, false);
  1162 + }
  1163 +
  1164 + /**
  1165 + * Return the blur bitmap fast.
  1166 + * <p>zoom out, blur, zoom in</p>
  1167 + *
  1168 + * @param src The source of bitmap.
  1169 + * @param scale The scale(0...1).
  1170 + * @param radius The radius(0...25).
  1171 + * @return the blur bitmap
  1172 + */
  1173 + public static Bitmap fastBlur(Context context, final Bitmap src,
  1174 + @FloatRange(
  1175 + from = 0, to = 1, fromInclusive = false
  1176 + ) final float scale,
  1177 + @FloatRange(
  1178 + from = 0, to = 25, fromInclusive = false
  1179 + ) final float radius,
  1180 + final boolean recycle) {
  1181 + return fastBlur(context, src, scale, radius, recycle, false);
  1182 + }
  1183 +
  1184 + /**
  1185 + * Return the blur bitmap fast.
  1186 + * <p>zoom out, blur, zoom in</p>
  1187 + *
  1188 + * @param src The source of bitmap.
  1189 + * @param scale The scale(0...1).
  1190 + * @param radius The radius(0...25).
  1191 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1192 + * @param isReturnScale True to return the scale blur bitmap, false otherwise.
  1193 + * @return the blur bitmap
  1194 + */
  1195 + public static Bitmap fastBlur(Context context, final Bitmap src,
  1196 + @FloatRange(
  1197 + from = 0, to = 1, fromInclusive = false
  1198 + ) final float scale,
  1199 + @FloatRange(
  1200 + from = 0, to = 25, fromInclusive = false
  1201 + ) final float radius,
  1202 + final boolean recycle,
  1203 + final boolean isReturnScale) {
  1204 + if (isEmptyBitmap(src)) return null;
  1205 + int width = src.getWidth();
  1206 + int height = src.getHeight();
  1207 + Matrix matrix = new Matrix();
  1208 + matrix.setScale(scale, scale);
  1209 + Bitmap scaleBitmap =
  1210 + Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
  1211 + Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
  1212 + Canvas canvas = new Canvas();
  1213 + PorterDuffColorFilter filter = new PorterDuffColorFilter(
  1214 + Color.TRANSPARENT, PorterDuff.Mode.SRC_ATOP);
  1215 + paint.setColorFilter(filter);
  1216 + canvas.scale(scale, scale);
  1217 + canvas.drawBitmap(scaleBitmap, 0, 0, paint);
  1218 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  1219 + scaleBitmap = renderScriptBlur(context, scaleBitmap, radius, recycle);
  1220 + } else {
  1221 + scaleBitmap = stackBlur(scaleBitmap, (int) radius, recycle);
  1222 + }
  1223 + if (scale == 1 || isReturnScale) {
  1224 + if (recycle && !src.isRecycled() && scaleBitmap != src) src.recycle();
  1225 + return scaleBitmap;
  1226 + }
  1227 + Bitmap ret = Bitmap.createScaledBitmap(scaleBitmap, width, height, true);
  1228 + if (!scaleBitmap.isRecycled()) scaleBitmap.recycle();
  1229 + if (recycle && !src.isRecycled() && ret != src) src.recycle();
  1230 + return ret;
  1231 + }
  1232 +
  1233 + /**
  1234 + * renderScript 模糊图片
  1235 + * Return the blur bitmap using render script.
  1236 + *
  1237 + * @param src The source of bitmap.
  1238 + * @param radius The radius(0...25).
  1239 + * @return the blur bitmap
  1240 + */
  1241 + @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
  1242 + public static Bitmap renderScriptBlur(Context context, final Bitmap src,
  1243 + @FloatRange(
  1244 + from = 0, to = 25, fromInclusive = false
  1245 + ) final float radius) {
  1246 + return renderScriptBlur(context, src, radius, false);
  1247 + }
  1248 +
  1249 + /**
  1250 + * Return the blur bitmap using render script.
  1251 + *
  1252 + * @param src The source of bitmap.
  1253 + * @param radius The radius(0...25).
  1254 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1255 + * @return the blur bitmap
  1256 + */
  1257 + @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
  1258 + public static Bitmap renderScriptBlur(Context context, final Bitmap src,
  1259 + @FloatRange(
  1260 + from = 0, to = 25, fromInclusive = false
  1261 + ) final float radius,
  1262 + final boolean recycle) {
  1263 + RenderScript rs = null;
  1264 + Bitmap ret = recycle ? src : src.copy(src.getConfig(), true);
  1265 + try {
  1266 + rs = RenderScript.create(context);
  1267 + rs.setMessageHandler(new RenderScript.RSMessageHandler());
  1268 + Allocation input = Allocation.createFromBitmap(rs,
  1269 + ret,
  1270 + Allocation.MipmapControl.MIPMAP_NONE,
  1271 + Allocation.USAGE_SCRIPT);
  1272 + Allocation output = Allocation.createTyped(rs, input.getType());
  1273 + ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
  1274 + blurScript.setInput(input);
  1275 + blurScript.setRadius(radius);
  1276 + blurScript.forEach(output);
  1277 + output.copyTo(ret);
  1278 + } finally {
  1279 + if (rs != null) {
  1280 + rs.destroy();
  1281 + }
  1282 + }
  1283 + return ret;
  1284 + }
  1285 +
  1286 + /**
  1287 + * stack 模糊图片
  1288 + * Return the blur bitmap using stack.
  1289 + *
  1290 + * @param src The source of bitmap.
  1291 + * @param radius The radius(0...25).
  1292 + * @return the blur bitmap
  1293 + */
  1294 + public static Bitmap stackBlur(final Bitmap src, final int radius) {
  1295 + return stackBlur(src, radius, false);
  1296 + }
  1297 +
  1298 + /**
  1299 + * Return the blur bitmap using stack.
  1300 + *
  1301 + * @param src The source of bitmap.
  1302 + * @param radius The radius(0...25).
  1303 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1304 + * @return the blur bitmap
  1305 + */
  1306 + public static Bitmap stackBlur(final Bitmap src, int radius, final boolean recycle) {
  1307 + Bitmap ret = recycle ? src : src.copy(src.getConfig(), true);
  1308 + if (radius < 1) {
  1309 + radius = 1;
  1310 + }
  1311 + int w = ret.getWidth();
  1312 + int h = ret.getHeight();
  1313 +
  1314 + int[] pix = new int[w * h];
  1315 + ret.getPixels(pix, 0, w, 0, 0, w, h);
  1316 +
  1317 + int wm = w - 1;
  1318 + int hm = h - 1;
  1319 + int wh = w * h;
  1320 + int div = radius + radius + 1;
  1321 +
  1322 + int r[] = new int[wh];
  1323 + int g[] = new int[wh];
  1324 + int b[] = new int[wh];
  1325 + int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
  1326 + int vmin[] = new int[Math.max(w, h)];
  1327 +
  1328 + int divsum = (div + 1) >> 1;
  1329 + divsum *= divsum;
  1330 + int dv[] = new int[256 * divsum];
  1331 + for (i = 0; i < 256 * divsum; i++) {
  1332 + dv[i] = (i / divsum);
  1333 + }
  1334 +
  1335 + yw = yi = 0;
  1336 +
  1337 + int[][] stack = new int[div][3];
  1338 + int stackpointer;
  1339 + int stackstart;
  1340 + int[] sir;
  1341 + int rbs;
  1342 + int r1 = radius + 1;
  1343 + int routsum, goutsum, boutsum;
  1344 + int rinsum, ginsum, binsum;
  1345 +
  1346 + for (y = 0; y < h; y++) {
  1347 + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
  1348 + for (i = -radius; i <= radius; i++) {
  1349 + p = pix[yi + Math.min(wm, Math.max(i, 0))];
  1350 + sir = stack[i + radius];
  1351 + sir[0] = (p & 0xff0000) >> 16;
  1352 + sir[1] = (p & 0x00ff00) >> 8;
  1353 + sir[2] = (p & 0x0000ff);
  1354 + rbs = r1 - Math.abs(i);
  1355 + rsum += sir[0] * rbs;
  1356 + gsum += sir[1] * rbs;
  1357 + bsum += sir[2] * rbs;
  1358 + if (i > 0) {
  1359 + rinsum += sir[0];
  1360 + ginsum += sir[1];
  1361 + binsum += sir[2];
  1362 + } else {
  1363 + routsum += sir[0];
  1364 + goutsum += sir[1];
  1365 + boutsum += sir[2];
  1366 + }
  1367 + }
  1368 + stackpointer = radius;
  1369 +
  1370 + for (x = 0; x < w; x++) {
  1371 +
  1372 + r[yi] = dv[rsum];
  1373 + g[yi] = dv[gsum];
  1374 + b[yi] = dv[bsum];
  1375 +
  1376 + rsum -= routsum;
  1377 + gsum -= goutsum;
  1378 + bsum -= boutsum;
  1379 +
  1380 + stackstart = stackpointer - radius + div;
  1381 + sir = stack[stackstart % div];
  1382 +
  1383 + routsum -= sir[0];
  1384 + goutsum -= sir[1];
  1385 + boutsum -= sir[2];
  1386 +
  1387 + if (y == 0) {
  1388 + vmin[x] = Math.min(x + radius + 1, wm);
  1389 + }
  1390 + p = pix[yw + vmin[x]];
  1391 +
  1392 + sir[0] = (p & 0xff0000) >> 16;
  1393 + sir[1] = (p & 0x00ff00) >> 8;
  1394 + sir[2] = (p & 0x0000ff);
  1395 +
  1396 + rinsum += sir[0];
  1397 + ginsum += sir[1];
  1398 + binsum += sir[2];
  1399 +
  1400 + rsum += rinsum;
  1401 + gsum += ginsum;
  1402 + bsum += binsum;
  1403 +
  1404 + stackpointer = (stackpointer + 1) % div;
  1405 + sir = stack[(stackpointer) % div];
  1406 +
  1407 + routsum += sir[0];
  1408 + goutsum += sir[1];
  1409 + boutsum += sir[2];
  1410 +
  1411 + rinsum -= sir[0];
  1412 + ginsum -= sir[1];
  1413 + binsum -= sir[2];
  1414 +
  1415 + yi++;
  1416 + }
  1417 + yw += w;
  1418 + }
  1419 + for (x = 0; x < w; x++) {
  1420 + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
  1421 + yp = -radius * w;
  1422 + for (i = -radius; i <= radius; i++) {
  1423 + yi = Math.max(0, yp) + x;
  1424 +
  1425 + sir = stack[i + radius];
  1426 +
  1427 + sir[0] = r[yi];
  1428 + sir[1] = g[yi];
  1429 + sir[2] = b[yi];
  1430 +
  1431 + rbs = r1 - Math.abs(i);
  1432 +
  1433 + rsum += r[yi] * rbs;
  1434 + gsum += g[yi] * rbs;
  1435 + bsum += b[yi] * rbs;
  1436 +
  1437 + if (i > 0) {
  1438 + rinsum += sir[0];
  1439 + ginsum += sir[1];
  1440 + binsum += sir[2];
  1441 + } else {
  1442 + routsum += sir[0];
  1443 + goutsum += sir[1];
  1444 + boutsum += sir[2];
  1445 + }
  1446 +
  1447 + if (i < hm) {
  1448 + yp += w;
  1449 + }
  1450 + }
  1451 + yi = x;
  1452 + stackpointer = radius;
  1453 + for (y = 0; y < h; y++) {
  1454 + // Preserve alpha channel: ( 0xff000000 & pix[yi] )
  1455 + pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
  1456 +
  1457 + rsum -= routsum;
  1458 + gsum -= goutsum;
  1459 + bsum -= boutsum;
  1460 +
  1461 + stackstart = stackpointer - radius + div;
  1462 + sir = stack[stackstart % div];
  1463 +
  1464 + routsum -= sir[0];
  1465 + goutsum -= sir[1];
  1466 + boutsum -= sir[2];
  1467 +
  1468 + if (x == 0) {
  1469 + vmin[y] = Math.min(y + r1, hm) * w;
  1470 + }
  1471 + p = x + vmin[y];
  1472 +
  1473 + sir[0] = r[p];
  1474 + sir[1] = g[p];
  1475 + sir[2] = b[p];
  1476 +
  1477 + rinsum += sir[0];
  1478 + ginsum += sir[1];
  1479 + binsum += sir[2];
  1480 +
  1481 + rsum += rinsum;
  1482 + gsum += ginsum;
  1483 + bsum += binsum;
  1484 +
  1485 + stackpointer = (stackpointer + 1) % div;
  1486 + sir = stack[stackpointer];
  1487 +
  1488 + routsum += sir[0];
  1489 + goutsum += sir[1];
  1490 + boutsum += sir[2];
  1491 +
  1492 + rinsum -= sir[0];
  1493 + ginsum -= sir[1];
  1494 + binsum -= sir[2];
  1495 +
  1496 + yi += w;
  1497 + }
  1498 + }
  1499 + ret.setPixels(pix, 0, w, 0, 0, w, h);
  1500 + return ret;
  1501 + }
  1502 +
  1503 + /**
  1504 + * Save the bitmap.
  1505 + *
  1506 + * @param src The source of bitmap.
  1507 + * @param filePath The path of file.
  1508 + * @param format The format of the image.
  1509 + * @return {@code true}: success<br>{@code false}: fail
  1510 + */
  1511 + public static boolean save(final Bitmap src,
  1512 + final String filePath,
  1513 + final CompressFormat format) {
  1514 + return save(src, getFileByPath(filePath), format, false);
  1515 + }
  1516 +
  1517 + /**
  1518 + * Save the bitmap.
  1519 + *
  1520 + * @param src The source of bitmap.
  1521 + * @param file The file.
  1522 + * @param format The format of the image.
  1523 + * @return {@code true}: success<br>{@code false}: fail
  1524 + */
  1525 + public static boolean save(final Bitmap src, final File file, final CompressFormat format) {
  1526 + return save(src, file, format, false);
  1527 + }
  1528 +
  1529 + /**
  1530 + * Save the bitmap.
  1531 + *
  1532 + * @param src The source of bitmap.
  1533 + * @param filePath The path of file.
  1534 + * @param format The format of the image.
  1535 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1536 + * @return {@code true}: success<br>{@code false}: fail
  1537 + */
  1538 + public static boolean save(final Bitmap src,
  1539 + final String filePath,
  1540 + final CompressFormat format,
  1541 + final boolean recycle) {
  1542 + return save(src, getFileByPath(filePath), format, recycle);
  1543 + }
  1544 +
  1545 + /**
  1546 + * Save the bitmap.
  1547 + *
  1548 + * @param src The source of bitmap.
  1549 + * @param file The file.
  1550 + * @param format The format of the image.
  1551 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1552 + * @return {@code true}: success<br>{@code false}: fail
  1553 + */
  1554 + public static boolean save(final Bitmap src,
  1555 + final File file,
  1556 + final CompressFormat format,
  1557 + final boolean recycle) {
  1558 + if (isEmptyBitmap(src) || !createFileByDeleteOldFile(file)) return false;
  1559 + OutputStream os = null;
  1560 + boolean ret = false;
  1561 + try {
  1562 + os = new BufferedOutputStream(new FileOutputStream(file));
  1563 + ret = src.compress(format, 100, os);
  1564 + if (recycle && !src.isRecycled()) src.recycle();
  1565 + } catch (IOException e) {
  1566 + e.printStackTrace();
  1567 + } finally {
  1568 + try {
  1569 + if (os != null) {
  1570 + os.close();
  1571 + }
  1572 + } catch (IOException e) {
  1573 + e.printStackTrace();
  1574 + }
  1575 + }
  1576 + return ret;
  1577 + }
  1578 +
  1579 + /**
  1580 + * Return whether it is a image according to the file name.
  1581 + *
  1582 + * @param file The file.//todo android q
  1583 + * @return {@code true}: yes<br>{@code false}: no
  1584 + */
  1585 + public static boolean isImage(final File file) {
  1586 + if (file == null || !file.exists()) {
  1587 + return false;
  1588 + }
  1589 + return isImage(file.getPath());
  1590 + }
  1591 +
  1592 + /**
  1593 + * Return whether it is a image according to the file name.
  1594 + *
  1595 + * @param filePath The path of file.
  1596 + * @return {@code true}: yes<br>{@code false}: no
  1597 + */
  1598 + public static boolean isImage(final String filePath) {
  1599 + BitmapFactory.Options options = new BitmapFactory.Options();
  1600 + options.inJustDecodeBounds = true;
  1601 + try {
  1602 + Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
  1603 + return options.outWidth != -1 && options.outHeight != -1;
  1604 + } catch (Exception e) {
  1605 + return false;
  1606 + }
  1607 + }
  1608 +
  1609 + /**
  1610 + * Return the type of image.//todo android Q
  1611 + *
  1612 + * @param filePath The
  1613 + * path of
  1614 + * file .
  1615 + * @return the type
  1616 + * of image
  1617 + */
  1618 +
  1619 + public static ImageType getImageType(final String filePath) {
  1620 + return getImageType(getFileByPath(filePath));
  1621 + }
  1622 +
  1623 + /**
  1624 + * Return the type of image.
  1625 + *
  1626 + * @param file The file.
  1627 + * @return the type of image
  1628 + */
  1629 + public static ImageType getImageType(final File file) {
  1630 + if (file == null) return null;
  1631 + InputStream is = null;
  1632 + try {
  1633 + is = new FileInputStream(file);
  1634 + ImageType type = getImageType(is);
  1635 + if (type != null) {
  1636 + return type;
  1637 + }
  1638 + } catch (IOException e) {
  1639 + e.printStackTrace();
  1640 + } finally {
  1641 + try {
  1642 + if (is != null) {
  1643 + is.close();
  1644 + }
  1645 + } catch (IOException e) {
  1646 + e.printStackTrace();
  1647 + }
  1648 + }
  1649 + return null;
  1650 + }
  1651 +
  1652 + private static ImageType getImageType(final InputStream is) {
  1653 + if (is == null) return null;
  1654 + try {
  1655 + byte[] bytes = new byte[12];
  1656 + return is.read(bytes) != -1 ? getImageType(bytes) : null;
  1657 + } catch (IOException e) {
  1658 + e.printStackTrace();
  1659 + return null;
  1660 + }
  1661 + }
  1662 +
  1663 + private static ImageType getImageType(final byte[] bytes) {
  1664 + String type = bytes2HexString(bytes).toUpperCase();
  1665 + if (type.contains("FFD8FF")) {
  1666 + return ImageType.TYPE_JPG;
  1667 + } else if (type.contains("89504E47")) {
  1668 + return ImageType.TYPE_PNG;
  1669 + } else if (type.contains("47494638")) {
  1670 + return ImageType.TYPE_GIF;
  1671 + } else if (type.contains("49492A00") || type.contains("4D4D002A")) {
  1672 + return ImageType.TYPE_TIFF;
  1673 + } else if (type.contains("424D")) {
  1674 + return ImageType.TYPE_BMP;
  1675 + } else if (type.startsWith("52494646") && type.endsWith("57454250")) {//524946461c57000057454250-12个字节
  1676 + return ImageType.TYPE_WEBP;
  1677 + } else if (type.contains("00000100") || type.contains("00000200")) {
  1678 + return ImageType.TYPE_ICO;
  1679 + } else {
  1680 + return ImageType.TYPE_UNKNOWN;
  1681 + }
  1682 + }
  1683 +
  1684 + private static final char[] hexDigits =
  1685 + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  1686 +
  1687 + private static String bytes2HexString(final byte[] bytes) {
  1688 + if (bytes == null) return "";
  1689 + int len = bytes.length;
  1690 + if (len <= 0) return "";
  1691 + char[] ret = new char[len << 1];
  1692 + for (int i = 0, j = 0; i < len; i++) {
  1693 + ret[j++] = hexDigits[bytes[i] >> 4 & 0x0f];
  1694 + ret[j++] = hexDigits[bytes[i] & 0x0f];
  1695 + }
  1696 + return new String(ret);
  1697 + }
  1698 +
  1699 +
  1700 + private static boolean isJPEG(final byte[] b) {
  1701 + return b.length >= 2
  1702 + && (b[0] == (byte) 0xFF) && (b[1] == (byte) 0xD8);
  1703 + }
  1704 +
  1705 + private static boolean isGIF(final byte[] b) {
  1706 + return b.length >= 6
  1707 + && b[0] == 'G' && b[1] == 'I'
  1708 + && b[2] == 'F' && b[3] == '8'
  1709 + && (b[4] == '7' || b[4] == '9') && b[5] == 'a';
  1710 + }
  1711 +
  1712 + private static boolean isPNG(final byte[] b) {
  1713 + return b.length >= 8
  1714 + && (b[0] == (byte) 137 && b[1] == (byte) 80
  1715 + && b[2] == (byte) 78 && b[3] == (byte) 71
  1716 + && b[4] == (byte) 13 && b[5] == (byte) 10
  1717 + && b[6] == (byte) 26 && b[7] == (byte) 10);
  1718 + }
  1719 +
  1720 + private static boolean isBMP(final byte[] b) {
  1721 + return b.length >= 2
  1722 + && (b[0] == 0x42) && (b[1] == 0x4d);
  1723 + }
  1724 +
  1725 + private static boolean isEmptyBitmap(final Bitmap src) {
  1726 + return src == null || src.getWidth() == 0 || src.getHeight() == 0;
  1727 + }
  1728 +
  1729 + ///////////////////////////////////////////////////////////////////////////
  1730 + // about compress
  1731 + ///////////////////////////////////////////////////////////////////////////
  1732 +
  1733 + /**
  1734 + * 按缩放压缩
  1735 + * Return the compressed bitmap using scale.
  1736 + *
  1737 + * @param src The source of bitmap.
  1738 + * @param newWidth The new width.
  1739 + * @param newHeight The new height.
  1740 + * @return the compressed bitmap
  1741 + */
  1742 + public static Bitmap compressByScale(final Bitmap src,
  1743 + final int newWidth,
  1744 + final int newHeight) {
  1745 + return scale(src, newWidth, newHeight, false);
  1746 + }
  1747 +
  1748 + /**
  1749 + * Return the compressed bitmap using scale.
  1750 + *
  1751 + * @param src The source of bitmap.
  1752 + * @param newWidth The new width.
  1753 + * @param newHeight The new height.
  1754 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1755 + * @return the compressed bitmap
  1756 + */
  1757 + public static Bitmap compressByScale(final Bitmap src,
  1758 + final int newWidth,
  1759 + final int newHeight,
  1760 + final boolean recycle) {
  1761 + return scale(src, newWidth, newHeight, recycle);
  1762 + }
  1763 +
  1764 + /**
  1765 + * Return the compressed bitmap using scale.
  1766 + *
  1767 + * @param src The source of bitmap.
  1768 + * @param scaleWidth The scale of width.
  1769 + * @param scaleHeight The scale of height.
  1770 + * @return the compressed bitmap
  1771 + */
  1772 + public static Bitmap compressByScale(final Bitmap src,
  1773 + final float scaleWidth,
  1774 + final float scaleHeight) {
  1775 + return scale(src, scaleWidth, scaleHeight, false);
  1776 + }
  1777 +
  1778 + /**
  1779 + * Return the compressed bitmap using scale.
  1780 + *
  1781 + * @param src The source of bitmap.
  1782 + * @param scaleWidth The scale of width.
  1783 + * @param scaleHeight The scale of height.
  1784 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1785 + * @return he compressed bitmap
  1786 + */
  1787 + public static Bitmap compressByScale(final Bitmap src,
  1788 + final float scaleWidth,
  1789 + final float scaleHeight,
  1790 + final boolean recycle) {
  1791 + return scale(src, scaleWidth, scaleHeight, recycle);
  1792 + }
  1793 +
  1794 + /**
  1795 + * 按质量压缩
  1796 + * Return the compressed bitmap using quality.
  1797 + *
  1798 + * @param src The source of bitmap.
  1799 + * @param quality The quality.
  1800 + * @return the compressed bitmap
  1801 + */
  1802 + public static Bitmap compressByQuality(final Bitmap src,
  1803 + @IntRange(from = 0, to = 100) final int quality) {
  1804 + return compressByQuality(src, quality, false);
  1805 + }
  1806 +
  1807 + /**
  1808 + * Return the compressed bitmap using quality.
  1809 + *
  1810 + * @param src The source of bitmap.
  1811 + * @param quality The quality.
  1812 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1813 + * @return the compressed bitmap
  1814 + */
  1815 + public static Bitmap compressByQuality(final Bitmap src,
  1816 + @IntRange(from = 0, to = 100) final int quality,
  1817 + final boolean recycle) {
  1818 + if (isEmptyBitmap(src)) return null;
  1819 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  1820 + src.compress(CompressFormat.JPEG, quality, baos);
  1821 + byte[] bytes = baos.toByteArray();
  1822 + if (recycle && !src.isRecycled()) src.recycle();
  1823 + return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
  1824 + }
  1825 +
  1826 + /**
  1827 + * Return the compressed bitmap using quality.
  1828 + *
  1829 + * @param src The source of bitmap.
  1830 + * @param maxByteSize The maximum size of byte.
  1831 + * @return the compressed bitmap
  1832 + */
  1833 + public static Bitmap compressByQuality(final Bitmap src, final long maxByteSize) {
  1834 + return compressByQuality(src, maxByteSize, false);
  1835 + }
  1836 +
  1837 + /**
  1838 + * Return the compressed bitmap using quality.
  1839 + *
  1840 + * @param src The source of bitmap.
  1841 + * @param maxByteSize The maximum size of byte.
  1842 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1843 + * @return the compressed bitmap
  1844 + */
  1845 + public static Bitmap compressByQuality(final Bitmap src,
  1846 + final long maxByteSize,
  1847 + final boolean recycle) {
  1848 + if (isEmptyBitmap(src) || maxByteSize <= 0) return null;
  1849 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  1850 + src.compress(CompressFormat.JPEG, 100, baos);
  1851 + byte[] bytes;
  1852 + if (baos.size() <= maxByteSize) {
  1853 + bytes = baos.toByteArray();
  1854 + } else {
  1855 + baos.reset();
  1856 + src.compress(CompressFormat.JPEG, 0, baos);
  1857 + if (baos.size() >= maxByteSize) {
  1858 + bytes = baos.toByteArray();
  1859 + } else {
  1860 + // find the best quality using binary search
  1861 + int st = 0;
  1862 + int end = 100;
  1863 + int mid = 0;
  1864 + while (st < end) {
  1865 + mid = (st + end) / 2;
  1866 + baos.reset();
  1867 + src.compress(CompressFormat.JPEG, mid, baos);
  1868 + int len = baos.size();
  1869 + if (len == maxByteSize) {
  1870 + break;
  1871 + } else if (len > maxByteSize) {
  1872 + end = mid - 1;
  1873 + } else {
  1874 + st = mid + 1;
  1875 + }
  1876 + }
  1877 + if (end == mid - 1) {
  1878 + baos.reset();
  1879 + src.compress(CompressFormat.JPEG, st, baos);
  1880 + }
  1881 + bytes = baos.toByteArray();
  1882 + }
  1883 + }
  1884 + if (recycle && !src.isRecycled()) src.recycle();
  1885 + return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
  1886 + }
  1887 +
  1888 + /**
  1889 + * 按采样大小压缩
  1890 + * Return the compressed bitmap using sample size.
  1891 + *
  1892 + * @param src The source of bitmap.
  1893 + * @param sampleSize The sample size.
  1894 + * @return the compressed bitmap
  1895 + */
  1896 +
  1897 + public static Bitmap compressBySampleSize(final Bitmap src, final int sampleSize) {
  1898 + return compressBySampleSize(src, sampleSize, false);
  1899 + }
  1900 +
  1901 + /**
  1902 + * Return the compressed bitmap using sample size.
  1903 + *
  1904 + * @param src The source of bitmap.
  1905 + * @param sampleSize The sample size.
  1906 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1907 + * @return the compressed bitmap
  1908 + */
  1909 + public static Bitmap compressBySampleSize(final Bitmap src,
  1910 + final int sampleSize,
  1911 + final boolean recycle) {
  1912 + if (isEmptyBitmap(src)) return null;
  1913 + BitmapFactory.Options options = new BitmapFactory.Options();
  1914 + options.inSampleSize = sampleSize;
  1915 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  1916 + src.compress(CompressFormat.JPEG, 100, baos);
  1917 + byte[] bytes = baos.toByteArray();
  1918 + if (recycle && !src.isRecycled()) src.recycle();
  1919 + return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
  1920 + }
  1921 +
  1922 + /**
  1923 + * Return the compressed bitmap using sample size.
  1924 + *
  1925 + * @param src The source of bitmap.
  1926 + * @param maxWidth The maximum width.
  1927 + * @param maxHeight The maximum height.
  1928 + * @return the compressed bitmap
  1929 + */
  1930 + public static Bitmap compressBySampleSize(final Bitmap src,
  1931 + final int maxWidth,
  1932 + final int maxHeight) {
  1933 + return compressBySampleSize(src, maxWidth, maxHeight, false);
  1934 + }
  1935 +
  1936 + /**
  1937 + * Return the compressed bitmap using sample size.
  1938 + *
  1939 + * @param src The source of bitmap.
  1940 + * @param maxWidth The maximum width.
  1941 + * @param maxHeight The maximum height.
  1942 + * @param recycle True to recycle the source of bitmap, false otherwise.
  1943 + * @return the compressed bitmap
  1944 + */
  1945 + public static Bitmap compressBySampleSize(final Bitmap src,
  1946 + final int maxWidth,
  1947 + final int maxHeight,
  1948 + final boolean recycle) {
  1949 + if (isEmptyBitmap(src)) return null;
  1950 + BitmapFactory.Options options = new BitmapFactory.Options();
  1951 + options.inJustDecodeBounds = true;
  1952 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  1953 + src.compress(CompressFormat.JPEG, 100, baos);
  1954 + byte[] bytes = baos.toByteArray();
  1955 + BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
  1956 + options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
  1957 + options.inJustDecodeBounds = false;
  1958 + if (recycle && !src.isRecycled()) src.recycle();
  1959 + return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
  1960 + }
  1961 +
  1962 + /**
  1963 + * Return the size of bitmap.
  1964 + *
  1965 + * @param filePath The path of file.
  1966 + * @return the size of bitmap
  1967 + */
  1968 + public static int[] getSize(String filePath) {
  1969 + return getSize(getFileByPath(filePath));
  1970 + }
  1971 +
  1972 + /**
  1973 + * Return the size of bitmap.
  1974 + *
  1975 + * @param file The file.
  1976 + * @return the size of bitmap
  1977 + */
  1978 + public static int[] getSize(File file) {
  1979 + if (file == null) return new int[]{0, 0};
  1980 + BitmapFactory.Options opts = new BitmapFactory.Options();
  1981 + opts.inJustDecodeBounds = true;
  1982 + BitmapFactory.decodeFile(file.getAbsolutePath(), opts);
  1983 + return new int[]{opts.outWidth, opts.outHeight};
  1984 + }
  1985 +
  1986 + /**
  1987 + * Return the sample size.
  1988 + *
  1989 + * @param options The options.
  1990 + * @param maxWidth The maximum width.
  1991 + * @param maxHeight The maximum height.
  1992 + * @return the sample size
  1993 + */
  1994 + private static int calculateInSampleSize(final BitmapFactory.Options options,
  1995 + final int maxWidth,
  1996 + final int maxHeight) {
  1997 + int height = options.outHeight;
  1998 + int width = options.outWidth;
  1999 + int inSampleSize = 1;
  2000 + while (height > maxHeight || width > maxWidth) {
  2001 + height >>= 1;
  2002 + width >>= 1;
  2003 + inSampleSize <<= 1;
  2004 + }
  2005 + return inSampleSize;
  2006 + }
  2007 +
  2008 + ///////////////////////////////////////////////////////////////////////////
  2009 + // other utils methods
  2010 + ///////////////////////////////////////////////////////////////////////////
  2011 +
  2012 + private static File getFileByPath(final String filePath) {
  2013 + return isSpace(filePath) ? null : new File(filePath);
  2014 + }
  2015 +
  2016 + private static boolean createFileByDeleteOldFile(final File file) {
  2017 + if (file == null) return false;
  2018 + if (file.exists() && !file.delete()) return false;
  2019 + if (!createOrExistsDir(file.getParentFile())) return false;
  2020 + try {
  2021 + return file.createNewFile();
  2022 + } catch (IOException e) {
  2023 + e.printStackTrace();
  2024 + return false;
  2025 + }
  2026 + }
  2027 +
  2028 + private static boolean createOrExistsDir(final File file) {
  2029 + return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
  2030 + }
  2031 +
  2032 + private static boolean isSpace(final String s) {
  2033 + if (s == null) return true;
  2034 + for (int i = 0, len = s.length(); i < len; ++i) {
  2035 + if (!Character.isWhitespace(s.charAt(i))) {
  2036 + return false;
  2037 + }
  2038 + }
  2039 + return true;
  2040 + }
  2041 +
  2042 + private static byte[] input2Byte(final InputStream is) {
  2043 + if (is == null) return null;
  2044 + try {
  2045 + ByteArrayOutputStream os = new ByteArrayOutputStream();
  2046 + byte[] b = new byte[1024];
  2047 + int len;
  2048 + while ((len = is.read(b, 0, 1024)) != -1) {
  2049 + os.write(b, 0, len);
  2050 + }
  2051 + return os.toByteArray();
  2052 + } catch (IOException e) {
  2053 + e.printStackTrace();
  2054 + return null;
  2055 + } finally {
  2056 + try {
  2057 + is.close();
  2058 + } catch (IOException e) {
  2059 + e.printStackTrace();
  2060 + }
  2061 + }
  2062 + }
  2063 +
  2064 + public enum ImageType {
  2065 + TYPE_JPG("jpg"),
  2066 +
  2067 + TYPE_PNG("png"),
  2068 +
  2069 + TYPE_GIF("gif"),
  2070 +
  2071 + TYPE_TIFF("tiff"),
  2072 +
  2073 + TYPE_BMP("bmp"),
  2074 +
  2075 + TYPE_WEBP("webp"),
  2076 +
  2077 + TYPE_ICO("ico"),
  2078 +
  2079 + TYPE_UNKNOWN("unknown");
  2080 +
  2081 + String value;
  2082 +
  2083 + ImageType(String value) {
  2084 + this.value = value;
  2085 + }
  2086 +
  2087 + public String getValue() {
  2088 + return value;
  2089 + }
  2090 + }
  2091 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/JumpParameter.java deleted 100644 → 0
1   -package com.cnlive.core.libs.base.util;
2   -
3   -import java.util.HashMap;
4   -import java.util.Map;
5   -
6   -/**
7   - * @Version: 6.7.0
8   - * @Author: Kongzue
9   - * @github: https://github.com/kongzue/BaseFramework
10   - * @link: http://kongzue.com/
11   - * @describe: 自动化代码流水线作业,以及对原生安卓、MIUI、flyme的透明状态栏显示灰色图标文字的支持,同时提供一些小工具简化开发难度,详细说明文档:https://github.com/kongzue/BaseFramework
12   - */
13   -
14   -public class JumpParameter {
15   -
16   - private Map<String, Object> datas;
17   -
18   - public JumpParameter put(String key, Object value) {
19   - if (datas == null) {
20   - datas = new HashMap<>();
21   - }
22   - datas.put(key, value);
23   - return this;
24   - }
25   -
26   - public JumpParameter cleanAll() {
27   - datas = new HashMap<>();
28   - return this;
29   - }
30   -
31   - public Object get(String key) {
32   - if (datas == null) {
33   - return null;
34   - }
35   - return datas.get(key);
36   - }
37   -
38   - public boolean getBoolean(String key) {
39   - if (datas == null || datas.get(key) == null) {
40   - return false;
41   - }
42   - return (boolean) datas.get(key);
43   - }
44   -
45   - public boolean getBoolean(String key, boolean defaultValue) {
46   - if (datas == null || datas.get(key) == null) {
47   - return defaultValue;
48   - }
49   - return (boolean) datas.get(key);
50   - }
51   -
52   - public int getInt(String key) {
53   - if (datas == null || datas.get(key) == null) {
54   - return 0;
55   - }
56   - return (int) datas.get(key);
57   - }
58   -
59   - public int getInt(String key, int defaultValue) {
60   - if (datas == null || datas.get(key) == null) {
61   - return defaultValue;
62   - }
63   - return (int) datas.get(key);
64   - }
65   -
66   - public String getString(String key) {
67   - if (datas == null || datas.get(key) == null) {
68   - return "";
69   - }
70   - return (String) datas.get(key);
71   - }
72   -
73   - public String getString(String key, String defaultValue) {
74   - if (datas == null || datas.get(key) == null) {
75   - return defaultValue;
76   - }
77   - return (String) datas.get(key);
78   - }
79   -
80   - public double getDouble(String key) {
81   - if (datas == null || datas.get(key) == null) {
82   - return 0;
83   - }
84   - return (double) datas.get(key);
85   - }
86   -
87   - public double getDouble(String key, double defaultValue) {
88   - if (datas == null || datas.get(key) == null) {
89   - return defaultValue;
90   - }
91   - return (double) datas.get(key);
92   - }
93   -
94   - public long getLong(String key) {
95   - if (datas == null || datas.get(key) == null) {
96   - return 0;
97   - }
98   - return (long) datas.get(key);
99   - }
100   -
101   - public long getLong(String key, long defaultValue) {
102   - if (datas == null || datas.get(key) == null) {
103   - return defaultValue;
104   - }
105   - return (long) datas.get(key);
106   - }
107   -
108   - public short getShort(String key) {
109   - if (datas == null || datas.get(key) == null) {
110   - return 0;
111   - }
112   - return (short) datas.get(key);
113   - }
114   -
115   - public short getShort(String key, short defaultValue) {
116   - if (datas == null || datas.get(key) == null) {
117   - return defaultValue;
118   - }
119   - return (short) datas.get(key);
120   - }
121   -
122   - public float getFloat(String key) {
123   - if (datas == null || datas.get(key) == null) {
124   - return 0;
125   - }
126   - return (float) datas.get(key);
127   - }
128   -
129   - public float getFloat(String key, float defaultValue) {
130   - if (datas == null || datas.get(key) == null) {
131   - return defaultValue;
132   - }
133   - return (float) datas.get(key);
134   - }
135   -
136   - public Map<String, Object> getAll() {
137   - return datas;
138   - }
139   -}
core/base/src/main/java/com/cnlive/core/libs/base/util/KeyboardUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Context;
  5 +import android.content.ContextWrapper;
  6 +import android.content.res.Resources;
  7 +import android.graphics.Rect;
  8 +import android.os.Bundle;
  9 +import android.os.Handler;
  10 +import android.os.ResultReceiver;
  11 +import android.util.Log;
  12 +import android.view.View;
  13 +import android.view.ViewGroup;
  14 +import android.view.ViewTreeObserver.OnGlobalLayoutListener;
  15 +import android.view.Window;
  16 +import android.view.WindowManager;
  17 +import android.view.inputmethod.InputMethodManager;
  18 +import android.widget.EditText;
  19 +import android.widget.FrameLayout;
  20 +
  21 +import androidx.annotation.NonNull;
  22 +
  23 +/**
  24 + * <pre>
  25 + * author: Blankj
  26 + * blog : http://blankj.com
  27 + * time : 2016/08/02
  28 + * desc : utils about keyboard
  29 + * </pre>
  30 + * showSoftInput : 显示软键盘
  31 + * hideSoftInput : 隐藏软键盘
  32 + * toggleSoftInput : 切换键盘显示与否状态
  33 + * isSoftInputVisible : 判断软键盘是否可见
  34 + * registerSoftInputChangedListener : 注册软键盘改变监听器
  35 + * unregisterSoftInputChangedListener: 注销软键盘改变监听器
  36 + * fixAndroidBug5497 : 修复安卓 5497 BUG
  37 + * fixSoftInputLeaks : 修复软键盘内存泄漏
  38 + * clickBlankArea2HideSoftInput : 点击屏幕空白区域隐藏软键盘
  39 + */
  40 +public final class KeyboardUtils {
  41 +
  42 + private KeyboardUtils() {
  43 + throw new UnsupportedOperationException("u can't instantiate me...");
  44 + }
  45 +
  46 + /**
  47 + * Show the soft input.
  48 + */
  49 + public static void showSoftInput(@NonNull Activity activity) {
  50 + if (!isSoftInputVisible(activity)) {
  51 + toggleSoftInput(activity);
  52 + }
  53 + }
  54 +
  55 + /**
  56 + * Show the soft input.
  57 + *
  58 + * @param view The view.
  59 + */
  60 + public static void showSoftInput(Context context,@NonNull final View view) {
  61 + showSoftInput(context,view, 0);
  62 + }
  63 +
  64 + /**
  65 + * Show the soft input.
  66 + *
  67 + * @param view The view.
  68 + * @param flags Provides additional operating flags. Currently may be
  69 + * 0 or have the {@link InputMethodManager#SHOW_IMPLICIT} bit set.
  70 + */
  71 + public static void showSoftInput(Context context,@NonNull final View view, final int flags) {
  72 + InputMethodManager imm =
  73 + (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
  74 + if (imm == null) return;
  75 + view.setFocusable(true);
  76 + view.setFocusableInTouchMode(true);
  77 + view.requestFocus();
  78 + imm.showSoftInput(view, flags, new ResultReceiver(new Handler()) {
  79 + @Override
  80 + protected void onReceiveResult(int resultCode, Bundle resultData) {
  81 + if (resultCode == InputMethodManager.RESULT_UNCHANGED_HIDDEN
  82 + || resultCode == InputMethodManager.RESULT_HIDDEN) {
  83 + toggleSoftInput(context);
  84 + }
  85 + }
  86 + });
  87 + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
  88 + }
  89 +
  90 + /**
  91 + * Hide the soft input.
  92 + *
  93 + * @param activity The activity.
  94 + */
  95 + public static void hideSoftInput(@NonNull final Activity activity) {
  96 + View view = activity.getCurrentFocus();
  97 + if (view == null) {
  98 + View decorView = activity.getWindow().getDecorView();
  99 + View focusView = decorView.findViewWithTag("keyboardTagView");
  100 + if (focusView == null) {
  101 + view = new EditText(activity);
  102 + view.setTag("keyboardTagView");
  103 + ((ViewGroup) decorView).addView(view, 0, 0);
  104 + } else {
  105 + view = focusView;
  106 + }
  107 + view.requestFocus();
  108 + }
  109 + hideSoftInput(activity,view);
  110 + }
  111 +
  112 + /**
  113 + * Hide the soft input.
  114 + *
  115 + * @param view The view.
  116 + */
  117 + public static void hideSoftInput(Context context,@NonNull final View view) {
  118 + InputMethodManager imm =
  119 + (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
  120 + if (imm == null) return;
  121 + imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
  122 + }
  123 +
  124 + /**
  125 + * Togg切换键盘显示与否状态le the soft input display or not.
  126 + */
  127 + public static void toggleSoftInput(Context context) {
  128 + InputMethodManager imm =
  129 + (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
  130 + if (imm == null) return;
  131 + imm.toggleSoftInput(0, 0);
  132 + }
  133 +
  134 + private static int sDecorViewDelta = 0;
  135 +
  136 + /**
  137 + * Return whether soft input is visible.
  138 + *
  139 + * @param activity The activity.
  140 + * @return {@code true}: yes<br>{@code false}: no
  141 + */
  142 + public static boolean isSoftInputVisible(@NonNull final Activity activity) {
  143 + return getDecorViewInvisibleHeight(activity,activity.getWindow()) > 0;
  144 + }
  145 +
  146 + private static int getDecorViewInvisibleHeight(Context context,@NonNull final Window window) {
  147 + final View decorView = window.getDecorView();
  148 + if (decorView == null) return 0;
  149 + final Rect outRect = new Rect();
  150 + decorView.getWindowVisibleDisplayFrame(outRect);
  151 + Log.d("KeyboardUtils", "getDecorViewInvisibleHeight: "
  152 + + (decorView.getBottom() - outRect.bottom));
  153 + int delta = Math.abs(decorView.getBottom() - outRect.bottom);
  154 + if (delta <= getNavBarHeight(context) + getStatusBarHeight(context)) {
  155 + sDecorViewDelta = delta;
  156 + return 0;
  157 + }
  158 + return delta - sDecorViewDelta;
  159 + }
  160 +
  161 + /**
  162 + * Register soft input changed listener.
  163 + *
  164 + * @param activity The activity.
  165 + * @param listener The soft input changed listener.
  166 + */
  167 + public static void registerSoftInputChangedListener(@NonNull final Activity activity,
  168 + @NonNull final OnSoftInputChangedListener listener) {
  169 + registerSoftInputChangedListener(activity, listener);
  170 + }
  171 +
  172 + /**
  173 + * Register soft input changed listener.
  174 + *
  175 + * @param window The window.
  176 + * @param listener The soft input changed listener.
  177 + */
  178 + public static void registerSoftInputChangedListener(Context context,@NonNull final Window window,
  179 + @NonNull final OnSoftInputChangedListener listener) {
  180 + final int flags = window.getAttributes().flags;
  181 + if ((flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) != 0) {
  182 + window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  183 + }
  184 + final FrameLayout contentView = window.findViewById(android.R.id.content);
  185 + final int[] decorViewInvisibleHeightPre = {getDecorViewInvisibleHeight(context,window)};
  186 + contentView.getViewTreeObserver()
  187 + .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  188 + @Override
  189 + public void onGlobalLayout() {
  190 + int height = getDecorViewInvisibleHeight(context,window);
  191 + if (decorViewInvisibleHeightPre[0] != height) {
  192 + listener.onSoftInputChanged(height);
  193 + decorViewInvisibleHeightPre[0] = height;
  194 + }
  195 + }
  196 + });
  197 + }
  198 +
  199 + /**
  200 + * Fix the bug of 5497 in Android.
  201 + * <p>Don't set adjustResize</p>
  202 + *
  203 + * @param activity The activity.
  204 + */
  205 + public static void fixAndroidBug5497(Context context,@NonNull final Activity activity) {
  206 + fixAndroidBug5497(context,activity.getWindow());
  207 + }
  208 +
  209 + /**
  210 + * Fix the bug of 5497 in Android.
  211 + * <p>Don't set adjustResize</p>
  212 + *
  213 + * @param window The window.
  214 + */
  215 + public static void fixAndroidBug5497(Context context,@NonNull final Window window) {
  216 +// int softInputMode = window.getAttributes().softInputMode;
  217 +// window.setSoftInputMode(softInputMode & ~WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
  218 + final FrameLayout contentView = window.findViewById(android.R.id.content);
  219 + final View contentViewChild = contentView.getChildAt(0);
  220 + final int paddingBottom = contentViewChild.getPaddingBottom();
  221 + final int[] contentViewInvisibleHeightPre5497 = {getContentViewInvisibleHeight(context,window)};
  222 + contentView.getViewTreeObserver()
  223 + .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  224 + @Override
  225 + public void onGlobalLayout() {
  226 + int height = getContentViewInvisibleHeight(context,window);
  227 + if (contentViewInvisibleHeightPre5497[0] != height) {
  228 + contentViewChild.setPadding(
  229 + contentViewChild.getPaddingLeft(),
  230 + contentViewChild.getPaddingTop(),
  231 + contentViewChild.getPaddingRight(),
  232 + paddingBottom + getDecorViewInvisibleHeight(context,window)
  233 + );
  234 + contentViewInvisibleHeightPre5497[0] = height;
  235 + }
  236 + }
  237 + });
  238 + }
  239 +
  240 + private static int getContentViewInvisibleHeight(Context context,final Window window) {
  241 + final View contentView = window.findViewById(android.R.id.content);
  242 + if (contentView == null) return 0;
  243 + final Rect outRect = new Rect();
  244 + contentView.getWindowVisibleDisplayFrame(outRect);
  245 + Log.d("KeyboardUtils", "getContentViewInvisibleHeight: "
  246 + + (contentView.getBottom() - outRect.bottom));
  247 + int delta = Math.abs(contentView.getBottom() - outRect.bottom);
  248 + if (delta <= getStatusBarHeight(context) + getNavBarHeight(context)) {
  249 + return 0;
  250 + }
  251 + return delta;
  252 + }
  253 +//
  254 +// /**
  255 +// * Fix the leaks of soft input.
  256 +// *
  257 +// * @param activity The activity.
  258 +// */
  259 +// public static void fixSoftInputLeaks(@NonNull final Activity activity) {
  260 +// fixSoftInputLeaks(activity.getWindow());
  261 +// }
  262 +
  263 +// /**
  264 +// * Fix the leaks of soft input.
  265 +// *
  266 +// * @param window The window.
  267 +// */
  268 +// public static void fixSoftInputLeaks(@NonNull final Window window) {
  269 +// Utils.fixSoftInputLeaks(window);
  270 +// }
  271 +
  272 + /**
  273 + * Click blank area to hide soft input.
  274 + * <p>Copy the following code in ur activity.</p>
  275 + */
  276 + public static void clickBlankArea2HideSoftInput() {
  277 + Log.i("KeyboardUtils", "Please refer to the following code.");
  278 + /*
  279 + @Override
  280 + public boolean dispatchTouchEvent(MotionEvent ev) {
  281 + if (ev.getAction() == MotionEvent.ACTION_DOWN) {
  282 + View v = getCurrentFocus();
  283 + if (isShouldHideKeyboard(v, ev)) {
  284 + KeyboardUtils.hideSoftInput(this);
  285 + }
  286 + }
  287 + return super.dispatchTouchEvent(ev);
  288 + }
  289 +
  290 + // Return whether touch the view.
  291 + private boolean isShouldHideKeyboard(View v, MotionEvent event) {
  292 + if (v != null && (v instanceof EditText)) {
  293 + int[] l = {0, 0};
  294 + v.getLocationInWindow(l);
  295 + int left = l[0],
  296 + top = l[1],
  297 + bottom = top + v.getHeight(),
  298 + right = left + v.getWidth();
  299 + return !(event.getX() > left && event.getX() < right
  300 + && event.getY() > top && event.getY() < bottom);
  301 + }
  302 + return false;
  303 + }
  304 + */
  305 + }
  306 +
  307 + private static int getStatusBarHeight(Context context) {
  308 + Resources resources =context.getResources();
  309 + int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
  310 + return resources.getDimensionPixelSize(resourceId);
  311 + }
  312 +
  313 + private static int getNavBarHeight(Context context) {
  314 + Resources res = context.getResources();
  315 + int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
  316 + if (resourceId != 0) {
  317 + return res.getDimensionPixelSize(resourceId);
  318 + } else {
  319 + return 0;
  320 + }
  321 + }
  322 +///////////////////////////////////////////////////////////////////////////
  323 +// interface
  324 +///////////////////////////////////////////////////////////////////////////
  325 +
  326 + public interface OnSoftInputChangedListener {
  327 + void onSoftInputChanged(int height);
  328 + }
  329 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/LogUtil.java deleted 100644 → 0
1   -package com.cnlive.core.libs.base.util;
2   -
3   -import android.util.Log;
4   -
5   -import com.cnlive.core.libs.base.application.AppConfig;
6   -
7   -public class LogUtil {
8   - private static boolean ENABLED = AppConfig.isDebug();
9   -
10   - public LogUtil() {
11   - }
12   -
13   - public static void setDebug(boolean debug) {
14   - ENABLED = debug;
15   - }
16   -
17   - public static void e(String tag, String msg) {
18   - if (ENABLED) {
19   - Log.e(tag, msg);
20   - }
21   -
22   - }
23   -
24   - public static void e(String tag, String msg, Throwable tr) {
25   - if (ENABLED) {
26   - Log.e(tag, msg, tr);
27   - }
28   -
29   - }
30   -
31   - public static void d(String tag, String msg) {
32   - if (ENABLED) {
33   - Log.d(tag, msg);
34   - }
35   -
36   - }
37   -
38   - public static void d(String tag, String msg, Throwable tr) {
39   - if (ENABLED) {
40   - Log.d(tag, msg, tr);
41   - }
42   -
43   - }
44   -}
core/base/src/main/java/com/cnlive/core/libs/base/util/MetaDataUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import android.app.Activity;
  4 +import android.app.Service;
  5 +import android.content.BroadcastReceiver;
  6 +import android.content.ComponentName;
  7 +import android.content.Context;
  8 +import android.content.pm.ActivityInfo;
  9 +import android.content.pm.ApplicationInfo;
  10 +import android.content.pm.PackageManager;
  11 +import android.content.pm.ServiceInfo;
  12 +
  13 +import androidx.annotation.NonNull;
  14 +
  15 +/**
  16 + * MetaData 相关
  17 + * <pre>
  18 + * author: Blankj
  19 + * blog : http://blankj.com
  20 + * time : 2018/05/15
  21 + * desc : utils about meta-data
  22 + * </pre>
  23 + * getMetaDataInApp : 获取 application 的 meta-data 值
  24 + * getMetaDataInActivity: 获取 activity 的 meta-data 值
  25 + * getMetaDataInService : 获取 service 的 meta-data 值
  26 + * getMetaDataInReceiver: 获取 receiver 的 meta-data 值
  27 + */
  28 +public final class MetaDataUtils {
  29 +
  30 + private MetaDataUtils() {
  31 + throw new UnsupportedOperationException("u can't instantiate me...");
  32 + }
  33 +
  34 + /**
  35 + * 获取 application 的 meta-data 值
  36 + * Return the value of meta-data in application.
  37 + *
  38 + * @param key The key of meta-data.
  39 + * @return the value of meta-data in application
  40 + */
  41 + public static String getMetaDataInApp(Context context, @NonNull final String key) {
  42 + String value = "";
  43 + PackageManager pm = context.getPackageManager();
  44 + String packageName = context.getPackageName();
  45 + try {
  46 + ApplicationInfo ai = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
  47 + value = String.valueOf(ai.metaData.get(key));
  48 + } catch (PackageManager.NameNotFoundException e) {
  49 + e.printStackTrace();
  50 + }
  51 + return value;
  52 + }
  53 +
  54 + /**
  55 + * Return the value of meta-data in activity.
  56 + *
  57 + * @param activity The activity.
  58 + * @param key The key of meta-data.
  59 + * @return the value of meta-data in activity
  60 + */
  61 + public static String getMetaDataInActivity(@NonNull final Activity activity,
  62 + @NonNull final String key) {
  63 + return getMetaDataInActivity(activity, activity.getClass(), key);
  64 + }
  65 +
  66 + /**
  67 + * 获取 activity 的 meta-data 值
  68 + * Return the value of meta-data in activity.
  69 + *
  70 + * @param clz The activity class.
  71 + * @param key The key of meta-data.
  72 + * @return the value of meta-data in activity
  73 + */
  74 + public static String getMetaDataInActivity(Context context, @NonNull final Class<? extends Activity> clz,
  75 + @NonNull final String key) {
  76 + String value = "";
  77 + PackageManager pm = context.getPackageManager();
  78 + ComponentName componentName = new ComponentName(context, clz);
  79 + try {
  80 + ActivityInfo ai = pm.getActivityInfo(componentName, PackageManager.GET_META_DATA);
  81 + value = String.valueOf(ai.metaData.get(key));
  82 + } catch (PackageManager.NameNotFoundException e) {
  83 + e.printStackTrace();
  84 + }
  85 + return value;
  86 + }
  87 +
  88 + /**
  89 + * Return the value of meta-data in service.
  90 + *
  91 + * @param service The service.
  92 + * @param key The key of meta-data.
  93 + * @return the value of meta-data in service
  94 + */
  95 + public static String getMetaDataInService(Context context, @NonNull final Service service,
  96 + @NonNull final String key) {
  97 + return getMetaDataInService(context, service.getClass(), key);
  98 + }
  99 +
  100 + /**
  101 + * 获取 service 的 meta-data 值
  102 + * Return the value of meta-data in service.
  103 + *
  104 + * @param clz The service class.
  105 + * @param key The key of meta-data.
  106 + * @return the value of meta-data in service
  107 + */
  108 + public static String getMetaDataInService(Context context, @NonNull final Class<? extends Service> clz,
  109 + @NonNull final String key) {
  110 + String value = "";
  111 + PackageManager pm = context.getPackageManager();
  112 + ComponentName componentName = new ComponentName(context, clz);
  113 + try {
  114 + ServiceInfo info = pm.getServiceInfo(componentName, PackageManager.GET_META_DATA);
  115 + value = String.valueOf(info.metaData.get(key));
  116 + } catch (PackageManager.NameNotFoundException e) {
  117 + e.printStackTrace();
  118 + }
  119 + return value;
  120 + }
  121 +
  122 + /**
  123 + * Return the value of meta-data in receiver.
  124 + *
  125 + * @param receiver The receiver.
  126 + * @param key The key of meta-data.
  127 + * @return the value of meta-data in receiver
  128 + */
  129 + public static String getMetaDataInReceiver(@NonNull final BroadcastReceiver receiver,
  130 + @NonNull final String key) {
  131 + return getMetaDataInReceiver(receiver, key);
  132 + }
  133 +
  134 + /**
  135 + * Return the value of meta-data in receiver.
  136 + *
  137 + * @param clz The receiver class.
  138 + * @param key The key of meta-data.
  139 + * @return the value of meta-data in receiver
  140 + */
  141 + public static String getMetaDataInReceiver(Context context, @NonNull final Class<? extends BroadcastReceiver> clz,
  142 + @NonNull final String key) {
  143 + String value = "";
  144 + PackageManager pm = context.getPackageManager();
  145 + ComponentName componentName = new ComponentName(context, clz);
  146 + try {
  147 + ActivityInfo info = pm.getReceiverInfo(componentName, PackageManager.GET_META_DATA);
  148 + value = String.valueOf(info.metaData.get(key));
  149 + } catch (PackageManager.NameNotFoundException e) {
  150 + e.printStackTrace();
  151 + }
  152 + return value;
  153 + }
  154 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/NetworkUtil.java
1 1 package com.cnlive.core.libs.base.util;
2 2  
3 3 import android.content.Context;
  4 +import android.content.Intent;
4 5 import android.net.ConnectivityManager;
5 6 import android.net.NetworkInfo;
  7 +import android.telephony.TelephonyManager;
  8 +
  9 +import java.util.ArrayList;
  10 +import java.util.List;
6 11  
7 12 public class NetworkUtil {
8 13  
  14 + private NetworkUtil() {
  15 + throw new UnsupportedOperationException("u can't instance me...");
  16 + }
  17 +
  18 + public static final int NETWORK_WIFI = 1; // wifi network
  19 + public static final int NETWORK_4G = 4; // "4G" networks
  20 + public static final int NETWORK_3G = 3; // "3G" networks
  21 + public static final int NETWORK_2G = 2; // "2G" networks
  22 + public static final int NETWORK_UNKNOWN = 5; // unknown network
  23 + public static final int NETWORK_NO = -1; // no network
  24 +
  25 + private static final int NETWORK_TYPE_GSM = 16;
  26 + private static final int NETWORK_TYPE_TD_SCDMA = 17;
  27 + private static final int NETWORK_TYPE_IWLAN = 18;
  28 +
  29 + public static List<String> typeList = new ArrayList<>();
  30 +
  31 + static {
  32 + typeList.add("打开网络设置界面");
  33 + typeList.add("获取活动网络信息");
  34 + typeList.add("判断网络是否可用");
  35 + typeList.add("判断网络是否是4G");
  36 + typeList.add("判断wifi是否连接状态");
  37 + typeList.add("获取移动网络运营商名称");
  38 + typeList.add("获取当前的网络类型");
  39 + typeList.add("获取当前的网络类型(WIFI,2G,3G,4G)");
  40 +
  41 +
  42 + }
  43 +
  44 + /**
  45 + * 打开网络设置界面
  46 + * <p>3.0以下打开设置界面</p>
  47 + *
  48 + * @param context 上下文
  49 + */
  50 + public static void openWirelessSettings(Context context) {
  51 + if (android.os.Build.VERSION.SDK_INT > 10) {
  52 + context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
  53 + } else {
  54 + context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
  55 + }
  56 + }
  57 +
  58 + /**
  59 + * 获取活动网络信息
  60 + *
  61 + * @param context 上下文
  62 + * @return NetworkInfo
  63 + */
  64 + public static NetworkInfo getActiveNetworkInfo(Context context) {
  65 + ConnectivityManager cm = (ConnectivityManager) context
  66 + .getSystemService(Context.CONNECTIVITY_SERVICE);
  67 + return cm.getActiveNetworkInfo();
  68 + }
  69 +
  70 + /**
  71 + * 判断网络是否可用
  72 + * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
  73 + *
  74 + * @param context 上下文
  75 + * @return {@code true}: 可用<br>{@code false}: 不可用
  76 + */
  77 + public static boolean isAvailable(Context context) {
  78 + NetworkInfo info = getActiveNetworkInfo(context);
  79 + return info != null && info.isAvailable();
  80 + }
  81 +
  82 + /**
  83 + * 判断网络是否连接
  84 + * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
  85 + *
  86 + * @param context 上下文
  87 + * @return {@code true}: 是<br>{@code false}: 否
  88 + */
9 89 public static boolean isConnectInternet(Context context) {
10 90 if (context == null) return false;
11 91 ConnectivityManager connectManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
... ... @@ -16,4 +96,162 @@ public class NetworkUtil {
16 96 return false;
17 97 }
18 98  
  99 + /**
  100 + * 判断网络是否是4G
  101 + * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
  102 + *
  103 + * @param context 上下文
  104 + * @return {@code true}: 是<br>{@code false}: 不是
  105 + */
  106 + public static boolean is4G(Context context) {
  107 + NetworkInfo info = getActiveNetworkInfo(context);
  108 + return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE;
  109 + }
  110 +
  111 + /**
  112 + * 判断wifi是否连接状态
  113 + * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
  114 + *
  115 + * @param context 上下文
  116 + * @return {@code true}: 连接<br>{@code false}: 未连接
  117 + */
  118 + public static boolean isWifiConnected(Context context) {
  119 + ConnectivityManager cm = (ConnectivityManager) context
  120 + .getSystemService(Context.CONNECTIVITY_SERVICE);
  121 + return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
  122 + }
  123 +
  124 + /**
  125 + * 获取移动网络运营商名称
  126 + * <p>如中国联通、中国移动、中国电信</p>
  127 + *
  128 + * @param context 上下文
  129 + * @return 移动网络运营商名称
  130 + */
  131 + public static String getNetworkOperatorName(Context context) {
  132 + TelephonyManager tm = (TelephonyManager) context
  133 + .getSystemService(Context.TELEPHONY_SERVICE);
  134 + return tm != null ? tm.getNetworkOperatorName() : null;
  135 + }
  136 +
  137 + /**
  138 + * 获取移动终端类型
  139 + *
  140 + * @param context 上下文
  141 + * @return 手机制式
  142 + * <ul>
  143 + * <li>{@link TelephonyManager#PHONE_TYPE_NONE } : 0 手机制式未知</li>
  144 + * <li>{@link TelephonyManager#PHONE_TYPE_GSM } : 1 手机制式为GSM,移动和联通</li>
  145 + * <li>{@link TelephonyManager#PHONE_TYPE_CDMA } : 2 手机制式为CDMA,电信</li>
  146 + * <li>{@link TelephonyManager#PHONE_TYPE_SIP } : 3</li>
  147 + * </ul>
  148 + */
  149 + public static int getPhoneType(Context context) {
  150 + TelephonyManager tm = (TelephonyManager) context
  151 + .getSystemService(Context.TELEPHONY_SERVICE);
  152 + return tm != null ? tm.getPhoneType() : -1;
  153 + }
  154 +
  155 +
  156 + /**
  157 + * 获取当前的网络类型(WIFI,2G,3G,4G)
  158 + * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
  159 + *
  160 + * @param context 上下文
  161 + * @return 网络类型
  162 + * <ul>
  163 + * <li>{@link #NETWORK_WIFI } = 1;</li>
  164 + * <li>{@link #NETWORK_4G } = 4;</li>
  165 + * <li>{@link #NETWORK_3G } = 3;</li>
  166 + * <li>{@link #NETWORK_2G } = 2;</li>
  167 + * <li>{@link #NETWORK_UNKNOWN} = 5;</li>
  168 + * <li>{@link #NETWORK_NO } = -1;</li>
  169 + * </ul>
  170 + */
  171 + public static int getNetWorkType(Context context) {
  172 + int netType = NETWORK_NO;
  173 + NetworkInfo info = getActiveNetworkInfo(context);
  174 + if (info != null && info.isAvailable()) {
  175 +
  176 + if (info.getType() == ConnectivityManager.TYPE_WIFI) {
  177 + netType = NETWORK_WIFI;
  178 + } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
  179 + switch (info.getSubtype()) {
  180 +
  181 + case NETWORK_TYPE_GSM:
  182 + case TelephonyManager.NETWORK_TYPE_GPRS:
  183 + case TelephonyManager.NETWORK_TYPE_CDMA:
  184 + case TelephonyManager.NETWORK_TYPE_EDGE:
  185 + case TelephonyManager.NETWORK_TYPE_1xRTT:
  186 + case TelephonyManager.NETWORK_TYPE_IDEN:
  187 + netType = NETWORK_2G;
  188 + break;
  189 +
  190 + case NETWORK_TYPE_TD_SCDMA:
  191 + case TelephonyManager.NETWORK_TYPE_EVDO_A:
  192 + case TelephonyManager.NETWORK_TYPE_UMTS:
  193 + case TelephonyManager.NETWORK_TYPE_EVDO_0:
  194 + case TelephonyManager.NETWORK_TYPE_HSDPA:
  195 + case TelephonyManager.NETWORK_TYPE_HSUPA:
  196 + case TelephonyManager.NETWORK_TYPE_HSPA:
  197 + case TelephonyManager.NETWORK_TYPE_EVDO_B:
  198 + case TelephonyManager.NETWORK_TYPE_EHRPD:
  199 + case TelephonyManager.NETWORK_TYPE_HSPAP:
  200 + netType = NETWORK_3G;
  201 + break;
  202 +
  203 + case NETWORK_TYPE_IWLAN:
  204 + case TelephonyManager.NETWORK_TYPE_LTE:
  205 + netType = NETWORK_4G;
  206 + break;
  207 + default:
  208 +
  209 + String subtypeName = info.getSubtypeName();
  210 + if (subtypeName.equalsIgnoreCase("TD-SCDMA")
  211 + || subtypeName.equalsIgnoreCase("WCDMA")
  212 + || subtypeName.equalsIgnoreCase("CDMA2000")) {
  213 + netType = NETWORK_3G;
  214 + } else {
  215 + netType = NETWORK_UNKNOWN;
  216 + }
  217 + break;
  218 + }
  219 + } else {
  220 + netType = NETWORK_UNKNOWN;
  221 + }
  222 + }
  223 + return netType;
  224 + }
  225 +
  226 + /**
  227 + * 获取当前的网络类型(WIFI,2G,3G,4G)
  228 + * <p>依赖上面的方法</p>
  229 + *
  230 + * @param context 上下文
  231 + * @return 网络类型名称
  232 + * <ul>
  233 + * <li>NETWORK_WIFI </li>
  234 + * <li>NETWORK_4G </li>
  235 + * <li>NETWORK_3G </li>
  236 + * <li>NETWORK_2G </li>
  237 + * <li>NETWORK_UNKNOWN</li>
  238 + * <li>NETWORK_NO </li>
  239 + * </ul>
  240 + */
  241 + public static String getNetWorkTypeName(Context context) {
  242 + switch (getNetWorkType(context)) {
  243 + case NETWORK_WIFI:
  244 + return "NETWORK_WIFI";
  245 + case NETWORK_4G:
  246 + return "NETWORK_4G";
  247 + case NETWORK_3G:
  248 + return "NETWORK_3G";
  249 + case NETWORK_2G:
  250 + return "NETWORK_2G";
  251 + case NETWORK_NO:
  252 + return "NETWORK_NO";
  253 + default:
  254 + return "NETWORK_UNKNOWN";
  255 + }
  256 + }
19 257 }
20 258 \ No newline at end of file
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/ParameterCache.java deleted 100644 → 0
1   -package com.cnlive.core.libs.base.util;
2   -
3   -import java.util.HashMap;
4   -import java.util.Map;
5   -
6   -/**
7   - * 数据传递的中间人
8   - * 本类负责缓存数据,承担 BaseActivity、BaseFragment 之间数据传输的缓存角色
9   - */
10   -public class ParameterCache {
11   -
12   - private static ParameterCache parameterCache;
13   -
14   - private ParameterCache() {
15   - }
16   -
17   - public static ParameterCache getInstance() {
18   - if (parameterCache == null) {
19   - synchronized (ParameterCache.class) {
20   - if (parameterCache == null) {
21   - parameterCache = new ParameterCache();
22   - }
23   - }
24   - }
25   - return parameterCache;
26   - }
27   -
28   - private Map<String, JumpParameter> parameterList;
29   -
30   - public JumpParameter get(String className) {
31   - if (parameterList == null) {
32   - return null;
33   - }
34   - return parameterList.get(className);
35   - }
36   -
37   - public void set(String className, JumpParameter jumpParameter) {
38   - if (parameterList == null) {
39   - parameterList = new HashMap<>();
40   - }
41   - parameterList.put(className, jumpParameter);
42   - }
43   -
44   -
45   - private Map<String, JumpParameter> parameterResponseList;
46   -
47   - public JumpParameter getResponse(String className) {
48   - if (parameterResponseList == null) {
49   - return null;
50   - }
51   - return parameterResponseList.get(className);
52   - }
53   -
54   - public void setResponse(String className, JumpParameter jumpParameter) {
55   - if (parameterResponseList == null) {
56   - parameterResponseList = new HashMap<>();
57   - }
58   - parameterResponseList.put(className, jumpParameter);
59   - }
60   -
61   - public void cleanResponse(String className) {
62   - if (parameterResponseList == null) {
63   - return;
64   - }
65   - parameterResponseList.put(className, null);
66   - }
67   -
68   - public void cleanParameter(String className) {
69   - if (parameterList == null) {
70   - return;
71   - }
72   - parameterList.put(className, null);
73   - }
74   -}
core/base/src/main/java/com/cnlive/core/libs/base/util/ScreenUtil.java
1 1 package com.cnlive.core.libs.base.util;
2 2  
  3 +import android.app.Activity;
3 4 import android.content.Context;
  5 +import android.content.pm.ActivityInfo;
  6 +import android.content.res.Configuration;
  7 +import android.content.res.Resources;
  8 +import android.graphics.Bitmap;
  9 +import android.graphics.Point;
  10 +import android.util.DisplayMetrics;
  11 +import android.view.Surface;
  12 +import android.view.View;
  13 +import android.view.Window;
4 14 import android.view.WindowManager;
5 15  
  16 +import androidx.annotation.NonNull;
  17 +
6 18 import java.text.DecimalFormat;
7 19  
8 20 /**
9 21 * Created by gujun on 2017/10/14.
  22 + * getScreenWidth : 获取屏幕的宽度(单位:px)
  23 + * getScreenHeight : 获取屏幕的高度(单位:px)
  24 + * getAppScreenWidth : 获取应用屏幕的宽度(单位:px)
  25 + * getAppScreenHeight : 获取应用屏幕的高度(单位:px)
  26 + * getScreenDensity : 获取屏幕密度
  27 + * getScreenDensityDpi: 获取屏幕密度 DPI
  28 + * setFullScreen : 设置屏幕为全屏
  29 + * setNonFullScreen : 设置屏幕为非全屏
  30 + * toggleFullScreen : 切换屏幕为全屏与否状态
  31 + * isFullScreen : 判断屏幕是否为全屏
  32 + * setLandscape : 设置屏幕为横屏
  33 + * setPortrait : 设置屏幕为竖屏
  34 + * isLandscape : 判断是否横屏
  35 + * isPortrait : 判断是否竖屏
  36 + * getScreenRotation : 获取屏幕旋转角度
  37 + * screenShot : 截屏
  38 + * isScreenLock : 判断是否锁屏
  39 + * setSleepDuration : 设置进入休眠时长
  40 + * getSleepDuration : 获取进入休眠时长
10 41 */
11 42  
12 43 public class ScreenUtil {
... ... @@ -46,4 +77,211 @@ public class ScreenUtil {
46 77 DecimalFormat decimalFormat = new DecimalFormat("0.0000");
47 78 return (int) (Float.parseFloat(decimalFormat.format(num)) * getScreenHeight(context));
48 79 }
  80 +
  81 +
  82 + /**
  83 + * 获取应用屏幕的宽度(单位:px)
  84 + * Return the application's width of screen, in pixel.
  85 + *
  86 + * @return the application's width of screen, in pixel
  87 + */
  88 + public static int getAppScreenWidth(Context context) {
  89 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  90 + if (wm == null) return -1;
  91 + Point point = new Point();
  92 + wm.getDefaultDisplay().getSize(point);
  93 + return point.x;
  94 + }
  95 +
  96 + /**
  97 + * 获取应用屏幕的高度(单位:px)
  98 + * Return the application's height of screen, in pixel.
  99 + *
  100 + * @return the application's height of screen, in pixel
  101 + */
  102 + public static int getAppScreenHeight(Context context) {
  103 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  104 + if (wm == null) return -1;
  105 + Point point = new Point();
  106 + wm.getDefaultDisplay().getSize(point);
  107 + return point.y;
  108 + }
  109 +
  110 + /**
  111 + * 获取屏幕密度
  112 + * Return the density of screen.
  113 + *
  114 + * @return the density of screen
  115 + */
  116 + public static float getScreenDensity(Context context) {
  117 + return context.getResources().getDisplayMetrics().density;
  118 + }
  119 +
  120 + /**
  121 + * 获取屏幕密度 DPI
  122 + * Return the screen density expressed as dots-per-inch.
  123 + *
  124 + * @return the screen density expressed as dots-per-inch
  125 + */
  126 + public static int getScreenDensityDpi(Context context) {
  127 + return context.getResources().getDisplayMetrics().densityDpi;
  128 + }
  129 +
  130 + /**
  131 + * 设置屏幕为全屏
  132 + * Set full screen.
  133 + *
  134 + * @param activity The activity.
  135 + */
  136 + public static void setFullScreen(@NonNull final Activity activity) {
  137 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  138 + }
  139 +
  140 + /**
  141 + * 设置屏幕为非全屏
  142 + * Set non full screen.
  143 + *
  144 + * @param activity The activity.
  145 + */
  146 + public static void setNonFullScreen(@NonNull final Activity activity) {
  147 + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  148 + }
  149 +
  150 + /**
  151 + * 切换屏幕为全屏与否状态
  152 + * Toggle full screen.
  153 + *
  154 + * @param activity The activity.
  155 + */
  156 + public static void toggleFullScreen(@NonNull final Activity activity) {
  157 + boolean isFullScreen = isFullScreen(activity);
  158 + Window window = activity.getWindow();
  159 + if (isFullScreen) {
  160 + window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  161 + } else {
  162 + window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  163 + }
  164 + }
  165 +
  166 + /**
  167 + * Return whether screen is full.
  168 + *
  169 + * @param activity The activity.
  170 + * @return {@code true}: yes<br>{@code false}: no
  171 + */
  172 + public static boolean isFullScreen(@NonNull final Activity activity) {
  173 + int fullScreenFlag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
  174 + return (activity.getWindow().getAttributes().flags & fullScreenFlag) == fullScreenFlag;
  175 + }
  176 +
  177 +
  178 + /**
  179 + * 设置屏幕为横屏
  180 + * Set the screen to landscape.
  181 + *
  182 + * @param activity The activity.
  183 + */
  184 + public static void setLandscape(@NonNull final Activity activity) {
  185 + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
  186 + }
  187 +
  188 + /**
  189 + * 设置屏幕为竖屏
  190 + * Set the screen to portrait.
  191 + *
  192 + * @param activity The activity.
  193 + */
  194 + public static void setPortrait(@NonNull final Activity activity) {
  195 + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  196 + }
  197 +
  198 +
  199 + /**
  200 + * 是否横屏
  201 + * Return whether screen is landscape.
  202 + *
  203 + * @return {@code true}: yes<br>{@code false}: no
  204 + */
  205 + public static boolean isLandscape(Context context) {
  206 + return context.getResources().getConfiguration().orientation
  207 + == Configuration.ORIENTATION_LANDSCAPE;
  208 + }
  209 +
  210 + /**
  211 + * 是否竖屏
  212 + * Return whether screen is portrait.
  213 + *
  214 + * @return {@code true}: yes<br>{@code false}: no
  215 + */
  216 + public static boolean isPortrait(Context context) {
  217 + return context.getResources().getConfiguration().orientation
  218 + == Configuration.ORIENTATION_PORTRAIT;
  219 + }
  220 +
  221 + /**
  222 + * 获取屏幕旋转角度
  223 + * Return the rotation of screen.
  224 + *
  225 + * @param activity The activity.
  226 + * @return the rotation of screen
  227 + */
  228 + public static int getScreenRotation(@NonNull final Activity activity) {
  229 + switch (activity.getWindowManager().getDefaultDisplay().getRotation()) {
  230 + case Surface.ROTATION_0:
  231 + return 0;
  232 + case Surface.ROTATION_90:
  233 + return 90;
  234 + case Surface.ROTATION_180:
  235 + return 180;
  236 + case Surface.ROTATION_270:
  237 + return 270;
  238 + default:
  239 + return 0;
  240 + }
  241 + }
  242 +
  243 + /**
  244 + * 截屏
  245 + * Return the bitmap of screen.
  246 + *
  247 + * @param activity The activity.
  248 + * @return the bitmap of screen
  249 + */
  250 + public static Bitmap screenShot(@NonNull final Activity activity) {
  251 + return screenShot(activity, false);
  252 + }
  253 +
  254 + /**
  255 + * Return the bitmap of screen.
  256 + *
  257 + * @param activity The activity.
  258 + * @param isDeleteStatusBar True to delete status bar, false otherwise.
  259 + * @return the bitmap of screen
  260 + */
  261 + public static Bitmap screenShot(@NonNull final Activity activity, boolean isDeleteStatusBar) {
  262 + View decorView = activity.getWindow().getDecorView();
  263 + decorView.setDrawingCacheEnabled(true);
  264 + decorView.setWillNotCacheDrawing(false);
  265 + Bitmap bmp = decorView.getDrawingCache();
  266 + if (bmp == null) return null;
  267 + DisplayMetrics dm = new DisplayMetrics();
  268 + activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
  269 + Bitmap ret;
  270 + if (isDeleteStatusBar) {
  271 + Resources resources = activity.getResources();
  272 + int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
  273 + int statusBarHeight = resources.getDimensionPixelSize(resourceId);
  274 + ret = Bitmap.createBitmap(
  275 + bmp,
  276 + 0,
  277 + statusBarHeight,
  278 + dm.widthPixels,
  279 + dm.heightPixels - statusBarHeight
  280 + );
  281 + } else {
  282 + ret = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels);
  283 + }
  284 + decorView.destroyDrawingCache();
  285 + return ret;
  286 + }
49 287 }
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/StatusBarConfig.java
1 1 package com.cnlive.core.libs.base.util;
2 2  
  3 +import androidx.annotation.IntDef;
  4 +
  5 +import java.lang.annotation.ElementType;
  6 +import java.lang.annotation.Retention;
  7 +import java.lang.annotation.RetentionPolicy;
  8 +import java.lang.annotation.Target;
  9 +
3 10 public class StatusBarConfig {
4 11 public static final int WHITE = 0;//白色
5 12 public static final int BLACK = 1;//黑色
  13 +
  14 + @IntDef({WHITE, BLACK})
  15 + @Retention(RetentionPolicy.SOURCE)
  16 + public @interface Unit {
  17 + }
6 18 }
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/StringUtils.java
... ... @@ -43,6 +43,98 @@ public class StringUtils {
43 43 private static final double MB = 1048576.0;
44 44 private static final double GB = 1073741824.0;
45 45  
  46 + /**
  47 + * 反转字符串
  48 + * Reverse the string.
  49 + *
  50 + * @param s The string.
  51 + * @return the reverse string.
  52 + */
  53 + public static String reverse(final String s) {
  54 + if (s == null) return "";
  55 + int len = s.length();
  56 + if (len <= 1) return s;
  57 + int mid = len >> 1;
  58 + char[] chars = s.toCharArray();
  59 + char c;
  60 + for (int i = 0; i < mid; ++i) {
  61 + c = chars[i];
  62 + chars[i] = chars[len - i - 1];
  63 + chars[len - i - 1] = c;
  64 + }
  65 + return new String(chars);
  66 + }
  67 +
  68 + /**
  69 + * 转化为半角字符
  70 + * Convert string to DBC.
  71 + *
  72 + * @param s The string.
  73 + * @return the DBC string
  74 + */
  75 + public static String toDBC(final String s) {
  76 + if (s == null || s.length() == 0) return "";
  77 + char[] chars = s.toCharArray();
  78 + for (int i = 0, len = chars.length; i < len; i++) {
  79 + if (chars[i] == 12288) {
  80 + chars[i] = ' ';
  81 + } else if (65281 <= chars[i] && chars[i] <= 65374) {
  82 + chars[i] = (char) (chars[i] - 65248);
  83 + } else {
  84 + chars[i] = chars[i];
  85 + }
  86 + }
  87 + return new String(chars);
  88 + }
  89 +
  90 + /**
  91 + * 转化为全角字符
  92 + * Convert string to SBC.
  93 + *
  94 + * @param s The string.
  95 + * @return the SBC string
  96 + */
  97 + public static String toSBC(final String s) {
  98 + if (s == null || s.length() == 0) return "";
  99 + char[] chars = s.toCharArray();
  100 + for (int i = 0, len = chars.length; i < len; i++) {
  101 + if (chars[i] == ' ') {
  102 + chars[i] = (char) 12288;
  103 + } else if (33 <= chars[i] && chars[i] <= 126) {
  104 + chars[i] = (char) (chars[i] + 65248);
  105 + } else {
  106 + chars[i] = chars[i];
  107 + }
  108 + }
  109 + return new String(chars);
  110 + }
  111 +
  112 + /**
  113 + * 首字母小写
  114 + * Set the first letter of string lower.
  115 + *
  116 + * @param s The string.
  117 + * @return the string with first letter lower.
  118 + */
  119 + public static String lowerFirstLetter(final String s) {
  120 + if (s == null || s.length() == 0) return "";
  121 + if (!Character.isUpperCase(s.charAt(0))) return s;
  122 + return String.valueOf((char) (s.charAt(0) + 32)) + s.substring(1);
  123 + }
  124 +
  125 + /**
  126 + * 首字母大写
  127 + * Set the first letter of string upper.
  128 + *
  129 + * @param s The string.
  130 + * @return the string with first letter upper.
  131 + */
  132 + public static String upperFirstLetter(final String s) {
  133 + if (s == null || s.length() == 0) return "";
  134 + if (!Character.isLowerCase(s.charAt(0))) return s;
  135 + return String.valueOf((char) (s.charAt(0) - 32)) + s.substring(1);
  136 + }
  137 +
46 138 public static String currentTimeString() {
47 139 return DATE_FORMAT_PART.format(Calendar.getInstance().getTime());
48 140 }
... ... @@ -282,6 +374,7 @@ public class StringUtils {
282 374 public static String substring(String search, String start, String end) {
283 375 return substring(search, start, end, "");
284 376 }
  377 +
285 378 /**
286 379 * 拼接字符串
287 380 *
... ... @@ -502,7 +595,6 @@ public class StringUtils {
502 595 }
503 596  
504 597  
505   -
506 598 /**
507 599 * 截取字符串
508 600 *
... ... @@ -528,9 +620,4 @@ public class StringUtils {
528 620 }
529 621  
530 622  
531   -
532   -
533   -
534   -
535   -
536 623 }
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/TimeUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +
  4 +import androidx.annotation.NonNull;
  5 +
  6 +import com.cnlive.core.libs.base.util.constant.TimeConstants;
  7 +
  8 +import java.text.DateFormat;
  9 +import java.text.ParseException;
  10 +import java.text.SimpleDateFormat;
  11 +import java.util.Calendar;
  12 +import java.util.Date;
  13 +import java.util.GregorianCalendar;
  14 +import java.util.Locale;
  15 +
  16 +/**
  17 + * <pre>
  18 + * author: Blankj
  19 + * blog : http://blankj.com
  20 + * time : 2016/08/02
  21 + * desc : utils about time
  22 + * </pre>
  23 + * millis2String : 将时间戳转为时间字符串
  24 + * string2Millis : 将时间字符串转为时间戳
  25 + * string2Date : 将时间字符串转为 Date 类型
  26 + * date2String : 将 Date 类型转为时间字符串
  27 + * date2Millis : 将 Date 类型转为时间戳
  28 + * millis2Date : 将时间戳转为 Date 类型
  29 + * getTimeSpan : 获取两个时间差(单位:unit)
  30 + * getFitTimeSpan : 获取合适型两个时间差
  31 + * getNowMills : 获取当前毫秒时间戳
  32 + * getNowString : 获取当前时间字符串
  33 + * getNowDate : 获取当前 Date
  34 + * getTimeSpanByNow : 获取与当前时间的差(单位:unit)
  35 + * getFitTimeSpanByNow : 获取合适型与当前时间的差
  36 + * getFriendlyTimeSpanByNow: 获取友好型与当前时间的差
  37 + * getMillis : 获取与给定时间等于时间差的时间戳
  38 + * getString : 获取与给定时间等于时间差的时间字符串
  39 + * getDate : 获取与给定时间等于时间差的 Date
  40 + * getMillisByNow : 获取与当前时间等于时间差的时间戳
  41 + * getStringByNow : 获取与当前时间等于时间差的时间字符串
  42 + * getDateByNow : 获取与当前时间等于时间差的 Date
  43 + * isToday : 判断是否今天
  44 + * isLeapYear : 判断是否闰年
  45 + * getChineseWeek : 获取中式星期
  46 + * getUSWeek : 获取美式式星期
  47 + * isAm : 判断是否上午
  48 + * isPm : 判断是否下午
  49 + * getValueByCalendarField : 根据日历字段获取值
  50 + * getChineseZodiac : 获取生肖
  51 + * getZodiac : 获取星座
  52 + */
  53 +public final class TimeUtils {
  54 +
  55 + private static final ThreadLocal<SimpleDateFormat> SDF_THREAD_LOCAL = new ThreadLocal<>();
  56 +
  57 + private static SimpleDateFormat getDefaultFormat() {
  58 + return getDateFormat("yyyy-MM-dd HH:mm:ss");
  59 + }
  60 +
  61 + private static SimpleDateFormat getDateFormat(String pattern) {
  62 + SimpleDateFormat simpleDateFormat = SDF_THREAD_LOCAL.get();
  63 + if (simpleDateFormat == null) {
  64 + simpleDateFormat = new SimpleDateFormat(pattern, Locale.getDefault());
  65 + SDF_THREAD_LOCAL.set(simpleDateFormat);
  66 + } else {
  67 + simpleDateFormat.applyPattern(pattern);
  68 + }
  69 + return simpleDateFormat;
  70 + }
  71 +
  72 + private TimeUtils() {
  73 + throw new UnsupportedOperationException("u can't instantiate me...");
  74 + }
  75 +
  76 + /**
  77 + * 将时间戳转为时间字符串
  78 + * Milliseconds to the formatted time string.
  79 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  80 + *
  81 + * @param millis The milliseconds.
  82 + * @return the formatted time string
  83 + */
  84 + public static String millis2String(final long millis) {
  85 + return millis2String(millis, getDefaultFormat());
  86 + }
  87 +
  88 + /**
  89 + * Milliseconds to the formatted time string.
  90 + *
  91 + * @param millis The milliseconds.
  92 + * @param pattern The pattern of date format, such as yyyy/MM/dd HH:mm
  93 + * @return the formatted time string
  94 + */
  95 + public static String millis2String(long millis, @NonNull final String pattern) {
  96 + return millis2String(millis, getDateFormat(pattern));
  97 + }
  98 +
  99 + /**
  100 + * Milliseconds to the formatted time string.
  101 + *
  102 + * @param millis The milliseconds.
  103 + * @param format The format.
  104 + * @return the formatted time string
  105 + */
  106 + public static String millis2String(final long millis, @NonNull final DateFormat format) {
  107 + return format.format(new Date(millis));
  108 + }
  109 +
  110 + /**
  111 + * 将时间字符串转为时间戳
  112 + * Formatted time string to the milliseconds.
  113 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  114 + *
  115 + * @param time The formatted time string.
  116 + * @return the milliseconds
  117 + */
  118 + public static long string2Millis(final String time) {
  119 + return string2Millis(time, getDefaultFormat());
  120 + }
  121 +
  122 + /**
  123 + * Formatted time string to the milliseconds.
  124 + *
  125 + * @param time The formatted time string.
  126 + * @param pattern The pattern of date format, such as yyyy/MM/dd HH:mm
  127 + * @return the milliseconds
  128 + */
  129 + public static long string2Millis(final String time, @NonNull final String pattern) {
  130 + return string2Millis(time, getDateFormat(pattern));
  131 + }
  132 +
  133 + /**
  134 + * Formatted time string to the milliseconds.
  135 + *
  136 + * @param time The formatted time string.
  137 + * @param format The format.
  138 + * @return the milliseconds
  139 + */
  140 + public static long string2Millis(final String time, @NonNull final DateFormat format) {
  141 + try {
  142 + return format.parse(time).getTime();
  143 + } catch (ParseException e) {
  144 + e.printStackTrace();
  145 + }
  146 + return -1;
  147 + }
  148 +
  149 + /**
  150 + * 将时间字符串转为 Date 类型
  151 + * Formatted time string to the date.
  152 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  153 + *
  154 + * @param time The formatted time string.
  155 + * @return the date
  156 + */
  157 + public static Date string2Date(final String time) {
  158 + return string2Date(time, getDefaultFormat());
  159 + }
  160 +
  161 + /**
  162 + * Formatted time string to the date.
  163 + *
  164 + * @param time The formatted time string.
  165 + * @param pattern The pattern of date format, such as yyyy/MM/dd HH:mm
  166 + * @return the date
  167 + */
  168 + public static Date string2Date(final String time, @NonNull final String pattern) {
  169 + return string2Date(time, getDateFormat(pattern));
  170 + }
  171 +
  172 + /**
  173 + * Formatted time string to the date.
  174 + *
  175 + * @param time The formatted time string.
  176 + * @param format The format.
  177 + * @return the date
  178 + */
  179 + public static Date string2Date(final String time, @NonNull final DateFormat format) {
  180 + try {
  181 + return format.parse(time);
  182 + } catch (ParseException e) {
  183 + e.printStackTrace();
  184 + }
  185 + return null;
  186 + }
  187 +
  188 + /**
  189 + * 将 Date 类型转为时间字符串
  190 + * Date to the formatted time string.
  191 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  192 + *
  193 + * @param date The date.
  194 + * @return the formatted time string
  195 + */
  196 + public static String date2String(final Date date) {
  197 + return date2String(date, getDefaultFormat());
  198 + }
  199 +
  200 + /**
  201 + * Date to the formatted time string.
  202 + *
  203 + * @param date The date.
  204 + * @param pattern The pattern of date format, such as yyyy/MM/dd HH:mm
  205 + * @return the formatted time string
  206 + */
  207 + public static String date2String(final Date date, @NonNull final String pattern) {
  208 + return getDateFormat(pattern).format(date);
  209 + }
  210 +
  211 + /**
  212 + * Date to the formatted time string.
  213 + *
  214 + * @param date The date.
  215 + * @param format The format.
  216 + * @return the formatted time string
  217 + */
  218 + public static String date2String(final Date date, @NonNull final DateFormat format) {
  219 + return format.format(date);
  220 + }
  221 +
  222 + /**
  223 + * 将 Date 类型转为时间戳
  224 + * Date to the milliseconds.
  225 + *
  226 + * @param date The date.
  227 + * @return the milliseconds
  228 + */
  229 + public static long date2Millis(final Date date) {
  230 + return date.getTime();
  231 + }
  232 +
  233 + /**
  234 + * 将时间戳转为 Date 类型
  235 + * Milliseconds to the date.
  236 + *
  237 + * @param millis The milliseconds.
  238 + * @return the date
  239 + */
  240 + public static Date millis2Date(final long millis) {
  241 + return new Date(millis);
  242 + }
  243 +
  244 + /**
  245 + * 获取两个时间差(单位:unit)
  246 + * Return the time span, in unit.
  247 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  248 + *
  249 + * @param time1 The first formatted time string.
  250 + * @param time2 The second formatted time string.
  251 + * @param unit The unit of time span.
  252 + * <ul>
  253 + * <li>{@link TimeConstants#MSEC}</li>
  254 + * <li>{@link TimeConstants#SEC }</li>
  255 + * <li>{@link TimeConstants#MIN }</li>
  256 + * <li>{@link TimeConstants#HOUR}</li>
  257 + * <li>{@link TimeConstants#DAY }</li>
  258 + * </ul>
  259 + * @return the time span, in unit
  260 + */
  261 + public static long getTimeSpan(final String time1,
  262 + final String time2,
  263 + @TimeConstants.Unit final int unit) {
  264 + return getTimeSpan(time1, time2, getDefaultFormat(), unit);
  265 + }
  266 +
  267 + /**
  268 + * Return the time span, in unit.
  269 + *
  270 + * @param time1 The first formatted time string.
  271 + * @param time2 The second formatted time string.
  272 + * @param format The format.
  273 + * @param unit The unit of time span.
  274 + * <ul>
  275 + * <li>{@link TimeConstants#MSEC}</li>
  276 + * <li>{@link TimeConstants#SEC }</li>
  277 + * <li>{@link TimeConstants#MIN }</li>
  278 + * <li>{@link TimeConstants#HOUR}</li>
  279 + * <li>{@link TimeConstants#DAY }</li>
  280 + * </ul>
  281 + * @return the time span, in unit
  282 + */
  283 + public static long getTimeSpan(final String time1,
  284 + final String time2,
  285 + @NonNull final DateFormat format,
  286 + @TimeConstants.Unit final int unit) {
  287 + return millis2TimeSpan(string2Millis(time1, format) - string2Millis(time2, format), unit);
  288 + }
  289 +
  290 + /**
  291 + * Return the time span, in unit.
  292 + *
  293 + * @param date1 The first date.
  294 + * @param date2 The second date.
  295 + * @param unit The unit of time span.
  296 + * <ul>
  297 + * <li>{@link TimeConstants#MSEC}</li>
  298 + * <li>{@link TimeConstants#SEC }</li>
  299 + * <li>{@link TimeConstants#MIN }</li>
  300 + * <li>{@link TimeConstants#HOUR}</li>
  301 + * <li>{@link TimeConstants#DAY }</li>
  302 + * </ul>
  303 + * @return the time span, in unit
  304 + */
  305 + public static long getTimeSpan(final Date date1,
  306 + final Date date2,
  307 + @TimeConstants.Unit final int unit) {
  308 + return millis2TimeSpan(date2Millis(date1) - date2Millis(date2), unit);
  309 + }
  310 +
  311 + /**
  312 + * Return the time span, in unit.
  313 + *
  314 + * @param millis1 The first milliseconds.
  315 + * @param millis2 The second milliseconds.
  316 + * @param unit The unit of time span.
  317 + * <ul>
  318 + * <li>{@link TimeConstants#MSEC}</li>
  319 + * <li>{@link TimeConstants#SEC }</li>
  320 + * <li>{@link TimeConstants#MIN }</li>
  321 + * <li>{@link TimeConstants#HOUR}</li>
  322 + * <li>{@link TimeConstants#DAY }</li>
  323 + * </ul>
  324 + * @return the time span, in unit
  325 + */
  326 + public static long getTimeSpan(final long millis1,
  327 + final long millis2,
  328 + @TimeConstants.Unit final int unit) {
  329 + return millis2TimeSpan(millis1 - millis2, unit);
  330 + }
  331 +
  332 + /**
  333 + * 获取合适型两个时间差
  334 + * Return the fit time span.
  335 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  336 + *
  337 + * @param time1 The first formatted time string.
  338 + * @param time2 The second formatted time string.
  339 + * @param precision The precision of time span.
  340 + * <ul>
  341 + * <li>precision = 0, return null</li>
  342 + * <li>precision = 1, return 天</li>
  343 + * <li>precision = 2, return 天, 小时</li>
  344 + * <li>precision = 3, return 天, 小时, 分钟</li>
  345 + * <li>precision = 4, return 天, 小时, 分钟, 秒</li>
  346 + * <li>precision &gt;= 5,return 天, 小时, 分钟, 秒, 毫秒</li>
  347 + * </ul>
  348 + * @return the fit time span
  349 + */
  350 + public static String getFitTimeSpan(final String time1,
  351 + final String time2,
  352 + final int precision) {
  353 + long delta = string2Millis(time1, getDefaultFormat()) - string2Millis(time2, getDefaultFormat());
  354 + return millis2FitTimeSpan(delta, precision);
  355 + }
  356 +
  357 + /**
  358 + * Return the fit time span.
  359 + *
  360 + * @param time1 The first formatted time string.
  361 + * @param time2 The second formatted time string.
  362 + * @param format The format.
  363 + * @param precision The precision of time span.
  364 + * <ul>
  365 + * <li>precision = 0, return null</li>
  366 + * <li>precision = 1, return 天</li>
  367 + * <li>precision = 2, return 天, 小时</li>
  368 + * <li>precision = 3, return 天, 小时, 分钟</li>
  369 + * <li>precision = 4, return 天, 小时, 分钟, 秒</li>
  370 + * <li>precision &gt;= 5,return 天, 小时, 分钟, 秒, 毫秒</li>
  371 + * </ul>
  372 + * @return the fit time span
  373 + */
  374 + public static String getFitTimeSpan(final String time1,
  375 + final String time2,
  376 + @NonNull final DateFormat format,
  377 + final int precision) {
  378 + long delta = string2Millis(time1, format) - string2Millis(time2, format);
  379 + return millis2FitTimeSpan(delta, precision);
  380 + }
  381 +
  382 + /**
  383 + * Return the fit time span.
  384 + *
  385 + * @param date1 The first date.
  386 + * @param date2 The second date.
  387 + * @param precision The precision of time span.
  388 + * <ul>
  389 + * <li>precision = 0, return null</li>
  390 + * <li>precision = 1, return 天</li>
  391 + * <li>precision = 2, return 天, 小时</li>
  392 + * <li>precision = 3, return 天, 小时, 分钟</li>
  393 + * <li>precision = 4, return 天, 小时, 分钟, 秒</li>
  394 + * <li>precision &gt;= 5,return 天, 小时, 分钟, 秒, 毫秒</li>
  395 + * </ul>
  396 + * @return the fit time span
  397 + */
  398 + public static String getFitTimeSpan(final Date date1, final Date date2, final int precision) {
  399 + return millis2FitTimeSpan(date2Millis(date1) - date2Millis(date2), precision);
  400 + }
  401 +
  402 + /**
  403 + * Return the fit time span.
  404 + *
  405 + * @param millis1 The first milliseconds.
  406 + * @param millis2 The second milliseconds.
  407 + * @param precision The precision of time span.
  408 + * <ul>
  409 + * <li>precision = 0, return null</li>
  410 + * <li>precision = 1, return 天</li>
  411 + * <li>precision = 2, return 天, 小时</li>
  412 + * <li>precision = 3, return 天, 小时, 分钟</li>
  413 + * <li>precision = 4, return 天, 小时, 分钟, 秒</li>
  414 + * <li>precision &gt;= 5,return 天, 小时, 分钟, 秒, 毫秒</li>
  415 + * </ul>
  416 + * @return the fit time span
  417 + */
  418 + public static String getFitTimeSpan(final long millis1,
  419 + final long millis2,
  420 + final int precision) {
  421 + return millis2FitTimeSpan(millis1 - millis2, precision);
  422 + }
  423 +
  424 + /**
  425 + * 获取当前毫秒时间戳
  426 + * Return the current time in milliseconds.
  427 + *
  428 + * @return the current time in milliseconds
  429 + */
  430 + public static long getNowMills() {
  431 + return System.currentTimeMillis();
  432 + }
  433 +
  434 + /**
  435 + * 获取当前时间字符串
  436 + * Return the current formatted time string.
  437 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  438 + *
  439 + * @return the current formatted time string
  440 + */
  441 + public static String getNowString() {
  442 + return millis2String(System.currentTimeMillis(), getDefaultFormat());
  443 + }
  444 +
  445 + /**
  446 + * Return the current formatted time string.
  447 + *
  448 + * @param format The format.
  449 + * @return the current formatted time string
  450 + */
  451 + public static String getNowString(@NonNull final DateFormat format) {
  452 + return millis2String(System.currentTimeMillis(), format);
  453 + }
  454 +
  455 + /**
  456 + * 获取当前 Date
  457 + * Return the current date.
  458 + *
  459 + * @return the current date
  460 + */
  461 + public static Date getNowDate() {
  462 + return new Date();
  463 + }
  464 +
  465 + /**
  466 + * 获取与当前时间的差(单位:unit)
  467 + * Return the time span by now, in unit.
  468 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  469 + *
  470 + * @param time The formatted time string.
  471 + * @param unit The unit of time span.
  472 + * <ul>
  473 + * <li>{@link TimeConstants#MSEC}</li>
  474 + * <li>{@link TimeConstants#SEC }</li>
  475 + * <li>{@link TimeConstants#MIN }</li>
  476 + * <li>{@link TimeConstants#HOUR}</li>
  477 + * <li>{@link TimeConstants#DAY }</li>
  478 + * </ul>
  479 + * @return the time span by now, in unit
  480 + */
  481 + public static long getTimeSpanByNow(final String time, @TimeConstants.Unit final int unit) {
  482 + return getTimeSpan(time, getNowString(), getDefaultFormat(), unit);
  483 + }
  484 +
  485 + /**
  486 + * Return the time span by now, in unit.
  487 + *
  488 + * @param time The formatted time string.
  489 + * @param format The format.
  490 + * @param unit The unit of time span.
  491 + * <ul>
  492 + * <li>{@link TimeConstants#MSEC}</li>
  493 + * <li>{@link TimeConstants#SEC }</li>
  494 + * <li>{@link TimeConstants#MIN }</li>
  495 + * <li>{@link TimeConstants#HOUR}</li>
  496 + * <li>{@link TimeConstants#DAY }</li>
  497 + * </ul>
  498 + * @return the time span by now, in unit
  499 + */
  500 + public static long getTimeSpanByNow(final String time,
  501 + @NonNull final DateFormat format,
  502 + @TimeConstants.Unit final int unit) {
  503 + return getTimeSpan(time, getNowString(format), format, unit);
  504 + }
  505 +
  506 + /**
  507 + * Return the time span by now, in unit.
  508 + *
  509 + * @param date The date.
  510 + * @param unit The unit of time span.
  511 + * <ul>
  512 + * <li>{@link TimeConstants#MSEC}</li>
  513 + * <li>{@link TimeConstants#SEC }</li>
  514 + * <li>{@link TimeConstants#MIN }</li>
  515 + * <li>{@link TimeConstants#HOUR}</li>
  516 + * <li>{@link TimeConstants#DAY }</li>
  517 + * </ul>
  518 + * @return the time span by now, in unit
  519 + */
  520 + public static long getTimeSpanByNow(final Date date, @TimeConstants.Unit final int unit) {
  521 + return getTimeSpan(date, new Date(), unit);
  522 + }
  523 +
  524 + /**
  525 + * Return the time span by now, in unit.
  526 + *
  527 + * @param millis The milliseconds.
  528 + * @param unit The unit of time span.
  529 + * <ul>
  530 + * <li>{@link TimeConstants#MSEC}</li>
  531 + * <li>{@link TimeConstants#SEC }</li>
  532 + * <li>{@link TimeConstants#MIN }</li>
  533 + * <li>{@link TimeConstants#HOUR}</li>
  534 + * <li>{@link TimeConstants#DAY }</li>
  535 + * </ul>
  536 + * @return the time span by now, in unit
  537 + */
  538 + public static long getTimeSpanByNow(final long millis, @TimeConstants.Unit final int unit) {
  539 + return getTimeSpan(millis, System.currentTimeMillis(), unit);
  540 + }
  541 +
  542 + /**
  543 + * 获取合适型与当前时间的差
  544 + * Return the fit time span by now.
  545 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  546 + *
  547 + * @param time The formatted time string.
  548 + * @param precision The precision of time span.
  549 + * <ul>
  550 + * <li>precision = 0,返回 null</li>
  551 + * <li>precision = 1,返回天</li>
  552 + * <li>precision = 2,返回天和小时</li>
  553 + * <li>precision = 3,返回天、小时和分钟</li>
  554 + * <li>precision = 4,返回天、小时、分钟和秒</li>
  555 + * <li>precision &gt;= 5,返回天、小时、分钟、秒和毫秒</li>
  556 + * </ul>
  557 + * @return the fit time span by now
  558 + */
  559 + public static String getFitTimeSpanByNow(final String time, final int precision) {
  560 + return getFitTimeSpan(time, getNowString(), getDefaultFormat(), precision);
  561 + }
  562 +
  563 + /**
  564 + * Return the fit time span by now.
  565 + *
  566 + * @param time The formatted time string.
  567 + * @param format The format.
  568 + * @param precision The precision of time span.
  569 + * <ul>
  570 + * <li>precision = 0,返回 null</li>
  571 + * <li>precision = 1,返回天</li>
  572 + * <li>precision = 2,返回天和小时</li>
  573 + * <li>precision = 3,返回天、小时和分钟</li>
  574 + * <li>precision = 4,返回天、小时、分钟和秒</li>
  575 + * <li>precision &gt;= 5,返回天、小时、分钟、秒和毫秒</li>
  576 + * </ul>
  577 + * @return the fit time span by now
  578 + */
  579 + public static String getFitTimeSpanByNow(final String time,
  580 + @NonNull final DateFormat format,
  581 + final int precision) {
  582 + return getFitTimeSpan(time, getNowString(format), format, precision);
  583 + }
  584 +
  585 + /**
  586 + * Return the fit time span by now.
  587 + *
  588 + * @param date The date.
  589 + * @param precision The precision of time span.
  590 + * <ul>
  591 + * <li>precision = 0,返回 null</li>
  592 + * <li>precision = 1,返回天</li>
  593 + * <li>precision = 2,返回天和小时</li>
  594 + * <li>precision = 3,返回天、小时和分钟</li>
  595 + * <li>precision = 4,返回天、小时、分钟和秒</li>
  596 + * <li>precision &gt;= 5,返回天、小时、分钟、秒和毫秒</li>
  597 + * </ul>
  598 + * @return the fit time span by now
  599 + */
  600 + public static String getFitTimeSpanByNow(final Date date, final int precision) {
  601 + return getFitTimeSpan(date, getNowDate(), precision);
  602 + }
  603 +
  604 + /**
  605 + * Return the fit time span by now.
  606 + *
  607 + * @param millis The milliseconds.
  608 + * @param precision The precision of time span.
  609 + * <ul>
  610 + * <li>precision = 0,返回 null</li>
  611 + * <li>precision = 1,返回天</li>
  612 + * <li>precision = 2,返回天和小时</li>
  613 + * <li>precision = 3,返回天、小时和分钟</li>
  614 + * <li>precision = 4,返回天、小时、分钟和秒</li>
  615 + * <li>precision &gt;= 5,返回天、小时、分钟、秒和毫秒</li>
  616 + * </ul>
  617 + * @return the fit time span by now
  618 + */
  619 + public static String getFitTimeSpanByNow(final long millis, final int precision) {
  620 + return getFitTimeSpan(millis, System.currentTimeMillis(), precision);
  621 + }
  622 +
  623 + /**
  624 + * 获取友好型与当前时间的差
  625 + * Return the friendly time span by now.
  626 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  627 + *
  628 + * @param time The formatted time string.
  629 + * @return the friendly time span by now
  630 + * <ul>
  631 + * <li>如果小于 1 秒钟内,显示刚刚</li>
  632 + * <li>如果在 1 分钟内,显示 XXX秒前</li>
  633 + * <li>如果在 1 小时内,显示 XXX分钟前</li>
  634 + * <li>如果在 1 小时外的今天内,显示今天15:32</li>
  635 + * <li>如果是昨天的,显示昨天15:32</li>
  636 + * <li>其余显示,2016-10-15</li>
  637 + * <li>时间不合法的情况全部日期和时间信息,如星期六 十月 27 14:21:20 CST 2007</li>
  638 + * </ul>
  639 + */
  640 + public static String getFriendlyTimeSpanByNow(final String time) {
  641 + return getFriendlyTimeSpanByNow(time, getDefaultFormat());
  642 + }
  643 +
  644 + /**
  645 + * Return the friendly time span by now.
  646 + *
  647 + * @param time The formatted time string.
  648 + * @param format The format.
  649 + * @return the friendly time span by now
  650 + * <ul>
  651 + * <li>如果小于 1 秒钟内,显示刚刚</li>
  652 + * <li>如果在 1 分钟内,显示 XXX秒前</li>
  653 + * <li>如果在 1 小时内,显示 XXX分钟前</li>
  654 + * <li>如果在 1 小时外的今天内,显示今天15:32</li>
  655 + * <li>如果是昨天的,显示昨天15:32</li>
  656 + * <li>其余显示,2016-10-15</li>
  657 + * <li>时间不合法的情况全部日期和时间信息,如星期六 十月 27 14:21:20 CST 2007</li>
  658 + * </ul>
  659 + */
  660 + public static String getFriendlyTimeSpanByNow(final String time,
  661 + @NonNull final DateFormat format) {
  662 + return getFriendlyTimeSpanByNow(string2Millis(time, format));
  663 + }
  664 +
  665 + /**
  666 + * Return the friendly time span by now.
  667 + *
  668 + * @param date The date.
  669 + * @return the friendly time span by now
  670 + * <ul>
  671 + * <li>如果小于 1 秒钟内,显示刚刚</li>
  672 + * <li>如果在 1 分钟内,显示 XXX秒前</li>
  673 + * <li>如果在 1 小时内,显示 XXX分钟前</li>
  674 + * <li>如果在 1 小时外的今天内,显示今天15:32</li>
  675 + * <li>如果是昨天的,显示昨天15:32</li>
  676 + * <li>其余显示,2016-10-15</li>
  677 + * <li>时间不合法的情况全部日期和时间信息,如星期六 十月 27 14:21:20 CST 2007</li>
  678 + * </ul>
  679 + */
  680 + public static String getFriendlyTimeSpanByNow(final Date date) {
  681 + return getFriendlyTimeSpanByNow(date.getTime());
  682 + }
  683 +
  684 + /**
  685 + * Return the friendly time span by now.
  686 + *
  687 + * @param millis The milliseconds.
  688 + * @return the friendly time span by now
  689 + * <ul>
  690 + * <li>如果小于 1 秒钟内,显示刚刚</li>
  691 + * <li>如果在 1 分钟内,显示 XXX秒前</li>
  692 + * <li>如果在 1 小时内,显示 XXX分钟前</li>
  693 + * <li>如果在 1 小时外的今天内,显示今天15:32</li>
  694 + * <li>如果是昨天的,显示昨天15:32</li>
  695 + * <li>其余显示,2016-10-15</li>
  696 + * <li>时间不合法的情况全部日期和时间信息,如星期六 十月 27 14:21:20 CST 2007</li>
  697 + * </ul>
  698 + */
  699 + public static String getFriendlyTimeSpanByNow(final long millis) {
  700 + long now = System.currentTimeMillis();
  701 + long span = now - millis;
  702 + if (span < 0)
  703 + // U can read http://www.apihome.cn/api/java/Formatter.html to understand it.
  704 + return String.format("%tc", millis);
  705 + if (span < 1000) {
  706 + return "刚刚";
  707 + } else if (span < TimeConstants.MIN) {
  708 + return String.format(Locale.getDefault(), "%d秒前", span / TimeConstants.SEC);
  709 + } else if (span < TimeConstants.HOUR) {
  710 + return String.format(Locale.getDefault(), "%d分钟前", span / TimeConstants.MIN);
  711 + }
  712 + // 获取当天 00:00
  713 + long wee = getWeeOfToday();
  714 + if (millis >= wee) {
  715 + return String.format("今天%tR", millis);
  716 + } else if (millis >= wee - TimeConstants.DAY) {
  717 + return String.format("昨天%tR", millis);
  718 + } else {
  719 + return String.format("%tF", millis);
  720 + }
  721 + }
  722 +
  723 + private static long getWeeOfToday() {
  724 + Calendar cal = Calendar.getInstance();
  725 + cal.set(Calendar.HOUR_OF_DAY, 0);
  726 + cal.set(Calendar.SECOND, 0);
  727 + cal.set(Calendar.MINUTE, 0);
  728 + cal.set(Calendar.MILLISECOND, 0);
  729 + return cal.getTimeInMillis();
  730 + }
  731 +
  732 + /**
  733 + * 获取与给定时间等于时间差的时间戳
  734 + * Return the milliseconds differ time span.
  735 + *
  736 + * @param millis The milliseconds.
  737 + * @param timeSpan The time span.
  738 + * @param unit The unit of time span.
  739 + * <ul>
  740 + * <li>{@link TimeConstants#MSEC}</li>
  741 + * <li>{@link TimeConstants#SEC }</li>
  742 + * <li>{@link TimeConstants#MIN }</li>
  743 + * <li>{@link TimeConstants#HOUR}</li>
  744 + * <li>{@link TimeConstants#DAY }</li>
  745 + * </ul>
  746 + * @return the milliseconds differ time span
  747 + */
  748 + public static long getMillis(final long millis,
  749 + final long timeSpan,
  750 + @TimeConstants.Unit final int unit) {
  751 + return millis + timeSpan2Millis(timeSpan, unit);
  752 + }
  753 +
  754 + /**
  755 + * Return the milliseconds differ time span.
  756 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  757 + *
  758 + * @param time The formatted time string.
  759 + * @param timeSpan The time span.
  760 + * @param unit The unit of time span.
  761 + * <ul>
  762 + * <li>{@link TimeConstants#MSEC}</li>
  763 + * <li>{@link TimeConstants#SEC }</li>
  764 + * <li>{@link TimeConstants#MIN }</li>
  765 + * <li>{@link TimeConstants#HOUR}</li>
  766 + * <li>{@link TimeConstants#DAY }</li>
  767 + * </ul>
  768 + * @return the milliseconds differ time span
  769 + */
  770 + public static long getMillis(final String time,
  771 + final long timeSpan,
  772 + @TimeConstants.Unit final int unit) {
  773 + return getMillis(time, getDefaultFormat(), timeSpan, unit);
  774 + }
  775 +
  776 + /**
  777 + * Return the milliseconds differ time span.
  778 + *
  779 + * @param time The formatted time string.
  780 + * @param format The format.
  781 + * @param timeSpan The time span.
  782 + * @param unit The unit of time span.
  783 + * <ul>
  784 + * <li>{@link TimeConstants#MSEC}</li>
  785 + * <li>{@link TimeConstants#SEC }</li>
  786 + * <li>{@link TimeConstants#MIN }</li>
  787 + * <li>{@link TimeConstants#HOUR}</li>
  788 + * <li>{@link TimeConstants#DAY }</li>
  789 + * </ul>
  790 + * @return the milliseconds differ time span.
  791 + */
  792 + public static long getMillis(final String time,
  793 + @NonNull final DateFormat format,
  794 + final long timeSpan,
  795 + @TimeConstants.Unit final int unit) {
  796 + return string2Millis(time, format) + timeSpan2Millis(timeSpan, unit);
  797 + }
  798 +
  799 + /**
  800 + * Return the milliseconds differ time span.
  801 + *
  802 + * @param date The date.
  803 + * @param timeSpan The time span.
  804 + * @param unit The unit of time span.
  805 + * <ul>
  806 + * <li>{@link TimeConstants#MSEC}</li>
  807 + * <li>{@link TimeConstants#SEC }</li>
  808 + * <li>{@link TimeConstants#MIN }</li>
  809 + * <li>{@link TimeConstants#HOUR}</li>
  810 + * <li>{@link TimeConstants#DAY }</li>
  811 + * </ul>
  812 + * @return the milliseconds differ time span.
  813 + */
  814 + public static long getMillis(final Date date,
  815 + final long timeSpan,
  816 + @TimeConstants.Unit final int unit) {
  817 + return date2Millis(date) + timeSpan2Millis(timeSpan, unit);
  818 + }
  819 +
  820 + /**
  821 + * 获取与给定时间等于时间差的时间字符串
  822 + * Return the formatted time string differ time span.
  823 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  824 + *
  825 + * @param millis The milliseconds.
  826 + * @param timeSpan The time span.
  827 + * @param unit The unit of time span.
  828 + * <ul>
  829 + * <li>{@link TimeConstants#MSEC}</li>
  830 + * <li>{@link TimeConstants#SEC }</li>
  831 + * <li>{@link TimeConstants#MIN }</li>
  832 + * <li>{@link TimeConstants#HOUR}</li>
  833 + * <li>{@link TimeConstants#DAY }</li>
  834 + * </ul>
  835 + * @return the formatted time string differ time span
  836 + */
  837 + public static String getString(final long millis,
  838 + final long timeSpan,
  839 + @TimeConstants.Unit final int unit) {
  840 + return getString(millis, getDefaultFormat(), timeSpan, unit);
  841 + }
  842 +
  843 + /**
  844 + * Return the formatted time string differ time span.
  845 + *
  846 + * @param millis The milliseconds.
  847 + * @param format The format.
  848 + * @param timeSpan The time span.
  849 + * @param unit The unit of time span.
  850 + * <ul>
  851 + * <li>{@link TimeConstants#MSEC}</li>
  852 + * <li>{@link TimeConstants#SEC }</li>
  853 + * <li>{@link TimeConstants#MIN }</li>
  854 + * <li>{@link TimeConstants#HOUR}</li>
  855 + * <li>{@link TimeConstants#DAY }</li>
  856 + * </ul>
  857 + * @return the formatted time string differ time span
  858 + */
  859 + public static String getString(final long millis,
  860 + @NonNull final DateFormat format,
  861 + final long timeSpan,
  862 + @TimeConstants.Unit final int unit) {
  863 + return millis2String(millis + timeSpan2Millis(timeSpan, unit), format);
  864 + }
  865 +
  866 + /**
  867 + * Return the formatted time string differ time span.
  868 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  869 + *
  870 + * @param time The formatted time string.
  871 + * @param timeSpan The time span.
  872 + * @param unit The unit of time span.
  873 + * <ul>
  874 + * <li>{@link TimeConstants#MSEC}</li>
  875 + * <li>{@link TimeConstants#SEC }</li>
  876 + * <li>{@link TimeConstants#MIN }</li>
  877 + * <li>{@link TimeConstants#HOUR}</li>
  878 + * <li>{@link TimeConstants#DAY }</li>
  879 + * </ul>
  880 + * @return the formatted time string differ time span
  881 + */
  882 + public static String getString(final String time,
  883 + final long timeSpan,
  884 + @TimeConstants.Unit final int unit) {
  885 + return getString(time, getDefaultFormat(), timeSpan, unit);
  886 + }
  887 +
  888 + /**
  889 + * Return the formatted time string differ time span.
  890 + *
  891 + * @param time The formatted time string.
  892 + * @param format The format.
  893 + * @param timeSpan The time span.
  894 + * @param unit The unit of time span.
  895 + * <ul>
  896 + * <li>{@link TimeConstants#MSEC}</li>
  897 + * <li>{@link TimeConstants#SEC }</li>
  898 + * <li>{@link TimeConstants#MIN }</li>
  899 + * <li>{@link TimeConstants#HOUR}</li>
  900 + * <li>{@link TimeConstants#DAY }</li>
  901 + * </ul>
  902 + * @return the formatted time string differ time span
  903 + */
  904 + public static String getString(final String time,
  905 + @NonNull final DateFormat format,
  906 + final long timeSpan,
  907 + @TimeConstants.Unit final int unit) {
  908 + return millis2String(string2Millis(time, format) + timeSpan2Millis(timeSpan, unit), format);
  909 + }
  910 +
  911 + /**
  912 + * Return the formatted time string differ time span.
  913 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  914 + *
  915 + * @param date The date.
  916 + * @param timeSpan The time span.
  917 + * @param unit The unit of time span.
  918 + * <ul>
  919 + * <li>{@link TimeConstants#MSEC}</li>
  920 + * <li>{@link TimeConstants#SEC }</li>
  921 + * <li>{@link TimeConstants#MIN }</li>
  922 + * <li>{@link TimeConstants#HOUR}</li>
  923 + * <li>{@link TimeConstants#DAY }</li>
  924 + * </ul>
  925 + * @return the formatted time string differ time span
  926 + */
  927 + public static String getString(final Date date,
  928 + final long timeSpan,
  929 + @TimeConstants.Unit final int unit) {
  930 + return getString(date, getDefaultFormat(), timeSpan, unit);
  931 + }
  932 +
  933 + /**
  934 + * Return the formatted time string differ time span.
  935 + *
  936 + * @param date The date.
  937 + * @param format The format.
  938 + * @param timeSpan The time span.
  939 + * @param unit The unit of time span.
  940 + * <ul>
  941 + * <li>{@link TimeConstants#MSEC}</li>
  942 + * <li>{@link TimeConstants#SEC }</li>
  943 + * <li>{@link TimeConstants#MIN }</li>
  944 + * <li>{@link TimeConstants#HOUR}</li>
  945 + * <li>{@link TimeConstants#DAY }</li>
  946 + * </ul>
  947 + * @return the formatted time string differ time span
  948 + */
  949 + public static String getString(final Date date,
  950 + @NonNull final DateFormat format,
  951 + final long timeSpan,
  952 + @TimeConstants.Unit final int unit) {
  953 + return millis2String(date2Millis(date) + timeSpan2Millis(timeSpan, unit), format);
  954 + }
  955 +
  956 + /**
  957 + * 获取与给定时间等于时间差的 Date
  958 + * Return the date differ time span.
  959 + *
  960 + * @param millis The milliseconds.
  961 + * @param timeSpan The time span.
  962 + * @param unit The unit of time span.
  963 + * <ul>
  964 + * <li>{@link TimeConstants#MSEC}</li>
  965 + * <li>{@link TimeConstants#SEC }</li>
  966 + * <li>{@link TimeConstants#MIN }</li>
  967 + * <li>{@link TimeConstants#HOUR}</li>
  968 + * <li>{@link TimeConstants#DAY }</li>
  969 + * </ul>
  970 + * @return the date differ time span
  971 + */
  972 + public static Date getDate(final long millis,
  973 + final long timeSpan,
  974 + @TimeConstants.Unit final int unit) {
  975 + return millis2Date(millis + timeSpan2Millis(timeSpan, unit));
  976 + }
  977 +
  978 + /**
  979 + * Return the date differ time span.
  980 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  981 + *
  982 + * @param time The formatted time string.
  983 + * @param timeSpan The time span.
  984 + * @param unit The unit of time span.
  985 + * <ul>
  986 + * <li>{@link TimeConstants#MSEC}</li>
  987 + * <li>{@link TimeConstants#SEC }</li>
  988 + * <li>{@link TimeConstants#MIN }</li>
  989 + * <li>{@link TimeConstants#HOUR}</li>
  990 + * <li>{@link TimeConstants#DAY }</li>
  991 + * </ul>
  992 + * @return the date differ time span
  993 + */
  994 + public static Date getDate(final String time,
  995 + final long timeSpan,
  996 + @TimeConstants.Unit final int unit) {
  997 + return getDate(time, getDefaultFormat(), timeSpan, unit);
  998 + }
  999 +
  1000 + /**
  1001 + * Return the date differ time span.
  1002 + *
  1003 + * @param time The formatted time string.
  1004 + * @param format The format.
  1005 + * @param timeSpan The time span.
  1006 + * @param unit The unit of time span.
  1007 + * <ul>
  1008 + * <li>{@link TimeConstants#MSEC}</li>
  1009 + * <li>{@link TimeConstants#SEC }</li>
  1010 + * <li>{@link TimeConstants#MIN }</li>
  1011 + * <li>{@link TimeConstants#HOUR}</li>
  1012 + * <li>{@link TimeConstants#DAY }</li>
  1013 + * </ul>
  1014 + * @return the date differ time span
  1015 + */
  1016 + public static Date getDate(final String time,
  1017 + @NonNull final DateFormat format,
  1018 + final long timeSpan,
  1019 + @TimeConstants.Unit final int unit) {
  1020 + return millis2Date(string2Millis(time, format) + timeSpan2Millis(timeSpan, unit));
  1021 + }
  1022 +
  1023 + /**
  1024 + * Return the date differ time span.
  1025 + *
  1026 + * @param date The date.
  1027 + * @param timeSpan The time span.
  1028 + * @param unit The unit of time span.
  1029 + * <ul>
  1030 + * <li>{@link TimeConstants#MSEC}</li>
  1031 + * <li>{@link TimeConstants#SEC }</li>
  1032 + * <li>{@link TimeConstants#MIN }</li>
  1033 + * <li>{@link TimeConstants#HOUR}</li>
  1034 + * <li>{@link TimeConstants#DAY }</li>
  1035 + * </ul>
  1036 + * @return the date differ time span
  1037 + */
  1038 + public static Date getDate(final Date date,
  1039 + final long timeSpan,
  1040 + @TimeConstants.Unit final int unit) {
  1041 + return millis2Date(date2Millis(date) + timeSpan2Millis(timeSpan, unit));
  1042 + }
  1043 +
  1044 + /**
  1045 + * 获取与当前时间等于时间差的时间戳
  1046 + * Return the milliseconds differ time span by now.
  1047 + *
  1048 + * @param timeSpan The time span.
  1049 + * @param unit The unit of time span.
  1050 + * <ul>
  1051 + * <li>{@link TimeConstants#MSEC}</li>
  1052 + * <li>{@link TimeConstants#SEC }</li>
  1053 + * <li>{@link TimeConstants#MIN }</li>
  1054 + * <li>{@link TimeConstants#HOUR}</li>
  1055 + * <li>{@link TimeConstants#DAY }</li>
  1056 + * </ul>
  1057 + * @return the milliseconds differ time span by now
  1058 + */
  1059 + public static long getMillisByNow(final long timeSpan, @TimeConstants.Unit final int unit) {
  1060 + return getMillis(getNowMills(), timeSpan, unit);
  1061 + }
  1062 +
  1063 + /**
  1064 + * 获取与当前时间等于时间差的时间字符串
  1065 + * Return the formatted time string differ time span by now.
  1066 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1067 + *
  1068 + * @param timeSpan The time span.
  1069 + * @param unit The unit of time span.
  1070 + * <ul>
  1071 + * <li>{@link TimeConstants#MSEC}</li>
  1072 + * <li>{@link TimeConstants#SEC }</li>
  1073 + * <li>{@link TimeConstants#MIN }</li>
  1074 + * <li>{@link TimeConstants#HOUR}</li>
  1075 + * <li>{@link TimeConstants#DAY }</li>
  1076 + * </ul>
  1077 + * @return the formatted time string differ time span by now
  1078 + */
  1079 + public static String getStringByNow(final long timeSpan, @TimeConstants.Unit final int unit) {
  1080 + return getStringByNow(timeSpan, getDefaultFormat(), unit);
  1081 + }
  1082 +
  1083 + /**
  1084 + * Return the formatted time string differ time span by now.
  1085 + *
  1086 + * @param timeSpan The time span.
  1087 + * @param format The format.
  1088 + * @param unit The unit of time span.
  1089 + * <ul>
  1090 + * <li>{@link TimeConstants#MSEC}</li>
  1091 + * <li>{@link TimeConstants#SEC }</li>
  1092 + * <li>{@link TimeConstants#MIN }</li>
  1093 + * <li>{@link TimeConstants#HOUR}</li>
  1094 + * <li>{@link TimeConstants#DAY }</li>
  1095 + * </ul>
  1096 + * @return the formatted time string differ time span by now
  1097 + */
  1098 + public static String getStringByNow(final long timeSpan,
  1099 + @NonNull final DateFormat format,
  1100 + @TimeConstants.Unit final int unit) {
  1101 + return getString(getNowMills(), format, timeSpan, unit);
  1102 + }
  1103 +
  1104 + /**
  1105 + * 获取与当前时间等于时间差的 Date
  1106 + * Return the date differ time span by now.
  1107 + *
  1108 + * @param timeSpan The time span.
  1109 + * @param unit The unit of time span.
  1110 + * <ul>
  1111 + * <li>{@link TimeConstants#MSEC}</li>
  1112 + * <li>{@link TimeConstants#SEC }</li>
  1113 + * <li>{@link TimeConstants#MIN }</li>
  1114 + * <li>{@link TimeConstants#HOUR}</li>
  1115 + * <li>{@link TimeConstants#DAY }</li>
  1116 + * </ul>
  1117 + * @return the date differ time span by now
  1118 + */
  1119 + public static Date getDateByNow(final long timeSpan, @TimeConstants.Unit final int unit) {
  1120 + return getDate(getNowMills(), timeSpan, unit);
  1121 + }
  1122 +
  1123 + /**
  1124 + * 判断是否今天
  1125 + * Return whether it is today.
  1126 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1127 + *
  1128 + * @param time The formatted time string.
  1129 + * @return {@code true}: yes<br>{@code false}: no
  1130 + */
  1131 + public static boolean isToday(final String time) {
  1132 + return isToday(string2Millis(time, getDefaultFormat()));
  1133 + }
  1134 +
  1135 + /**
  1136 + * Return whether it is today.
  1137 + *
  1138 + * @param time The formatted time string.
  1139 + * @param format The format.
  1140 + * @return {@code true}: yes<br>{@code false}: no
  1141 + */
  1142 + public static boolean isToday(final String time, @NonNull final DateFormat format) {
  1143 + return isToday(string2Millis(time, format));
  1144 + }
  1145 +
  1146 + /**
  1147 + * Return whether it is today.
  1148 + *
  1149 + * @param date The date.
  1150 + * @return {@code true}: yes<br>{@code false}: no
  1151 + */
  1152 + public static boolean isToday(final Date date) {
  1153 + return isToday(date.getTime());
  1154 + }
  1155 +
  1156 + /**
  1157 + * Return whether it is today.
  1158 + *
  1159 + * @param millis The milliseconds.
  1160 + * @return {@code true}: yes<br>{@code false}: no
  1161 + */
  1162 + public static boolean isToday(final long millis) {
  1163 + long wee = getWeeOfToday();
  1164 + return millis >= wee && millis < wee + TimeConstants.DAY;
  1165 + }
  1166 +
  1167 + /**
  1168 + * 判断是否闰年
  1169 + * Return whether it is leap year.
  1170 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1171 + *
  1172 + * @param time The formatted time string.
  1173 + * @return {@code true}: yes<br>{@code false}: no
  1174 + */
  1175 + public static boolean isLeapYear(final String time) {
  1176 + return isLeapYear(string2Date(time, getDefaultFormat()));
  1177 + }
  1178 +
  1179 + /**
  1180 + * Return whether it is leap year.
  1181 + *
  1182 + * @param time The formatted time string.
  1183 + * @param format The format.
  1184 + * @return {@code true}: yes<br>{@code false}: no
  1185 + */
  1186 + public static boolean isLeapYear(final String time, @NonNull final DateFormat format) {
  1187 + return isLeapYear(string2Date(time, format));
  1188 + }
  1189 +
  1190 + /**
  1191 + * Return whether it is leap year.
  1192 + *
  1193 + * @param date The date.
  1194 + * @return {@code true}: yes<br>{@code false}: no
  1195 + */
  1196 + public static boolean isLeapYear(final Date date) {
  1197 + Calendar cal = Calendar.getInstance();
  1198 + cal.setTime(date);
  1199 + int year = cal.get(Calendar.YEAR);
  1200 + return isLeapYear(year);
  1201 + }
  1202 +
  1203 + /**
  1204 + * Return whether it is leap year.
  1205 + *
  1206 + * @param millis The milliseconds.
  1207 + * @return {@code true}: yes<br>{@code false}: no
  1208 + */
  1209 + public static boolean isLeapYear(final long millis) {
  1210 + return isLeapYear(millis2Date(millis));
  1211 + }
  1212 +
  1213 + /**
  1214 + * Return whether it is leap year.
  1215 + *
  1216 + * @param year The year.
  1217 + * @return {@code true}: yes<br>{@code false}: no
  1218 + */
  1219 + public static boolean isLeapYear(final int year) {
  1220 + return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
  1221 + }
  1222 +
  1223 + /**
  1224 + * 获取中式星期
  1225 + * Return the day of week in Chinese.
  1226 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1227 + *
  1228 + * @param time The formatted time string.
  1229 + * @return the day of week in Chinese
  1230 + */
  1231 + public static String getChineseWeek(final String time) {
  1232 + return getChineseWeek(string2Date(time, getDefaultFormat()));
  1233 + }
  1234 +
  1235 + /**
  1236 + * Return the day of week in Chinese.
  1237 + *
  1238 + * @param time The formatted time string.
  1239 + * @param format The format.
  1240 + * @return the day of week in Chinese
  1241 + */
  1242 + public static String getChineseWeek(final String time, @NonNull final DateFormat format) {
  1243 + return getChineseWeek(string2Date(time, format));
  1244 + }
  1245 +
  1246 + /**
  1247 + * Return the day of week in Chinese.
  1248 + *
  1249 + * @param date The date.
  1250 + * @return the day of week in Chinese
  1251 + */
  1252 + public static String getChineseWeek(final Date date) {
  1253 + return new SimpleDateFormat("E", Locale.CHINA).format(date);
  1254 + }
  1255 +
  1256 + /**
  1257 + * Return the day of week in Chinese.
  1258 + *
  1259 + * @param millis The milliseconds.
  1260 + * @return the day of week in Chinese
  1261 + */
  1262 + public static String getChineseWeek(final long millis) {
  1263 + return getChineseWeek(new Date(millis));
  1264 + }
  1265 +
  1266 + /**
  1267 + * 获取美式式星期
  1268 + * Return the day of week in US.
  1269 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1270 + *
  1271 + * @param time The formatted time string.
  1272 + * @return the day of week in US
  1273 + */
  1274 + public static String getUSWeek(final String time) {
  1275 + return getUSWeek(string2Date(time, getDefaultFormat()));
  1276 + }
  1277 +
  1278 + /**
  1279 + * Return the day of week in US.
  1280 + *
  1281 + * @param time The formatted time string.
  1282 + * @param format The format.
  1283 + * @return the day of week in US
  1284 + */
  1285 + public static String getUSWeek(final String time, @NonNull final DateFormat format) {
  1286 + return getUSWeek(string2Date(time, format));
  1287 + }
  1288 +
  1289 + /**
  1290 + * Return the day of week in US.
  1291 + *
  1292 + * @param date The date.
  1293 + * @return the day of week in US
  1294 + */
  1295 + public static String getUSWeek(final Date date) {
  1296 + return new SimpleDateFormat("EEEE", Locale.US).format(date);
  1297 + }
  1298 +
  1299 + /**
  1300 + * Return the day of week in US.
  1301 + *
  1302 + * @param millis The milliseconds.
  1303 + * @return the day of week in US
  1304 + */
  1305 + public static String getUSWeek(final long millis) {
  1306 + return getUSWeek(new Date(millis));
  1307 + }
  1308 +
  1309 + /**
  1310 + * 判断是否上午
  1311 + * Return whether it is am.
  1312 + *
  1313 + * @return {@code true}: yes<br>{@code false}: no
  1314 + */
  1315 + public static boolean isAm() {
  1316 + Calendar cal = Calendar.getInstance();
  1317 + return cal.get(GregorianCalendar.AM_PM) == 0;
  1318 + }
  1319 +
  1320 + /**
  1321 + * Return whether it is am.
  1322 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1323 + *
  1324 + * @param time The formatted time string.
  1325 + * @return {@code true}: yes<br>{@code false}: no
  1326 + */
  1327 + public static boolean isAm(final String time) {
  1328 + return getValueByCalendarField(time, getDefaultFormat(), GregorianCalendar.AM_PM) == 0;
  1329 + }
  1330 +
  1331 + /**
  1332 + * Return whether it is am.
  1333 + *
  1334 + * @param time The formatted time string.
  1335 + * @param format The format.
  1336 + * @return {@code true}: yes<br>{@code false}: no
  1337 + */
  1338 + public static boolean isAm(final String time,
  1339 + @NonNull final DateFormat format) {
  1340 + return getValueByCalendarField(time, format, GregorianCalendar.AM_PM) == 0;
  1341 + }
  1342 +
  1343 + /**
  1344 + * Return whether it is am.
  1345 + *
  1346 + * @param date The date.
  1347 + * @return {@code true}: yes<br>{@code false}: no
  1348 + */
  1349 + public static boolean isAm(final Date date) {
  1350 + return getValueByCalendarField(date, GregorianCalendar.AM_PM) == 0;
  1351 + }
  1352 +
  1353 + /**
  1354 + * Return whether it is am.
  1355 + *
  1356 + * @param millis The milliseconds.
  1357 + * @return {@code true}: yes<br>{@code false}: no
  1358 + */
  1359 + public static boolean isAm(final long millis) {
  1360 + return getValueByCalendarField(millis, GregorianCalendar.AM_PM) == 0;
  1361 + }
  1362 +
  1363 + /**
  1364 + * 判断是否下午
  1365 + * Return whether it is am.
  1366 + *
  1367 + * @return {@code true}: yes<br>{@code false}: no
  1368 + */
  1369 + public static boolean isPm() {
  1370 + return !isAm();
  1371 + }
  1372 +
  1373 + /**
  1374 + * Return whether it is am.
  1375 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1376 + *
  1377 + * @param time The formatted time string.
  1378 + * @return {@code true}: yes<br>{@code false}: no
  1379 + */
  1380 + public static boolean isPm(final String time) {
  1381 + return !isAm(time);
  1382 + }
  1383 +
  1384 + /**
  1385 + * Return whether it is am.
  1386 + *
  1387 + * @param time The formatted time string.
  1388 + * @param format The format.
  1389 + * @return {@code true}: yes<br>{@code false}: no
  1390 + */
  1391 + public static boolean isPm(final String time,
  1392 + @NonNull final DateFormat format) {
  1393 + return !isAm(time, format);
  1394 + }
  1395 +
  1396 + /**
  1397 + * Return whether it is am.
  1398 + *
  1399 + * @param date The date.
  1400 + * @return {@code true}: yes<br>{@code false}: no
  1401 + */
  1402 + public static boolean isPm(final Date date) {
  1403 + return !isAm(date);
  1404 + }
  1405 +
  1406 + /**
  1407 + * Return whether it is am.
  1408 + *
  1409 + * @param millis The milliseconds.
  1410 + * @return {@code true}: yes<br>{@code false}: no
  1411 + */
  1412 + public static boolean isPm(final long millis) {
  1413 + return !isAm(millis);
  1414 + }
  1415 +
  1416 + /**
  1417 + * 根据日历字段获取值
  1418 + * Returns the value of the given calendar field.
  1419 + *
  1420 + * @param field The given calendar field.
  1421 + * <ul>
  1422 + * <li>{@link Calendar#ERA}</li>
  1423 + * <li>{@link Calendar#YEAR}</li>
  1424 + * <li>{@link Calendar#MONTH}</li>
  1425 + * <li>...</li>
  1426 + * <li>{@link Calendar#DST_OFFSET}</li>
  1427 + * </ul>
  1428 + * @return the value of the given calendar field
  1429 + */
  1430 + public static int getValueByCalendarField(final int field) {
  1431 + Calendar cal = Calendar.getInstance();
  1432 + return cal.get(field);
  1433 + }
  1434 +
  1435 + /**
  1436 + * Returns the value of the given calendar field.
  1437 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1438 + *
  1439 + * @param time The formatted time string.
  1440 + * @param field The given calendar field.
  1441 + * <ul>
  1442 + * <li>{@link Calendar#ERA}</li>
  1443 + * <li>{@link Calendar#YEAR}</li>
  1444 + * <li>{@link Calendar#MONTH}</li>
  1445 + * <li>...</li>
  1446 + * <li>{@link Calendar#DST_OFFSET}</li>
  1447 + * </ul>
  1448 + * @return the value of the given calendar field
  1449 + */
  1450 + public static int getValueByCalendarField(final String time, final int field) {
  1451 + return getValueByCalendarField(string2Date(time, getDefaultFormat()), field);
  1452 + }
  1453 +
  1454 + /**
  1455 + * Returns the value of the given calendar field.
  1456 + *
  1457 + * @param time The formatted time string.
  1458 + * @param format The format.
  1459 + * @param field The given calendar field.
  1460 + * <ul>
  1461 + * <li>{@link Calendar#ERA}</li>
  1462 + * <li>{@link Calendar#YEAR}</li>
  1463 + * <li>{@link Calendar#MONTH}</li>
  1464 + * <li>...</li>
  1465 + * <li>{@link Calendar#DST_OFFSET}</li>
  1466 + * </ul>
  1467 + * @return the value of the given calendar field
  1468 + */
  1469 + public static int getValueByCalendarField(final String time,
  1470 + @NonNull final DateFormat format,
  1471 + final int field) {
  1472 + return getValueByCalendarField(string2Date(time, format), field);
  1473 + }
  1474 +
  1475 + /**
  1476 + * Returns the value of the given calendar field.
  1477 + *
  1478 + * @param date The date.
  1479 + * @param field The given calendar field.
  1480 + * <ul>
  1481 + * <li>{@link Calendar#ERA}</li>
  1482 + * <li>{@link Calendar#YEAR}</li>
  1483 + * <li>{@link Calendar#MONTH}</li>
  1484 + * <li>...</li>
  1485 + * <li>{@link Calendar#DST_OFFSET}</li>
  1486 + * </ul>
  1487 + * @return the value of the given calendar field
  1488 + */
  1489 + public static int getValueByCalendarField(final Date date, final int field) {
  1490 + Calendar cal = Calendar.getInstance();
  1491 + cal.setTime(date);
  1492 + return cal.get(field);
  1493 + }
  1494 +
  1495 + /**
  1496 + * Returns the value of the given calendar field.
  1497 + *
  1498 + * @param millis The milliseconds.
  1499 + * @param field The given calendar field.
  1500 + * <ul>
  1501 + * <li>{@link Calendar#ERA}</li>
  1502 + * <li>{@link Calendar#YEAR}</li>
  1503 + * <li>{@link Calendar#MONTH}</li>
  1504 + * <li>...</li>
  1505 + * <li>{@link Calendar#DST_OFFSET}</li>
  1506 + * </ul>
  1507 + * @return the value of the given calendar field
  1508 + */
  1509 + public static int getValueByCalendarField(final long millis, final int field) {
  1510 + Calendar cal = Calendar.getInstance();
  1511 + cal.setTimeInMillis(millis);
  1512 + return cal.get(field);
  1513 + }
  1514 +
  1515 + private static final String[] CHINESE_ZODIAC =
  1516 + {"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"};
  1517 +
  1518 + /**
  1519 + * 获取生肖
  1520 + * Return the Chinese zodiac.
  1521 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1522 + *
  1523 + * @param time The formatted time string.
  1524 + * @return the Chinese zodiac
  1525 + */
  1526 + public static String getChineseZodiac(final String time) {
  1527 + return getChineseZodiac(string2Date(time, getDefaultFormat()));
  1528 + }
  1529 +
  1530 + /**
  1531 + * Return the Chinese zodiac.
  1532 + *
  1533 + * @param time The formatted time string.
  1534 + * @param format The format.
  1535 + * @return the Chinese zodiac
  1536 + */
  1537 + public static String getChineseZodiac(final String time, @NonNull final DateFormat format) {
  1538 + return getChineseZodiac(string2Date(time, format));
  1539 + }
  1540 +
  1541 + /**
  1542 + * Return the Chinese zodiac.
  1543 + *
  1544 + * @param date The date.
  1545 + * @return the Chinese zodiac
  1546 + */
  1547 + public static String getChineseZodiac(final Date date) {
  1548 + Calendar cal = Calendar.getInstance();
  1549 + cal.setTime(date);
  1550 + return CHINESE_ZODIAC[cal.get(Calendar.YEAR) % 12];
  1551 + }
  1552 +
  1553 + /**
  1554 + * Return the Chinese zodiac.
  1555 + *
  1556 + * @param millis The milliseconds.
  1557 + * @return the Chinese zodiac
  1558 + */
  1559 + public static String getChineseZodiac(final long millis) {
  1560 + return getChineseZodiac(millis2Date(millis));
  1561 + }
  1562 +
  1563 + /**
  1564 + * Return the Chinese zodiac.
  1565 + *
  1566 + * @param year The year.
  1567 + * @return the Chinese zodiac
  1568 + */
  1569 + public static String getChineseZodiac(final int year) {
  1570 + return CHINESE_ZODIAC[year % 12];
  1571 + }
  1572 +
  1573 + private static final int[] ZODIAC_FLAGS = {20, 19, 21, 21, 21, 22, 23, 23, 23, 24, 23, 22};
  1574 + private static final String[] ZODIAC = {
  1575 + "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座",
  1576 + "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "魔羯座"
  1577 + };
  1578 +
  1579 + /**
  1580 + * 获取星座
  1581 + * Return the zodiac.
  1582 + * <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
  1583 + *
  1584 + * @param time The formatted time string.
  1585 + * @return the zodiac
  1586 + */
  1587 + public static String getZodiac(final String time) {
  1588 + return getZodiac(string2Date(time, getDefaultFormat()));
  1589 + }
  1590 +
  1591 + /**
  1592 + * Return the zodiac.
  1593 + *
  1594 + * @param time The formatted time string.
  1595 + * @param format The format.
  1596 + * @return the zodiac
  1597 + */
  1598 + public static String getZodiac(final String time, @NonNull final DateFormat format) {
  1599 + return getZodiac(string2Date(time, format));
  1600 + }
  1601 +
  1602 + /**
  1603 + * Return the zodiac.
  1604 + *
  1605 + * @param date The date.
  1606 + * @return the zodiac
  1607 + */
  1608 + public static String getZodiac(final Date date) {
  1609 + Calendar cal = Calendar.getInstance();
  1610 + cal.setTime(date);
  1611 + int month = cal.get(Calendar.MONTH) + 1;
  1612 + int day = cal.get(Calendar.DAY_OF_MONTH);
  1613 + return getZodiac(month, day);
  1614 + }
  1615 +
  1616 + /**
  1617 + * Return the zodiac.
  1618 + *
  1619 + * @param millis The milliseconds.
  1620 + * @return the zodiac
  1621 + */
  1622 + public static String getZodiac(final long millis) {
  1623 + return getZodiac(millis2Date(millis));
  1624 + }
  1625 +
  1626 + /**
  1627 + * Return the zodiac.
  1628 + *
  1629 + * @param month The month.
  1630 + * @param day The day.
  1631 + * @return the zodiac
  1632 + */
  1633 + public static String getZodiac(final int month, final int day) {
  1634 + return ZODIAC[day >= ZODIAC_FLAGS[month - 1]
  1635 + ? month - 1
  1636 + : (month + 10) % 12];
  1637 + }
  1638 +
  1639 + private static long timeSpan2Millis(final long timeSpan, @TimeConstants.Unit final int unit) {
  1640 + return timeSpan * unit;
  1641 + }
  1642 +
  1643 + private static long millis2TimeSpan(final long millis, @TimeConstants.Unit final int unit) {
  1644 + return millis / unit;
  1645 + }
  1646 +
  1647 + private static String millis2FitTimeSpan(long millis, int precision) {
  1648 + if (precision <= 0) return null;
  1649 + precision = Math.min(precision, 5);
  1650 + String[] units = {"天", "小时", "分钟", "秒", "毫秒"};
  1651 + if (millis == 0) return 0 + units[precision - 1];
  1652 + StringBuilder sb = new StringBuilder();
  1653 + if (millis < 0) {
  1654 + sb.append("-");
  1655 + millis = -millis;
  1656 + }
  1657 + int[] unitLen = {86400000, 3600000, 60000, 1000, 1};
  1658 + for (int i = 0; i < precision; i++) {
  1659 + if (millis >= unitLen[i]) {
  1660 + long mode = millis / unitLen[i];
  1661 + millis -= mode * unitLen[i];
  1662 + sb.append(mode).append(units[i]);
  1663 + }
  1664 + }
  1665 + return sb.toString();
  1666 + }
  1667 +
  1668 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/TimerUtil.java renamed to core/base/src/main/java/com/cnlive/core/libs/base/util/TimerWaitUtil.java
... ... @@ -6,7 +6,7 @@ import android.os.SystemClock;
6 6  
7 7 import java.lang.ref.WeakReference;
8 8  
9   -public class TimerUtil {
  9 +public class TimerWaitUtil {
10 10 private long totalTime = -1L;
11 11 private long intervalTime = 0L;
12 12 private long remainTime;
... ... @@ -17,7 +17,7 @@ public class TimerUtil {
17 17 private boolean isPause = false;
18 18 private MyHandler mHandler = new MyHandler(this);
19 19  
20   - public TimerUtil() {
  20 + public TimerWaitUtil() {
21 21 }
22 22  
23 23 public void setIntervalTime(long intervalTime) {
... ... @@ -122,14 +122,14 @@ public class TimerUtil {
122 122 }
123 123  
124 124 private static class MyHandler extends Handler {
125   - WeakReference<TimerUtil> mActivity;
  125 + WeakReference<TimerWaitUtil> mActivity;
126 126  
127   - MyHandler(TimerUtil activity) {
  127 + MyHandler(TimerWaitUtil activity) {
128 128 this.mActivity = new WeakReference<>(activity);
129 129 }
130 130  
131 131 public void handleMessage(Message msg) {
132   - TimerUtil theActivity = mActivity == null ? null : this.mActivity.get();
  132 + TimerWaitUtil theActivity = mActivity == null ? null : this.mActivity.get();
133 133  
134 134 if (theActivity == null) return;
135 135  
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/ToastUtil.java
... ... @@ -2,6 +2,7 @@ package com.cnlive.core.libs.base.util;
2 2  
3 3 import android.content.Context;
4 4 import android.text.TextUtils;
  5 +import android.util.Log;
5 6 import android.view.LayoutInflater;
6 7 import android.view.View;
7 8 import android.view.ViewGroup;
... ... @@ -60,7 +61,7 @@ public class ToastUtil {
60 61 Toast toast =
61 62 // (android.os.Build.VERSION.SDK_INT == 25 || android.os.Build.VERSION.SDK_INT == 24) ?
62 63 // Toast.makeText(var10000, str, duration) :
63   - ToastCompat.makeText(var10000, str, duration);
  64 + ToastCompat.makeText(var10000, str, duration);
64 65 toast.setGravity(this.config == null ? 0 : this.config.gravity, this.config == null ? 0 : this.config.xOffset, this.config == null ? 0 : this.config.yOffset);
65 66 if (view != null) {
66 67 toast.setView(view);
... ... @@ -85,7 +86,7 @@ public class ToastUtil {
85 86 TextView textView = (TextView) view.findViewById(this.config.viewId);
86 87 textView.setText(message);
87 88 } catch (Exception var4) {
88   - LogUtil.d("ToastUtil", "", var4);
  89 + Log.d(TAG, "getView: " + var4);
89 90 }
90 91  
91 92 return view;
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/constant/CacheConstants.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util.constant;
  2 +
  3 +/**
  4 + * <pre>
  5 + * author: Blankj
  6 + * blog : http://blankj.com
  7 + * time : 2018/06/13
  8 + * desc : constants of cache
  9 + * </pre>
  10 + */
  11 +public interface CacheConstants {
  12 + int SEC = 1;
  13 + int MIN = 60;
  14 + int HOUR = 3600;
  15 + int DAY = 86400;
  16 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/constant/MemoryConstants.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util.constant;
  2 +
  3 +
  4 +import androidx.annotation.IntDef;
  5 +
  6 +import java.lang.annotation.Retention;
  7 +import java.lang.annotation.RetentionPolicy;
  8 +
  9 +/**
  10 + * <pre>
  11 + * author: Blankj
  12 + * blog : http://blankj.com
  13 + * time : 2017/03/13
  14 + * desc : constants of memory
  15 + * </pre>
  16 + */
  17 +public final class MemoryConstants {
  18 +
  19 + public static final int BYTE = 1;
  20 + public static final int KB = 1024;
  21 + public static final int MB = 1048576;
  22 + public static final int GB = 1073741824;
  23 +
  24 + @IntDef({BYTE, KB, MB, GB})
  25 + @Retention(RetentionPolicy.SOURCE)
  26 + public @interface Unit {
  27 + }
  28 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/constant/PermissionConstants.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util.constant;
  2 +
  3 +import android.Manifest;
  4 +import android.Manifest.permission;
  5 +import android.annotation.SuppressLint;
  6 +import android.os.Build;
  7 +
  8 +import androidx.annotation.StringDef;
  9 +
  10 +import java.lang.annotation.Retention;
  11 +import java.lang.annotation.RetentionPolicy;
  12 +
  13 +
  14 +/**
  15 + * <pre>
  16 + * author: Blankj
  17 + * blog : http://blankj.com
  18 + * time : 2017/12/29
  19 + * desc : constants of permission
  20 + * </pre>
  21 + */
  22 +@SuppressLint("InlinedApi")
  23 +public final class PermissionConstants {
  24 +
  25 + public static final String CALENDAR = Manifest.permission_group.CALENDAR;
  26 + public static final String CAMERA = Manifest.permission_group.CAMERA;
  27 + public static final String CONTACTS = Manifest.permission_group.CONTACTS;
  28 + public static final String LOCATION = Manifest.permission_group.LOCATION;
  29 + public static final String MICROPHONE = Manifest.permission_group.MICROPHONE;
  30 + public static final String PHONE = Manifest.permission_group.PHONE;
  31 + public static final String SENSORS = Manifest.permission_group.SENSORS;
  32 + public static final String SMS = Manifest.permission_group.SMS;
  33 + public static final String STORAGE = Manifest.permission_group.STORAGE;
  34 +
  35 + private static final String[] GROUP_CALENDAR = {
  36 + permission.READ_CALENDAR, permission.WRITE_CALENDAR
  37 + };
  38 + private static final String[] GROUP_CAMERA = {
  39 + permission.CAMERA
  40 + };
  41 + private static final String[] GROUP_CONTACTS = {
  42 + permission.READ_CONTACTS, permission.WRITE_CONTACTS, permission.GET_ACCOUNTS
  43 + };
  44 + private static final String[] GROUP_LOCATION = {
  45 + permission.ACCESS_FINE_LOCATION, permission.ACCESS_COARSE_LOCATION
  46 + };
  47 + private static final String[] GROUP_MICROPHONE = {
  48 + permission.RECORD_AUDIO
  49 + };
  50 + private static final String[] GROUP_PHONE = {
  51 + permission.READ_PHONE_STATE, permission.READ_PHONE_NUMBERS, permission.CALL_PHONE,
  52 + permission.READ_CALL_LOG, permission.WRITE_CALL_LOG, permission.ADD_VOICEMAIL,
  53 + permission.USE_SIP, permission.PROCESS_OUTGOING_CALLS, permission.ANSWER_PHONE_CALLS
  54 + };
  55 + private static final String[] GROUP_PHONE_BELOW_O = {
  56 + permission.READ_PHONE_STATE, permission.READ_PHONE_NUMBERS, permission.CALL_PHONE,
  57 + permission.READ_CALL_LOG, permission.WRITE_CALL_LOG, permission.ADD_VOICEMAIL,
  58 + permission.USE_SIP, permission.PROCESS_OUTGOING_CALLS
  59 + };
  60 + private static final String[] GROUP_SENSORS = {
  61 + permission.BODY_SENSORS
  62 + };
  63 + private static final String[] GROUP_SMS = {
  64 + permission.SEND_SMS, permission.RECEIVE_SMS, permission.READ_SMS,
  65 + permission.RECEIVE_WAP_PUSH, permission.RECEIVE_MMS,
  66 + };
  67 + private static final String[] GROUP_STORAGE = {
  68 + permission.READ_EXTERNAL_STORAGE, permission.WRITE_EXTERNAL_STORAGE,
  69 + };
  70 +
  71 + @StringDef({CALENDAR, CAMERA, CONTACTS, LOCATION, MICROPHONE, PHONE, SENSORS, SMS, STORAGE,})
  72 + @Retention(RetentionPolicy.SOURCE)
  73 + public @interface Permission {
  74 + }
  75 +
  76 + public static String[] getPermissions(@Permission final String permission) {
  77 + switch (permission) {
  78 + case CALENDAR:
  79 + return GROUP_CALENDAR;
  80 + case CAMERA:
  81 + return GROUP_CAMERA;
  82 + case CONTACTS:
  83 + return GROUP_CONTACTS;
  84 + case LOCATION:
  85 + return GROUP_LOCATION;
  86 + case MICROPHONE:
  87 + return GROUP_MICROPHONE;
  88 + case PHONE:
  89 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
  90 + return GROUP_PHONE_BELOW_O;
  91 + } else {
  92 + return GROUP_PHONE;
  93 + }
  94 + case SENSORS:
  95 + return GROUP_SENSORS;
  96 + case SMS:
  97 + return GROUP_SMS;
  98 + case STORAGE:
  99 + return GROUP_STORAGE;
  100 + }
  101 + return new String[]{permission};
  102 + }
  103 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/constant/RegexConstants.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util.constant;
  2 +
  3 +/**
  4 + * <pre>
  5 + * author: Blankj
  6 + * blog : http://blankj.com
  7 + * time : 2017/03/13
  8 + * desc : constants of regex
  9 + * </pre>
  10 + */
  11 +public final class RegexConstants {
  12 +
  13 + /**
  14 + * Regex of simple mobile.
  15 + */
  16 + public static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$";
  17 + /**
  18 + * Regex of exact mobile.
  19 + * <p>china mobile: 134(0-8), 135, 136, 137, 138, 139, 147, 150, 151, 152, 157, 158, 159, 178, 182, 183, 184, 187, 188, 198</p>
  20 + * <p>china unicom: 130, 131, 132, 145, 155, 156, 166, 171, 175, 176, 185, 186</p>
  21 + * <p>china telecom: 133, 153, 173, 177, 180, 181, 189, 199, 191</p>
  22 + * <p>global star: 1349</p>
  23 + * <p>virtual operator: 170</p>
  24 + */
  25 + public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(16[6])|(17[0,1,3,5-8])|(18[0-9])|(19[1,8,9]))\\d{8}$";
  26 + /**
  27 + * Regex of telephone number.
  28 + */
  29 + public static final String REGEX_TEL = "^0\\d{2,3}[- ]?\\d{7,8}";
  30 + /**
  31 + * Regex of id card number which length is 15.
  32 + */
  33 + public static final String REGEX_ID_CARD15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$";
  34 + /**
  35 + * Regex of id card number which length is 18.
  36 + */
  37 + public static final String REGEX_ID_CARD18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9Xx])$";
  38 + /**
  39 + * Regex of email.
  40 + */
  41 + public static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
  42 + /**
  43 + * Regex of url.
  44 + */
  45 + public static final String REGEX_URL = "[a-zA-z]+://[^\\s]*";
  46 + /**
  47 + * Regex of Chinese character.
  48 + */
  49 + public static final String REGEX_ZH = "^[\\u4e00-\\u9fa5]+$";
  50 + /**
  51 + * Regex of username.
  52 + * <p>scope for "a-z", "A-Z", "0-9", "_", "Chinese character"</p>
  53 + * <p>can't end with "_"</p>
  54 + * <p>length is between 6 to 20</p>
  55 + */
  56 + public static final String REGEX_USERNAME = "^[\\w\\u4e00-\\u9fa5]{6,20}(?<!_)$";
  57 + /**
  58 + * Regex of date which pattern is "yyyy-MM-dd".
  59 + */
  60 + public static final String REGEX_DATE = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";
  61 + /**
  62 + * Regex of ip address.
  63 + */
  64 + public static final String REGEX_IP = "((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
  65 +
  66 + ///////////////////////////////////////////////////////////////////////////
  67 + // The following come from http://tool.oschina.net/regex
  68 + ///////////////////////////////////////////////////////////////////////////
  69 +
  70 + /**
  71 + * Regex of double-byte characters.
  72 + */
  73 + public static final String REGEX_DOUBLE_BYTE_CHAR = "[^\\x00-\\xff]";
  74 + /**
  75 + * Regex of blank line.
  76 + */
  77 + public static final String REGEX_BLANK_LINE = "\\n\\s*\\r";
  78 + /**
  79 + * Regex of QQ number.
  80 + */
  81 + public static final String REGEX_QQ_NUM = "[1-9][0-9]{4,}";
  82 + /**
  83 + * Regex of postal code in China.
  84 + */
  85 + public static final String REGEX_CHINA_POSTAL_CODE = "[1-9]\\d{5}(?!\\d)";
  86 + /**
  87 + * Regex of positive integer.
  88 + */
  89 + public static final String REGEX_POSITIVE_INTEGER = "^[1-9]\\d*$";
  90 + /**
  91 + * Regex of negative integer.
  92 + */
  93 + public static final String REGEX_NEGATIVE_INTEGER = "^-[1-9]\\d*$";
  94 + /**
  95 + * Regex of integer.
  96 + */
  97 + public static final String REGEX_INTEGER = "^-?[1-9]\\d*$";
  98 + /**
  99 + * Regex of non-negative integer.
  100 + */
  101 + public static final String REGEX_NOT_NEGATIVE_INTEGER = "^[1-9]\\d*|0$";
  102 + /**
  103 + * Regex of non-positive integer.
  104 + */
  105 + public static final String REGEX_NOT_POSITIVE_INTEGER = "^-[1-9]\\d*|0$";
  106 + /**
  107 + * Regex of positive float.
  108 + */
  109 + public static final String REGEX_POSITIVE_FLOAT = "^[1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$";
  110 + /**
  111 + * Regex of negative float.
  112 + */
  113 + public static final String REGEX_NEGATIVE_FLOAT = "^-[1-9]\\d*\\.\\d*|-0\\.\\d*[1-9]\\d*$";
  114 +
  115 + ///////////////////////////////////////////////////////////////////////////
  116 + // If u want more please visit http://toutiao.com/i6231678548520731137
  117 + ///////////////////////////////////////////////////////////////////////////
  118 +}
... ...
core/base/src/main/java/com/cnlive/core/libs/base/util/constant/TimeConstants.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util.constant;
  2 +import androidx.annotation.IntDef;
  3 +
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +
  7 +/**
  8 + * <pre>
  9 + * author: Blankj
  10 + * blog : http://blankj.com
  11 + * time : 2017/03/13
  12 + * desc : constants of time
  13 + * </pre>
  14 + */
  15 +public final class TimeConstants {
  16 +
  17 + public static final int MSEC = 1;
  18 + public static final int SEC = 1000;
  19 + public static final int MIN = 60000;
  20 + public static final int HOUR = 3600000;
  21 + public static final int DAY = 86400000;
  22 +
  23 + @IntDef({MSEC, SEC, MIN, HOUR, DAY})
  24 + @Retention(RetentionPolicy.SOURCE)
  25 + public @interface Unit {
  26 + }
  27 +}
... ...
core/imageload/build.gradle
... ... @@ -26,8 +26,6 @@ android {
26 26  
27 27 dependencies {
28 28 implementation fileTree(dir: 'libs', include: ['*.jar'])
29   - //滤镜
30   - implementation 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'
31 29 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.3.3'
32 30 implementation 'com.cnlive.libs:largeimage:1.0.1'
33 31 implementation "com.cnlive.libs:mediapicker:$rootProject.libMediaPicker"
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/util/DownLoadImageService.java
... ... @@ -48,7 +48,7 @@ public class DownLoadImageService implements Runnable{
48 48 bitmap = Glide.with(context)
49 49 .asBitmap()
50 50 .load(url)
51   - .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
  51 + .submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
52 52 .get();
53 53 if (bitmap != null){
54 54 // 在这里执行图片保存方法
... ...
core/network/src/main/java/com/cnlive/core/network/HttpConn.java
... ... @@ -5,7 +5,7 @@ import com.cnlive.core.libs.base.application.BaseApplication;
5 5 import com.cnlive.core.libs.base.network.manager.SubscriptionManager;
6 6 import com.cnlive.core.network.model.BaseObserver;
7 7 import com.cnlive.core.network.model.BaseResult;
8   -import com.cnlive.core.network.util.NetworkUtil;
  8 +import com.cnlive.core.libs.base.util.NetworkUtil;
9 9  
10 10 import io.reactivex.Observable;
11 11 import io.reactivex.android.schedulers.AndroidSchedulers;
... ...
core/network/src/main/java/com/cnlive/core/network/util/NetworkUtil.java deleted 100644 → 0
1   -package com.cnlive.core.network.util;
2   -
3   -import android.content.Context;
4   -import android.net.ConnectivityManager;
5   -import android.net.NetworkInfo;
6   -
7   -public class NetworkUtil {
8   -
9   - public static boolean isConnectInternet(Context context) {
10   - if (context == null) return false;
11   - ConnectivityManager connectManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
12   - if (connectManager != null) {
13   - NetworkInfo networkinfo = connectManager.getActiveNetworkInfo();
14   - return networkinfo != null && networkinfo.isAvailable();
15   - }
16   - return false;
17   - }
18   -
19   -}
20 0 \ No newline at end of file
module/pedometer/src/main/java/com/cnlive/moudle/pedometer/ui/fragment/RaceRecorFragment.java
... ... @@ -51,6 +51,8 @@ public class RaceRecorFragment extends BaseFragment&lt;RaceRecorView, RaceRecorPres
51 51 protected void initView() {
52 52 super.initView();
53 53 if (getMvpView() != null) getMvpView().initView();
  54 + getPresenter().getData(getActivity(), CommonInfo.getStreetId(getActivity()), CommonInfo.getUserId(getActivity()), currentPage, pageSize);
  55 +
54 56 binding.refreshLayout.setOnRefreshListener(v -> {
55 57 currentPage = 1;
56 58 getPresenter().getData(getActivity(), CommonInfo.getStreetId(getActivity()), CommonInfo.getUserId(getActivity()), currentPage, pageSize);
... ...