+ */
+ public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[579])|(15[0-35-9])|(16[2567])|(17[0-35-8])|(18[0-9])|(19[0-35-9]))\\d{8}$";
+ /**
+ * Regex of telephone number.
+ */
+ public static final String REGEX_TEL = "^0\\d{2,3}[- ]?\\d{7,8}$";
+ /**
+ * Regex of id card number which length is 15.
+ */
+ 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}$";
+ /**
+ * Regex of id card number which length is 18.
+ */
+ 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])$";
+ /**
+ * Regex of email.
+ */
+ public static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
+ /**
+ * Regex of url.
+ */
+ public static final String REGEX_URL = "[a-zA-z]+://[^\\s]*";
+ /**
+ * Regex of Chinese character.
+ */
+ public static final String REGEX_ZH = "^[\\u4e00-\\u9fa5]+$";
+ /**
+ * Regex of username.
+ *
scope for "a-z", "A-Z", "0-9", "_", "Chinese character"
+ *
can't end with "_"
+ *
length is between 6 to 20
+ */
+ public static final String REGEX_USERNAME = "^[\\w\\u4e00-\\u9fa5]{6,20}(?
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2017/03/13
+ * desc : constants of time
+ *
+ */
+public final class TimeConstants {
+
+ public static final int MSEC = 1;
+ public static final int SEC = 1000;
+ public static final int MIN = 60000;
+ public static final int HOUR = 3600000;
+ public static final int DAY = 86400000;
+
+ @IntDef({MSEC, SEC, MIN, HOUR, DAY})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Unit {
+ }
+}
diff --git a/common/src/main/java/com/blankj/utilcode/util/ActivityUtils.java b/common/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
new file mode 100644
index 0000000..0566686
--- /dev/null
+++ b/common/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
@@ -0,0 +1,2141 @@
+package com.blankj.utilcode.util;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.AnimRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.app.ActivityOptionsCompat;
+import androidx.core.util.Pair;
+import androidx.fragment.app.Fragment;
+
+/**
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/09/23
+ * desc : utils about activity
+ *
+ */
+public final class ActivityUtils {
+
+ private ActivityUtils() {
+ throw new UnsupportedOperationException("u can't instantiate me...");
+ }
+
+ /**
+ * Add callbacks of activity lifecycle.
+ *
+ * @param callbacks The callbacks.
+ */
+ public static void addActivityLifecycleCallbacks(@Nullable final Utils.ActivityLifecycleCallbacks callbacks) {
+ UtilsBridge.addActivityLifecycleCallbacks(callbacks);
+ }
+
+ /**
+ * Add callbacks of activity lifecycle.
+ *
+ * @param activity The activity.
+ * @param callbacks The callbacks.
+ */
+ public static void addActivityLifecycleCallbacks(@Nullable final Activity activity,
+ @Nullable final Utils.ActivityLifecycleCallbacks callbacks) {
+ UtilsBridge.addActivityLifecycleCallbacks(activity, callbacks);
+ }
+
+ /**
+ * Remove callbacks of activity lifecycle.
+ *
+ * @param callbacks The callbacks.
+ */
+ public static void removeActivityLifecycleCallbacks(@Nullable final Utils.ActivityLifecycleCallbacks callbacks) {
+ UtilsBridge.removeActivityLifecycleCallbacks(callbacks);
+ }
+
+ /**
+ * Remove callbacks of activity lifecycle.
+ *
+ * @param activity The activity.
+ */
+ public static void removeActivityLifecycleCallbacks(@Nullable final Activity activity) {
+ UtilsBridge.removeActivityLifecycleCallbacks(activity);
+ }
+
+ /**
+ * Remove callbacks of activity lifecycle.
+ *
+ * @param activity The activity.
+ * @param callbacks The callbacks.
+ */
+ public static void removeActivityLifecycleCallbacks(@Nullable final Activity activity,
+ @Nullable final Utils.ActivityLifecycleCallbacks callbacks) {
+ UtilsBridge.removeActivityLifecycleCallbacks(activity, callbacks);
+ }
+
+ /**
+ * Return the activity by context.
+ *
+ * @param context The context.
+ * @return the activity by context.
+ */
+ @Nullable
+ public static Activity getActivityByContext(@Nullable Context context) {
+ if (context == null) return null;
+ Activity activity = getActivityByContextInner(context);
+ if (!isActivityAlive(activity)) return null;
+ return activity;
+ }
+
+ @Nullable
+ private static Activity getActivityByContextInner(@Nullable Context context) {
+ if (context == null) return null;
+ List list = new ArrayList<>();
+ while (context instanceof ContextWrapper) {
+ if (context instanceof Activity) {
+ return (Activity) context;
+ }
+ Activity activity = getActivityFromDecorContext(context);
+ if (activity != null) return activity;
+ list.add(context);
+ context = ((ContextWrapper) context).getBaseContext();
+ if (context == null) {
+ return null;
+ }
+ if (list.contains(context)) {
+ // loop context
+ return null;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static Activity getActivityFromDecorContext(@Nullable Context context) {
+ if (context == null) return null;
+ if (context.getClass().getName().equals("com.android.internal.policy.DecorContext")) {
+ try {
+ Field mActivityContextField = context.getClass().getDeclaredField("mActivityContext");
+ mActivityContextField.setAccessible(true);
+ //noinspection ConstantConditions,unchecked
+ return ((WeakReference) mActivityContextField.get(context)).get();
+ } catch (Exception ignore) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return whether the activity exists.
+ *
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isActivityExists(@NonNull final String pkg,
+ @NonNull final String cls) {
+ Intent intent = new Intent();
+ intent.setClassName(pkg, cls);
+ PackageManager pm = Utils.getApp().getPackageManager();
+ return !(pm.resolveActivity(intent, 0) == null ||
+ intent.resolveActivity(pm) == null ||
+ pm.queryIntentActivities(intent, 0).size() == 0);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param clz The activity class.
+ */
+ public static void startActivity(@NonNull final Class extends Activity> clz) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, null, context.getPackageName(), clz.getName(), null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param clz The activity class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Class extends Activity> clz,
+ @Nullable final Bundle options) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, null, context.getPackageName(), clz.getName(), options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param clz The activity class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Class extends Activity> clz,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, null, context.getPackageName(), clz.getName(),
+ getOptionsBundle(context, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
+ ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz) {
+ startActivity(activity, null, activity.getPackageName(), clz.getName(), null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ @Nullable final Bundle options) {
+ startActivity(activity, null, activity.getPackageName(), clz.getName(), options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final View... sharedElements) {
+ startActivity(activity, null, activity.getPackageName(), clz.getName(),
+ getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivity(activity, null, activity.getPackageName(), clz.getName(),
+ getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param clz The activity class.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Class extends Activity> clz) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, extras, context.getPackageName(), clz.getName(), null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param clz The activity class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Class extends Activity> clz,
+ @Nullable final Bundle options) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, extras, context.getPackageName(), clz.getName(), options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param clz The activity class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Class extends Activity> clz,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, extras, context.getPackageName(), clz.getName(),
+ getOptionsBundle(context, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
+ ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz) {
+ startActivity(activity, extras, activity.getPackageName(), clz.getName(), null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ @Nullable final Bundle options) {
+ startActivity(activity, extras, activity.getPackageName(), clz.getName(), options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final View... sharedElements) {
+ startActivity(activity, extras, activity.getPackageName(), clz.getName(),
+ getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivity(activity, extras, activity.getPackageName(), clz.getName(),
+ getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ */
+ public static void startActivity(@NonNull final String pkg,
+ @NonNull final String cls) {
+ startActivity(getTopActivityOrApp(), null, pkg, cls, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final String pkg,
+ @NonNull final String cls,
+ @Nullable final Bundle options) {
+ startActivity(getTopActivityOrApp(), null, pkg, cls, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final String pkg,
+ @NonNull final String cls,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, null, pkg, cls, getOptionsBundle(context, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
+ ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls) {
+ startActivity(activity, null, pkg, cls, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ @Nullable final Bundle options) {
+ startActivity(activity, null, pkg, cls, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final View... sharedElements) {
+ startActivity(activity, null, pkg, cls, getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivity(activity, null, pkg, cls, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final String pkg,
+ @NonNull final String cls) {
+ startActivity(getTopActivityOrApp(), extras, pkg, cls, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ @Nullable final Bundle options) {
+ startActivity(getTopActivityOrApp(), extras, pkg, cls, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ Context context = getTopActivityOrApp();
+ startActivity(context, extras, pkg, cls, getOptionsBundle(context, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
+ ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls) {
+ startActivity(activity, extras, pkg, cls, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ @Nullable final Bundle options) {
+ startActivity(activity, extras, pkg, cls, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final View... sharedElements) {
+ startActivity(activity, extras, pkg, cls, getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivity(activity, extras, pkg, cls, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param intent The description of the activity to start.
+ * @return {@code true}: success {@code false}: fail
+ */
+ public static boolean startActivity(@NonNull final Intent intent) {
+ return startActivity(intent, getTopActivityOrApp(), null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param intent The description of the activity to start.
+ * @param options Additional options for how the Activity should be started.
+ * @return {@code true}: success {@code false}: fail
+ */
+ public static boolean startActivity(@NonNull final Intent intent,
+ @Nullable final Bundle options) {
+ return startActivity(intent, getTopActivityOrApp(), options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param intent The description of the activity to start.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ * @return {@code true}: success {@code false}: fail
+ */
+ public static boolean startActivity(@NonNull final Intent intent,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ Context context = getTopActivityOrApp();
+ boolean isSuccess = startActivity(intent, context, getOptionsBundle(context, enterAnim, exitAnim));
+ if (isSuccess) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
+ ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+ return isSuccess;
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Intent intent) {
+ startActivity(intent, activity, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Intent intent,
+ @Nullable final Bundle options) {
+ startActivity(intent, activity, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Intent intent,
+ final View... sharedElements) {
+ startActivity(intent, activity, getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivity(@NonNull final Activity activity,
+ @NonNull final Intent intent,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivity(intent, activity, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode) {
+ startActivityForResult(activity, null, activity.getPackageName(), clz.getName(),
+ requestCode, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(activity, null, activity.getPackageName(), clz.getName(),
+ requestCode, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(activity, null, activity.getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(activity, null, activity.getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode) {
+ startActivityForResult(activity, extras, activity.getPackageName(), clz.getName(),
+ requestCode, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(activity, extras, activity.getPackageName(), clz.getName(),
+ requestCode, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(activity, extras, activity.getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(activity, extras, activity.getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param activity The activity.
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode) {
+ startActivityForResult(activity, extras, pkg, cls, requestCode, null);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(activity, extras, pkg, cls, requestCode, options);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param activity The activity.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(activity, extras, pkg, cls,
+ requestCode, getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Activity activity,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(activity, extras, pkg, cls,
+ requestCode, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Intent intent,
+ final int requestCode) {
+ startActivityForResult(intent, activity, requestCode, null);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Intent intent,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(intent, activity, requestCode, options);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Intent intent,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(intent, activity,
+ requestCode, getOptionsBundle(activity, sharedElements));
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param activity The activity.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Activity activity,
+ @NonNull final Intent intent,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(intent, activity,
+ requestCode, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode) {
+ startActivityForResult(fragment, null, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(fragment, null, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(fragment, null, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(fragment, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(fragment, null, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(fragment, enterAnim, exitAnim));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode) {
+ startActivityForResult(fragment, extras, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, null);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(fragment, extras, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, options);
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(fragment, extras, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(fragment, sharedElements));
+ }
+
+ /**
+ * Start the activity.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param fragment The fragment.
+ * @param clz The activity class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final Class extends Activity> clz,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(fragment, extras, Utils.getApp().getPackageName(), clz.getName(),
+ requestCode, getOptionsBundle(fragment, enterAnim, exitAnim));
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param fragment The fragment.
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode) {
+ startActivityForResult(fragment, extras, pkg, cls, requestCode, null);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param fragment The fragment.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(fragment, extras, pkg, cls, requestCode, options);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param fragment The fragment.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(fragment, extras, pkg, cls,
+ requestCode, getOptionsBundle(fragment, sharedElements));
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param extras The Bundle of extras to add to this intent.
+ * @param pkg The name of the package.
+ * @param cls The name of the class.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Bundle extras,
+ @NonNull final Fragment fragment,
+ @NonNull final String pkg,
+ @NonNull final String cls,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(fragment, extras, pkg, cls,
+ requestCode, getOptionsBundle(fragment, enterAnim, exitAnim));
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param fragment The fragment.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Intent intent,
+ final int requestCode) {
+ startActivityForResult(intent, fragment, requestCode, null);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param fragment The fragment.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Intent intent,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ startActivityForResult(intent, fragment, requestCode, options);
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param fragment The fragment.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param sharedElements The names of the shared elements to transfer to the called
+ * Activity and their associated Views.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Intent intent,
+ final int requestCode,
+ final View... sharedElements) {
+ startActivityForResult(intent, fragment,
+ requestCode, getOptionsBundle(fragment, sharedElements));
+ }
+
+ /**
+ * Start the activity for result.
+ *
+ * @param fragment The fragment.
+ * @param intent The description of the activity to start.
+ * @param requestCode if >= 0, this code will be returned in
+ * onActivityResult() when the activity exits.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivityForResult(@NonNull final Fragment fragment,
+ @NonNull final Intent intent,
+ final int requestCode,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivityForResult(intent, fragment,
+ requestCode, getOptionsBundle(fragment, enterAnim, exitAnim));
+ }
+
+ /**
+ * Start activities.
+ *
+ * @param intents The descriptions of the activities to start.
+ */
+ public static void startActivities(@NonNull final Intent[] intents) {
+ startActivities(intents, getTopActivityOrApp(), null);
+ }
+
+ /**
+ * Start activities.
+ *
+ * @param intents The descriptions of the activities to start.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivities(@NonNull final Intent[] intents,
+ @Nullable final Bundle options) {
+ startActivities(intents, getTopActivityOrApp(), options);
+ }
+
+ /**
+ * Start activities.
+ *
+ * @param intents The descriptions of the activities to start.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivities(@NonNull final Intent[] intents,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ Context context = getTopActivityOrApp();
+ startActivities(intents, context, getOptionsBundle(context, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
+ ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start activities.
+ *
+ * @param activity The activity.
+ * @param intents The descriptions of the activities to start.
+ */
+ public static void startActivities(@NonNull final Activity activity,
+ @NonNull final Intent[] intents) {
+ startActivities(intents, activity, null);
+ }
+
+ /**
+ * Start activities.
+ *
+ * @param activity The activity.
+ * @param intents The descriptions of the activities to start.
+ * @param options Additional options for how the Activity should be started.
+ */
+ public static void startActivities(@NonNull final Activity activity,
+ @NonNull final Intent[] intents,
+ @Nullable final Bundle options) {
+ startActivities(intents, activity, options);
+ }
+
+ /**
+ * Start activities.
+ *
+ * @param activity The activity.
+ * @param intents The descriptions of the activities to start.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void startActivities(@NonNull final Activity activity,
+ @NonNull final Intent[] intents,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ startActivities(intents, activity, getOptionsBundle(activity, enterAnim, exitAnim));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Start home activity.
+ */
+ public static void startHomeActivity() {
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(homeIntent);
+ }
+
+ /**
+ * Start the launcher activity.
+ */
+ public static void startLauncherActivity() {
+ startLauncherActivity(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Start the launcher activity.
+ *
+ * @param pkg The name of the package.
+ */
+ public static void startLauncherActivity(@NonNull final String pkg) {
+ String launcherActivity = getLauncherActivity(pkg);
+ if (TextUtils.isEmpty(launcherActivity)) return;
+ startActivity(pkg, launcherActivity);
+ }
+
+ /**
+ * Return the list of activity.
+ *
+ * @return the list of activity
+ */
+ public static List getActivityList() {
+ return UtilsBridge.getActivityList();
+ }
+
+ /**
+ * Return the name of launcher activity.
+ *
+ * @return the name of launcher activity
+ */
+ public static String getLauncherActivity() {
+ return getLauncherActivity(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the name of launcher activity.
+ *
+ * @param pkg The name of the package.
+ * @return the name of launcher activity
+ */
+ public static String getLauncherActivity(@NonNull final String pkg) {
+ if (UtilsBridge.isSpace(pkg)) return "";
+ Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setPackage(pkg);
+ PackageManager pm = Utils.getApp().getPackageManager();
+ List info = pm.queryIntentActivities(intent, 0);
+ if (info == null || info.size() == 0) {
+ return "";
+ }
+ return info.get(0).activityInfo.name;
+ }
+
+ /**
+ * Return the list of main activities.
+ *
+ * @return the list of main activities
+ */
+ public static List getMainActivities() {
+ return getMainActivities(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the list of main activities.
+ *
+ * @param pkg The name of the package.
+ * @return the list of main activities
+ */
+ public static List getMainActivities(@NonNull final String pkg) {
+ List ret = new ArrayList<>();
+ Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.setPackage(pkg);
+ PackageManager pm = Utils.getApp().getPackageManager();
+ List info = pm.queryIntentActivities(intent, 0);
+ int size = info.size();
+ if (size == 0) return ret;
+ for (int i = 0; i < size; i++) {
+ ResolveInfo ri = info.get(i);
+ if (ri.activityInfo.processName.equals(pkg)) {
+ ret.add(ri.activityInfo.name);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Return the top activity in activity's stack.
+ *
+ * @return the top activity in activity's stack
+ */
+ public static Activity getTopActivity() {
+ return UtilsBridge.getTopActivity();
+ }
+
+ /**
+ * Return whether the activity is alive.
+ *
+ * @param context The context.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isActivityAlive(final Context context) {
+ return isActivityAlive(getActivityByContext(context));
+ }
+
+ /**
+ * Return whether the activity is alive.
+ *
+ * @param activity The activity.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isActivityAlive(final Activity activity) {
+ return activity != null && !activity.isFinishing()
+ && (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !activity.isDestroyed());
+ }
+
+ /**
+ * Return whether the activity exists in activity's stack.
+ *
+ * @param activity The activity.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isActivityExistsInStack(@NonNull final Activity activity) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity aActivity : activities) {
+ if (aActivity.equals(activity)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return whether the activity exists in activity's stack.
+ *
+ * @param clz The activity class.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isActivityExistsInStack(@NonNull final Class extends Activity> clz) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity aActivity : activities) {
+ if (aActivity.getClass().equals(clz)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Finish the activity.
+ *
+ * @param activity The activity.
+ */
+ public static void finishActivity(@NonNull final Activity activity) {
+ finishActivity(activity, false);
+ }
+
+ /**
+ * Finish the activity.
+ *
+ * @param activity The activity.
+ * @param isLoadAnim True to use animation for the outgoing activity, false otherwise.
+ */
+ public static void finishActivity(@NonNull final Activity activity, final boolean isLoadAnim) {
+ activity.finish();
+ if (!isLoadAnim) {
+ activity.overridePendingTransition(0, 0);
+ }
+ }
+
+ /**
+ * Finish the activity.
+ *
+ * @param activity The activity.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void finishActivity(@NonNull final Activity activity,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ activity.finish();
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+
+ /**
+ * Finish the activity.
+ *
+ * @param clz The activity class.
+ */
+ public static void finishActivity(@NonNull final Class extends Activity> clz) {
+ finishActivity(clz, false);
+ }
+
+ /**
+ * Finish the activity.
+ *
+ * @param clz The activity class.
+ * @param isLoadAnim True to use animation for the outgoing activity, false otherwise.
+ */
+ public static void finishActivity(@NonNull final Class extends Activity> clz,
+ final boolean isLoadAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity activity : activities) {
+ if (activity.getClass().equals(clz)) {
+ activity.finish();
+ if (!isLoadAnim) {
+ activity.overridePendingTransition(0, 0);
+ }
+ }
+ }
+ }
+
+ /**
+ * Finish the activity.
+ *
+ * @param clz The activity class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void finishActivity(@NonNull final Class extends Activity> clz,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity activity : activities) {
+ if (activity.getClass().equals(clz)) {
+ activity.finish();
+ activity.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+ }
+
+ /**
+ * Finish to the activity.
+ *
+ * @param activity The activity.
+ * @param isIncludeSelf True to include the activity, false otherwise.
+ */
+ public static boolean finishToActivity(@NonNull final Activity activity,
+ final boolean isIncludeSelf) {
+ return finishToActivity(activity, isIncludeSelf, false);
+ }
+
+ /**
+ * Finish to the activity.
+ *
+ * @param activity The activity.
+ * @param isIncludeSelf True to include the activity, false otherwise.
+ * @param isLoadAnim True to use animation for the outgoing activity, false otherwise.
+ */
+ public static boolean finishToActivity(@NonNull final Activity activity,
+ final boolean isIncludeSelf,
+ final boolean isLoadAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity act : activities) {
+ if (act.equals(activity)) {
+ if (isIncludeSelf) {
+ finishActivity(act, isLoadAnim);
+ }
+ return true;
+ }
+ finishActivity(act, isLoadAnim);
+ }
+ return false;
+ }
+
+ /**
+ * Finish to the activity.
+ *
+ * @param activity The activity.
+ * @param isIncludeSelf True to include the activity, false otherwise.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static boolean finishToActivity(@NonNull final Activity activity,
+ final boolean isIncludeSelf,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity act : activities) {
+ if (act.equals(activity)) {
+ if (isIncludeSelf) {
+ finishActivity(act, enterAnim, exitAnim);
+ }
+ return true;
+ }
+ finishActivity(act, enterAnim, exitAnim);
+ }
+ return false;
+ }
+
+ /**
+ * Finish to the activity.
+ *
+ * @param clz The activity class.
+ * @param isIncludeSelf True to include the activity, false otherwise.
+ */
+ public static boolean finishToActivity(@NonNull final Class extends Activity> clz,
+ final boolean isIncludeSelf) {
+ return finishToActivity(clz, isIncludeSelf, false);
+ }
+
+ /**
+ * Finish to the activity.
+ *
+ * @param clz The activity class.
+ * @param isIncludeSelf True to include the activity, false otherwise.
+ * @param isLoadAnim True to use animation for the outgoing activity, false otherwise.
+ */
+ public static boolean finishToActivity(@NonNull final Class extends Activity> clz,
+ final boolean isIncludeSelf,
+ final boolean isLoadAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity act : activities) {
+ if (act.getClass().equals(clz)) {
+ if (isIncludeSelf) {
+ finishActivity(act, isLoadAnim);
+ }
+ return true;
+ }
+ finishActivity(act, isLoadAnim);
+ }
+ return false;
+ }
+
+ /**
+ * Finish to the activity.
+ *
+ * @param clz The activity class.
+ * @param isIncludeSelf True to include the activity, false otherwise.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static boolean finishToActivity(@NonNull final Class extends Activity> clz,
+ final boolean isIncludeSelf,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity act : activities) {
+ if (act.getClass().equals(clz)) {
+ if (isIncludeSelf) {
+ finishActivity(act, enterAnim, exitAnim);
+ }
+ return true;
+ }
+ finishActivity(act, enterAnim, exitAnim);
+ }
+ return false;
+ }
+
+ /**
+ * Finish the activities whose type not equals the activity class.
+ *
+ * @param clz The activity class.
+ */
+ public static void finishOtherActivities(@NonNull final Class extends Activity> clz) {
+ finishOtherActivities(clz, false);
+ }
+
+
+ /**
+ * Finish the activities whose type not equals the activity class.
+ *
+ * @param clz The activity class.
+ * @param isLoadAnim True to use animation for the outgoing activity, false otherwise.
+ */
+ public static void finishOtherActivities(@NonNull final Class extends Activity> clz,
+ final boolean isLoadAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity act : activities) {
+ if (!act.getClass().equals(clz)) {
+ finishActivity(act, isLoadAnim);
+ }
+ }
+ }
+
+ /**
+ * Finish the activities whose type not equals the activity class.
+ *
+ * @param clz The activity class.
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void finishOtherActivities(@NonNull final Class extends Activity> clz,
+ @AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (Activity act : activities) {
+ if (!act.getClass().equals(clz)) {
+ finishActivity(act, enterAnim, exitAnim);
+ }
+ }
+ }
+
+ /**
+ * Finish all of activities.
+ */
+ public static void finishAllActivities() {
+ finishAllActivities(false);
+ }
+
+ /**
+ * Finish all of activities.
+ *
+ * @param isLoadAnim True to use animation for the outgoing activity, false otherwise.
+ */
+ public static void finishAllActivities(final boolean isLoadAnim) {
+ List activityList = UtilsBridge.getActivityList();
+ for (Activity act : activityList) {
+ // sActivityList remove the index activity at onActivityDestroyed
+ act.finish();
+ if (!isLoadAnim) {
+ act.overridePendingTransition(0, 0);
+ }
+ }
+ }
+
+ /**
+ * Finish all of activities.
+ *
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void finishAllActivities(@AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ List activityList = UtilsBridge.getActivityList();
+ for (Activity act : activityList) {
+ // sActivityList remove the index activity at onActivityDestroyed
+ act.finish();
+ act.overridePendingTransition(enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Finish all of activities except the newest activity.
+ */
+ public static void finishAllActivitiesExceptNewest() {
+ finishAllActivitiesExceptNewest(false);
+ }
+
+ /**
+ * Finish all of activities except the newest activity.
+ *
+ * @param isLoadAnim True to use animation for the outgoing activity, false otherwise.
+ */
+ public static void finishAllActivitiesExceptNewest(final boolean isLoadAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (int i = 1; i < activities.size(); i++) {
+ finishActivity(activities.get(i), isLoadAnim);
+ }
+ }
+
+ /**
+ * Finish all of activities except the newest activity.
+ *
+ * @param enterAnim A resource ID of the animation resource to use for the
+ * incoming activity.
+ * @param exitAnim A resource ID of the animation resource to use for the
+ * outgoing activity.
+ */
+ public static void finishAllActivitiesExceptNewest(@AnimRes final int enterAnim,
+ @AnimRes final int exitAnim) {
+ List activities = UtilsBridge.getActivityList();
+ for (int i = 1; i < activities.size(); i++) {
+ finishActivity(activities.get(i), enterAnim, exitAnim);
+ }
+ }
+
+ /**
+ * Return the icon of activity.
+ *
+ * @param activity The activity.
+ * @return the icon of activity
+ */
+ @Nullable
+ public static Drawable getActivityIcon(@NonNull final Activity activity) {
+ return getActivityIcon(activity.getComponentName());
+ }
+
+ /**
+ * Return the icon of activity.
+ *
+ * @param clz The activity class.
+ * @return the icon of activity
+ */
+ @Nullable
+ public static Drawable getActivityIcon(@NonNull final Class extends Activity> clz) {
+ return getActivityIcon(new ComponentName(Utils.getApp(), clz));
+ }
+
+ /**
+ * Return the icon of activity.
+ *
+ * @param activityName The name of activity.
+ * @return the icon of activity
+ */
+ @Nullable
+ public static Drawable getActivityIcon(@NonNull final ComponentName activityName) {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ try {
+ return pm.getActivityIcon(activityName);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Return the logo of activity.
+ *
+ * @param activity The activity.
+ * @return the logo of activity
+ */
+ @Nullable
+ public static Drawable getActivityLogo(@NonNull final Activity activity) {
+ return getActivityLogo(activity.getComponentName());
+ }
+
+ /**
+ * Return the logo of activity.
+ *
+ * @param clz The activity class.
+ * @return the logo of activity
+ */
+ @Nullable
+ public static Drawable getActivityLogo(@NonNull final Class extends Activity> clz) {
+ return getActivityLogo(new ComponentName(Utils.getApp(), clz));
+ }
+
+ /**
+ * Return the logo of activity.
+ *
+ * @param activityName The name of activity.
+ * @return the logo of activity
+ */
+ @Nullable
+ public static Drawable getActivityLogo(@NonNull final ComponentName activityName) {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ try {
+ return pm.getActivityLogo(activityName);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static void startActivity(final Context context,
+ final Bundle extras,
+ final String pkg,
+ final String cls,
+ @Nullable final Bundle options) {
+ Intent intent = new Intent();
+ if (extras != null) intent.putExtras(extras);
+ intent.setComponent(new ComponentName(pkg, cls));
+ startActivity(intent, context, options);
+ }
+
+ private static boolean startActivity(final Intent intent,
+ final Context context,
+ final Bundle options) {
+ if (!isIntentAvailable(intent)) {
+ Log.e("ActivityUtils", "intent is unavailable");
+ return false;
+ }
+ if (!(context instanceof Activity)) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+ if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ context.startActivity(intent, options);
+ } else {
+ context.startActivity(intent);
+ }
+ return true;
+ }
+
+ private static boolean isIntentAvailable(final Intent intent) {
+// return Utils.getApp()
+// .getPackageManager()
+// .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
+// .size() > 0;
+ return true;
+ }
+
+ private static boolean startActivityForResult(final Activity activity,
+ final Bundle extras,
+ final String pkg,
+ final String cls,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ Intent intent = new Intent();
+ if (extras != null) intent.putExtras(extras);
+ intent.setComponent(new ComponentName(pkg, cls));
+ return startActivityForResult(intent, activity, requestCode, options);
+ }
+
+ private static boolean startActivityForResult(final Intent intent,
+ final Activity activity,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ if (!isIntentAvailable(intent)) {
+ Log.e("ActivityUtils", "intent is unavailable");
+ return false;
+ }
+ if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ activity.startActivityForResult(intent, requestCode, options);
+ } else {
+ activity.startActivityForResult(intent, requestCode);
+ }
+ return true;
+ }
+
+ private static void startActivities(final Intent[] intents,
+ final Context context,
+ @Nullable final Bundle options) {
+ if (!(context instanceof Activity)) {
+ for (Intent intent : intents) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+ }
+ if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ context.startActivities(intents, options);
+ } else {
+ context.startActivities(intents);
+ }
+ }
+
+ private static boolean startActivityForResult(final Fragment fragment,
+ final Bundle extras,
+ final String pkg,
+ final String cls,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ Intent intent = new Intent();
+ if (extras != null) intent.putExtras(extras);
+ intent.setComponent(new ComponentName(pkg, cls));
+ return startActivityForResult(intent, fragment, requestCode, options);
+ }
+
+ private static boolean startActivityForResult(final Intent intent,
+ final Fragment fragment,
+ final int requestCode,
+ @Nullable final Bundle options) {
+ if (!isIntentAvailable(intent)) {
+ Log.e("ActivityUtils", "intent is unavailable");
+ return false;
+ }
+ if (fragment.getActivity() == null) {
+ Log.e("ActivityUtils", "Fragment " + fragment + " not attached to Activity");
+ return false;
+ }
+ if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ fragment.startActivityForResult(intent, requestCode, options);
+ } else {
+ fragment.startActivityForResult(intent, requestCode);
+ }
+ return true;
+ }
+
+ private static Bundle getOptionsBundle(final Fragment fragment,
+ final int enterAnim,
+ final int exitAnim) {
+ Activity activity = fragment.getActivity();
+ if (activity == null) return null;
+ return ActivityOptionsCompat.makeCustomAnimation(activity, enterAnim, exitAnim).toBundle();
+ }
+
+ private static Bundle getOptionsBundle(final Context context,
+ final int enterAnim,
+ final int exitAnim) {
+ return ActivityOptionsCompat.makeCustomAnimation(context, enterAnim, exitAnim).toBundle();
+ }
+
+ private static Bundle getOptionsBundle(final Fragment fragment,
+ final View[] sharedElements) {
+ Activity activity = fragment.getActivity();
+ if (activity == null) return null;
+ return getOptionsBundle(activity, sharedElements);
+ }
+
+ private static Bundle getOptionsBundle(final Activity activity,
+ final View[] sharedElements) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null;
+ if (sharedElements == null) return null;
+ int len = sharedElements.length;
+ if (len <= 0) return null;
+ @SuppressWarnings("unchecked")
+ Pair[] pairs = new Pair[len];
+ for (int i = 0; i < len; i++) {
+ pairs[i] = Pair.create(sharedElements[i], sharedElements[i].getTransitionName());
+ }
+ return ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs).toBundle();
+ }
+
+ private static Context getTopActivityOrApp() {
+ if (UtilsBridge.isAppForeground()) {
+ Activity topActivity = getTopActivity();
+ return topActivity == null ? Utils.getApp() : topActivity;
+ } else {
+ return Utils.getApp();
+ }
+ }
+}
diff --git a/common/src/main/java/com/blankj/utilcode/util/AdaptScreenUtils.java b/common/src/main/java/com/blankj/utilcode/util/AdaptScreenUtils.java
new file mode 100644
index 0000000..aef62a4
--- /dev/null
+++ b/common/src/main/java/com/blankj/utilcode/util/AdaptScreenUtils.java
@@ -0,0 +1,165 @@
+package com.blankj.utilcode.util;
+
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+
+/**
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2018/11/15
+ * desc : utils about adapt screen
+ *
+ */
+public final class AdaptScreenUtils {
+
+ private static List sMetricsFields;
+
+ private AdaptScreenUtils() {
+ throw new UnsupportedOperationException("u can't instantiate me...");
+ }
+
+ /**
+ * Adapt for the horizontal screen, and call it in {@link android.app.Activity#getResources()}.
+ */
+ @NonNull
+ public static Resources adaptWidth(@NonNull final Resources resources, final int designWidth) {
+ float newXdpi = (resources.getDisplayMetrics().widthPixels * 72f) / designWidth;
+ applyDisplayMetrics(resources, newXdpi);
+ return resources;
+ }
+
+ /**
+ * Adapt for the vertical screen, and call it in {@link android.app.Activity#getResources()}.
+ */
+ @NonNull
+ public static Resources adaptHeight(@NonNull final Resources resources, final int designHeight) {
+ return adaptHeight(resources, designHeight, false);
+ }
+
+ /**
+ * Adapt for the vertical screen, and call it in {@link android.app.Activity#getResources()}.
+ */
+ @NonNull
+ public static Resources adaptHeight(@NonNull final Resources resources, final int designHeight, final boolean includeNavBar) {
+ float screenHeight = (resources.getDisplayMetrics().heightPixels
+ + (includeNavBar ? getNavBarHeight(resources) : 0)) * 72f;
+ float newXdpi = screenHeight / designHeight;
+ applyDisplayMetrics(resources, newXdpi);
+ return resources;
+ }
+
+ private static int getNavBarHeight(@NonNull final Resources resources) {
+ int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
+ if (resourceId != 0) {
+ return resources.getDimensionPixelSize(resourceId);
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * @param resources The resources.
+ * @return the resource
+ */
+ @NonNull
+ public static Resources closeAdapt(@NonNull final Resources resources) {
+ float newXdpi = Resources.getSystem().getDisplayMetrics().density * 72f;
+ applyDisplayMetrics(resources, newXdpi);
+ return resources;
+ }
+
+ /**
+ * Value of pt to value of px.
+ *
+ * @param ptValue The value of pt.
+ * @return value of px
+ */
+ public static int pt2Px(final float ptValue) {
+ DisplayMetrics metrics = Utils.getApp().getResources().getDisplayMetrics();
+ return (int) (ptValue * metrics.xdpi / 72f + 0.5);
+ }
+
+ /**
+ * Value of px to value of pt.
+ *
+ * @param pxValue The value of px.
+ * @return value of pt
+ */
+ public static int px2Pt(final float pxValue) {
+ DisplayMetrics metrics = Utils.getApp().getResources().getDisplayMetrics();
+ return (int) (pxValue * 72 / metrics.xdpi + 0.5);
+ }
+
+ private static void applyDisplayMetrics(@NonNull final Resources resources, final float newXdpi) {
+ resources.getDisplayMetrics().xdpi = newXdpi;
+ Utils.getApp().getResources().getDisplayMetrics().xdpi = newXdpi;
+ applyOtherDisplayMetrics(resources, newXdpi);
+ }
+
+ static Runnable getPreLoadRunnable() {
+ return new Runnable() {
+ @Override
+ public void run() {
+ preLoad();
+ }
+ };
+ }
+
+ private static void preLoad() {
+ applyDisplayMetrics(Resources.getSystem(), Resources.getSystem().getDisplayMetrics().xdpi);
+ }
+
+ private static void applyOtherDisplayMetrics(final Resources resources, final float newXdpi) {
+ if (sMetricsFields == null) {
+ sMetricsFields = new ArrayList<>();
+ Class resCls = resources.getClass();
+ Field[] declaredFields = resCls.getDeclaredFields();
+ while (declaredFields != null && declaredFields.length > 0) {
+ for (Field field : declaredFields) {
+ if (field.getType().isAssignableFrom(DisplayMetrics.class)) {
+ field.setAccessible(true);
+ DisplayMetrics tmpDm = getMetricsFromField(resources, field);
+ if (tmpDm != null) {
+ sMetricsFields.add(field);
+ tmpDm.xdpi = newXdpi;
+ }
+ }
+ }
+ resCls = resCls.getSuperclass();
+ if (resCls != null) {
+ declaredFields = resCls.getDeclaredFields();
+ } else {
+ break;
+ }
+ }
+ } else {
+ applyMetricsFields(resources, newXdpi);
+ }
+ }
+
+ private static void applyMetricsFields(final Resources resources, final float newXdpi) {
+ for (Field metricsField : sMetricsFields) {
+ try {
+ DisplayMetrics dm = (DisplayMetrics) metricsField.get(resources);
+ if (dm != null) dm.xdpi = newXdpi;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static DisplayMetrics getMetricsFromField(final Resources resources, final Field field) {
+ try {
+ return (DisplayMetrics) field.get(resources);
+ } catch (Exception ignore) {
+ return null;
+ }
+ }
+}
diff --git a/common/src/main/java/com/blankj/utilcode/util/ApiUtils.java b/common/src/main/java/com/blankj/utilcode/util/ApiUtils.java
new file mode 100644
index 0000000..2fb3a88
--- /dev/null
+++ b/common/src/main/java/com/blankj/utilcode/util/ApiUtils.java
@@ -0,0 +1,115 @@
+package com.blankj.utilcode.util;
+
+import android.util.Log;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2019/07/09
+ * desc : utils about api
+ *
+ */
+public final class ApiUtils {
+
+ private static final String TAG = "ApiUtils";
+
+ private Map mApiMap = new ConcurrentHashMap<>();
+ private Map mInjectApiImplMap = new HashMap<>();
+
+ private ApiUtils() {
+ init();
+ }
+
+ /**
+ * It'll be injected the implClasses who have {@link ApiUtils.Api} annotation
+ * by function of {@link ApiUtils#registerImpl} when execute transform task.
+ */
+ private void init() {/*inject*/}
+
+ private void registerImpl(Class implClass) {
+ mInjectApiImplMap.put(implClass.getSuperclass(), implClass);
+ }
+
+ /**
+ * Get api.
+ *
+ * @param apiClass The class of api.
+ * @param The type.
+ * @return the api
+ */
+ @Nullable
+ public static T getApi(@NonNull final Class apiClass) {
+ return getInstance().getApiInner(apiClass);
+ }
+
+ public static void register(@Nullable Class extends BaseApi> implClass) {
+ if (implClass == null) return;
+ getInstance().registerImpl(implClass);
+ }
+
+ @NonNull
+ public static String toString_() {
+ return getInstance().toString();
+ }
+
+ @Override
+ public String toString() {
+ return "ApiUtils: " + mInjectApiImplMap;
+ }
+
+ private static ApiUtils getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ private Result getApiInner(Class apiClass) {
+ BaseApi api = mApiMap.get(apiClass);
+ if (api != null) {
+ return (Result) api;
+ }
+ synchronized (apiClass) {
+ api = mApiMap.get(apiClass);
+ if (api != null) {
+ return (Result) api;
+ }
+ Class implClass = mInjectApiImplMap.get(apiClass);
+ if (implClass != null) {
+ try {
+ api = (BaseApi) implClass.newInstance();
+ mApiMap.put(apiClass, api);
+ return (Result) api;
+ } catch (Exception ignore) {
+ Log.e(TAG, "The <" + implClass + "> has no parameterless constructor.");
+ return null;
+ }
+ } else {
+ Log.e(TAG, "The <" + apiClass + "> doesn't implement.");
+ return null;
+ }
+ }
+ }
+
+ private static class LazyHolder {
+ private static final ApiUtils INSTANCE = new ApiUtils();
+ }
+
+ @Target({ElementType.TYPE})
+ @Retention(RetentionPolicy.CLASS)
+ public @interface Api {
+ boolean isMock() default false;
+ }
+
+ public static class BaseApi {
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/blankj/utilcode/util/AppUtils.java b/common/src/main/java/com/blankj/utilcode/util/AppUtils.java
new file mode 100644
index 0000000..3a07653
--- /dev/null
+++ b/common/src/main/java/com/blankj/utilcode/util/AppUtils.java
@@ -0,0 +1,1024 @@
+package com.blankj.utilcode.util;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.content.pm.SigningInfo;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/08/02
+ * desc : utils about app
+ *
+ */
+public final class AppUtils {
+
+ private AppUtils() {
+ throw new UnsupportedOperationException("u can't instantiate me...");
+ }
+
+ /**
+ * Register the status of application changed listener.
+ *
+ * @param listener The status of application changed listener
+ */
+ public static void registerAppStatusChangedListener(@NonNull final Utils.OnAppStatusChangedListener listener) {
+ UtilsBridge.addOnAppStatusChangedListener(listener);
+ }
+
+ /**
+ * Unregister the status of application changed listener.
+ *
+ * @param listener The status of application changed listener
+ */
+ public static void unregisterAppStatusChangedListener(@NonNull final Utils.OnAppStatusChangedListener listener) {
+ UtilsBridge.removeOnAppStatusChangedListener(listener);
+ }
+
+ /**
+ * Install the app.
+ *
Target APIs greater than 25 must hold
+ * {@code }
+ *
+ * @param filePath The path of file.
+ */
+ public static void installApp(final String filePath) {
+ installApp(UtilsBridge.getFileByPath(filePath));
+ }
+
+ /**
+ * Install the app.
+ *
Target APIs greater than 25 must hold
+ * {@code }
Target APIs greater than 25 must hold
+ * {@code }
+ *
+ * @param uri The uri.
+ */
+ public static void installApp(final Uri uri) {
+ Intent installAppIntent = UtilsBridge.getInstallAppIntent(uri);
+ if (installAppIntent == null) return;
+ Utils.getApp().startActivity(installAppIntent);
+ }
+
+ /**
+ * Uninstall the app.
+ *
Target APIs greater than 25 must hold
+ * Must hold {@code }
+ *
+ * @param packageName The name of the package.
+ */
+ public static void uninstallApp(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return;
+ Utils.getApp().startActivity(UtilsBridge.getUninstallAppIntent(packageName));
+ }
+
+ /**
+ * Return whether the app is installed.
+ *
+ * @param pkgName The name of the package.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppInstalled(final String pkgName) {
+ if (UtilsBridge.isSpace(pkgName)) return false;
+ PackageManager pm = Utils.getApp().getPackageManager();
+ try {
+ return pm.getApplicationInfo(pkgName, 0).enabled;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Return whether the application with root permission.
+ *
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppRoot() {
+ ShellUtils.CommandResult result = UtilsBridge.execCmd("echo root", true);
+ return result.result == 0;
+ }
+
+ /**
+ * Return whether it is a debug application.
+ *
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppDebug() {
+ return isAppDebug(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return whether it is a debug application.
+ *
+ * @param packageName The name of the package.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppDebug(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return false;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
+ return (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * Return whether it is a system application.
+ *
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppSystem() {
+ return isAppSystem(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return whether it is a system application.
+ *
+ * @param packageName The name of the package.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppSystem(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return false;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
+ return (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * Return whether application is foreground.
+ *
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppForeground() {
+ return UtilsBridge.isAppForeground();
+ }
+
+ /**
+ * Return whether application is foreground.
+ *
Target APIs greater than 21 must hold
+ * {@code }
+ *
+ * @param pkgName The name of the package.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppForeground(@NonNull final String pkgName) {
+ return !UtilsBridge.isSpace(pkgName) && pkgName.equals(UtilsBridge.getForegroundProcessName());
+ }
+
+ /**
+ * Return whether application is running.
+ *
+ * @param pkgName The name of the package.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isAppRunning(final String pkgName) {
+ if (UtilsBridge.isSpace(pkgName)) return false;
+ ActivityManager am = (ActivityManager) Utils.getApp().getSystemService(Context.ACTIVITY_SERVICE);
+ if (am != null) {
+ List taskInfo = am.getRunningTasks(Integer.MAX_VALUE);
+ if (taskInfo != null && taskInfo.size() > 0) {
+ for (ActivityManager.RunningTaskInfo aInfo : taskInfo) {
+ if (aInfo.baseActivity != null) {
+ if (pkgName.equals(aInfo.baseActivity.getPackageName())) {
+ return true;
+ }
+ }
+ }
+ }
+ List serviceInfo = am.getRunningServices(Integer.MAX_VALUE);
+ if (serviceInfo != null && serviceInfo.size() > 0) {
+ for (ActivityManager.RunningServiceInfo aInfo : serviceInfo) {
+ if (pkgName.equals(aInfo.service.getPackageName())) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Launch the application.
+ *
+ * @param packageName The name of the package.
+ */
+ public static void launchApp(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return;
+ Intent launchAppIntent = UtilsBridge.getLaunchAppIntent(packageName);
+ if (launchAppIntent == null) {
+ Log.e("AppUtils", "Didn't exist launcher activity.");
+ return;
+ }
+ Utils.getApp().startActivity(launchAppIntent);
+ }
+
+ /**
+ * Relaunch the application.
+ */
+ public static void relaunchApp() {
+ relaunchApp(false);
+ }
+
+ /**
+ * Relaunch the application.
+ *
+ * @param isKillProcess True to kill the process, false otherwise.
+ */
+ public static void relaunchApp(final boolean isKillProcess) {
+ Intent intent = UtilsBridge.getLaunchAppIntent(Utils.getApp().getPackageName());
+ if (intent == null) {
+ Log.e("AppUtils", "Didn't exist launcher activity.");
+ return;
+ }
+ intent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
+ );
+ Utils.getApp().startActivity(intent);
+ if (!isKillProcess) return;
+ android.os.Process.killProcess(android.os.Process.myPid());
+ System.exit(0);
+ }
+
+ /**
+ * Launch the application's details settings.
+ */
+ public static void launchAppDetailsSettings() {
+ launchAppDetailsSettings(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Launch the application's details settings.
+ *
+ * @param pkgName The name of the package.
+ */
+ public static void launchAppDetailsSettings(final String pkgName) {
+ if (UtilsBridge.isSpace(pkgName)) return;
+ Intent intent = UtilsBridge.getLaunchAppDetailsSettingsIntent(pkgName, true);
+ if (!UtilsBridge.isIntentAvailable(intent)) return;
+ Utils.getApp().startActivity(intent);
+ }
+
+ /**
+ * Launch the application's details settings.
+ *
+ * @param activity The activity.
+ * @param requestCode The requestCode.
+ */
+ public static void launchAppDetailsSettings(final Activity activity, final int requestCode) {
+ launchAppDetailsSettings(activity, requestCode, Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Launch the application's details settings.
+ *
+ * @param activity The activity.
+ * @param requestCode The requestCode.
+ * @param pkgName The name of the package.
+ */
+ public static void launchAppDetailsSettings(final Activity activity, final int requestCode, final String pkgName) {
+ if (activity == null || UtilsBridge.isSpace(pkgName)) return;
+ Intent intent = UtilsBridge.getLaunchAppDetailsSettingsIntent(pkgName, false);
+ if (!UtilsBridge.isIntentAvailable(intent)) return;
+ activity.startActivityForResult(intent, requestCode);
+ }
+
+ /**
+ * Exit the application.
+ */
+ public static void exitApp() {
+ UtilsBridge.finishAllActivities();
+ System.exit(0);
+ }
+
+ /**
+ * Return the application's icon.
+ *
+ * @return the application's icon
+ */
+ @Nullable
+ public static Drawable getAppIcon() {
+ return getAppIcon(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's icon.
+ *
+ * @param packageName The name of the package.
+ * @return the application's icon
+ */
+ @Nullable
+ public static Drawable getAppIcon(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return null;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ return pi == null ? null : pi.applicationInfo.loadIcon(pm);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Return the application's icon resource identifier.
+ *
+ * @return the application's icon resource identifier
+ */
+ public static int getAppIconId() {
+ return getAppIconId(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's icon resource identifier.
+ *
+ * @param packageName The name of the package.
+ * @return the application's icon resource identifier
+ */
+ public static int getAppIconId(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return 0;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ return pi == null ? 0 : pi.applicationInfo.icon;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+
+ /**
+ * Return true if this is the first ever time that the application is installed on the device.
+ *
+ * @return true if this is the first ever time that the application is installed on the device.
+ */
+ public static boolean isFirstTimeInstall() {
+ try {
+ long firstInstallTime = Utils.getApp().getPackageManager().getPackageInfo(getAppPackageName(), 0).firstInstallTime;
+ long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(getAppPackageName(), 0).lastUpdateTime;
+ return firstInstallTime == lastUpdateTime;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Return true if app was previously installed and this one is an update/upgrade to that one, returns false if this is a fresh installation and not an update/upgrade.
+ *
+ * @return true if app was previously installed and this one is an update/upgrade to that one, returns false if this is a fresh installation and not an update/upgrade.
+ */
+ public static boolean isAppUpgraded() {
+ try {
+ long firstInstallTime = Utils.getApp().getPackageManager().getPackageInfo(getAppPackageName(), 0).firstInstallTime;
+ long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(getAppPackageName(), 0).lastUpdateTime;
+ return firstInstallTime != lastUpdateTime;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+
+ /**
+ * Return the application's package name.
+ *
+ * @return the application's package name
+ */
+ @NonNull
+ public static String getAppPackageName() {
+ return Utils.getApp().getPackageName();
+ }
+
+ /**
+ * Return the application's name.
+ *
+ * @return the application's name
+ */
+ @NonNull
+ public static String getAppName() {
+ return getAppName(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's name.
+ *
+ * @param packageName The name of the package.
+ * @return the application's name
+ */
+ @NonNull
+ public static String getAppName(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return "";
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ return pi == null ? "" : pi.applicationInfo.loadLabel(pm).toString();
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ /**
+ * Return the application's path.
+ *
+ * @return the application's path
+ */
+ @NonNull
+ public static String getAppPath() {
+ return getAppPath(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's path.
+ *
+ * @param packageName The name of the package.
+ * @return the application's path
+ */
+ @NonNull
+ public static String getAppPath(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return "";
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ return pi == null ? "" : pi.applicationInfo.sourceDir;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ /**
+ * Return the application's version name.
+ *
+ * @return the application's version name
+ */
+ @NonNull
+ public static String getAppVersionName() {
+ return getAppVersionName(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's version name.
+ *
+ * @param packageName The name of the package.
+ * @return the application's version name
+ */
+ @NonNull
+ public static String getAppVersionName(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return "";
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ return pi == null ? "" : pi.versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ /**
+ * Return the application's version code.
+ *
+ * @return the application's version code
+ */
+ public static int getAppVersionCode() {
+ return getAppVersionCode(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's version code.
+ *
+ * @param packageName The name of the package.
+ * @return the application's version code
+ */
+ public static int getAppVersionCode(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return -1;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ return pi == null ? -1 : pi.versionCode;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ /**
+ * Return the application's minimum sdk version code.
+ *
+ * @return the application's minimum sdk version code
+ */
+ public static int getAppMinSdkVersion() {
+ return getAppMinSdkVersion(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's minimum sdk version code.
+ *
+ * @param packageName The name of the package.
+ * @return the application's minimum sdk version code
+ */
+ public static int getAppMinSdkVersion(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return -1;
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N) return -1;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ if (null == pi) return -1;
+ ApplicationInfo ai = pi.applicationInfo;
+ return null == ai ? -1 : ai.minSdkVersion;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ /**
+ * Return the application's target sdk version code.
+ *
+ * @return the application's target sdk version code
+ */
+ public static int getAppTargetSdkVersion() {
+ return getAppTargetSdkVersion(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's target sdk version code.
+ *
+ * @param packageName The name of the package.
+ * @return the application's target sdk version code
+ */
+ public static int getAppTargetSdkVersion(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return -1;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ if (null == pi) return -1;
+ ApplicationInfo ai = pi.applicationInfo;
+ return null == ai ? -1 : ai.targetSdkVersion;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ /**
+ * Return the application's signature.
+ *
+ * @return the application's signature
+ */
+ @Nullable
+ public static Signature[] getAppSignatures() {
+ return getAppSignatures(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's signature.
+ *
+ * @param packageName The name of the package.
+ * @return the application's signature
+ */
+ @Nullable
+ public static Signature[] getAppSignatures(final String packageName) {
+ if (UtilsBridge.isSpace(packageName)) return null;
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ PackageInfo pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES);
+ if (pi == null) return null;
+
+ SigningInfo signingInfo = pi.signingInfo;
+ if (signingInfo.hasMultipleSigners()) {
+ return signingInfo.getApkContentsSigners();
+ } else {
+ return signingInfo.getSigningCertificateHistory();
+ }
+ } else {
+ PackageInfo pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+ if (pi == null) return null;
+
+ return pi.signatures;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Return the application's signature.
+ *
+ * @param file The file.
+ * @return the application's signature
+ */
+ @Nullable
+ public static Signature[] getAppSignatures(final File file) {
+ if (file == null) return null;
+ PackageManager pm = Utils.getApp().getPackageManager();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ PackageInfo pi = pm.getPackageArchiveInfo(file.getAbsolutePath(), PackageManager.GET_SIGNING_CERTIFICATES);
+ if (pi == null) return null;
+
+ SigningInfo signingInfo = pi.signingInfo;
+ if (signingInfo.hasMultipleSigners()) {
+ return signingInfo.getApkContentsSigners();
+ } else {
+ return signingInfo.getSigningCertificateHistory();
+ }
+ } else {
+ PackageInfo pi = pm.getPackageArchiveInfo(file.getAbsolutePath(), PackageManager.GET_SIGNATURES);
+ if (pi == null) return null;
+
+ return pi.signatures;
+ }
+ }
+
+ /**
+ * Return the application's signature for SHA1 value.
+ *
+ * @return the application's signature for SHA1 value
+ */
+ @NonNull
+ public static List getAppSignaturesSHA1() {
+ return getAppSignaturesSHA1(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's signature for SHA1 value.
+ *
+ * @param packageName The name of the package.
+ * @return the application's signature for SHA1 value
+ */
+ @NonNull
+ public static List getAppSignaturesSHA1(final String packageName) {
+ return getAppSignaturesHash(packageName, "SHA1");
+ }
+
+ /**
+ * Return the application's signature for SHA256 value.
+ *
+ * @return the application's signature for SHA256 value
+ */
+ @NonNull
+ public static List getAppSignaturesSHA256() {
+ return getAppSignaturesSHA256(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's signature for SHA256 value.
+ *
+ * @param packageName The name of the package.
+ * @return the application's signature for SHA256 value
+ */
+ @NonNull
+ public static List getAppSignaturesSHA256(final String packageName) {
+ return getAppSignaturesHash(packageName, "SHA256");
+ }
+
+ /**
+ * Return the application's signature for MD5 value.
+ *
+ * @return the application's signature for MD5 value
+ */
+ @NonNull
+ public static List getAppSignaturesMD5() {
+ return getAppSignaturesMD5(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's signature for MD5 value.
+ *
+ * @param packageName The name of the package.
+ * @return the application's signature for MD5 value
+ */
+ @NonNull
+ public static List getAppSignaturesMD5(final String packageName) {
+ return getAppSignaturesHash(packageName, "MD5");
+ }
+
+ /**
+ * Return the application's user-ID.
+ *
+ * @return the application's signature for MD5 value
+ */
+ public static int getAppUid() {
+ return getAppUid(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's user-ID.
+ *
+ * @param pkgName The name of the package.
+ * @return the application's signature for MD5 value
+ */
+ public static int getAppUid(String pkgName) {
+ try {
+ return Utils.getApp().getPackageManager().getApplicationInfo(pkgName, 0).uid;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ private static List getAppSignaturesHash(final String packageName, final String algorithm) {
+ ArrayList result = new ArrayList<>();
+ if (UtilsBridge.isSpace(packageName)) return result;
+ Signature[] signatures = getAppSignatures(packageName);
+ if (signatures == null || signatures.length <= 0) return result;
+ for (Signature signature : signatures) {
+ String hash = UtilsBridge.bytes2HexString(UtilsBridge.hashTemplate(signature.toByteArray(), algorithm))
+ .replaceAll("(?<=[0-9A-F]{2})[0-9A-F]{2}", ":$0");
+ result.add(hash);
+ }
+ return result;
+ }
+
+ /**
+ * Return the application's information.
+ *
+ *
name of package
+ *
icon
+ *
name
+ *
path of package
+ *
version name
+ *
version code
+ *
minimum sdk version code
+ *
target sdk version code
+ *
is system
+ *
+ *
+ * @return the application's information
+ */
+ @Nullable
+ public static AppInfo getAppInfo() {
+ return getAppInfo(Utils.getApp().getPackageName());
+ }
+
+ /**
+ * Return the application's information.
+ *
+ *
name of package
+ *
icon
+ *
name
+ *
path of package
+ *
version name
+ *
version code
+ *
minimum sdk version code
+ *
target sdk version code
+ *
is system
+ *
+ *
+ * @param packageName The name of the package.
+ * @return the application's information
+ */
+ @Nullable
+ public static AppInfo getAppInfo(final String packageName) {
+ try {
+ PackageManager pm = Utils.getApp().getPackageManager();
+ if (pm == null) return null;
+ return getBean(pm, pm.getPackageInfo(packageName, 0));
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Return the applications' information.
+ *
+ * @return the applications' information
+ */
+ @NonNull
+ public static List getAppsInfo() {
+ List list = new ArrayList<>();
+ PackageManager pm = Utils.getApp().getPackageManager();
+ if (pm == null) return list;
+ List installedPackages = pm.getInstalledPackages(0);
+ for (PackageInfo pi : installedPackages) {
+ AppInfo ai = getBean(pm, pi);
+ if (ai == null) continue;
+ list.add(ai);
+ }
+ return list;
+ }
+
+ /**
+ * Return the application's package information.
+ *
+ * @return the application's package information
+ */
+ @Nullable
+ public static AppUtils.AppInfo getApkInfo(final File apkFile) {
+ if (apkFile == null || !apkFile.isFile() || !apkFile.exists()) return null;
+ return getApkInfo(apkFile.getAbsolutePath());
+ }
+
+ /**
+ * Return the application's package information.
+ *
+ * @return the application's package information
+ */
+ @Nullable
+ public static AppUtils.AppInfo getApkInfo(final String apkFilePath) {
+ if (UtilsBridge.isSpace(apkFilePath)) return null;
+ PackageManager pm = Utils.getApp().getPackageManager();
+ if (pm == null) return null;
+ PackageInfo pi = pm.getPackageArchiveInfo(apkFilePath, 0);
+ if (pi == null) return null;
+ ApplicationInfo appInfo = pi.applicationInfo;
+ appInfo.sourceDir = apkFilePath;
+ appInfo.publicSourceDir = apkFilePath;
+ return getBean(pm, pi);
+ }
+
+
+ /**
+ * Return whether the application was first installed.
+ *
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isFirstTimeInstalled() {
+ try {
+ PackageInfo pi = Utils.getApp().getPackageManager().getPackageInfo(Utils.getApp().getPackageName(), 0);
+ return pi.firstInstallTime == pi.lastUpdateTime;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return true;
+ }
+ }
+
+ private static AppInfo getBean(final PackageManager pm, final PackageInfo pi) {
+ if (pi == null) return null;
+ String versionName = pi.versionName;
+ int versionCode = pi.versionCode;
+ String packageName = pi.packageName;
+ ApplicationInfo ai = pi.applicationInfo;
+ if (ai == null) {
+ return new AppInfo(packageName, "", null, "", versionName, versionCode, -1, -1, false);
+ }
+ String name = ai.loadLabel(pm).toString();
+ Drawable icon = ai.loadIcon(pm);
+ String packagePath = ai.sourceDir;
+ int minSdkVersion = -1;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
+ minSdkVersion = ai.minSdkVersion;
+ }
+ int targetSdkVersion = ai.targetSdkVersion;
+ boolean isSystem = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != 0;
+ return new AppInfo(packageName, name, icon, packagePath, versionName, versionCode, minSdkVersion, targetSdkVersion, isSystem);
+ }
+
+ /**
+ * The application's information.
+ */
+ public static class AppInfo {
+
+ private String packageName;
+ private String name;
+ private Drawable icon;
+ private String packagePath;
+ private String versionName;
+ private int versionCode;
+ private int minSdkVersion;
+ private int targetSdkVersion;
+ private boolean isSystem;
+
+ public Drawable getIcon() {
+ return icon;
+ }
+
+ public void setIcon(final Drawable icon) {
+ this.icon = icon;
+ }
+
+ public boolean isSystem() {
+ return isSystem;
+ }
+
+ public void setSystem(final boolean isSystem) {
+ this.isSystem = isSystem;
+ }
+
+ public String getPackageName() {
+ return packageName;
+ }
+
+ public void setPackageName(final String packageName) {
+ this.packageName = packageName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getPackagePath() {
+ return packagePath;
+ }
+
+ public void setPackagePath(final String packagePath) {
+ this.packagePath = packagePath;
+ }
+
+ public int getVersionCode() {
+ return versionCode;
+ }
+
+ public void setVersionCode(final int versionCode) {
+ this.versionCode = versionCode;
+ }
+
+ public String getVersionName() {
+ return versionName;
+ }
+
+ public void setVersionName(final String versionName) {
+ this.versionName = versionName;
+ }
+
+ public int getMinSdkVersion() {
+ return minSdkVersion;
+ }
+
+ public void setMinSdkVersion(int minSdkVersion) {
+ this.minSdkVersion = minSdkVersion;
+ }
+
+ public int getTargetSdkVersion() {
+ return targetSdkVersion;
+ }
+
+ public void setTargetSdkVersion(int targetSdkVersion) {
+ this.targetSdkVersion = targetSdkVersion;
+ }
+
+ public AppInfo(String packageName, String name, Drawable icon, String packagePath, String versionName, int versionCode, int minSdkVersion, int targetSdkVersion, boolean isSystem) {
+ this.setName(name);
+ this.setIcon(icon);
+ this.setPackageName(packageName);
+ this.setPackagePath(packagePath);
+ this.setVersionName(versionName);
+ this.setVersionCode(versionCode);
+ this.setMinSdkVersion(minSdkVersion);
+ this.setTargetSdkVersion(targetSdkVersion);
+ this.setSystem(isSystem);
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return "{" +
+ "\n pkg name: " + getPackageName() +
+ "\n app icon: " + getIcon() +
+ "\n app name: " + getName() +
+ "\n app path: " + getPackagePath() +
+ "\n app v name: " + getVersionName() +
+ "\n app v code: " + getVersionCode() +
+ "\n app v min: " + getMinSdkVersion() +
+ "\n app v target: " + getTargetSdkVersion() +
+ "\n is system: " + isSystem() +
+ "\n}";
+ }
+ }
+}
diff --git a/common/src/main/java/com/blankj/utilcode/util/ArrayUtils.java b/common/src/main/java/com/blankj/utilcode/util/ArrayUtils.java
new file mode 100644
index 0000000..48594ce
--- /dev/null
+++ b/common/src/main/java/com/blankj/utilcode/util/ArrayUtils.java
@@ -0,0 +1,2143 @@
+package com.blankj.utilcode.util;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ *
+ * author: blankj
+ * blog : http://blankj.com
+ * time : 2019/08/10
+ * desc : utils about array
+ *
+ */
+public class ArrayUtils {
+
+ public static final int INDEX_NOT_FOUND = -1;
+
+ private ArrayUtils() {
+ throw new UnsupportedOperationException("u can't instantiate me...");
+ }
+
+ /**
+ * Returns a new array only of those given elements.
+ *
+ * @param array The array.
+ * @return a new array only of those given elements.
+ */
+ @NonNull
+ public static T[] newArray(T... array) {
+ return array;
+ }
+
+ @NonNull
+ public static long[] newLongArray(long... array) {
+ return array;
+ }
+
+ @NonNull
+ public static int[] newIntArray(int... array) {
+ return array;
+ }
+
+ @NonNull
+ public static short[] newShortArray(short... array) {
+ return array;
+ }
+
+ @NonNull
+ public static char[] newCharArray(char... array) {
+ return array;
+ }
+
+ @NonNull
+ public static byte[] newByteArray(byte... array) {
+ return array;
+ }
+
+ @NonNull
+ public static double[] newDoubleArray(double... array) {
+ return array;
+ }
+
+ @NonNull
+ public static float[] newFloatArray(float... array) {
+ return array;
+ }
+
+ @NonNull
+ public static boolean[] newBooleanArray(boolean... array) {
+ return array;
+ }
+
+ /**
+ * Return the array is empty.
+ *
+ * @param array The array.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isEmpty(@Nullable Object array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ * Return the size of array.
+ *
+ * @param array The array.
+ * @return the size of array
+ */
+ public static int getLength(@Nullable Object array) {
+ if (array == null) return 0;
+ return Array.getLength(array);
+ }
+
+ public static boolean isSameLength(@Nullable Object array1, @Nullable Object array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ * Get the value of the specified index of the array.
+ *
+ * @param array The array.
+ * @param index The index into the array.
+ * @return the value of the specified index of the array
+ */
+ @Nullable
+ public static Object get(@Nullable Object array, int index) {
+ return get(array, index, null);
+ }
+
+ /**
+ * Get the value of the specified index of the array.
+ *
+ * @param array The array.
+ * @param index The index into the array.
+ * @param defaultValue The default value.
+ * @return the value of the specified index of the array
+ */
+ @Nullable
+ public static Object get(@Nullable Object array, int index, @Nullable Object defaultValue) {
+ if (array == null) return defaultValue;
+ try {
+ return Array.get(array, index);
+ } catch (Exception ignore) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Set the value of the specified index of the array.
+ *
+ * @param array The array.
+ * @param index The index into the array.
+ * @param value The new value of the indexed component.
+ */
+ public static void set(@Nullable Object array, int index, @Nullable Object value) {
+ if (array == null) return;
+ Array.set(array, index, value);
+ }
+
+ /**
+ * Return whether the two arrays are equals.
+ *
+ * @param a One array.
+ * @param a2 The other array.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean equals(@Nullable Object[] a, @Nullable Object[] a2) {
+ return Arrays.deepEquals(a, a2);
+ }
+
+ public static boolean equals(boolean[] a, boolean[] a2) {
+ return Arrays.equals(a, a2);
+ }
+
+ public static boolean equals(byte[] a, byte[] a2) {
+ return Arrays.equals(a, a2);
+ }
+
+ public static boolean equals(char[] a, char[] a2) {
+ return Arrays.equals(a, a2);
+ }
+
+ public static boolean equals(double[] a, double[] a2) {
+ return Arrays.equals(a, a2);
+ }
+
+ public static boolean equals(float[] a, float[] a2) {
+ return Arrays.equals(a, a2);
+ }
+
+ public static boolean equals(int[] a, int[] a2) {
+ return Arrays.equals(a, a2);
+ }
+
+ public static boolean equals(short[] a, short[] a2) {
+ return Arrays.equals(a, a2);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // reverse
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
There is no special handling for multi-dimensional arrays.
+ *
+ *
This method does nothing for a null input array.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(T[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ T tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(long[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ long tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(int[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ int tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(short[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ short tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(char[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ char tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(byte[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ byte tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(double[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ double tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(float[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ float tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ public static void reverse(boolean[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ boolean tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // copy
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ *
Copies the specified array and handling
+ * null.
+ *
+ *
The objects in the array are not cloned, thus there is no special
+ * handling for multi-dimensional arrays.
+ *
+ *
This method returns null for a null input array.
+ *
+ * @param array the array to shallow clone, may be null
+ * @return the cloned array, null if null input
+ */
+ @Nullable
+ public static T[] copy(@Nullable T[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static long[] copy(@Nullable long[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static int[] copy(@Nullable int[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static short[] copy(@Nullable short[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static char[] copy(@Nullable char[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static byte[] copy(@Nullable byte[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static double[] copy(@Nullable double[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static float[] copy(@Nullable float[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ public static boolean[] copy(@Nullable boolean[] array) {
+ if (array == null) return null;
+ return subArray(array, 0, array.length);
+ }
+
+ @Nullable
+ private static Object realCopy(@Nullable Object array) {
+ if (array == null) return null;
+ return realSubArray(array, 0, getLength(array));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // subArray
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static T[] subArray(@Nullable T[] array, int startIndexInclusive, int endIndexExclusive) {
+ //noinspection unchecked
+ return (T[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static long[] subArray(@Nullable long[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (long[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static int[] subArray(@Nullable int[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (int[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static short[] subArray(@Nullable short[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (short[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static char[] subArray(@Nullable char[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (char[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static byte[] subArray(@Nullable byte[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (byte[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static double[] subArray(@Nullable double[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (double[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static float[] subArray(@Nullable float[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (float[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ public static boolean[] subArray(@Nullable boolean[] array, int startIndexInclusive, int endIndexExclusive) {
+ return (boolean[]) realSubArray(array, startIndexInclusive, endIndexExclusive);
+ }
+
+ @Nullable
+ private static Object realSubArray(@Nullable Object array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ int length = getLength(array);
+ if (endIndexExclusive > length) {
+ endIndexExclusive = length;
+ }
+ int newSize = endIndexExclusive - startIndexInclusive;
+ Class type = array.getClass().getComponentType();
+ if (newSize <= 0) {
+ return Array.newInstance(type, 0);
+ }
+ Object subArray = Array.newInstance(type, newSize);
+ System.arraycopy(array, startIndexInclusive, subArray, 0, newSize);
+ return subArray;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // add
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ *
Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is null, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ * @param array the array to "realAdd" the element to, may be null
+ * @param element the object to realAdd
+ * @return A new array containing the existing elements plus the new element
+ */
+ @NonNull
+ public static T[] add(@Nullable T[] array, @Nullable T element) {
+ Class type = array != null ? array.getClass() : (element != null ? element.getClass() : Object.class);
+ return (T[]) realAddOne(array, element, type);
+ }
+
+ @NonNull
+ public static boolean[] add(@Nullable boolean[] array, boolean element) {
+ return (boolean[]) realAddOne(array, element, Boolean.TYPE);
+ }
+
+ @NonNull
+ public static byte[] add(@Nullable byte[] array, byte element) {
+ return (byte[]) realAddOne(array, element, Byte.TYPE);
+ }
+
+ @NonNull
+ public static char[] add(@Nullable char[] array, char element) {
+ return (char[]) realAddOne(array, element, Character.TYPE);
+ }
+
+ @NonNull
+ public static double[] add(@Nullable double[] array, double element) {
+ return (double[]) realAddOne(array, element, Double.TYPE);
+ }
+
+ @NonNull
+ public static float[] add(@Nullable float[] array, float element) {
+ return (float[]) realAddOne(array, element, Float.TYPE);
+ }
+
+ @NonNull
+ public static int[] add(@Nullable int[] array, int element) {
+ return (int[]) realAddOne(array, element, Integer.TYPE);
+ }
+
+ @NonNull
+ public static long[] add(@Nullable long[] array, long element) {
+ return (long[]) realAddOne(array, element, Long.TYPE);
+ }
+
+ @NonNull
+ public static short[] add(@Nullable short[] array, short element) {
+ return (short[]) realAddOne(array, element, Short.TYPE);
+ }
+
+ @NonNull
+ private static Object realAddOne(@Nullable Object array, @Nullable Object element, Class newArrayComponentType) {
+ Object newArray;
+ int arrayLength = 0;
+ if (array != null) {
+ arrayLength = getLength(array);
+ newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
+ System.arraycopy(array, 0, newArray, 0, arrayLength);
+ } else {
+ newArray = Array.newInstance(newArrayComponentType, 1);
+ }
+ Array.set(newArray, arrayLength, element);
+ return newArray;
+ }
+
+ /**
+ *
Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of array1 followed
+ * by all of the elements array2. When an array is returned, it is always
+ * a new array.
+ *
+ * @param array1 the first array whose elements are added to the new array, may be null
+ * @param array2 the second array whose elements are added to the new array, may be null
+ * @return The new array, null if null array inputs.
+ * The type of the new array is the type of the first array.
+ */
+ @Nullable
+ public static T[] add(@Nullable T[] array1, @Nullable T[] array2) {
+ return (T[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static boolean[] add(@Nullable boolean[] array1, @Nullable boolean[] array2) {
+ return (boolean[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static char[] add(@Nullable char[] array1, @Nullable char[] array2) {
+ return (char[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static byte[] add(@Nullable byte[] array1, @Nullable byte[] array2) {
+ return (byte[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static short[] add(@Nullable short[] array1, @Nullable short[] array2) {
+ return (short[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static int[] add(@Nullable int[] array1, @Nullable int[] array2) {
+ return (int[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static long[] add(@Nullable long[] array1, @Nullable long[] array2) {
+ return (long[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static float[] add(@Nullable float[] array1, @Nullable float[] array2) {
+ return (float[]) realAddArr(array1, array2);
+ }
+
+ @Nullable
+ public static double[] add(@Nullable double[] array1, @Nullable double[] array2) {
+ return (double[]) realAddArr(array1, array2);
+ }
+
+ private static Object realAddArr(@Nullable Object array1, @Nullable Object array2) {
+ if (array1 == null && array2 == null) return null;
+ if (array1 == null) {
+ return realCopy(array2);
+ }
+ if (array2 == null) {
+ return realCopy(array1);
+ }
+ int len1 = getLength(array1);
+ int len2 = getLength(array2);
+ Object joinedArray = Array.newInstance(array1.getClass().getComponentType(), len1 + len2);
+ System.arraycopy(array1, 0, joinedArray, 0, len1);
+ System.arraycopy(array2, 0, joinedArray, len1, len2);
+ return joinedArray;
+ }
+
+ /**
+ *
Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is null, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ * @param array1 the array to realAdd the element to, may be null
+ * @param index the position of the new object
+ * @param array2 the array to realAdd
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ @Nullable
+ public static T[] add(@Nullable T[] array1, int index, @Nullable T[] array2) {
+ Class clss;
+ if (array1 != null) {
+ clss = array1.getClass().getComponentType();
+ } else if (array2 != null) {
+ clss = array2.getClass().getComponentType();
+ } else {
+ return null;
+ }
+ return (T[]) realAddArr(array1, index, array2, clss);
+ }
+
+ @Nullable
+ public static boolean[] add(@Nullable boolean[] array1, int index, @Nullable boolean[] array2) {
+ Object result = realAddArr(array1, index, array2, Boolean.TYPE);
+ if (result == null) return null;
+ return (boolean[]) result;
+ }
+
+ public static char[] add(@Nullable char[] array1, int index, @Nullable char[] array2) {
+ Object result = realAddArr(array1, index, array2, Character.TYPE);
+ if (result == null) return null;
+ return (char[]) result;
+ }
+
+ @Nullable
+ public static byte[] add(@Nullable byte[] array1, int index, @Nullable byte[] array2) {
+ Object result = realAddArr(array1, index, array2, Byte.TYPE);
+ if (result == null) return null;
+ return (byte[]) result;
+ }
+
+ @Nullable
+ public static short[] add(@Nullable short[] array1, int index, @Nullable short[] array2) {
+ Object result = realAddArr(array1, index, array2, Short.TYPE);
+ if (result == null) return null;
+ return (short[]) result;
+ }
+
+ @Nullable
+ public static int[] add(@Nullable int[] array1, int index, @Nullable int[] array2) {
+ Object result = realAddArr(array1, index, array2, Integer.TYPE);
+ if (result == null) return null;
+ return (int[]) result;
+ }
+
+ @Nullable
+ public static long[] add(@Nullable long[] array1, int index, @Nullable long[] array2) {
+ Object result = realAddArr(array1, index, array2, Long.TYPE);
+ if (result == null) return null;
+ return (long[]) result;
+ }
+
+ @Nullable
+ public static float[] add(@Nullable float[] array1, int index, @Nullable float[] array2) {
+ Object result = realAddArr(array1, index, array2, Float.TYPE);
+ if (result == null) return null;
+ return (float[]) result;
+ }
+
+ @Nullable
+ public static double[] add(@Nullable double[] array1, int index, @Nullable double[] array2) {
+ Object result = realAddArr(array1, index, array2, Double.TYPE);
+ if (result == null) return null;
+ return (double[]) result;
+ }
+
+ @Nullable
+ private static Object realAddArr(@Nullable Object array1, int index, @Nullable Object array2, Class clss) {
+ if (array1 == null && array2 == null) return null;
+ int len1 = getLength(array1);
+ int len2 = getLength(array2);
+ if (len1 == 0) {
+ if (index != 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", array1 Length: 0");
+ }
+ return realCopy(array2);
+ }
+ if (len2 == 0) {
+ return realCopy(array1);
+ }
+ if (index > len1 || index < 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", array1 Length: " + len1);
+ }
+ Object joinedArray = Array.newInstance(array1.getClass().getComponentType(), len1 + len2);
+ if (index == len1) {
+ System.arraycopy(array1, 0, joinedArray, 0, len1);
+ System.arraycopy(array2, 0, joinedArray, len1, len2);
+ } else if (index == 0) {
+ System.arraycopy(array2, 0, joinedArray, 0, len2);
+ System.arraycopy(array1, 0, joinedArray, len2, len1);
+ } else {
+ System.arraycopy(array1, 0, joinedArray, 0, index);
+ System.arraycopy(array2, 0, joinedArray, index, len2);
+ System.arraycopy(array1, index, joinedArray, index + len2, len1 - index);
+ }
+ return joinedArray;
+ }
+
+ /**
+ *
Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is null, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ * @param array the array to realAdd the element to, may be null
+ * @param index the position of the new object
+ * @param element the object to realAdd
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ @NonNull
+ public static T[] add(@Nullable T[] array, int index, @Nullable T element) {
+ Class clss;
+ if (array != null) {
+ clss = array.getClass().getComponentType();
+ } else if (element != null) {
+ clss = element.getClass();
+ } else {
+ return (T[]) new Object[]{null};
+ }
+ return (T[]) realAdd(array, index, element, clss);
+ }
+
+ @NonNull
+ public static boolean[] add(@Nullable boolean[] array, int index, boolean element) {
+ return (boolean[]) realAdd(array, index, element, Boolean.TYPE);
+ }
+
+ @NonNull
+ public static char[] add(@Nullable char[] array, int index, char element) {
+ return (char[]) realAdd(array, index, element, Character.TYPE);
+ }
+
+ @NonNull
+ public static byte[] add(@Nullable byte[] array, int index, byte element) {
+ return (byte[]) realAdd(array, index, element, Byte.TYPE);
+ }
+
+ @NonNull
+ public static short[] add(@Nullable short[] array, int index, short element) {
+ return (short[]) realAdd(array, index, element, Short.TYPE);
+ }
+
+ @NonNull
+ public static int[] add(@Nullable int[] array, int index, int element) {
+ return (int[]) realAdd(array, index, element, Integer.TYPE);
+ }
+
+ @NonNull
+ public static long[] add(@Nullable long[] array, int index, long element) {
+ return (long[]) realAdd(array, index, element, Long.TYPE);
+ }
+
+ @NonNull
+ public static float[] add(@Nullable float[] array, int index, float element) {
+ return (float[]) realAdd(array, index, element, Float.TYPE);
+ }
+
+ @NonNull
+ public static double[] add(@Nullable double[] array, int index, double element) {
+ return (double[]) realAdd(array, index, element, Double.TYPE);
+ }
+
+ @NonNull
+ private static Object realAdd(@Nullable Object array, int index, @Nullable Object element, Class clss) {
+ if (array == null) {
+ if (index != 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
+ }
+ Object joinedArray = Array.newInstance(clss, 1);
+ Array.set(joinedArray, 0, element);
+ return joinedArray;
+ }
+ int length = Array.getLength(array);
+ if (index > length || index < 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+ Object result = Array.newInstance(clss, length + 1);
+ System.arraycopy(array, 0, result, 0, index);
+ Array.set(result, index, element);
+ if (index < length) {
+ System.arraycopy(array, index, result, index + 1, length - index);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // remove
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ *
Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (substracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is null, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ * @param array the array to remove the element from, may be null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length)
+ */
+ @Nullable
+ public static Object[] remove(@Nullable Object[] array, int index) {
+ if (array == null) return null;
+ return (Object[]) remove((Object) array, index);
+ }
+
+ /**
+ *
Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (substracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ * @param array the array to remove the element from, may be null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ */
+ @Nullable
+ public static Object[] removeElement(@Nullable Object[] array, @Nullable Object element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static boolean[] remove(@Nullable boolean[] array, int index) {
+ if (array == null) return null;
+ return (boolean[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static boolean[] removeElement(@Nullable boolean[] array, boolean element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static byte[] remove(@Nullable byte[] array, int index) {
+ if (array == null) return null;
+ return (byte[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static byte[] removeElement(@Nullable byte[] array, byte element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static char[] remove(@Nullable char[] array, int index) {
+ if (array == null) return null;
+ return (char[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static char[] removeElement(@Nullable char[] array, char element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static double[] remove(@Nullable double[] array, int index) {
+ if (array == null) return null;
+ return (double[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static double[] removeElement(@Nullable double[] array, double element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ //noinspection ConstantConditions
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static float[] remove(@Nullable float[] array, int index) {
+ if (array == null) return null;
+ return (float[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static float[] removeElement(@Nullable float[] array, float element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static int[] remove(@Nullable int[] array, int index) {
+ if (array == null) return null;
+ return (int[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static int[] removeElement(@Nullable int[] array, int element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static long[] remove(@Nullable long[] array, int index) {
+ if (array == null) return null;
+ return (long[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static long[] removeElement(@Nullable long[] array, long element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @Nullable
+ public static short[] remove(@Nullable short[] array, int index) {
+ if (array == null) return null;
+ return (short[]) remove((Object) array, index);
+ }
+
+ @Nullable
+ public static short[] removeElement(@Nullable short[] array, short element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return copy(array);
+ }
+ return remove(array, index);
+ }
+
+ @NonNull
+ private static Object remove(@NonNull Object array, int index) {
+ int length = getLength(array);
+ if (index < 0 || index >= length) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+
+ Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
+ System.arraycopy(array, 0, result, 0, index);
+ if (index < length - 1) {
+ System.arraycopy(array, index + 1, result, index, length - index - 1);
+ }
+
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // object indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable Object[] array, @Nullable Object objectToFind) {
+ return indexOf(array, objectToFind, 0);
+ }
+
+ public static int indexOf(@Nullable Object[] array, @Nullable final Object objectToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i < array.length; i++) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = startIndex; i < array.length; i++) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable Object[] array, @Nullable Object objectToFind) {
+ return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable Object[] array, @Nullable Object objectToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i >= 0; i--) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = startIndex; i >= 0; i--) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable Object[] array, @Nullable Object objectToFind) {
+ return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // long indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable long[] array, long valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable long[] array, long valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable long[] array, long valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable long[] array, long valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable long[] array, long valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // int indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable int[] array, int valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable int[] array, int valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable int[] array, int valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable int[] array, int valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable int[] array, int valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // short indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable short[] array, short valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable short[] array, short valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable short[] array, short valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable short[] array, short valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable short[] array, short valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // char indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable char[] array, char valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable char[] array, char valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable char[] array, char valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable char[] array, char valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable char[] array, char valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // byte indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable byte[] array, byte valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable byte[] array, byte valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable byte[] array, byte valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable byte[] array, byte valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable byte[] array, byte valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // double indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable double[] array, double valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable double[] array, double valueToFind, double tolerance) {
+ return indexOf(array, valueToFind, 0, tolerance);
+ }
+
+ public static int indexOf(@Nullable double[] array, double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int indexOf(@Nullable double[] array, double valueToFind, int startIndex, double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ double min = valueToFind - tolerance;
+ double max = valueToFind + tolerance;
+ for (int i = startIndex; i < array.length; i++) {
+ if (array[i] >= min && array[i] <= max) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable double[] array, double valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable double[] array, double valueToFind, double tolerance) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
+ }
+
+ public static int lastIndexOf(@Nullable double[] array, double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable double[] array, double valueToFind, int startIndex, double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ double min = valueToFind - tolerance;
+ double max = valueToFind + tolerance;
+ for (int i = startIndex; i >= 0; i--) {
+ if (array[i] >= min && array[i] <= max) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable double[] array, double valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable double[] array, double valueToFind, double tolerance) {
+ return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // float indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable float[] array, float valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable float[] array, float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable float[] array, float valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable float[] array, float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable float[] array, float valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // bool indexOf
+ ///////////////////////////////////////////////////////////////////////////
+
+ public static int indexOf(@Nullable boolean[] array, boolean valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ public static int indexOf(@Nullable boolean[] array, boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static int lastIndexOf(@Nullable boolean[] array, boolean valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ public static int lastIndexOf(@Nullable boolean[] array, boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ public static boolean contains(@Nullable boolean[] array, boolean valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // char converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static char[] toPrimitive(@Nullable Character[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new char[0];
+ }
+ final char[] result = new char[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].charValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static char[] toPrimitive(@Nullable Character[] array, char valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new char[0];
+ }
+ final char[] result = new char[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Character b = array[i];
+ result[i] = (b == null ? valueForNull : b.charValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Character[] toObject(@Nullable char[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Character[0];
+ }
+ final Character[] result = new Character[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Character(array[i]);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // long converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static long[] toPrimitive(@Nullable Long[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new long[0];
+ }
+ final long[] result = new long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].longValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static long[] toPrimitive(@Nullable Long[] array, long valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new long[0];
+ }
+ final long[] result = new long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Long b = array[i];
+ result[i] = (b == null ? valueForNull : b.longValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Long[] toObject(@Nullable long[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Long[0];
+ }
+ final Long[] result = new Long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Long(array[i]);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // int converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static int[] toPrimitive(@Nullable Integer[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new int[0];
+ }
+ final int[] result = new int[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].intValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static int[] toPrimitive(@Nullable Integer[] array, int valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new int[0];
+ }
+ final int[] result = new int[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Integer b = array[i];
+ result[i] = (b == null ? valueForNull : b.intValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Integer[] toObject(@Nullable int[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Integer[0];
+ }
+ final Integer[] result = new Integer[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Integer(array[i]);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // short converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static short[] toPrimitive(@Nullable Short[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new short[0];
+ }
+ final short[] result = new short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].shortValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static short[] toPrimitive(@Nullable Short[] array, short valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new short[0];
+ }
+ final short[] result = new short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Short b = array[i];
+ result[i] = (b == null ? valueForNull : b.shortValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Short[] toObject(@Nullable short[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Short[0];
+ }
+ final Short[] result = new Short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Short(array[i]);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // byte converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static byte[] toPrimitive(@Nullable Byte[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new byte[0];
+ }
+ final byte[] result = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].byteValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static byte[] toPrimitive(@Nullable Byte[] array, byte valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new byte[0];
+ }
+ final byte[] result = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Byte b = array[i];
+ result[i] = (b == null ? valueForNull : b.byteValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Byte[] toObject(@Nullable byte[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Byte[0];
+ }
+ final Byte[] result = new Byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Byte(array[i]);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // double converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static double[] toPrimitive(@Nullable Double[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new double[0];
+ }
+ final double[] result = new double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].doubleValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static double[] toPrimitive(@Nullable Double[] array, double valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new double[0];
+ }
+ final double[] result = new double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Double b = array[i];
+ result[i] = (b == null ? valueForNull : b.doubleValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Double[] toObject(@Nullable double[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Double[0];
+ }
+ final Double[] result = new Double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Double(array[i]);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // float converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static float[] toPrimitive(@Nullable Float[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new float[0];
+ }
+ final float[] result = new float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].floatValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static float[] toPrimitive(@Nullable Float[] array, float valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new float[0];
+ }
+ final float[] result = new float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Float b = array[i];
+ result[i] = (b == null ? valueForNull : b.floatValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Float[] toObject(@Nullable float[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Float[0];
+ }
+ final Float[] result = new Float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Float(array[i]);
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // boolean converters
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Nullable
+ public static boolean[] toPrimitive(@Nullable Boolean[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new boolean[0];
+ }
+ final boolean[] result = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].booleanValue();
+ }
+ return result;
+ }
+
+ @Nullable
+ public static boolean[] toPrimitive(@Nullable Boolean[] array, boolean valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new boolean[0];
+ }
+ final boolean[] result = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Boolean b = array[i];
+ result[i] = (b == null ? valueForNull : b.booleanValue());
+ }
+ return result;
+ }
+
+ @Nullable
+ public static Boolean[] toObject(@Nullable boolean[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return new Boolean[0];
+ }
+ final Boolean[] result = new Boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
+ }
+ return result;
+ }
+
+ @NonNull
+ public static List asList(@Nullable T... array) {
+ if (array == null || array.length == 0) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(array);
+ }
+
+ @NonNull
+ public static List asUnmodifiableList(@Nullable T... array) {
+ return Collections.unmodifiableList(asList(array));
+ }
+
+ @NonNull
+ public static List asArrayList(@Nullable T... array) {
+ List list = new ArrayList<>();
+ if (array == null || array.length == 0) return list;
+ list.addAll(Arrays.asList(array));
+ return list;
+ }
+
+ @NonNull
+ public static List asLinkedList(@Nullable T... array) {
+ List list = new LinkedList<>();
+ if (array == null || array.length == 0) return list;
+ list.addAll(Arrays.asList(array));
+ return list;
+ }
+
+ public static void sort(@Nullable T[] array, Comparator super T> c) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array, c);
+ }
+
+ public static void sort(@Nullable byte[] array) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array);
+ }
+
+ public static void sort(@Nullable char[] array) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array);
+ }
+
+ public static void sort(@Nullable double[] array) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array);
+ }
+
+ public static void sort(@Nullable float[] array) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array);
+ }
+
+ public static void sort(@Nullable int[] array) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array);
+ }
+
+ public static void sort(@Nullable long[] array) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array);
+ }
+
+ public static void sort(@Nullable short[] array) {
+ if (array == null || array.length < 2) return;
+ Arrays.sort(array);
+ }
+
+ /**
+ * Executes the given closure on each element in the array.
+ *
+ * If the input array or closure is null, there is no change made.
+ *
+ * @param array The array.
+ * @param closure the closure to perform, may be null
+ */
+ public static void forAllDo(@Nullable Object array, @Nullable Closure closure) {
+ if (array == null || closure == null) return;
+ if (array instanceof Object[]) {
+ Object[] objects = (Object[]) array;
+ for (int i = 0, length = objects.length; i < length; i++) {
+ Object ele = objects[i];
+ closure.execute(i, (E) ele);
+ }
+ } else if (array instanceof boolean[]) {
+ boolean[] booleans = (boolean[]) array;
+ for (int i = 0, length = booleans.length; i < length; i++) {
+ boolean ele = booleans[i];
+ closure.execute(i, (E) (ele ? Boolean.TRUE : Boolean.FALSE));
+ }
+ } else if (array instanceof byte[]) {
+ byte[] bytes = (byte[]) array;
+ for (int i = 0, length = bytes.length; i < length; i++) {
+ byte ele = bytes[i];
+ closure.execute(i, (E) Byte.valueOf(ele));
+ }
+ } else if (array instanceof char[]) {
+ char[] chars = (char[]) array;
+ for (int i = 0, length = chars.length; i < length; i++) {
+ char ele = chars[i];
+ closure.execute(i, (E) Character.valueOf(ele));
+ }
+ } else if (array instanceof short[]) {
+ short[] shorts = (short[]) array;
+ for (int i = 0, length = shorts.length; i < length; i++) {
+ short ele = shorts[i];
+ closure.execute(i, (E) Short.valueOf(ele));
+ }
+ } else if (array instanceof int[]) {
+ int[] ints = (int[]) array;
+ for (int i = 0, length = ints.length; i < length; i++) {
+ int ele = ints[i];
+ closure.execute(i, (E) Integer.valueOf(ele));
+ }
+ } else if (array instanceof long[]) {
+ long[] longs = (long[]) array;
+ for (int i = 0, length = longs.length; i < length; i++) {
+ long ele = longs[i];
+ closure.execute(i, (E) Long.valueOf(ele));
+ }
+ } else if (array instanceof float[]) {
+ float[] floats = (float[]) array;
+ for (int i = 0, length = floats.length; i < length; i++) {
+ float ele = floats[i];
+ closure.execute(i, (E) Float.valueOf(ele));
+ }
+ } else if (array instanceof double[]) {
+ double[] doubles = (double[]) array;
+ for (int i = 0, length = doubles.length; i < length; i++) {
+ double ele = doubles[i];
+ closure.execute(i, (E) Double.valueOf(ele));
+ }
+ } else {
+ throw new IllegalArgumentException("Not an array: " + array.getClass());
+ }
+ }
+
+ /**
+ * Return the string of array.
+ *
+ * @param array The array.
+ * @return the string of array
+ */
+ @NonNull
+ public static String toString(@Nullable Object array) {
+ if (array == null) return "null";
+ if (array instanceof Object[]) {
+ return Arrays.deepToString((Object[]) array);
+ } else if (array instanceof boolean[]) {
+ return Arrays.toString((boolean[]) array);
+ } else if (array instanceof byte[]) {
+ return Arrays.toString((byte[]) array);
+ } else if (array instanceof char[]) {
+ return Arrays.toString((char[]) array);
+ } else if (array instanceof double[]) {
+ return Arrays.toString((double[]) array);
+ } else if (array instanceof float[]) {
+ return Arrays.toString((float[]) array);
+ } else if (array instanceof int[]) {
+ return Arrays.toString((int[]) array);
+ } else if (array instanceof long[]) {
+ return Arrays.toString((long[]) array);
+ } else if (array instanceof short[]) {
+ return Arrays.toString((short[]) array);
+ }
+ throw new IllegalArgumentException("Array has incompatible type: " + array.getClass());
+ }
+
+ public interface Closure {
+ void execute(int index, E item);
+ }
+}
diff --git a/common/src/main/java/com/blankj/utilcode/util/BarUtils.java b/common/src/main/java/com/blankj/utilcode/util/BarUtils.java
new file mode 100644
index 0000000..e8cacc5
--- /dev/null
+++ b/common/src/main/java/com/blankj/utilcode/util/BarUtils.java
@@ -0,0 +1,740 @@
+package com.blankj.utilcode.util;
+
+import static android.Manifest.permission.EXPAND_STATUS_BAR;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.os.Build;
+import android.provider.Settings;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.view.Window;
+import android.view.WindowManager;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RequiresPermission;
+import androidx.drawerlayout.widget.DrawerLayout;
+
+import java.lang.reflect.Method;
+
+/**
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/09/23
+ * desc : utils about bar
+ *
+ */
+public final class BarUtils {
+
+ ///////////////////////////////////////////////////////////////////////////
+ // status bar
+ ///////////////////////////////////////////////////////////////////////////
+
+ private static final String TAG_STATUS_BAR = "TAG_STATUS_BAR";
+ private static final String TAG_OFFSET = "TAG_OFFSET";
+ private static final int KEY_OFFSET = -123;
+
+ private BarUtils() {
+ throw new UnsupportedOperationException("u can't instantiate me...");
+ }
+
+ /**
+ * Return the status bar's height.
+ *
+ * @return the status bar's height
+ */
+ public static int getStatusBarHeight() {
+ Resources resources = Resources.getSystem();
+ int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
+ return resources.getDimensionPixelSize(resourceId);
+ }
+
+ /**
+ * Set the status bar's visibility.
+ *
+ * @param activity The activity.
+ * @param isVisible True to set status bar visible, false otherwise.
+ */
+ public static void setStatusBarVisibility(@NonNull final Activity activity,
+ final boolean isVisible) {
+ setStatusBarVisibility(activity.getWindow(), isVisible);
+ }
+
+ /**
+ * Set the status bar's visibility.
+ *
+ * @param window The window.
+ * @param isVisible True to set status bar visible, false otherwise.
+ */
+ public static void setStatusBarVisibility(@NonNull final Window window,
+ final boolean isVisible) {
+ if (isVisible) {
+ window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ showStatusBarView(window);
+ addMarginTopEqualStatusBarHeight(window);
+ } else {
+ window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ hideStatusBarView(window);
+ subtractMarginTopEqualStatusBarHeight(window);
+ }
+ }
+
+ /**
+ * Return whether the status bar is visible.
+ *
+ * @param activity The activity.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isStatusBarVisible(@NonNull final Activity activity) {
+ int flags = activity.getWindow().getAttributes().flags;
+ return (flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
+ }
+
+ /**
+ * Set the status bar's light mode.
+ *
+ * @param activity The activity.
+ * @param isLightMode True to set status bar light mode, false otherwise.
+ */
+ public static void setStatusBarLightMode(@NonNull final Activity activity,
+ final boolean isLightMode) {
+ setStatusBarLightMode(activity.getWindow(), isLightMode);
+ }
+
+ /**
+ * Set the status bar's light mode.
+ *
+ * @param window The window.
+ * @param isLightMode True to set status bar light mode, false otherwise.
+ */
+ public static void setStatusBarLightMode(@NonNull final Window window,
+ final boolean isLightMode) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ View decorView = window.getDecorView();
+ int vis = decorView.getSystemUiVisibility();
+ if (isLightMode) {
+ vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ } else {
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ }
+ decorView.setSystemUiVisibility(vis);
+ }
+ }
+
+ /**
+ * Is the status bar light mode.
+ *
+ * @param activity The activity.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isStatusBarLightMode(@NonNull final Activity activity) {
+ return isStatusBarLightMode(activity.getWindow());
+ }
+
+ /**
+ * Is the status bar light mode.
+ *
+ * @param window The window.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isStatusBarLightMode(@NonNull final Window window) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ View decorView = window.getDecorView();
+ int vis = decorView.getSystemUiVisibility();
+ return (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
+ }
+ return false;
+ }
+
+ /**
+ * Add the top margin size equals status bar's height for view.
+ *
+ * @param view The view.
+ */
+ public static void addMarginTopEqualStatusBarHeight(@NonNull View view) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ view.setTag(TAG_OFFSET);
+ Object haveSetOffset = view.getTag(KEY_OFFSET);
+ if (haveSetOffset != null && (Boolean) haveSetOffset) return;
+ MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
+ layoutParams.setMargins(layoutParams.leftMargin,
+ layoutParams.topMargin + getStatusBarHeight(),
+ layoutParams.rightMargin,
+ layoutParams.bottomMargin);
+ view.setTag(KEY_OFFSET, true);
+ }
+
+ /**
+ * Subtract the top margin size equals status bar's height for view.
+ *
+ * @param view The view.
+ */
+ public static void subtractMarginTopEqualStatusBarHeight(@NonNull View view) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ Object haveSetOffset = view.getTag(KEY_OFFSET);
+ if (haveSetOffset == null || !(Boolean) haveSetOffset) return;
+ MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
+ layoutParams.setMargins(layoutParams.leftMargin,
+ layoutParams.topMargin - getStatusBarHeight(),
+ layoutParams.rightMargin,
+ layoutParams.bottomMargin);
+ view.setTag(KEY_OFFSET, false);
+ }
+
+ private static void addMarginTopEqualStatusBarHeight(@NonNull final Window window) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ View withTag = window.getDecorView().findViewWithTag(TAG_OFFSET);
+ if (withTag == null) return;
+ addMarginTopEqualStatusBarHeight(withTag);
+ }
+
+ private static void subtractMarginTopEqualStatusBarHeight(@NonNull final Window window) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ View withTag = window.getDecorView().findViewWithTag(TAG_OFFSET);
+ if (withTag == null) return;
+ subtractMarginTopEqualStatusBarHeight(withTag);
+ }
+
+ /**
+ * Set the status bar's color.
+ *
+ * @param activity The activity.
+ * @param color The status bar's color.
+ */
+ public static View setStatusBarColor(@NonNull final Activity activity,
+ @ColorInt final int color) {
+ return setStatusBarColor(activity, color, false);
+ }
+
+ /**
+ * Set the status bar's color.
+ *
+ * @param activity The activity.
+ * @param color The status bar's color.
+ * @param isDecor True to add fake status bar in DecorView,
+ * false to add fake status bar in ContentView.
+ */
+ public static View setStatusBarColor(@NonNull final Activity activity,
+ @ColorInt final int color,
+ final boolean isDecor) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null;
+ transparentStatusBar(activity);
+ return applyStatusBarColor(activity, color, isDecor);
+ }
+
+
+ /**
+ * Set the status bar's color.
+ *
+ * @param window The window.
+ * @param color The status bar's color.
+ */
+ public static View setStatusBarColor(@NonNull final Window window,
+ @ColorInt final int color) {
+ return setStatusBarColor(window, color, false);
+ }
+
+ /**
+ * Set the status bar's color.
+ *
+ * @param window The window.
+ * @param color The status bar's color.
+ * @param isDecor True to add fake status bar in DecorView,
+ * false to add fake status bar in ContentView.
+ */
+ public static View setStatusBarColor(@NonNull final Window window,
+ @ColorInt final int color,
+ final boolean isDecor) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null;
+ transparentStatusBar(window);
+ return applyStatusBarColor(window, color, isDecor);
+ }
+
+ /**
+ * Set the status bar's color.
+ *
+ * @param fakeStatusBar The fake status bar view.
+ * @param color The status bar's color.
+ */
+ public static void setStatusBarColor(@NonNull final View fakeStatusBar,
+ @ColorInt final int color) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ Activity activity = UtilsBridge.getActivityByContext(fakeStatusBar.getContext());
+ if (activity == null) return;
+ transparentStatusBar(activity);
+ fakeStatusBar.setVisibility(View.VISIBLE);
+ ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
+ layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.height = getStatusBarHeight();
+ fakeStatusBar.setBackgroundColor(color);
+ }
+
+ /**
+ * Set the custom status bar.
+ *
+ * @param fakeStatusBar The fake status bar view.
+ */
+ public static void setStatusBarCustom(@NonNull final View fakeStatusBar) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ Activity activity = UtilsBridge.getActivityByContext(fakeStatusBar.getContext());
+ if (activity == null) return;
+ transparentStatusBar(activity);
+ fakeStatusBar.setVisibility(View.VISIBLE);
+ ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
+ if (layoutParams == null) {
+ layoutParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ getStatusBarHeight()
+ );
+ fakeStatusBar.setLayoutParams(layoutParams);
+ } else {
+ layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.height = getStatusBarHeight();
+ }
+ }
+
+ /**
+ * Set the status bar's color for DrawerLayout.
+ *
DrawLayout must add {@code android:fitsSystemWindows="true"}
+ *
+ * @param drawer The DrawLayout.
+ * @param fakeStatusBar The fake status bar view.
+ * @param color The status bar's color.
+ */
+ public static void setStatusBarColor4Drawer(@NonNull final DrawerLayout drawer,
+ @NonNull final View fakeStatusBar,
+ @ColorInt final int color) {
+ setStatusBarColor4Drawer(drawer, fakeStatusBar, color, false);
+ }
+
+ /**
+ * Set the status bar's color for DrawerLayout.
+ *
DrawLayout must add {@code android:fitsSystemWindows="true"}
+ *
+ * @param drawer The DrawLayout.
+ * @param fakeStatusBar The fake status bar view.
+ * @param color The status bar's color.
+ * @param isTop True to set DrawerLayout at the top layer, false otherwise.
+ */
+ public static void setStatusBarColor4Drawer(@NonNull final DrawerLayout drawer,
+ @NonNull final View fakeStatusBar,
+ @ColorInt final int color,
+ final boolean isTop) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ Activity activity = UtilsBridge.getActivityByContext(fakeStatusBar.getContext());
+ if (activity == null) return;
+ transparentStatusBar(activity);
+ drawer.setFitsSystemWindows(false);
+ setStatusBarColor(fakeStatusBar, color);
+ for (int i = 0, count = drawer.getChildCount(); i < count; i++) {
+ drawer.getChildAt(i).setFitsSystemWindows(false);
+ }
+ if (isTop) {
+ hideStatusBarView(activity);
+ } else {
+ setStatusBarColor(activity, color, false);
+ }
+ }
+
+ private static View applyStatusBarColor(@NonNull final Activity activity,
+ final int color,
+ boolean isDecor) {
+ return applyStatusBarColor(activity.getWindow(), color, isDecor);
+ }
+
+ private static View applyStatusBarColor(@NonNull final Window window,
+ final int color,
+ boolean isDecor) {
+ ViewGroup parent = isDecor ?
+ (ViewGroup) window.getDecorView() :
+ (ViewGroup) window.findViewById(android.R.id.content);
+ View fakeStatusBarView = parent.findViewWithTag(TAG_STATUS_BAR);
+ if (fakeStatusBarView != null) {
+ if (fakeStatusBarView.getVisibility() == View.GONE) {
+ fakeStatusBarView.setVisibility(View.VISIBLE);
+ }
+ fakeStatusBarView.setBackgroundColor(color);
+ } else {
+ fakeStatusBarView = createStatusBarView(window.getContext(), color);
+ parent.addView(fakeStatusBarView);
+ }
+ return fakeStatusBarView;
+ }
+
+ private static void hideStatusBarView(@NonNull final Activity activity) {
+ hideStatusBarView(activity.getWindow());
+ }
+
+ private static void hideStatusBarView(@NonNull final Window window) {
+ ViewGroup decorView = (ViewGroup) window.getDecorView();
+ View fakeStatusBarView = decorView.findViewWithTag(TAG_STATUS_BAR);
+ if (fakeStatusBarView == null) return;
+ fakeStatusBarView.setVisibility(View.GONE);
+ }
+
+ private static void showStatusBarView(@NonNull final Window window) {
+ ViewGroup decorView = (ViewGroup) window.getDecorView();
+ View fakeStatusBarView = decorView.findViewWithTag(TAG_STATUS_BAR);
+ if (fakeStatusBarView == null) return;
+ fakeStatusBarView.setVisibility(View.VISIBLE);
+ }
+
+ private static View createStatusBarView(@NonNull final Context context,
+ final int color) {
+ View statusBarView = new View(context);
+ statusBarView.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()));
+ statusBarView.setBackgroundColor(color);
+ statusBarView.setTag(TAG_STATUS_BAR);
+ return statusBarView;
+ }
+
+ public static void transparentStatusBar(@NonNull final Activity activity) {
+ transparentStatusBar(activity.getWindow());
+ }
+
+ public static void transparentStatusBar(@NonNull final Window window) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ int option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ int vis = window.getDecorView().getSystemUiVisibility();
+ window.getDecorView().setSystemUiVisibility(option | vis);
+ window.setStatusBarColor(Color.TRANSPARENT);
+ } else {
+ window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // action bar
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Return the action bar's height.
+ *
+ * @return the action bar's height
+ */
+ public static int getActionBarHeight() {
+ TypedValue tv = new TypedValue();
+ if (Utils.getApp().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
+ return TypedValue.complexToDimensionPixelSize(
+ tv.data, Utils.getApp().getResources().getDisplayMetrics()
+ );
+ }
+ return 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // notification bar
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Set the notification bar's visibility.
+ *
Must hold {@code }
+ *
+ * @param isVisible True to set notification bar visible, false otherwise.
+ */
+ @RequiresPermission(EXPAND_STATUS_BAR)
+ public static void setNotificationBarVisibility(final boolean isVisible) {
+ String methodName;
+ if (isVisible) {
+ methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel";
+ } else {
+ methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels";
+ }
+ invokePanels(methodName);
+ }
+
+ private static void invokePanels(final String methodName) {
+ try {
+ @SuppressLint("WrongConstant")
+ Object service = Utils.getApp().getSystemService("statusbar");
+ @SuppressLint("PrivateApi")
+ Class> statusBarManager = Class.forName("android.app.StatusBarManager");
+ Method expand = statusBarManager.getMethod(methodName);
+ expand.invoke(service);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // navigation bar
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Return the navigation bar's height.
+ *
+ * @return the navigation bar's height
+ */
+ public static int getNavBarHeight() {
+ Resources res = Resources.getSystem();
+ int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
+ if (resourceId != 0) {
+ return res.getDimensionPixelSize(resourceId);
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Set the navigation bar's visibility.
+ *
+ * @param activity The activity.
+ * @param isVisible True to set navigation bar visible, false otherwise.
+ */
+ public static void setNavBarVisibility(@NonNull final Activity activity, boolean isVisible) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ setNavBarVisibility(activity.getWindow(), isVisible);
+
+ }
+
+ /**
+ * Set the navigation bar's visibility.
+ *
+ * @param window The window.
+ * @param isVisible True to set navigation bar visible, false otherwise.
+ */
+ public static void setNavBarVisibility(@NonNull final Window window, boolean isVisible) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
+ final ViewGroup decorView = (ViewGroup) window.getDecorView();
+ for (int i = 0, count = decorView.getChildCount(); i < count; i++) {
+ final View child = decorView.getChildAt(i);
+ final int id = child.getId();
+ if (id != View.NO_ID) {
+ String resourceEntryName = getResNameById(id);
+ if ("navigationBarBackground".equals(resourceEntryName)) {
+ child.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
+ }
+ }
+ }
+ final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ if (isVisible) {
+ decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() & ~uiOptions);
+ } else {
+ decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | uiOptions);
+ }
+ }
+
+ /**
+ * Return whether the navigation bar visible.
+ *
Call it in onWindowFocusChanged will get right result.
+ *
+ * @param activity The activity.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isNavBarVisible(@NonNull final Activity activity) {
+ return isNavBarVisible(activity.getWindow());
+ }
+
+ /**
+ * Return whether the navigation bar visible.
+ *
Call it in onWindowFocusChanged will get right result.
+ *
+ * @param window The window.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isNavBarVisible(@NonNull final Window window) {
+ boolean isVisible = false;
+ ViewGroup decorView = (ViewGroup) window.getDecorView();
+ for (int i = 0, count = decorView.getChildCount(); i < count; i++) {
+ final View child = decorView.getChildAt(i);
+ final int id = child.getId();
+ if (id != View.NO_ID) {
+ String resourceEntryName = getResNameById(id);
+ if ("navigationBarBackground".equals(resourceEntryName)
+ && child.getVisibility() == View.VISIBLE) {
+ isVisible = true;
+ break;
+ }
+ }
+ }
+ if (isVisible) {
+ // 对于三星手机,android10以下非OneUI2的版本,比如 s8,note8 等设备上,
+ // 导航栏显示存在bug:"当用户隐藏导航栏时显示输入法的时候导航栏会跟随显示",会导致隐藏输入法之后判断错误
+ // 这个问题在 OneUI 2 & android 10 版本已修复
+ if (UtilsBridge.isSamsung()
+ && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1
+ && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ try {
+ return Settings.Global.getInt(Utils.getApp().getContentResolver(), "navigationbar_hide_bar_enabled") == 0;
+ } catch (Exception ignore) {
+ }
+ }
+
+ int visibility = decorView.getSystemUiVisibility();
+ isVisible = (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+ }
+
+ return isVisible;
+ }
+
+ private static String getResNameById(int id) {
+ try {
+ return Utils.getApp().getResources().getResourceEntryName(id);
+ } catch (Exception ignore) {
+ return "";
+ }
+ }
+
+ /**
+ * Set the navigation bar's color.
+ *
+ * @param activity The activity.
+ * @param color The navigation bar's color.
+ */
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ public static void setNavBarColor(@NonNull final Activity activity, @ColorInt final int color) {
+ setNavBarColor(activity.getWindow(), color);
+ }
+
+ /**
+ * Set the navigation bar's color.
+ *
+ * @param window The window.
+ * @param color The navigation bar's color.
+ */
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ public static void setNavBarColor(@NonNull final Window window, @ColorInt final int color) {
+ window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ window.setNavigationBarColor(color);
+ }
+
+ /**
+ * Return the color of navigation bar.
+ *
+ * @param activity The activity.
+ * @return the color of navigation bar
+ */
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ public static int getNavBarColor(@NonNull final Activity activity) {
+ return getNavBarColor(activity.getWindow());
+ }
+
+ /**
+ * Return the color of navigation bar.
+ *
+ * @param window The window.
+ * @return the color of navigation bar
+ */
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ public static int getNavBarColor(@NonNull final Window window) {
+ return window.getNavigationBarColor();
+ }
+
+ /**
+ * Return whether the navigation bar visible.
+ *
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isSupportNavBar() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ WindowManager wm = (WindowManager) Utils.getApp().getSystemService(Context.WINDOW_SERVICE);
+ if (wm == null) return false;
+ Display display = wm.getDefaultDisplay();
+ Point size = new Point();
+ Point realSize = new Point();
+ display.getSize(size);
+ display.getRealSize(realSize);
+ return realSize.y != size.y || realSize.x != size.x;
+ }
+ boolean menu = ViewConfiguration.get(Utils.getApp()).hasPermanentMenuKey();
+ boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
+ return !menu && !back;
+ }
+
+ /**
+ * Set the nav bar's light mode.
+ *
+ * @param activity The activity.
+ * @param isLightMode True to set nav bar light mode, false otherwise.
+ */
+ public static void setNavBarLightMode(@NonNull final Activity activity,
+ final boolean isLightMode) {
+ setNavBarLightMode(activity.getWindow(), isLightMode);
+ }
+
+ /**
+ * Set the nav bar's light mode.
+ *
+ * @param window The window.
+ * @param isLightMode True to set nav bar light mode, false otherwise.
+ */
+ public static void setNavBarLightMode(@NonNull final Window window,
+ final boolean isLightMode) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ View decorView = window.getDecorView();
+ int vis = decorView.getSystemUiVisibility();
+ if (isLightMode) {
+ vis |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ } else {
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ }
+ decorView.setSystemUiVisibility(vis);
+ }
+ }
+
+ /**
+ * Is the nav bar light mode.
+ *
+ * @param activity The activity.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isNavBarLightMode(@NonNull final Activity activity) {
+ return isNavBarLightMode(activity.getWindow());
+ }
+
+ /**
+ * Is the nav bar light mode.
+ *
+ * @param window The window.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isNavBarLightMode(@NonNull final Window window) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ View decorView = window.getDecorView();
+ int vis = decorView.getSystemUiVisibility();
+ return (vis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0;
+ }
+ return false;
+ }
+
+ public static void transparentNavBar(@NonNull final Activity activity) {
+ transparentNavBar(activity.getWindow());
+ }
+
+ public static void transparentNavBar(@NonNull final Window window) {
+ if (Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) return;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ window.setNavigationBarContrastEnforced(false);
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ window.setNavigationBarColor(Color.TRANSPARENT);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ if ((window.getAttributes().flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0) {
+ window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ }
+ }
+ View decorView = window.getDecorView();
+ int vis = decorView.getSystemUiVisibility();
+ int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ decorView.setSystemUiVisibility(vis | option);
+ }
+}
diff --git a/common/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java b/common/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
new file mode 100644
index 0000000..08dd46f
--- /dev/null
+++ b/common/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
@@ -0,0 +1,115 @@
+package com.blankj.utilcode.util;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.view.Window;
+import android.view.WindowManager;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
+/**
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2018/02/08
+ * desc : utils about brightness
+ *