From 55c3fc2eb9344eb3278b2690b32488d8a200adaa Mon Sep 17 00:00:00 2001 From: Blankj <625783482@qq.com> Date: Fri, 8 Mar 2019 17:46:44 +0800 Subject: [PATCH 01/49] see 03/08 log --- CHANGELOG.md | 1 + config.gradle | 17 ++++++------- gradle.properties | 4 ++- .../com/blankj/launcher/pkg/MainActivity.kt | 2 +- .../pkg/src/main/res/layout/activity_main.xml | 18 ++++++------- lib/base/build.gradle | 6 ++--- .../java/com/blankj/lib/base/BaseActivity.kt | 2 +- .../com/blankj/lib/base/BaseApplication.kt | 2 +- .../com/blankj/lib/base/BaseDrawerActivity.kt | 6 ++--- .../java/com/blankj/lib/base/BaseFragment.kt | 6 ++--- .../blankj/lib/base/rv/BaseViewHolder.java | 4 +-- .../lib/base/rv/RecycleViewDivider.java | 10 ++++---- .../lib/base/rv/adapter/BaseAdapter.java | 6 ++--- .../lib/base/rv/adapter/SingleAdapter.java | 2 +- .../src/main/res/layout/activity_back.xml | 14 +++++------ .../src/main/res/layout/activity_drawer.xml | 6 ++--- subutil/lib/build.gradle | 6 ++--- .../blankj/subutil/util/LocationUtils.java | 2 +- .../com/blankj/subutil/util/PinyinUtils.java | 2 +- .../java/com/blankj/subutil/util/Utils.java | 4 +-- .../blankj/subutil/pkg/helper/DialogHelper.kt | 2 +- utilcode/lib/build.gradle | 8 +++--- utilcode/lib/project.properties | 2 +- .../utilcode/constant/MemoryConstants.java | 2 +- .../constant/PermissionConstants.java | 2 +- .../utilcode/constant/TimeConstants.java | 2 +- .../blankj/utilcode/util/ActivityUtils.java | 9 ++++--- .../blankj/utilcode/util/AntiShakeUtils.java | 5 ++-- .../com/blankj/utilcode/util/AppUtils.java | 5 ++-- .../com/blankj/utilcode/util/BarUtils.java | 11 ++++---- .../blankj/utilcode/util/BrightnessUtils.java | 5 ++-- .../utilcode/util/CacheDiskStaticUtils.java | 3 ++- .../blankj/utilcode/util/CacheDiskUtils.java | 3 ++- .../utilcode/util/CacheDoubleStaticUtils.java | 3 ++- .../utilcode/util/CacheDoubleUtils.java | 2 +- .../utilcode/util/CacheMemoryStaticUtils.java | 2 +- .../utilcode/util/CacheMemoryUtils.java | 4 +-- .../com/blankj/utilcode/util/ColorUtils.java | 12 ++++----- .../com/blankj/utilcode/util/CrashUtils.java | 4 +-- .../com/blankj/utilcode/util/DeviceUtils.java | 4 +-- .../blankj/utilcode/util/FragmentUtils.java | 21 ++++++++-------- .../com/blankj/utilcode/util/ImageUtils.java | 14 +++++------ .../com/blankj/utilcode/util/IntentUtils.java | 4 +-- .../com/blankj/utilcode/util/LogUtils.java | 8 +++--- .../blankj/utilcode/util/MetaDataUtils.java | 2 +- .../blankj/utilcode/util/NetworkUtils.java | 2 +- .../utilcode/util/NotificationUtils.java | 6 ++--- .../com/blankj/utilcode/util/ObjectUtils.java | 6 ++--- .../blankj/utilcode/util/PermissionUtils.java | 8 +++--- .../com/blankj/utilcode/util/PhoneUtils.java | 2 +- .../blankj/utilcode/util/ProcessUtils.java | 4 +-- .../com/blankj/utilcode/util/RegexUtils.java | 2 +- .../blankj/utilcode/util/ResourceUtils.java | 2 +- .../blankj/utilcode/util/SPStaticUtils.java | 2 +- .../com/blankj/utilcode/util/SPUtils.java | 2 +- .../com/blankj/utilcode/util/ScreenUtils.java | 5 ++-- .../blankj/utilcode/util/SnackbarUtils.java | 14 +++++------ .../com/blankj/utilcode/util/SpanUtils.java | 16 ++++++------ .../com/blankj/utilcode/util/StringUtils.java | 4 +-- .../com/blankj/utilcode/util/ThreadUtils.java | 7 +++--- .../com/blankj/utilcode/util/TimeUtils.java | 2 +- .../com/blankj/utilcode/util/ToastUtils.java | 10 ++++---- .../com/blankj/utilcode/util/UriUtils.java | 25 +++++++++++++------ .../java/com/blankj/utilcode/util/Utils.java | 2 +- .../blankj/utilcode/util/VibrateUtils.java | 2 +- .../blankj/utilcode/util/ObjectUtilsTest.java | 5 ++-- .../pkg/feature/activity/ActivityActivity.kt | 2 +- .../feature/activity/SubActivityActivity.kt | 2 +- .../feature/bar/BarStatusFragmentActivity.kt | 16 ++++++------ .../pkg/feature/fragment/ContainerFragment.kt | 6 ++--- .../pkg/feature/fragment/FragmentActivity.kt | 6 ++--- .../pkg/feature/image/ImageActivity.kt | 8 +++--- .../pkg/feature/snackbar/SnackbarActivity.kt | 2 +- .../utilcode/pkg/feature/span/SpanActivity.kt | 2 +- .../utilcode/pkg/feature/toast/CustomToast.kt | 2 +- .../pkg/feature/toast/ToastActivity.kt | 2 +- .../utilcode/pkg/helper/DialogHelper.kt | 2 +- .../main/res/layout/activity_adaptscreen.xml | 4 +-- .../res/layout/activity_adaptscreen_close.xml | 4 +-- .../layout/activity_adaptscreen_height.xml | 4 +-- .../res/layout/activity_adaptscreen_width.xml | 4 +-- .../layout/activity_bar_status_fragment.xml | 4 +-- .../src/main/res/layout/activity_fragment.xml | 2 +- .../src/main/res/layout/activity_image.xml | 2 +- 84 files changed, 241 insertions(+), 220 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8271c33548..a1706be701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +* `19/03/09` [fix] UriUtils#uri2File. * `19/03/08` [add] LogUtils support multi process. Publish v1.23.7. * `19/03/02` [fix] LogUtils#file. * `19/02/28` [fix] ImageUtils#calculateInSampleSize. Publish v1.23.6. diff --git a/config.gradle b/config.gradle index 57c3d35e99..106f066059 100644 --- a/config.gradle +++ b/config.gradle @@ -2,7 +2,7 @@ ext { applicationId = 'com.blankj.androidutilcode' appName = 'Util' - compileSdkVersion = 27 + compileSdkVersion = 28 minSdkVersion = 14 targetSdkVersion = 27 versionCode = 1_023_007 @@ -16,8 +16,8 @@ ext { // lib version kotlin_version = '1.3.0' - support_version = '27.1.1' leakcanary_version = '1.6.3' + androidx_version = '1.0.0' dep = [ plugin : [ @@ -30,19 +30,18 @@ ext { ], // lib - support : [ - appcompat_v7: "com.android.support:appcompat-v7:$support_version", - design : "com.android.support:design:$support_version", - multidex : "com.android.support:multidex:1.0.2", - ], - constraint : "com.android.support.constraint:constraint-layout:1.1.3", + appcompat : "androidx.appcompat:appcompat:$androidx_version", + design : "com.google.android.material:material:$androidx_version", + multidex : "androidx.multidex:multidex:2.0.1", + constraint : "androidx.constraintlayout:constraintlayout:1.1.3", + kotlin : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version", leakcanary : [ android : "com.squareup.leakcanary:leakcanary-android:$leakcanary_version", android_no_op : "com.squareup.leakcanary:leakcanary-android-no-op:$leakcanary_version", support_fragment: "com.squareup.leakcanary:leakcanary-support-fragment:$leakcanary_version" ], - free_proguard: "com.blankj:free-proguard:0.0.7", + free_proguard: "com.blankj:free-proguard:0.0.12", adapt_screen : "com.blankj:adapt-screen:0.0.3", gson : "com.google.code.gson:gson:2.8.2", diff --git a/gradle.properties b/gradle.properties index e98b0a89fc..ad5471a961 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,6 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -#org.gradle.jvmargs=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 \ No newline at end of file +#org.gradle.jvmargs=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 +android.enableJetifier=true +android.useAndroidX=true \ No newline at end of file diff --git a/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt b/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt index 27d29a032a..e6dc516ed6 100644 --- a/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt +++ b/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt @@ -2,7 +2,7 @@ package com.blankj.launcher.pkg import android.graphics.Color import android.os.Bundle -import android.support.v7.app.ActionBarDrawerToggle +import androidx.appcompat.app.ActionBarDrawerToggle import android.view.View import android.widget.ImageView import com.blankj.lib.base.BaseDrawerActivity diff --git a/launcher/pkg/src/main/res/layout/activity_main.xml b/launcher/pkg/src/main/res/layout/activity_main.xml index 3b31dafe32..ee8b62a6fa 100644 --- a/launcher/pkg/src/main/res/layout/activity_main.xml +++ b/launcher/pkg/src/main/res/layout/activity_main.xml @@ -1,17 +1,17 @@ - - - - - - + + - @@ -69,5 +69,5 @@ android:text="@string/sub_util" /> - - + + diff --git a/lib/base/build.gradle b/lib/base/build.gradle index bd369d23ee..8c6cb29835 100644 --- a/lib/base/build.gradle +++ b/lib/base/build.gradle @@ -7,9 +7,9 @@ dependencies { api project(':utilcode-lib') api project(':subutil-lib') - api dep.support.appcompat_v7 - api dep.support.design - api dep.support.multidex + api dep.appcompat + api dep.design + api dep.multidex api dep.constraint api dep.kotlin api dep.free_proguard diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.kt b/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.kt index deb05718a9..b1b3086f14 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.kt +++ b/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.kt @@ -2,7 +2,7 @@ package com.blankj.lib.base import android.app.Activity import android.os.Bundle -import android.support.v7.app.AppCompatActivity +import androidx.appcompat.app.AppCompatActivity import android.view.LayoutInflater import android.view.View import com.blankj.utilcode.util.AntiShakeUtils diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.kt b/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.kt index f3eb078f79..873c71fa49 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.kt +++ b/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.kt @@ -2,7 +2,7 @@ package com.blankj.lib.base import android.app.Application import android.content.Context -import android.support.multidex.MultiDex +import androidx.multidex.MultiDex import com.blankj.utilcode.util.AppUtils import com.blankj.utilcode.util.CrashUtils import com.blankj.utilcode.util.LogUtils diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.kt b/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.kt index a29cc60cc8..3514d2fdd3 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.kt +++ b/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.kt @@ -2,8 +2,8 @@ package com.blankj.lib.base import android.content.Intent import android.net.Uri -import android.support.annotation.StringRes -import android.support.v4.widget.DrawerLayout +import androidx.annotation.StringRes +import androidx.drawerlayout.widget.DrawerLayout import android.view.LayoutInflater import android.widget.FrameLayout import com.blankj.utilcode.util.ActivityUtils @@ -20,7 +20,7 @@ import kotlinx.android.synthetic.main.activity_drawer.* */ abstract class BaseDrawerActivity : BaseActivity() { - protected lateinit var mBaseDrawerRootLayout: DrawerLayout + protected lateinit var mBaseDrawerRootLayout: androidx.drawerlayout.widget.DrawerLayout protected lateinit var mBaseDrawerContainerView: FrameLayout override fun isSwipeBack(): Boolean { diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.kt b/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.kt index 42e7073529..3db893bea2 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.kt +++ b/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.kt @@ -3,8 +3,8 @@ package com.blankj.lib.base import android.app.Activity import android.content.Context import android.os.Bundle -import android.support.annotation.IdRes -import android.support.v4.app.Fragment +import androidx.annotation.IdRes +import androidx.fragment.app.Fragment import android.util.Log import android.view.LayoutInflater import android.view.View @@ -19,7 +19,7 @@ import com.blankj.utilcode.util.AntiShakeUtils * desc : base about v4-fragment * ``` */ -abstract class BaseFragment : Fragment(), IBaseView { +abstract class BaseFragment : androidx.fragment.app.Fragment(), IBaseView { companion object { private const val TAG = "BaseFragment" diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java index ee47e751f5..6441f8c1fd 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java +++ b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java @@ -1,7 +1,7 @@ package com.blankj.lib.base.rv; -import android.support.annotation.IdRes; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.IdRes; +import androidx.recyclerview.widget.RecyclerView; import android.util.SparseArray; import android.view.View; diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java b/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java index 3d2b90f302..dd20894e10 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java +++ b/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java @@ -5,11 +5,11 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.ViewCompat; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.RecyclerView; import android.view.View; import android.widget.LinearLayout; diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/BaseAdapter.java b/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/BaseAdapter.java index f5acee0bb3..b8cf5ae12d 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/BaseAdapter.java +++ b/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/BaseAdapter.java @@ -1,9 +1,9 @@ package com.blankj.lib.base.rv.adapter; import android.content.Context; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/SingleAdapter.java b/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/SingleAdapter.java index 619c8fc688..b7e81b892b 100644 --- a/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/SingleAdapter.java +++ b/lib/base/src/main/java/com/blankj/lib/base/rv/adapter/SingleAdapter.java @@ -1,6 +1,6 @@ package com.blankj.lib.base.rv.adapter; -import android.support.annotation.LayoutRes; +import androidx.annotation.LayoutRes; import java.util.List; diff --git a/lib/base/src/main/res/layout/activity_back.xml b/lib/base/src/main/res/layout/activity_back.xml index 5747922950..848cc885fe 100644 --- a/lib/base/src/main/res/layout/activity_back.xml +++ b/lib/base/src/main/res/layout/activity_back.xml @@ -1,26 +1,26 @@ - - - - + - - - + + diff --git a/lib/base/src/main/res/layout/activity_drawer.xml b/lib/base/src/main/res/layout/activity_drawer.xml index 1fec3fc953..697e83f643 100644 --- a/lib/base/src/main/res/layout/activity_drawer.xml +++ b/lib/base/src/main/res/layout/activity_drawer.xml @@ -1,5 +1,5 @@ - - - + diff --git a/subutil/lib/build.gradle b/subutil/lib/build.gradle index a8b9264e6c..8f8aa8198f 100644 --- a/subutil/lib/build.gradle +++ b/subutil/lib/build.gradle @@ -1,7 +1,7 @@ apply { from "${rootDir.path}/config_lib.gradle" - plugin "tech.harmonysoft.oss.traute" +// plugin "tech.harmonysoft.oss.traute" plugin "com.github.dcendents.android-maven" plugin "com.jfrog.bintray" plugin "readme-sub" @@ -13,8 +13,8 @@ readme { } dependencies { - compileOnly dep.support.appcompat_v7 - compileOnly dep.support.design + compileOnly dep.appcompat + compileOnly dep.design api(dep.glide) { exclude group: "com.android.support" } diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java b/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java index 7ee8747902..0c177b534c 100755 --- a/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java +++ b/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java @@ -11,7 +11,7 @@ import android.location.LocationProvider; import android.os.Bundle; import android.provider.Settings; -import android.support.annotation.RequiresPermission; +import androidx.annotation.RequiresPermission; import android.util.Log; import java.io.IOException; diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java b/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java index 22486b3a91..934408c65e 100644 --- a/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java +++ b/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java @@ -1,6 +1,6 @@ package com.blankj.subutil.util; -import android.support.v4.util.SimpleArrayMap; +import androidx.collection.SimpleArrayMap; /** *
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java b/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java
index 9cbf4e06fd..91b336abcf 100644
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java
@@ -7,8 +7,8 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import java.lang.reflect.InvocationTargetException;
 
diff --git a/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt b/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt
index 45e67a4a0d..9eba25c622 100644
--- a/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt
+++ b/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt
@@ -1,6 +1,6 @@
 package com.blankj.subutil.pkg.helper
 
-import android.support.v7.app.AlertDialog
+import androidx.appcompat.app.AlertDialog
 import com.blankj.subutil.pkg.R
 import com.blankj.utilcode.util.ActivityUtils
 import com.blankj.utilcode.util.PermissionUtils
diff --git a/utilcode/lib/build.gradle b/utilcode/lib/build.gradle
index 3570124816..41b0dacaa4 100644
--- a/utilcode/lib/build.gradle
+++ b/utilcode/lib/build.gradle
@@ -1,7 +1,7 @@
 apply {
     from "${rootDir.path}/config_lib.gradle"
 
-    plugin "tech.harmonysoft.oss.traute"
+//    plugin "tech.harmonysoft.oss.traute"
     plugin "com.github.dcendents.android-maven"
     plugin "com.jfrog.bintray"
     plugin "readme-core"
@@ -17,10 +17,10 @@ apply from: "${rootDir.path}/gradle/bintrayUploadAndroid.gradle"
 dependencies {
     compile dep.gson
 
-    compileOnly dep.support.appcompat_v7
-    compileOnly dep.support.design
+    compileOnly dep.appcompat
+    compileOnly dep.design
 
     testImplementation dep.junit
     testImplementation dep.robolectric
-    testImplementation dep.support.appcompat_v7
+    testImplementation dep.appcompat
 }
\ No newline at end of file
diff --git a/utilcode/lib/project.properties b/utilcode/lib/project.properties
index 22ae3b8603..d0f2a3f7e0 100644
--- a/utilcode/lib/project.properties
+++ b/utilcode/lib/project.properties
@@ -1,7 +1,7 @@
 #project
 project.name=UtilCode
 project.groupId=com.blankj
-project.artifactId=utilcode
+project.artifactId=utilcodex
 project.packaging=aar
 project.siteUrl=https://github.com/Blankj/AndroidUtilCode
 project.gitUrl=https://github.com/Blankj/AndroidUtilCode.git
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java
index b68bfcb113..5c05c0163e 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.constant;
 
-import android.support.annotation.IntDef;
+import androidx.annotation.IntDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java
index 76f7e9a217..6db826e4ab 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java
@@ -4,7 +4,7 @@
 import android.Manifest.permission;
 import android.annotation.SuppressLint;
 import android.os.Build;
-import android.support.annotation.StringDef;
+import androidx.annotation.StringDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java
index 9932037bf8..45090576e3 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.constant;
 
-import android.support.annotation.IntDef;
+import androidx.annotation.IntDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
index 4b8a9a07b5..9dd16d6e48 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
@@ -10,15 +10,16 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.annotation.AnimRes;
-import android.support.annotation.NonNull;
-import android.support.v4.app.ActivityOptionsCompat;
-import android.support.v4.util.Pair;
 import android.util.Log;
 import android.view.View;
 
 import java.util.List;
 
+import androidx.annotation.AnimRes;
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityOptionsCompat;
+import androidx.core.util.Pair;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java
index 7e87e73474..ca9036225e 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java
@@ -1,9 +1,10 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
 import android.view.View;
 
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java
index 136f27b5ed..357c423fc6 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java
@@ -17,8 +17,6 @@
 import android.net.Uri;
 import android.os.Build;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.v4.content.FileProvider;
 import android.util.Log;
 
 import java.io.File;
@@ -27,6 +25,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import androidx.annotation.NonNull;
+import androidx.core.content.FileProvider;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java
index 7b5509b2b5..22178a5c20 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java
@@ -8,11 +8,6 @@
 import android.graphics.Color;
 import android.graphics.Point;
 import android.os.Build;
-import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresApi;
-import android.support.annotation.RequiresPermission;
-import android.support.v4.widget.DrawerLayout;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.Display;
@@ -27,6 +22,12 @@
 
 import java.lang.reflect.Method;
 
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RequiresPermission;
+import androidx.drawerlayout.widget.DrawerLayout;
+
 import static android.Manifest.permission.EXPAND_STATUS_BAR;
 
 /**
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
index f9344b0a59..bacc519540 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
@@ -2,11 +2,12 @@
 
 import android.content.ContentResolver;
 import android.provider.Settings;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
 import android.view.Window;
 import android.view.WindowManager;
 
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java
index bb48a4b5cf..c5a9a17a6d 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java
@@ -3,13 +3,14 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
 
 import org.json.JSONArray;
 import org.json.JSONObject;
 
 import java.io.Serializable;
 
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java
index 99aef6b078..2e6637febf 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java
@@ -8,7 +8,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
 import android.util.Log;
 
 import com.blankj.utilcode.constant.CacheConstants;
@@ -37,6 +36,8 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java
index 2ef267bd01..6dbb9f7475 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java
@@ -3,13 +3,14 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
 
 import org.json.JSONArray;
 import org.json.JSONObject;
 
 import java.io.Serializable;
 
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java
index c800423c78..aca1c25837 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java
@@ -3,7 +3,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import com.blankj.utilcode.constant.CacheConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java
index 56abfba117..aedcfa7fc4 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java
index d0e06e394d..ddaa2baed9 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java
@@ -1,7 +1,7 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
-import android.support.v4.util.LruCache;
+import androidx.annotation.NonNull;
+import androidx.collection.LruCache;
 
 import com.blankj.utilcode.constant.CacheConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java
index 4c0c22232b..a6603cfc44 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java
@@ -1,12 +1,12 @@
 package com.blankj.utilcode.util;
 
 import android.graphics.Color;
-import android.support.annotation.ColorInt;
-import android.support.annotation.ColorRes;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java
index 9ef930c467..a096321cf4 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java
@@ -5,8 +5,8 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Environment;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresPermission;
 import android.util.Log;
 
 import java.io.BufferedWriter;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
index c1c2c3c76e..d0c1788a02 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
@@ -8,8 +8,8 @@
 import android.os.Build;
 import android.os.PowerManager;
 import android.provider.Settings;
-import android.support.annotation.RequiresApi;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RequiresPermission;
 import android.text.TextUtils;
 
 import java.io.File;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
index 43b8537e75..9e8ae14ef1 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
@@ -3,16 +3,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.annotation.AnimRes;
-import android.support.annotation.AnimatorRes;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.IdRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
 import android.util.Log;
 import android.view.View;
 
@@ -20,6 +10,17 @@
 import java.util.Collections;
 import java.util.List;
 
+import androidx.annotation.AnimRes;
+import androidx.annotation.AnimatorRes;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java
index 83e01eb1ad..cbee7dd4bd 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java
@@ -27,13 +27,13 @@
 import android.renderscript.Element;
 import android.renderscript.RenderScript;
 import android.renderscript.ScriptIntrinsicBlur;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresApi;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.core.content.ContextCompat;
 import android.view.View;
 
 import java.io.BufferedOutputStream;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java
index 6faa37d043..1e26dc8a9a 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java
@@ -8,8 +8,8 @@
 import android.os.Bundle;
 import android.provider.MediaStore;
 import android.provider.Settings;
-import android.support.annotation.RequiresPermission;
-import android.support.v4.content.FileProvider;
+import androidx.annotation.RequiresPermission;
+import androidx.core.content.FileProvider;
 
 import java.io.File;
 import java.util.ArrayList;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java
index e1e2e78600..f5d814207d 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java
@@ -12,10 +12,10 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
-import android.support.annotation.IntDef;
-import android.support.annotation.IntRange;
-import android.support.annotation.RequiresApi;
-import android.support.v4.util.SimpleArrayMap;
+import androidx.annotation.IntDef;
+import androidx.annotation.IntRange;
+import androidx.annotation.RequiresApi;
+import androidx.collection.SimpleArrayMap;
 import android.util.Log;
 
 import com.google.gson.Gson;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
index 6f6cf85b80..bd4b8da935 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
@@ -8,7 +8,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
index f281d777c2..3171837f46 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
@@ -7,7 +7,7 @@
 import android.net.NetworkInfo;
 import android.net.wifi.WifiManager;
 import android.os.Build;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.RequiresPermission;
 import android.telephony.TelephonyManager;
 import android.text.format.Formatter;
 import android.util.Log;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java
index b8163d2e66..73a900b465 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java
@@ -5,9 +5,9 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.support.annotation.Nullable;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationManagerCompat;
+import androidx.annotation.Nullable;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java
index be5491ece0..3c0c087a39 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java
@@ -1,9 +1,9 @@
 package com.blankj.utilcode.util;
 
 import android.os.Build;
-import android.support.annotation.RequiresApi;
-import android.support.v4.util.LongSparseArray;
-import android.support.v4.util.SimpleArrayMap;
+import androidx.annotation.RequiresApi;
+import androidx.collection.LongSparseArray;
+import androidx.collection.SimpleArrayMap;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java
index 235a0f3f94..1cb3df0156 100755
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java
@@ -10,10 +10,10 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.RequiresApi;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.core.content.ContextCompat;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.WindowManager;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java
index 99068781a4..f407f81b5f 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java
@@ -7,7 +7,7 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Build;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.RequiresPermission;
 import android.telephony.SmsManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java
index 7db75522d9..00c2bf6f73 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java
@@ -10,8 +10,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresPermission;
 import android.util.Log;
 
 import java.io.BufferedReader;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java
index ba57fab956..817a94149f 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.v4.util.SimpleArrayMap;
+import androidx.collection.SimpleArrayMap;
 
 import com.blankj.utilcode.constant.RegexConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java
index 92424163bb..ee41e95958 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.RawRes;
+import androidx.annotation.RawRes;
 
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java
index d3e21fb873..21274c3023 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java
@@ -1,7 +1,7 @@
 package com.blankj.utilcode.util;
 
 import android.content.SharedPreferences;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import java.util.Map;
 import java.util.Set;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java
index 554a2ed586..a9d18a1a55 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java
@@ -3,7 +3,7 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
index c3e089a90f..f55e4a21db 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
@@ -7,12 +7,11 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.Point;
 import android.os.Build;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresPermission;
 import android.util.DisplayMetrics;
 import android.view.Surface;
 import android.view.View;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java
index b164e6154e..eab1990d29 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java
@@ -1,12 +1,12 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.IntDef;
-import android.support.annotation.IntRange;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
-import android.support.design.widget.Snackbar;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IntDef;
+import androidx.annotation.IntRange;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import com.google.android.material.snackbar.Snackbar;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java
index 641204fd63..d79cf9262b 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java
@@ -14,14 +14,14 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntDef;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntDef;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
 import android.text.Layout;
 import android.text.Layout.Alignment;
 import android.text.SpannableStringBuilder;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java
index c3254e3d32..70f0defe50 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java
@@ -1,8 +1,8 @@
 package com.blankj.utilcode.util;
 
 import android.content.res.Resources;
-import android.support.annotation.ArrayRes;
-import android.support.annotation.StringRes;
+import androidx.annotation.ArrayRes;
+import androidx.annotation.StringRes;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java
index ba7122e366..819af790e8 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java
@@ -2,9 +2,6 @@
 
 import android.os.Handler;
 import android.os.Looper;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -21,6 +18,10 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java
index adaa920474..a5286b0fbe 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import com.blankj.utilcode.constant.TimeConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java
index b4fe658945..b25360e52c 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java
@@ -14,11 +14,11 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.StringRes;
-import android.support.v4.app.NotificationManagerCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.StringRes;
+import androidx.core.app.NotificationManagerCompat;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java
index 98f3ef66a8..8e4fd9d09c 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java
@@ -8,12 +8,14 @@
 import android.os.Environment;
 import android.provider.DocumentsContract;
 import android.provider.MediaStore;
-import android.support.annotation.NonNull;
-import android.support.v4.content.FileProvider;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.File;
 
+import androidx.annotation.NonNull;
+import androidx.core.content.FileProvider;
+
 /**
  * 
  *     author: Blankj
@@ -70,12 +72,19 @@ public static File uri2File(@NonNull final Uri uri) {
                 Log.d("UriUtils", uri.toString() + " parse failed. -> 1");
                 return null;
             } else if ("com.android.providers.downloads.documents".equals(authority)) {
-                final String id = DocumentsContract.getDocumentId(uri);
-                final Uri contentUri = ContentUris.withAppendedId(
-                        Uri.parse("content://downloads/public_downloads"),
-                        Long.valueOf(id)
-                );
-                return getFileFromUri(contentUri, 2);
+                String id = DocumentsContract.getDocumentId(uri);
+                if (!TextUtils.isEmpty(id)) {
+                    if (id.startsWith("raw:")) {
+                        return new File(id.substring(4));
+                    }
+                    final Uri contentUri = ContentUris.withAppendedId(
+                            Uri.parse(Environment.DIRECTORY_DOWNLOADS),
+                            Long.valueOf(id)
+                    );
+                    return getFileFromUri(contentUri, 2);
+                }
+                Log.d("UriUtils", uri.toString() + " parse failed. -> 3");
+                return null;
             } else if ("com.android.providers.media.documents".equals(authority)) {
                 final String docId = DocumentsContract.getDocumentId(uri);
                 final String[] split = docId.split(":");
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java
index 52b82376e1..d858e4ad22 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java
@@ -7,7 +7,7 @@
 import android.app.Application.ActivityLifecycleCallbacks;
 import android.content.Context;
 import android.os.Bundle;
-import android.support.v4.content.FileProvider;
+import androidx.core.content.FileProvider;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java
index a57bbb8241..622d657817 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java
@@ -2,7 +2,7 @@
 
 import android.content.Context;
 import android.os.Vibrator;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.RequiresPermission;
 
 import static android.Manifest.permission.VIBRATE;
 
diff --git a/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java b/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java
index a0203f78fc..ed12c24d8d 100644
--- a/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java
+++ b/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java
@@ -1,7 +1,5 @@
 package com.blankj.utilcode.util;
 
-import android.support.v4.util.LongSparseArray;
-import android.support.v4.util.SimpleArrayMap;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
@@ -12,6 +10,9 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 
+import androidx.collection.LongSparseArray;
+import androidx.collection.SimpleArrayMap;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt
index 5ace21f5b1..f3d3600a27 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt
@@ -6,7 +6,7 @@ import android.graphics.Bitmap
 import android.graphics.drawable.BitmapDrawable
 import android.os.Build
 import android.os.Bundle
-import android.support.v4.app.ActivityOptionsCompat
+import androidx.core.app.ActivityOptionsCompat
 import android.view.View
 import android.view.Window
 import com.blankj.lib.base.BaseTitleBarActivity
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt
index 4815032936..864f1c12b4 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt
@@ -2,7 +2,7 @@ package com.blankj.utilcode.pkg.feature.activity
 
 import android.os.Build
 import android.os.Bundle
-import android.support.v4.app.ActivityCompat
+import androidx.core.app.ActivityCompat
 import android.view.View
 import android.view.Window
 import com.blankj.lib.base.BaseTitleBarActivity
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt
index b2633ddf5c..0dac18c72c 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt
@@ -3,10 +3,10 @@ package com.blankj.utilcode.pkg.feature.bar
 import android.content.Context
 import android.content.Intent
 import android.os.Bundle
-import android.support.design.widget.BottomNavigationView
-import android.support.v4.app.Fragment
-import android.support.v4.app.FragmentPagerAdapter
-import android.support.v4.view.ViewPager
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentPagerAdapter
+import androidx.viewpager.widget.ViewPager
 import android.view.View
 import com.blankj.lib.base.BaseActivity
 import com.blankj.utilcode.pkg.R
@@ -37,7 +37,7 @@ class BarStatusFragmentActivity : BaseActivity() {
             R.id.barStatusFragmentNavigationCustom
     )
 
-    private val mFragmentList = ArrayList()
+    private val mFragmentList = ArrayList()
 
     private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener l@{ item ->
         when (item.itemId) {
@@ -78,8 +78,8 @@ class BarStatusFragmentActivity : BaseActivity() {
         mFragmentList.add(BarStatusCustomFragment.newInstance())
 
         barStatusFragmentVp.offscreenPageLimit = 3
-        barStatusFragmentVp.adapter = object : FragmentPagerAdapter(supportFragmentManager) {
-            override fun getItem(position: Int): Fragment {
+        barStatusFragmentVp.adapter = object : androidx.fragment.app.FragmentPagerAdapter(supportFragmentManager) {
+            override fun getItem(position: Int): androidx.fragment.app.Fragment {
                 return mFragmentList[position]
             }
 
@@ -88,7 +88,7 @@ class BarStatusFragmentActivity : BaseActivity() {
             }
         }
 
-        barStatusFragmentVp.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
+        barStatusFragmentVp.addOnPageChangeListener(object : androidx.viewpager.widget.ViewPager.OnPageChangeListener {
             override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
 
             override fun onPageSelected(position: Int) {
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt
index ca0289a158..117c7d121e 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt
@@ -2,8 +2,8 @@ package com.blankj.utilcode.pkg.feature.fragment
 
 import android.os.Build
 import android.os.Bundle
-import android.support.annotation.RequiresApi
-import android.support.v4.app.Fragment
+import androidx.annotation.RequiresApi
+import androidx.fragment.app.Fragment
 import android.transition.*
 import android.view.View
 import com.blankj.lib.base.BaseLazyFragment
@@ -129,7 +129,7 @@ class ContainerFragment : BaseLazyFragment(), FragmentUtils.OnBackClickListener
         }
     }
 
-    private fun addSharedElement(fragment: Fragment): Fragment {
+    private fun addSharedElement(fragment: androidx.fragment.app.Fragment): androidx.fragment.app.Fragment {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             fragment.sharedElementEnterTransition = DetailTransition()
             fragment.enterTransition = Fade()
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt
index b768f563e5..6e3137b9c6 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt
@@ -4,8 +4,8 @@ import android.content.Context
 import android.content.Intent
 import android.os.Bundle
 import android.os.PersistableBundle
-import android.support.design.widget.BottomNavigationView
-import android.support.v4.app.Fragment
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import androidx.fragment.app.Fragment
 import android.view.View
 import com.blankj.lib.base.BaseActivity
 import com.blankj.utilcode.pkg.R
@@ -30,7 +30,7 @@ class FragmentActivity : BaseActivity() {
         }
     }
 
-    private val mFragments = arrayListOf()
+    private val mFragments = arrayListOf()
     private var curIndex: Int = 0
 
     private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt
index 496c5a4032..636d92c030 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt
@@ -6,9 +6,9 @@ import android.graphics.Bitmap
 import android.graphics.Color
 import android.os.Build
 import android.os.Bundle
-import android.support.annotation.LayoutRes
-import android.support.annotation.StringRes
-import android.support.v7.widget.LinearLayoutManager
+import androidx.annotation.LayoutRes
+import androidx.annotation.StringRes
+import androidx.recyclerview.widget.LinearLayoutManager
 import android.view.View
 import android.widget.ImageView
 import android.widget.TextView
@@ -92,7 +92,7 @@ class ImageActivity : BaseActivity() {
         }
 
         imageRv.adapter = ImageAdapter(mList, R.layout.item_image)
-        imageRv.layoutManager = LinearLayoutManager(this)
+        imageRv.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this)
     }
 
     override fun doBusiness() {}
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt
index 4bd07d274e..34d3914fe1 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt
@@ -4,7 +4,7 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.Color
 import android.os.Bundle
-import android.support.annotation.StringRes
+import androidx.annotation.StringRes
 import android.text.SpannableStringBuilder
 import android.view.View
 import android.view.ViewGroup
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt
index f3a1a3ee02..7c5fd45308 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt
@@ -5,7 +5,7 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.*
 import android.os.Bundle
-import android.support.annotation.ColorInt
+import androidx.annotation.ColorInt
 import android.text.Layout
 import android.text.SpannableStringBuilder
 import android.text.TextPaint
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt
index 314ba33d59..458ecbb3fb 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt
@@ -2,7 +2,7 @@ package com.blankj.utilcode.pkg.feature.toast
 
 import android.os.Handler
 import android.os.Looper
-import android.support.annotation.StringRes
+import androidx.annotation.StringRes
 import android.widget.TextView
 import android.widget.Toast
 
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
index ea6c10c24d..40055d14b9 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
@@ -4,7 +4,7 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.Color
 import android.os.Bundle
-import android.support.v4.content.ContextCompat
+import androidx.core.content.ContextCompat
 import android.view.Gravity
 import android.view.View
 import com.blankj.lib.base.BaseTitleBarActivity
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt
index 7e6094414a..c3247b1312 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.pkg.helper
 
-import android.support.v7.app.AlertDialog
+import androidx.appcompat.app.AlertDialog
 import android.text.method.ScrollingMovementMethod
 import android.view.LayoutInflater
 import android.view.View
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml
index 003c6f5840..e33848b84d 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml
@@ -1,5 +1,5 @@
 
-
 
-
+
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml
index c3f88ecba3..e43cbb2bb5 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml
@@ -8,7 +8,7 @@
     android:background="@color/white"
     tools:context=".feature.adaptScreen.CloseAdaptActivity">
 
-    
 
@@ -42,6 +42,6 @@
             android:textSize="30pt"
             app:layout_constraintTop_toBottomOf="@id/adaptScreenCloseAdaptDpTv" />
 
-    
+    
 
 
\ No newline at end of file
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml
index 0b207d97f5..07c76be55b 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml
@@ -8,7 +8,7 @@
     android:background="@color/white"
     tools:context=".feature.adaptScreen.HeightActivity">
 
-    
 
@@ -94,6 +94,6 @@
         
 
 
-    
+    
 
 
\ No newline at end of file
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml
index 46e0f2f1a2..5a791d924f 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml
@@ -8,7 +8,7 @@
     android:background="@color/white"
     tools:context=".feature.adaptScreen.WidthActivity">
 
-    
 
@@ -147,6 +147,6 @@
 
         
 
-    
+    
 
 
\ No newline at end of file
diff --git a/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml b/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml
index c5f975b58f..1a36770b58 100644
--- a/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml
@@ -7,7 +7,7 @@
     android:background="@color/white"
     android:orientation="vertical">
 
-    
 
-    
 
-    
 
-    

From 70b6089109b6e58734d0a500820f54cb41858eba Mon Sep 17 00:00:00 2001
From: Blankj <625783482@qq.com>
Date: Fri, 8 Mar 2019 18:07:14 +0800
Subject: [PATCH 02/49] see 03/08 log

---
 utilcode/README-CN.md | 3 +++
 utilcode/README.md    | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/utilcode/README-CN.md b/utilcode/README-CN.md
index f3756be966..7fc06ebf99 100644
--- a/utilcode/README-CN.md
+++ b/utilcode/README-CN.md
@@ -3,6 +3,9 @@
 Gradle:
 ```groovy
 implementation 'com.blankj:utilcode:1.23.7'
+
+// if u use AndroidX, use the following
+implementation 'com.blankj:utilcodex:1.23.7'
 ```
 
 
diff --git a/utilcode/README.md b/utilcode/README.md
index 75d8757892..094cc44c08 100644
--- a/utilcode/README.md
+++ b/utilcode/README.md
@@ -3,6 +3,9 @@
 Gradle:
 ```groovy
 implementation 'com.blankj:utilcode:1.23.7'
+
+// if u use AndroidX, use the following
+implementation 'com.blankj:utilcodex:1.23.7'
 ```
 
 

From 2fa66306221456a5be12d9d201c7495958596fb4 Mon Sep 17 00:00:00 2001
From: Blankj <625783482@qq.com>
Date: Mon, 11 Mar 2019 20:45:31 +0800
Subject: [PATCH 03/49] see 03/11 log

---
 utilcode/lib/project.properties | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/utilcode/lib/project.properties b/utilcode/lib/project.properties
index d0f2a3f7e0..d238eda740 100644
--- a/utilcode/lib/project.properties
+++ b/utilcode/lib/project.properties
@@ -1,9 +1,9 @@
 #project
-project.name=UtilCode
+project.name=UtilCodeX
 project.groupId=com.blankj
 project.artifactId=utilcodex
 project.packaging=aar
 project.siteUrl=https://github.com/Blankj/AndroidUtilCode
 project.gitUrl=https://github.com/Blankj/AndroidUtilCode.git
 #javadoc
-javadoc.name=UtilCode
\ No newline at end of file
+javadoc.name=UtilCodeX
\ No newline at end of file

From 6b0ff9575675cf0ae15c9c9a85eb249b5591c3a8 Mon Sep 17 00:00:00 2001
From: Blankj <625783482@qq.com>
Date: Mon, 3 Jun 2019 20:49:21 +0800
Subject: [PATCH 04/49] see 06/03 log

---
 .gitignore                                    |  2 +-
 CHANGELOG.md                                  |  1 +
 gradle.properties                             |  8 +++++-
 gradle/config/config.gradle                   | 10 ++++----
 gradle/config/configApp.gradle                |  5 +++-
 launcher/app/build.gradle                     |  6 ++---
 launcher/pkg/build.gradle                     |  2 +-
 .../com/blankj/launcher/pkg/MainActivity.kt   |  2 +-
 .../pkg/src/main/res/layout/activity_main.xml | 18 ++++++-------
 lib/base/build.gradle                         |  2 +-
 .../com/blankj/lib/base/BaseActivity.java     |  5 ++--
 .../com/blankj/lib/base/BaseApplication.java  |  3 ++-
 .../blankj/lib/base/BaseDrawerActivity.java   | 11 ++++----
 .../com/blankj/lib/base/BaseFragment.java     | 13 +++++-----
 .../blankj/lib/base/BaseTitleActivity.java    |  9 ++++---
 .../java/com/blankj/lib/base/IBaseView.java   |  5 ++--
 .../com/blankj/lib/base/rv/BaseAdapter.java   |  5 ++--
 .../java/com/blankj/lib/base/rv/BaseCell.java |  3 ++-
 .../blankj/lib/base/rv/BaseViewHolder.java    |  4 +--
 .../lib/base/rv/RecycleViewDivider.java       | 10 ++++----
 .../main/res/layout/activity_base_title.xml   | 11 ++++----
 .../activity_base_title_stub_scroll.xml       |  4 +--
 .../src/main/res/layout/activity_drawer.xml   |  6 ++---
 subutil/app/build.gradle                      |  2 +-
 subutil/lib/build.gradle                      |  2 +-
 .../blankj/subutil/util/LocationUtils.java    |  2 +-
 .../com/blankj/subutil/util/PinyinUtils.java  |  2 +-
 .../java/com/blankj/subutil/util/Utils.java   |  4 +--
 .../subutil/util/http/ExecutorFactory.java    |  3 ++-
 .../blankj/subutil/util/http/HttpUtils.java   |  3 ++-
 .../com/blankj/subutil/util/http/Request.java |  3 ++-
 .../blankj/subutil/util/http/SSLConfig.java   |  3 ++-
 subutil/pkg/build.gradle                      |  2 +-
 .../blankj/subutil/pkg/helper/DialogHelper.kt |  2 +-
 utilcode/README-CN.md                         |  2 +-
 utilcode/README.md                            |  2 +-
 utilcode/app/build.gradle                     |  2 +-
 utilcode/lib/build.gradle                     |  2 +-
 utilcode/lib/project.properties               |  6 ++---
 .../utilcode/constant/MemoryConstants.java    |  2 +-
 .../constant/PermissionConstants.java         |  2 +-
 .../utilcode/constant/TimeConstants.java      |  2 +-
 .../blankj/utilcode/util/ActivityUtils.java   | 11 ++++----
 .../blankj/utilcode/util/AntiShakeUtils.java  |  5 ++--
 .../com/blankj/utilcode/util/AppUtils.java    |  5 ++--
 .../com/blankj/utilcode/util/BarUtils.java    | 11 ++++----
 .../blankj/utilcode/util/BrightnessUtils.java |  5 ++--
 .../com/blankj/utilcode/util/BusUtils.java    |  5 ++--
 .../utilcode/util/CacheDiskStaticUtils.java   |  3 ++-
 .../blankj/utilcode/util/CacheDiskUtils.java  |  3 ++-
 .../utilcode/util/CacheDoubleStaticUtils.java |  3 ++-
 .../utilcode/util/CacheDoubleUtils.java       |  2 +-
 .../utilcode/util/CacheMemoryStaticUtils.java |  2 +-
 .../utilcode/util/CacheMemoryUtils.java       |  4 +--
 .../com/blankj/utilcode/util/ColorUtils.java  | 12 ++++-----
 .../com/blankj/utilcode/util/CrashUtils.java  |  4 +--
 .../com/blankj/utilcode/util/DeviceUtils.java |  5 ++--
 .../blankj/utilcode/util/FragmentUtils.java   | 21 ++++++++--------
 .../com/blankj/utilcode/util/ImageUtils.java  | 14 +++++------
 .../com/blankj/utilcode/util/IntentUtils.java |  4 +--
 .../blankj/utilcode/util/KeyboardUtils.java   |  3 ++-
 .../com/blankj/utilcode/util/LogUtils.java    |  8 +++---
 .../blankj/utilcode/util/MetaDataUtils.java   |  2 +-
 .../blankj/utilcode/util/NetworkUtils.java    |  5 ++--
 .../utilcode/util/NotificationUtils.java      |  6 ++---
 .../com/blankj/utilcode/util/ObjectUtils.java |  6 ++---
 .../blankj/utilcode/util/PermissionUtils.java |  8 +++---
 .../com/blankj/utilcode/util/PhoneUtils.java  |  2 +-
 .../blankj/utilcode/util/ProcessUtils.java    |  4 +--
 .../com/blankj/utilcode/util/RegexUtils.java  |  2 +-
 .../blankj/utilcode/util/ResourceUtils.java   |  2 +-
 .../blankj/utilcode/util/SPStaticUtils.java   |  2 +-
 .../com/blankj/utilcode/util/SPUtils.java     |  2 +-
 .../com/blankj/utilcode/util/ScreenUtils.java |  4 +--
 .../com/blankj/utilcode/util/ShellUtils.java  |  2 +-
 .../blankj/utilcode/util/SnackbarUtils.java   | 14 +++++------
 .../com/blankj/utilcode/util/SpanUtils.java   | 16 ++++++------
 .../com/blankj/utilcode/util/StringUtils.java |  4 +--
 .../com/blankj/utilcode/util/ThreadUtils.java |  5 ++--
 .../com/blankj/utilcode/util/TimeUtils.java   |  2 +-
 .../com/blankj/utilcode/util/ToastUtils.java  | 10 ++++----
 .../com/blankj/utilcode/util/UriUtils.java    | 25 +++++++++++++------
 .../java/com/blankj/utilcode/util/Utils.java  |  3 ++-
 .../blankj/utilcode/util/VibrateUtils.java    |  2 +-
 .../com/blankj/utilcode/util/BaseTest.java    | 11 +++-----
 .../blankj/utilcode/util/ObjectUtilsTest.java |  5 ++--
 utilcode/pkg/build.gradle                     |  2 +-
 .../pkg/feature/activity/ActivityActivity.kt  |  2 +-
 .../feature/activity/SubActivityActivity.kt   |  2 +-
 .../feature/bar/BarStatusFragmentActivity.kt  | 16 ++++++------
 .../pkg/feature/fragment/ContainerFragment.kt |  6 ++---
 .../pkg/feature/fragment/FragmentActivity.kt  |  6 ++---
 .../pkg/feature/image/ImageActivity.kt        |  4 +--
 .../pkg/feature/snackbar/SnackbarActivity.kt  |  2 +-
 .../utilcode/pkg/feature/span/SpanActivity.kt |  2 +-
 .../utilcode/pkg/feature/toast/CustomToast.kt |  2 +-
 .../pkg/feature/toast/ToastActivity.kt        |  2 +-
 .../utilcode/pkg/helper/DialogHelper.kt       |  5 ++--
 .../main/res/layout/activity_adaptscreen.xml  |  4 +--
 .../res/layout/activity_adaptscreen_close.xml |  4 +--
 .../layout/activity_adaptscreen_height.xml    |  7 +++---
 .../res/layout/activity_adaptscreen_width.xml |  4 +--
 .../layout/activity_bar_status_fragment.xml   |  4 +--
 .../src/main/res/layout/activity_fragment.xml |  2 +-
 .../src/main/res/layout/activity_image.xml    |  3 +--
 105 files changed, 293 insertions(+), 253 deletions(-)

diff --git a/.gitignore b/.gitignore
index 201b88771a..193619553c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,4 @@
 .externalNativeBuild
 /apk
 *.phrof
-/maven
+/busMaven
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95dfb60cc3..9c48786e89 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
 * `19/04/24` [upd] The swipe panel.
 * `19/03/17` [fix] The ugly UI.
 * `19/03/14` [fix] AdaptScreenUtils didn't work on some HaWei tablet.
+* `19/03/09` [fix] UriUtils#uri2File.
 * `19/03/08` [add] LogUtils support multi process. Publish v1.23.7.
 * `19/03/02` [fix] LogUtils#file.
 * `19/02/28` [fix] ImageUtils#calculateInSampleSize. Publish v1.23.6.
diff --git a/gradle.properties b/gradle.properties
index 110f0cb7ef..c209c08b84 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -19,4 +19,10 @@
 
 #org.gradle.jvmargs=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
 
-org.gradle.jvmargs=-XX:MaxHeapSize=1024m -Xmx1024m
\ No newline at end of file
+org.gradle.jvmargs=-Xmx8192m -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+org.gradle.daemon=true
+org.gradle.configureondemand=true
+org.gradle.parallel=true
+
+android.enableJetifier=true
+android.useAndroidX=true
\ No newline at end of file
diff --git a/gradle/config/config.gradle b/gradle/config/config.gradle
index e455c4dba6..e8c793b6b3 100644
--- a/gradle/config/config.gradle
+++ b/gradle/config/config.gradle
@@ -5,7 +5,7 @@ gradle.ext {
     applicationId = 'com.blankj.androidutilcode'
     appName = 'Util'
 
-    compileSdkVersion = 27
+    compileSdkVersion = 28
     minSdkVersion = 14
     targetSdkVersion = 27
     versionCode = 1_024_000
@@ -13,8 +13,8 @@ gradle.ext {
 
     // lib version
     kotlin_version = '1.3.10'
-    support_version = '27.1.1'
     leakcanary_version = '1.6.3'
+    androidx_version = '1.0.0'
 
     dep = [:]
 
@@ -36,11 +36,11 @@ gradle.ext {
             subutil_lib                : new DepConfig(":subutil:lib"),
             subutil_pkg                : new DepConfig(":subutil:pkg"),
             utilcode_app               : new DepConfig(":utilcode:app"),
-            utilcode_lib               : new DepConfig(false, ":utilcode:lib", "com.blankj:utilcode:$versionName"),
+            utilcode_lib               : new DepConfig(true, ":utilcode:lib", "com.blankj:utilcode:$versionName"),
             utilcode_pkg               : new DepConfig(":utilcode:pkg"),
 
-            support_appcompat_v7       : new DepConfig("com.android.support:appcompat-v7:$support_version"),
-            support_design             : new DepConfig("com.android.support:design:$support_version"),
+            support_appcompat_v7       : new DepConfig("androidx.appcompat:appcompat:$androidx_version"),
+            support_material           : new DepConfig("com.google.android.material:material:$androidx_version"),
             support_multidex           : new DepConfig("com.android.support:multidex:1.0.2"),
 
             constraint                 : new DepConfig("com.android.support.constraint:constraint-layout:1.1.3"),
diff --git a/gradle/config/configApp.gradle b/gradle/config/configApp.gradle
index cb8d5a290a..809cb07cd4 100644
--- a/gradle/config/configApp.gradle
+++ b/gradle/config/configApp.gradle
@@ -42,8 +42,11 @@ android {
     }
 
     dexOptions {
+        preDexLibraries true
         javaMaxHeapSize "8g"
         maxProcessCount 8
+        incremental true
+        dexInProcess = true
     }
 }
 
@@ -57,7 +60,7 @@ dependencies {
 
 private String getSuffix() {
     if (project.path == ":launcher:app") return ""
-    return project.path.replace(":" , "_").substring(0, project.path.length() - 4)
+    return project.path.replace(":", "_").substring(0, project.path.length() - 4)
 }
 
 def configSigning(Project pro) {
diff --git a/launcher/app/build.gradle b/launcher/app/build.gradle
index eb9f8d906f..bf68fb45ff 100644
--- a/launcher/app/build.gradle
+++ b/launcher/app/build.gradle
@@ -4,7 +4,7 @@ apply {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    implementation project(':launcher:pkg')
-    implementation project(':subutil:pkg')
-    implementation project(':utilcode:pkg')
+    implementation gradle.ext.dep.launcher_pkg
+    implementation gradle.ext.dep.subutil_pkg
+    implementation gradle.ext.dep.utilcode_pkg
 }
\ No newline at end of file
diff --git a/launcher/pkg/build.gradle b/launcher/pkg/build.gradle
index 9fe360a5dd..881637b34a 100644
--- a/launcher/pkg/build.gradle
+++ b/launcher/pkg/build.gradle
@@ -4,5 +4,5 @@ apply {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    api project(':lib:base')
+    api gradle.ext.dep.lib_base
 }
\ No newline at end of file
diff --git a/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt b/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt
index 02491cd88d..0e9f0a8477 100644
--- a/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt
+++ b/launcher/pkg/src/main/java/com/blankj/launcher/pkg/MainActivity.kt
@@ -2,7 +2,7 @@ package com.blankj.launcher.pkg
 
 import android.graphics.Color
 import android.os.Bundle
-import android.support.v7.app.ActionBarDrawerToggle
+import androidx.appcompat.app.ActionBarDrawerToggle
 import android.view.View
 import android.widget.ImageView
 import com.blankj.lib.base.BaseDrawerActivity
diff --git a/launcher/pkg/src/main/res/layout/activity_main.xml b/launcher/pkg/src/main/res/layout/activity_main.xml
index 3b31dafe32..ee8b62a6fa 100644
--- a/launcher/pkg/src/main/res/layout/activity_main.xml
+++ b/launcher/pkg/src/main/res/layout/activity_main.xml
@@ -1,17 +1,17 @@
 
-
 
-    
 
-        
 
-            
 
-        
-    
+        
+    
 
     
 
-    
@@ -69,5 +69,5 @@
                 android:text="@string/sub_util" />
 
         
-    
-
+    
+
diff --git a/lib/base/build.gradle b/lib/base/build.gradle
index 370036c062..67f9762d82 100644
--- a/lib/base/build.gradle
+++ b/lib/base/build.gradle
@@ -8,7 +8,7 @@ dependencies {
     api gradle.ext.dep.subutil_lib
 
     api gradle.ext.dep.support_appcompat_v7
-    api gradle.ext.dep.support_design
+    api gradle.ext.dep.support_material
     api gradle.ext.dep.support_multidex
     api gradle.ext.dep.constraint
     api gradle.ext.dep.kotlin
diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.java b/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.java
index caae1d45cf..0c9d8fa419 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/BaseActivity.java
@@ -3,11 +3,12 @@
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.os.Bundle;
-import android.support.annotation.LayoutRes;
-import android.support.v7.app.AppCompatActivity;
 import android.view.LayoutInflater;
 import android.view.View;
 
+import androidx.annotation.LayoutRes;
+import androidx.appcompat.app.AppCompatActivity;
+
 import com.blankj.swipepanel.SwipePanel;
 import com.blankj.utilcode.util.AntiShakeUtils;
 import com.blankj.utilcode.util.AppUtils;
diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.java b/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.java
index 1e0ddc0b27..5d2eba8260 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/BaseApplication.java
@@ -2,7 +2,8 @@
 
 import android.app.Application;
 import android.content.Context;
-import android.support.multidex.MultiDex;
+
+import androidx.multidex.MultiDex;
 
 import com.blankj.utilcode.util.AppUtils;
 import com.blankj.utilcode.util.CrashUtils;
diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.java b/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.java
index c7f7f1daea..ec3c895f6e 100755
--- a/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/BaseDrawerActivity.java
@@ -3,17 +3,18 @@
 import android.annotation.SuppressLint;
 import android.content.Intent;
 import android.net.Uri;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.StringRes;
-import android.support.design.widget.NavigationView;
-import android.support.v4.widget.DrawerLayout;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.widget.FrameLayout;
 
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+import androidx.drawerlayout.widget.DrawerLayout;
+
 import com.blankj.utilcode.util.ActivityUtils;
 import com.blankj.utilcode.util.StringUtils;
+import com.google.android.material.navigation.NavigationView;
 
 
 /**
diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.java b/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.java
index 5667f3f02c..0e4e7ba5cc 100755
--- a/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/BaseFragment.java
@@ -4,17 +4,18 @@
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
-import android.support.annotation.IdRes;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.annotation.IdRes;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+
 import com.blankj.utilcode.util.AntiShakeUtils;
 
 /**
diff --git a/lib/base/src/main/java/com/blankj/lib/base/BaseTitleActivity.java b/lib/base/src/main/java/com/blankj/lib/base/BaseTitleActivity.java
index a40230420d..e0ed3ed10a 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/BaseTitleActivity.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/BaseTitleActivity.java
@@ -1,16 +1,17 @@
 package com.blankj.lib.base;
 
 import android.annotation.SuppressLint;
-import android.support.annotation.LayoutRes;
-import android.support.design.widget.CoordinatorLayout;
-import android.support.v7.app.ActionBar;
-import android.support.v7.widget.Toolbar;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewStub;
 import android.widget.FrameLayout;
 
+import androidx.annotation.LayoutRes;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+
 import com.blankj.utilcode.util.BarUtils;
 import com.blankj.utilcode.util.ColorUtils;
 
diff --git a/lib/base/src/main/java/com/blankj/lib/base/IBaseView.java b/lib/base/src/main/java/com/blankj/lib/base/IBaseView.java
index 29e8553899..b0550f126c 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/IBaseView.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/IBaseView.java
@@ -1,10 +1,11 @@
 package com.blankj.lib.base;
 
 import android.os.Bundle;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
 import android.view.View;
 
+import androidx.annotation.LayoutRes;
+import androidx.annotation.Nullable;
+
 
 /**
  * 
diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseAdapter.java b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseAdapter.java
index 11aa94e015..e69be6c6df 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseAdapter.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseAdapter.java
@@ -1,12 +1,13 @@
 package com.blankj.lib.base.rv;
 
 import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
 import java.util.List;
 
 /**
diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseCell.java b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseCell.java
index cdf42c7882..332c4caee0 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseCell.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseCell.java
@@ -1,10 +1,11 @@
 package com.blankj.lib.base.rv;
 
-import android.support.annotation.NonNull;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: blankj
diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java
index ceb1c46eac..0bd892f317 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/rv/BaseViewHolder.java
@@ -1,7 +1,7 @@
 package com.blankj.lib.base.rv;
 
-import android.support.annotation.IdRes;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.IdRes;
+import androidx.recyclerview.widget.RecyclerView;
 import android.util.SparseArray;
 import android.view.View;
 
diff --git a/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java b/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java
index 3d2b90f302..dd20894e10 100644
--- a/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java
+++ b/lib/base/src/main/java/com/blankj/lib/base/rv/RecycleViewDivider.java
@@ -5,11 +5,11 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
-import android.support.v4.view.ViewCompat;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.RecyclerView;
 import android.view.View;
 import android.widget.LinearLayout;
 
diff --git a/lib/base/src/main/res/layout/activity_base_title.xml b/lib/base/src/main/res/layout/activity_base_title.xml
index b11ecf7341..986d3669b6 100644
--- a/lib/base/src/main/res/layout/activity_base_title.xml
+++ b/lib/base/src/main/res/layout/activity_base_title.xml
@@ -1,24 +1,23 @@
 
-
 
-    
 
-        
-    
+    
 
     
 
-
+
diff --git a/lib/base/src/main/res/layout/activity_base_title_stub_scroll.xml b/lib/base/src/main/res/layout/activity_base_title_stub_scroll.xml
index 96f5e09d49..bd031cfb67 100644
--- a/lib/base/src/main/res/layout/activity_base_title_stub_scroll.xml
+++ b/lib/base/src/main/res/layout/activity_base_title_stub_scroll.xml
@@ -1,5 +1,5 @@
 
-
 
-
+
 
diff --git a/lib/base/src/main/res/layout/activity_drawer.xml b/lib/base/src/main/res/layout/activity_drawer.xml
index 72f70ed969..be44cd718c 100644
--- a/lib/base/src/main/res/layout/activity_drawer.xml
+++ b/lib/base/src/main/res/layout/activity_drawer.xml
@@ -1,5 +1,5 @@
 
-
 
-    
 
-
+
diff --git a/subutil/app/build.gradle b/subutil/app/build.gradle
index a2e0172413..a7027c15ef 100644
--- a/subutil/app/build.gradle
+++ b/subutil/app/build.gradle
@@ -4,5 +4,5 @@ apply {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    implementation project(':subutil:pkg')
+    implementation gradle.ext.dep.subutil_pkg
 }
\ No newline at end of file
diff --git a/subutil/lib/build.gradle b/subutil/lib/build.gradle
index 9dcbe0b542..f3140b4f0b 100644
--- a/subutil/lib/build.gradle
+++ b/subutil/lib/build.gradle
@@ -14,7 +14,7 @@ readme {
 
 dependencies {
     compileOnly gradle.ext.dep.support_appcompat_v7
-    compileOnly gradle.ext.dep.support_design
+    compileOnly gradle.ext.dep.support_material
     api(gradle.ext.dep.glide) {
         exclude group: "com.android.support"
     }
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java b/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java
index 7ee8747902..0c177b534c 100755
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/LocationUtils.java
@@ -11,7 +11,7 @@
 import android.location.LocationProvider;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.RequiresPermission;
 import android.util.Log;
 
 import java.io.IOException;
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java b/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java
index 22486b3a91..934408c65e 100644
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/PinyinUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.subutil.util;
 
-import android.support.v4.util.SimpleArrayMap;
+import androidx.collection.SimpleArrayMap;
 
 /**
  * 
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java b/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java
index 9cbf4e06fd..91b336abcf 100644
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/Utils.java
@@ -7,8 +7,8 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import java.lang.reflect.InvocationTargetException;
 
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/http/ExecutorFactory.java b/subutil/lib/src/main/java/com/blankj/subutil/util/http/ExecutorFactory.java
index f5583397d9..2f26fb9c24 100644
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/http/ExecutorFactory.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/http/ExecutorFactory.java
@@ -2,7 +2,8 @@
 
 import android.os.Handler;
 import android.os.Looper;
-import android.support.annotation.NonNull;
+
+import androidx.annotation.NonNull;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/http/HttpUtils.java b/subutil/lib/src/main/java/com/blankj/subutil/util/http/HttpUtils.java
index b952f318cb..bdd4174486 100644
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/http/HttpUtils.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/http/HttpUtils.java
@@ -1,7 +1,8 @@
 package com.blankj.subutil.util.http;
 
 import android.accounts.NetworkErrorException;
-import android.support.annotation.NonNull;
+
+import androidx.annotation.NonNull;
 
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/http/Request.java b/subutil/lib/src/main/java/com/blankj/subutil/util/http/Request.java
index fe39b1299c..c6eddf9b96 100644
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/http/Request.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/http/Request.java
@@ -1,6 +1,7 @@
 package com.blankj.subutil.util.http;
 
-import android.support.annotation.NonNull;
+
+import androidx.annotation.NonNull;
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
diff --git a/subutil/lib/src/main/java/com/blankj/subutil/util/http/SSLConfig.java b/subutil/lib/src/main/java/com/blankj/subutil/util/http/SSLConfig.java
index b8624af490..0cf43662f2 100644
--- a/subutil/lib/src/main/java/com/blankj/subutil/util/http/SSLConfig.java
+++ b/subutil/lib/src/main/java/com/blankj/subutil/util/http/SSLConfig.java
@@ -2,7 +2,8 @@
 
 import android.annotation.SuppressLint;
 import android.os.Build;
-import android.support.annotation.NonNull;
+
+import androidx.annotation.NonNull;
 
 import java.io.IOException;
 import java.net.InetAddress;
diff --git a/subutil/pkg/build.gradle b/subutil/pkg/build.gradle
index 9fe360a5dd..881637b34a 100644
--- a/subutil/pkg/build.gradle
+++ b/subutil/pkg/build.gradle
@@ -4,5 +4,5 @@ apply {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    api project(':lib:base')
+    api gradle.ext.dep.lib_base
 }
\ No newline at end of file
diff --git a/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt b/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt
index 45e67a4a0d..9eba25c622 100644
--- a/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt
+++ b/subutil/pkg/src/main/java/com/blankj/subutil/pkg/helper/DialogHelper.kt
@@ -1,6 +1,6 @@
 package com.blankj.subutil.pkg.helper
 
-import android.support.v7.app.AlertDialog
+import androidx.appcompat.app.AlertDialog
 import com.blankj.subutil.pkg.R
 import com.blankj.utilcode.util.ActivityUtils
 import com.blankj.utilcode.util.PermissionUtils
diff --git a/utilcode/README-CN.md b/utilcode/README-CN.md
index 445f206121..0bdb622940 100644
--- a/utilcode/README-CN.md
+++ b/utilcode/README-CN.md
@@ -5,7 +5,7 @@ Gradle:
 implementation 'com.blankj:utilcode:1.24.0'
 
 // if u use AndroidX, use the following
-implementation 'com.blankj:utilcodex:1.23.7'
+implementation 'com.blankj:utilcodex:1.24.0'
 ```
 
 
diff --git a/utilcode/README.md b/utilcode/README.md
index f449736061..5a6a295b4c 100644
--- a/utilcode/README.md
+++ b/utilcode/README.md
@@ -5,7 +5,7 @@ Gradle:
 implementation 'com.blankj:utilcode:1.24.0'
 
 // if u use AndroidX, use the following
-implementation 'com.blankj:utilcodex:1.23.7'
+implementation 'com.blankj:utilcodex:1.24.0'
 ```
 
 
diff --git a/utilcode/app/build.gradle b/utilcode/app/build.gradle
index 5616386892..ea5c172cd7 100644
--- a/utilcode/app/build.gradle
+++ b/utilcode/app/build.gradle
@@ -4,5 +4,5 @@ apply {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    implementation project(':utilcode:pkg')
+    implementation gradle.ext.dep.utilcode_pkg
 }
\ No newline at end of file
diff --git a/utilcode/lib/build.gradle b/utilcode/lib/build.gradle
index e4dd3a6716..6d6c599298 100644
--- a/utilcode/lib/build.gradle
+++ b/utilcode/lib/build.gradle
@@ -18,7 +18,7 @@ dependencies {
     compile gradle.ext.dep.gson
 
     compileOnly gradle.ext.dep.support_appcompat_v7
-    compileOnly gradle.ext.dep.support_design
+    compileOnly gradle.ext.dep.support_material
 
     testImplementation gradle.ext.dep.junit
     testImplementation gradle.ext.dep.robolectric
diff --git a/utilcode/lib/project.properties b/utilcode/lib/project.properties
index 22ae3b8603..d238eda740 100644
--- a/utilcode/lib/project.properties
+++ b/utilcode/lib/project.properties
@@ -1,9 +1,9 @@
 #project
-project.name=UtilCode
+project.name=UtilCodeX
 project.groupId=com.blankj
-project.artifactId=utilcode
+project.artifactId=utilcodex
 project.packaging=aar
 project.siteUrl=https://github.com/Blankj/AndroidUtilCode
 project.gitUrl=https://github.com/Blankj/AndroidUtilCode.git
 #javadoc
-javadoc.name=UtilCode
\ No newline at end of file
+javadoc.name=UtilCodeX
\ No newline at end of file
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java
index b68bfcb113..5c05c0163e 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.constant;
 
-import android.support.annotation.IntDef;
+import androidx.annotation.IntDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java
index 76f7e9a217..6db826e4ab 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/PermissionConstants.java
@@ -4,7 +4,7 @@
 import android.Manifest.permission;
 import android.annotation.SuppressLint;
 import android.os.Build;
-import android.support.annotation.StringDef;
+import androidx.annotation.StringDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java
index 9932037bf8..45090576e3 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/constant/TimeConstants.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.constant;
 
-import android.support.annotation.IntDef;
+import androidx.annotation.IntDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
index d6a671e4fe..de1bfeb005 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
@@ -10,14 +10,15 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.annotation.AnimRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.ActivityOptionsCompat;
-import android.support.v4.util.Pair;
 import android.util.Log;
 import android.view.View;
 
+import androidx.annotation.AnimRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.app.ActivityOptionsCompat;
+import androidx.core.util.Pair;
+
 import java.util.List;
 
 /**
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java
index 7e87e73474..ca9036225e 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AntiShakeUtils.java
@@ -1,9 +1,10 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
 import android.view.View;
 
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java
index a9368be59f..5a9194ce66 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/AppUtils.java
@@ -17,8 +17,6 @@
 import android.net.Uri;
 import android.os.Build;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.v4.content.FileProvider;
 import android.util.Log;
 
 import java.io.File;
@@ -27,6 +25,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import androidx.annotation.NonNull;
+import androidx.core.content.FileProvider;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java
index 7b5509b2b5..22178a5c20 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BarUtils.java
@@ -8,11 +8,6 @@
 import android.graphics.Color;
 import android.graphics.Point;
 import android.os.Build;
-import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresApi;
-import android.support.annotation.RequiresPermission;
-import android.support.v4.widget.DrawerLayout;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.Display;
@@ -27,6 +22,12 @@
 
 import java.lang.reflect.Method;
 
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RequiresPermission;
+import androidx.drawerlayout.widget.DrawerLayout;
+
 import static android.Manifest.permission.EXPAND_STATUS_BAR;
 
 /**
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
index f9344b0a59..bacc519540 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java
@@ -2,11 +2,12 @@
 
 import android.content.ContentResolver;
 import android.provider.Settings;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
 import android.view.Window;
 import android.view.WindowManager;
 
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BusUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BusUtils.java
index f04202043e..d272c99b98 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/BusUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/BusUtils.java
@@ -16,11 +16,12 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java
index bb48a4b5cf..c5a9a17a6d 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java
@@ -3,13 +3,14 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
 
 import org.json.JSONArray;
 import org.json.JSONObject;
 
 import java.io.Serializable;
 
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java
index 67e6b3fb0e..a8ae8afa5b 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDiskUtils.java
@@ -8,9 +8,10 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import com.blankj.utilcode.constant.CacheConstants;
 
 import org.json.JSONArray;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java
index 2ef267bd01..6dbb9f7475 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleStaticUtils.java
@@ -3,13 +3,14 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
 
 import org.json.JSONArray;
 import org.json.JSONObject;
 
 import java.io.Serializable;
 
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java
index c800423c78..aca1c25837 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java
@@ -3,7 +3,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import com.blankj.utilcode.constant.CacheConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java
index 56abfba117..aedcfa7fc4 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryStaticUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java
index d0e06e394d..ddaa2baed9 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CacheMemoryUtils.java
@@ -1,7 +1,7 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
-import android.support.v4.util.LruCache;
+import androidx.annotation.NonNull;
+import androidx.collection.LruCache;
 
 import com.blankj.utilcode.constant.CacheConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java
index 4c0c22232b..a6603cfc44 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ColorUtils.java
@@ -1,12 +1,12 @@
 package com.blankj.utilcode.util;
 
 import android.graphics.Color;
-import android.support.annotation.ColorInt;
-import android.support.annotation.ColorRes;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java
index 18b5f814a3..081dd09761 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/CrashUtils.java
@@ -5,8 +5,8 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Environment;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresPermission;
 import android.util.Log;
 
 import java.io.BufferedWriter;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
index e6b1910cfc..c641c9bdae 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
@@ -11,11 +11,12 @@
 import android.os.Debug;
 import android.os.PowerManager;
 import android.provider.Settings;
-import android.support.annotation.RequiresApi;
-import android.support.annotation.RequiresPermission;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RequiresPermission;
+
 import java.io.File;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
index 43b8537e75..9e8ae14ef1 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
@@ -3,16 +3,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.annotation.AnimRes;
-import android.support.annotation.AnimatorRes;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.IdRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
 import android.util.Log;
 import android.view.View;
 
@@ -20,6 +10,17 @@
 import java.util.Collections;
 import java.util.List;
 
+import androidx.annotation.AnimRes;
+import androidx.annotation.AnimatorRes;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
 /**
  * 
  *     author: Blankj
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java
index 83e01eb1ad..cbee7dd4bd 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ImageUtils.java
@@ -27,13 +27,13 @@
 import android.renderscript.Element;
 import android.renderscript.RenderScript;
 import android.renderscript.ScriptIntrinsicBlur;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresApi;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.core.content.ContextCompat;
 import android.view.View;
 
 import java.io.BufferedOutputStream;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java
index 6faa37d043..1e26dc8a9a 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/IntentUtils.java
@@ -8,8 +8,8 @@
 import android.os.Bundle;
 import android.provider.MediaStore;
 import android.provider.Settings;
-import android.support.annotation.RequiresPermission;
-import android.support.v4.content.FileProvider;
+import androidx.annotation.RequiresPermission;
+import androidx.core.content.FileProvider;
 
 import java.io.File;
 import java.util.ArrayList;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java
index cfa568fa7c..de3eb285cc 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java
@@ -7,7 +7,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.ResultReceiver;
-import android.support.annotation.NonNull;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -16,6 +15,8 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.FrameLayout;
 
+import androidx.annotation.NonNull;
+
 import java.lang.reflect.Field;
 
 /**
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java
index 1372ecd40b..9a7e11cbf5 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/LogUtils.java
@@ -10,10 +10,10 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
-import android.support.annotation.IntDef;
-import android.support.annotation.IntRange;
-import android.support.annotation.RequiresApi;
-import android.support.v4.util.SimpleArrayMap;
+import androidx.annotation.IntDef;
+import androidx.annotation.IntRange;
+import androidx.annotation.RequiresApi;
+import androidx.collection.SimpleArrayMap;
 import android.util.Log;
 
 import com.google.gson.Gson;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
index 6f6cf85b80..bd4b8da935 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
@@ -8,7 +8,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
index d59eb28240..24a05a26b7 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
@@ -7,13 +7,14 @@
 import android.net.NetworkInfo;
 import android.net.wifi.WifiManager;
 import android.os.Build;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresPermission;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresPermission;
+
 import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java
index b8163d2e66..73a900b465 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/NotificationUtils.java
@@ -5,9 +5,9 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.support.annotation.Nullable;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationManagerCompat;
+import androidx.annotation.Nullable;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java
index be5491ece0..3c0c087a39 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ObjectUtils.java
@@ -1,9 +1,9 @@
 package com.blankj.utilcode.util;
 
 import android.os.Build;
-import android.support.annotation.RequiresApi;
-import android.support.v4.util.LongSparseArray;
-import android.support.v4.util.SimpleArrayMap;
+import androidx.annotation.RequiresApi;
+import androidx.collection.LongSparseArray;
+import androidx.collection.SimpleArrayMap;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java
index d35cbcc620..602efcb5db 100755
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PermissionUtils.java
@@ -9,10 +9,10 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.RequiresApi;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.core.content.ContextCompat;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.WindowManager;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java
index 99068781a4..f407f81b5f 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/PhoneUtils.java
@@ -7,7 +7,7 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Build;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.RequiresPermission;
 import android.telephony.SmsManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java
index adcd265f72..619b175549 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ProcessUtils.java
@@ -10,8 +10,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresPermission;
 import android.util.Log;
 
 import java.util.Arrays;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java
index ba57fab956..817a94149f 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/RegexUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.v4.util.SimpleArrayMap;
+import androidx.collection.SimpleArrayMap;
 
 import com.blankj.utilcode.constant.RegexConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java
index 81d10f08cf..3fb515c06b 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ResourceUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.RawRes;
+import androidx.annotation.RawRes;
 
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java
index d3e21fb873..21274c3023 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPStaticUtils.java
@@ -1,7 +1,7 @@
 package com.blankj.utilcode.util;
 
 import android.content.SharedPreferences;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import java.util.Map;
 import java.util.Set;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java
index 554a2ed586..a9d18a1a55 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SPUtils.java
@@ -3,7 +3,7 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
index 7390fceed0..3245eb115c 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
@@ -10,8 +10,8 @@
 import android.graphics.Point;
 import android.os.Build;
 import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresPermission;
 import android.util.DisplayMetrics;
 import android.view.Surface;
 import android.view.View;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ShellUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ShellUtils.java
index b7ad2fa9d2..fc10a601ae 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ShellUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ShellUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import java.io.BufferedReader;
 import java.io.DataOutputStream;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java
index b164e6154e..eab1990d29 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java
@@ -1,12 +1,12 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.IntDef;
-import android.support.annotation.IntRange;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
-import android.support.design.widget.Snackbar;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IntDef;
+import androidx.annotation.IntRange;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import com.google.android.material.snackbar.Snackbar;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java
index b8d9d53aed..4d49451ec0 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/SpanUtils.java
@@ -14,14 +14,14 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntDef;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntDef;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
 import android.text.Layout;
 import android.text.Layout.Alignment;
 import android.text.SpannableStringBuilder;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java
index c3254e3d32..70f0defe50 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/StringUtils.java
@@ -1,8 +1,8 @@
 package com.blankj.utilcode.util;
 
 import android.content.res.Resources;
-import android.support.annotation.ArrayRes;
-import android.support.annotation.StringRes;
+import androidx.annotation.ArrayRes;
+import androidx.annotation.StringRes;
 
 /**
  * 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java
index 0545a27fa0..19de94ca33 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ThreadUtils.java
@@ -2,10 +2,11 @@
 
 import android.os.Handler;
 import android.os.Looper;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
 import android.util.Log;
 
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.Executor;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java
index adaa920474..a5286b0fbe 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/TimeUtils.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
 
 import com.blankj.utilcode.constant.TimeConstants;
 
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java
index 150425cdba..0dd47cfa3e 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/ToastUtils.java
@@ -12,11 +12,11 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.StringRes;
-import android.support.v4.app.NotificationManagerCompat;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.StringRes;
+import androidx.core.app.NotificationManagerCompat;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java
index 9ad408912a..20fdc39b81 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/UriUtils.java
@@ -8,12 +8,14 @@
 import android.os.Environment;
 import android.provider.DocumentsContract;
 import android.provider.MediaStore;
-import android.support.annotation.NonNull;
-import android.support.v4.content.FileProvider;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.File;
 
+import androidx.annotation.NonNull;
+import androidx.core.content.FileProvider;
+
 /**
  * 
  *     author: Blankj
@@ -75,12 +77,19 @@ public static File uri2File(@NonNull final Uri uri) {
                 Log.d("UriUtils", uri.toString() + " parse failed. -> 1");
                 return null;
             } else if ("com.android.providers.downloads.documents".equals(authority)) {
-                final String id = DocumentsContract.getDocumentId(uri);
-                final Uri contentUri = ContentUris.withAppendedId(
-                        Uri.parse("content://downloads/public_downloads"),
-                        Long.valueOf(id)
-                );
-                return getFileFromUri(contentUri, 2);
+                String id = DocumentsContract.getDocumentId(uri);
+                if (!TextUtils.isEmpty(id)) {
+                    if (id.startsWith("raw:")) {
+                        return new File(id.substring(4));
+                    }
+                    final Uri contentUri = ContentUris.withAppendedId(
+                            Uri.parse(Environment.DIRECTORY_DOWNLOADS),
+                            Long.valueOf(id)
+                    );
+                    return getFileFromUri(contentUri, 2);
+                }
+                Log.d("UriUtils", uri.toString() + " parse failed. -> 3");
+                return null;
             } else if ("com.android.providers.media.documents".equals(authority)) {
                 final String docId = DocumentsContract.getDocumentId(uri);
                 final String[] split = docId.split(":");
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java
index d0c98afc96..1992a2c902 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/Utils.java
@@ -13,13 +13,14 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
-import android.support.v4.content.FileProvider;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
+import androidx.core.content.FileProvider;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
diff --git a/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java b/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java
index a57bbb8241..622d657817 100644
--- a/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java
+++ b/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java
@@ -2,7 +2,7 @@
 
 import android.content.Context;
 import android.os.Vibrator;
-import android.support.annotation.RequiresPermission;
+import androidx.annotation.RequiresPermission;
 
 import static android.Manifest.permission.VIBRATE;
 
diff --git a/utilcode/lib/src/test/java/com/blankj/utilcode/util/BaseTest.java b/utilcode/lib/src/test/java/com/blankj/utilcode/util/BaseTest.java
index 85bc9d8ac2..2dadedff8c 100644
--- a/utilcode/lib/src/test/java/com/blankj/utilcode/util/BaseTest.java
+++ b/utilcode/lib/src/test/java/com/blankj/utilcode/util/BaseTest.java
@@ -1,8 +1,5 @@
 package com.blankj.utilcode.util;
 
-
-import android.support.annotation.NonNull;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -29,7 +26,7 @@ public BaseTest() {
         ShadowLog.stream = System.out;
         ThreadUtils.setDeliver(new Executor() {
             @Override
-            public void execute(@NonNull Runnable command) {
+            public void execute(Runnable command) {
                 command.run();
             }
         });
@@ -201,8 +198,8 @@ public void onFail(Throwable t) {
     static class Person implements Comparable {
 
         String name;
-        int age;
-        int time;
+        int    age;
+        int    time;
 
         public Person(String name) {
             this.name = name;
@@ -220,7 +217,7 @@ public String toString() {
         }
 
         @Override
-        public int compareTo(@NonNull Person o) {
+        public int compareTo(Person o) {
             int res = o.age - age;
             if (res != 0) {
                 return res;
diff --git a/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java b/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java
index a0203f78fc..ed12c24d8d 100644
--- a/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java
+++ b/utilcode/lib/src/test/java/com/blankj/utilcode/util/ObjectUtilsTest.java
@@ -1,7 +1,5 @@
 package com.blankj.utilcode.util;
 
-import android.support.v4.util.LongSparseArray;
-import android.support.v4.util.SimpleArrayMap;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
@@ -12,6 +10,9 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 
+import androidx.collection.LongSparseArray;
+import androidx.collection.SimpleArrayMap;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
diff --git a/utilcode/pkg/build.gradle b/utilcode/pkg/build.gradle
index 9fe360a5dd..881637b34a 100644
--- a/utilcode/pkg/build.gradle
+++ b/utilcode/pkg/build.gradle
@@ -4,5 +4,5 @@ apply {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    api project(':lib:base')
+    api gradle.ext.dep.lib_base
 }
\ No newline at end of file
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt
index e784f98401..9982c948b7 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/ActivityActivity.kt
@@ -6,7 +6,7 @@ import android.graphics.Bitmap
 import android.graphics.drawable.BitmapDrawable
 import android.os.Build
 import android.os.Bundle
-import android.support.v4.app.ActivityOptionsCompat
+import androidx.core.app.ActivityOptionsCompat
 import android.view.View
 import android.view.Window
 import com.blankj.lib.base.BaseTitleActivity
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt
index 0c63773639..abf0151bbc 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/activity/SubActivityActivity.kt
@@ -2,7 +2,7 @@ package com.blankj.utilcode.pkg.feature.activity
 
 import android.os.Build
 import android.os.Bundle
-import android.support.v4.app.ActivityCompat
+import androidx.core.app.ActivityCompat
 import android.view.View
 import android.view.Window
 import com.blankj.lib.base.BaseTitleActivity
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt
index d4f0d60530..fc8020b3e5 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/BarStatusFragmentActivity.kt
@@ -3,10 +3,10 @@ package com.blankj.utilcode.pkg.feature.bar
 import android.content.Context
 import android.content.Intent
 import android.os.Bundle
-import android.support.design.widget.BottomNavigationView
-import android.support.v4.app.Fragment
-import android.support.v4.app.FragmentPagerAdapter
-import android.support.v4.view.ViewPager
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentPagerAdapter
+import androidx.viewpager.widget.ViewPager
 import android.view.View
 import com.blankj.lib.base.BaseActivity
 import com.blankj.utilcode.pkg.R
@@ -37,7 +37,7 @@ class BarStatusFragmentActivity : BaseActivity() {
             R.id.barStatusFragmentNavigationCustom
     )
 
-    private val mFragmentList = ArrayList()
+    private val mFragmentList = ArrayList()
 
     private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener l@{ item ->
         when (item.itemId) {
@@ -78,8 +78,8 @@ class BarStatusFragmentActivity : BaseActivity() {
         mFragmentList.add(BarStatusCustomFragment.newInstance())
 
         barStatusFragmentVp.offscreenPageLimit = 3
-        barStatusFragmentVp.adapter = object : FragmentPagerAdapter(supportFragmentManager) {
-            override fun getItem(position: Int): Fragment {
+        barStatusFragmentVp.adapter = object : androidx.fragment.app.FragmentPagerAdapter(supportFragmentManager) {
+            override fun getItem(position: Int): androidx.fragment.app.Fragment {
                 return mFragmentList[position]
             }
 
@@ -88,7 +88,7 @@ class BarStatusFragmentActivity : BaseActivity() {
             }
         }
 
-        barStatusFragmentVp.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
+        barStatusFragmentVp.addOnPageChangeListener(object : androidx.viewpager.widget.ViewPager.OnPageChangeListener {
             override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
 
             override fun onPageSelected(position: Int) {
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt
index ada9dd0d10..86972c449d 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/ContainerFragment.kt
@@ -2,8 +2,8 @@ package com.blankj.utilcode.pkg.feature.fragment
 
 import android.os.Build
 import android.os.Bundle
-import android.support.annotation.RequiresApi
-import android.support.v4.app.Fragment
+import androidx.annotation.RequiresApi
+import androidx.fragment.app.Fragment
 import android.transition.*
 import android.view.View
 import com.blankj.lib.base.BaseLazyFragment
@@ -128,7 +128,7 @@ class ContainerFragment : BaseLazyFragment(), FragmentUtils.OnBackClickListener
         }
     }
 
-    private fun addSharedElement(fragment: Fragment): Fragment {
+    private fun addSharedElement(fragment: androidx.fragment.app.Fragment): androidx.fragment.app.Fragment {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             fragment.sharedElementEnterTransition = DetailTransition()
             fragment.enterTransition = Fade()
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt
index 446271b366..b18a2e236b 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/fragment/FragmentActivity.kt
@@ -4,8 +4,8 @@ import android.content.Context
 import android.content.Intent
 import android.os.Bundle
 import android.os.PersistableBundle
-import android.support.design.widget.BottomNavigationView
-import android.support.v4.app.Fragment
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import androidx.fragment.app.Fragment
 import android.view.View
 import com.blankj.lib.base.BaseActivity
 import com.blankj.utilcode.pkg.R
@@ -29,7 +29,7 @@ class FragmentActivity : BaseActivity() {
         }
     }
 
-    private val mFragments = arrayListOf()
+    private val mFragments = arrayListOf()
     private var curIndex: Int = 0
 
     private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt
index 0e092e0062..2c6656f220 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/image/ImageActivity.kt
@@ -6,12 +6,12 @@ import android.graphics.Bitmap
 import android.graphics.Color
 import android.os.Build
 import android.os.Bundle
-import android.support.annotation.StringRes
-import android.support.v7.widget.LinearLayoutManager
 import android.view.View
 import android.widget.Button
 import android.widget.ImageView
 import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.recyclerview.widget.LinearLayoutManager
 import com.blankj.lib.base.BaseTaskActivity
 import com.blankj.lib.base.rv.BaseAdapter
 import com.blankj.lib.base.rv.BaseCell
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt
index a0ea36d528..cd1c1b0d99 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/snackbar/SnackbarActivity.kt
@@ -4,7 +4,7 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.Color
 import android.os.Bundle
-import android.support.annotation.StringRes
+import androidx.annotation.StringRes
 import android.text.SpannableStringBuilder
 import android.view.View
 import android.view.ViewGroup
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt
index d84ced168c..202069ed61 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/span/SpanActivity.kt
@@ -5,7 +5,7 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.*
 import android.os.Bundle
-import android.support.annotation.ColorInt
+import androidx.annotation.ColorInt
 import android.text.Layout
 import android.text.SpannableStringBuilder
 import android.text.TextPaint
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt
index 314ba33d59..458ecbb3fb 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/CustomToast.kt
@@ -2,7 +2,7 @@ package com.blankj.utilcode.pkg.feature.toast
 
 import android.os.Handler
 import android.os.Looper
-import android.support.annotation.StringRes
+import androidx.annotation.StringRes
 import android.widget.TextView
 import android.widget.Toast
 
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
index 51c9e53774..47f91e826e 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
@@ -4,7 +4,7 @@ import android.content.Context
 import android.content.Intent
 import android.graphics.Color
 import android.os.Bundle
-import android.support.v4.content.ContextCompat
+import androidx.core.content.ContextCompat
 import android.view.Gravity
 import android.view.View
 import com.blankj.lib.base.BaseTitleActivity
diff --git a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt
index 344a69e448..a495a13013 100644
--- a/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt
+++ b/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/helper/DialogHelper.kt
@@ -3,7 +3,6 @@ package com.blankj.utilcode.pkg.helper
 import android.app.Dialog
 import android.graphics.Bitmap
 import android.graphics.drawable.ColorDrawable
-import android.support.v7.app.AlertDialog
 import android.text.method.ScrollingMovementMethod
 import android.view.Gravity
 import android.view.LayoutInflater
@@ -12,9 +11,9 @@ import android.widget.Button
 import android.widget.EditText
 import android.widget.ImageView
 import android.widget.TextView
+import androidx.appcompat.app.AlertDialog
 import com.blankj.utilcode.pkg.R
 import com.blankj.utilcode.util.*
-import com.blankj.utilcode.util.PermissionUtils.OnRationaleListener.ShouldRequest
 
 /**
  * ```
@@ -26,7 +25,7 @@ import com.blankj.utilcode.util.PermissionUtils.OnRationaleListener.ShouldReques
  */
 object DialogHelper {
 
-    fun showRationaleDialog(shouldRequest: ShouldRequest) {
+    fun showRationaleDialog(shouldRequest: PermissionUtils.OnRationaleListener.ShouldRequest) {
         val topActivity = ActivityUtils.getTopActivity()
         AlertDialog.Builder(topActivity)
                 .setTitle(android.R.string.dialog_alert_title)
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml
index 792ae5672e..9be8749952 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen.xml
@@ -1,5 +1,5 @@
 
-
 
-
+
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml
index ccc88dddb6..1522b0741b 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_close.xml
@@ -8,7 +8,7 @@
     android:fillViewport="true"
     tools:context=".feature.adaptScreen.AdaptCloseActivity">
 
-    
 
@@ -43,6 +43,6 @@
             android:textSize="30pt"
             app:layout_constraintTop_toBottomOf="@id/adaptScreenCloseAdaptDpTv" />
 
-    
+    
 
 
\ No newline at end of file
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml
index 350921b04d..75fa87e8e5 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_height.xml
@@ -1,13 +1,12 @@
 
-
 
-    
 
@@ -94,6 +93,6 @@
                 android:textSize="30pt" />
         
 
-    
+    
 
 
\ No newline at end of file
diff --git a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml
index 121415e1b6..dd9f9f40c7 100644
--- a/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_adaptscreen_width.xml
@@ -8,7 +8,7 @@
     android:fillViewport="true"
     tools:context=".feature.adaptScreen.AdaptWidthActivity">
 
-    
 
@@ -149,6 +149,6 @@
 
         
 
-    
+    
 
 
\ No newline at end of file
diff --git a/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml b/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml
index 3ce196004b..bd6e43e7a7 100644
--- a/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml
+++ b/utilcode/pkg/src/main/res/layout/activity_bar_status_fragment.xml
@@ -6,7 +6,7 @@
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-    
 
-    
 
-    
-
Date: Sat, 29 Jun 2019 19:59:42 +0800
Subject: [PATCH 05/49] see 06/29 log

---
 .../test/java/com/blankj/utilcode/util/TimeUtilsTest.java    | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/utilcode/lib/src/test/java/com/blankj/utilcode/util/TimeUtilsTest.java b/utilcode/lib/src/test/java/com/blankj/utilcode/util/TimeUtilsTest.java
index 2ba0a41586..5ab8ee17eb 100644
--- a/utilcode/lib/src/test/java/com/blankj/utilcode/util/TimeUtilsTest.java
+++ b/utilcode/lib/src/test/java/com/blankj/utilcode/util/TimeUtilsTest.java
@@ -42,15 +42,14 @@ public class TimeUtilsTest  {
     public void millis2String() {
         assertEquals(timeString, TimeUtils.millis2String(timeMillis));
         assertEquals(timeStringFormat, TimeUtils.millis2String(timeMillis, mFormat));
-        assertEquals("2017年05月04日", TimeUtils.millis2String(timeMillis, "yyyy年MM月dd日"));
-        assertEquals("16时37分", TimeUtils.millis2String(timeMillis, "HH时mm分"));
+        assertEquals(timeStringFormat, TimeUtils.millis2String(timeMillis, "yyyy MM dd HH:mm:ss"));
     }
 
     @Test
     public void string2Millis() {
         assertEquals(timeMillis, TimeUtils.string2Millis(timeString));
         assertEquals(timeMillis, TimeUtils.string2Millis(timeStringFormat, mFormat));
-        assertEquals(timeMillis, TimeUtils.string2Millis(timeStringFormat, "yyyy年MM月dd日HH时mm分"));
+        assertEquals(timeMillis, TimeUtils.string2Millis(timeStringFormat, "yyyy MM dd HH:mm:ss"));
     }
 
     @Test

From 40c0e36fbb1dc33ebce09a6fa162e07380271cf9 Mon Sep 17 00:00:00 2001
From: Blankj <625783482@qq.com>
Date: Thu, 15 Aug 2019 01:36:03 +0800
Subject: [PATCH 06/49] see 08/15 log

---
 lib/utilcode/README-CN.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
index d610595e3c..cce78181fc 100644
--- a/lib/utilcode/README-CN.md
+++ b/lib/utilcode/README-CN.md
@@ -1185,7 +1185,7 @@ getComments       : 获取压缩文件中的注释链表
 [log.demo]: https://github.com/Blankj/AndroidUtilCode/blob/master/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/log/LogActivity.kt
 
 [map.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/src/main/java/com/blankj/utilcode/util/MapUtils.java
-[map.demo]: https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/src/test/java/com/blankj/utilcode/util/MapUtilsTest.java
+[map.test]: https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/src/test/java/com/blankj/utilcode/util/MapUtilsTest.java
 
 [metaData.java]: https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
 [metaData.demo]: https://github.com/Blankj/AndroidUtilCode/blob/master/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/metaData/MetaDataActivity.kt

From 73dc60c4cdfa10a2b296df3e28ce9af2784be582 Mon Sep 17 00:00:00 2001
From: Blankj <625783482@qq.com>
Date: Sat, 30 Nov 2019 13:03:30 +0800
Subject: [PATCH 07/49] see 11/30 log

---
 buildSrc/src/main/groovy/Config.groovy                        | 2 +-
 config.json                                                   | 2 +-
 .../pkg/src/main/java/com/blankj/main/pkg/MainActivity.kt     | 2 +-
 .../utilcode/pkg/feature/reflect/TestPrivateStaticFinal.java  | 2 +-
 lib/base/build.gradle                                         | 2 +-
 lib/subutil/build.gradle                                      | 4 ++--
 lib/utildebug/build.gradle                                    | 2 +-
 7 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy
index 03181d7927..cc279262a8 100644
--- a/buildSrc/src/main/groovy/Config.groovy
+++ b/buildSrc/src/main/groovy/Config.groovy
@@ -41,7 +41,7 @@ class Config {
             lib_base                   : new DepConfig(true, true, ":lib:base"),
             lib_common                 : new DepConfig(true, true, ":lib:common"),
             lib_subutil                : new DepConfig(true, true, ":lib:subutil"),
-            lib_utilcode               : new DepConfig(true, true, ":lib:utilcode", "com.blankj:utilcode:1.26.0"),
+            lib_utilcodex              : new DepConfig(true, true, ":lib:utilcodex", "com.blankj:utilcodex:1.26.0"),
             lib_utildebug              : new DepConfig(true, true, ":lib:utildebug", "com.blankj:utildebug:1.25.10-alpha5"),
             lib_utildebug_no_op        : new DepConfig(true, true, ":lib:utildebug-no-op", "com.blankj:utildebug-no-op:1.25.10-alpha5"),
             /*Never delete this line*/
diff --git a/config.json b/config.json
index 188e2ff509..630e76de6a 100644
--- a/config.json
+++ b/config.json
@@ -20,7 +20,7 @@
     {"isApply": true, "useLocal": true, "localPath": ":lib:base"},
     {"isApply": true, "useLocal": true, "localPath": ":lib:common"},
     {"isApply": true, "useLocal": true, "localPath": ":lib:subutil"},
-    {"isApply": true, "useLocal": true, "localPath": ":lib:utilcode", "remotePath": "com.blankj:utilcode:1.26.0"},
+    {"isApply": true, "useLocal": true, "localPath": ":lib:utilcodex", "remotePath": "com.blankj:utilcodex:1.26.0"},
     {"isApply": true, "useLocal": true, "localPath": ":lib:utildebug", "remotePath": "com.blankj:utildebug:1.25.10-alpha5"},
     {"isApply": true, "useLocal": true, "localPath": ":lib:utildebug-no-op", "remotePath": "com.blankj:utildebug-no-op:1.25.10-alpha5"}
   ]
diff --git a/feature/main/pkg/src/main/java/com/blankj/main/pkg/MainActivity.kt b/feature/main/pkg/src/main/java/com/blankj/main/pkg/MainActivity.kt
index fb45369c5b..ccce008ded 100644
--- a/feature/main/pkg/src/main/java/com/blankj/main/pkg/MainActivity.kt
+++ b/feature/main/pkg/src/main/java/com/blankj/main/pkg/MainActivity.kt
@@ -2,8 +2,8 @@ package com.blankj.main.pkg
 
 import android.graphics.Color
 import android.os.Bundle
-import androidx.appcompat.app.ActionBarDrawerToggle
 import android.view.View
+import androidx.appcompat.app.ActionBarDrawerToggle
 import com.blankj.common.activity.CommonActivity
 import com.blankj.common.item.CommonItem
 import com.blankj.common.item.CommonItemClick
diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/reflect/TestPrivateStaticFinal.java b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/reflect/TestPrivateStaticFinal.java
index e62c518699..b7efb5f4d7 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/reflect/TestPrivateStaticFinal.java
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/reflect/TestPrivateStaticFinal.java
@@ -1,6 +1,6 @@
 package com.blankj.utilcode.pkg.feature.reflect;
 
-import android.support.annotation.Keep;
+import androidx.annotation.Keep;
 
 /**
  * 
diff --git a/lib/base/build.gradle b/lib/base/build.gradle
index 2285071b5e..6fffd3af61 100644
--- a/lib/base/build.gradle
+++ b/lib/base/build.gradle
@@ -1,7 +1,7 @@
 dependencies {
     implementation fileTree(include: ['*.jar'], dir: 'libs')
     api Config.depConfig.lib_subutil.dep
-    api Config.depConfig.lib_utilcode.dep
+    api Config.depConfig.lib_utilcodex.dep
 
     api Config.depConfig.support_appcompat.dep
     api Config.depConfig.support_material.dep
diff --git a/lib/subutil/build.gradle b/lib/subutil/build.gradle
index 662f2a4ec7..e7eaf45da1 100644
--- a/lib/subutil/build.gradle
+++ b/lib/subutil/build.gradle
@@ -13,14 +13,14 @@ readme {
 dependencies {
     compileOnly Config.depConfig.support_appcompat.dep
     compileOnly Config.depConfig.support_material.dep
-    compileOnly Config.depConfig.lib_utilcode.dep
+    compileOnly Config.depConfig.lib_utilcodex.dep
     api(Config.depConfig.glide.dep) {
         exclude group: "com.android.support"
     }
     api Config.depConfig.retrofit.dep
     api Config.depConfig.gson.dep
 
-    testImplementation Config.depConfig.lib_utilcode.dep
+    testImplementation Config.depConfig.lib_utilcodex.dep
     testImplementation Config.depConfig.test_junit.dep
     testImplementation Config.depConfig.test_robolectric.dep
 }
\ No newline at end of file
diff --git a/lib/utildebug/build.gradle b/lib/utildebug/build.gradle
index b6380100bb..558735162a 100644
--- a/lib/utildebug/build.gradle
+++ b/lib/utildebug/build.gradle
@@ -5,7 +5,7 @@ apply {
 }
 
 dependencies {
-    implementation Config.depConfig.lib_utilcode.dep
+    implementation Config.depConfig.lib_utilcodex.dep
     implementation Config.depConfig.swipe_panel.dep
     implementation Config.depConfig.photo_view.dep
     compileOnly Config.depConfig.support_appcompat.dep

From 3fd7a91e0e3bbd2ddbaf2b79163527b02dcc87d9 Mon Sep 17 00:00:00 2001
From: Blankj 
Date: Tue, 7 Apr 2020 00:11:37 +0800
Subject: [PATCH 08/49] see 04/07 log

---
 lib/utildebug/build.gradle | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/utildebug/build.gradle b/lib/utildebug/build.gradle
index b733473cf1..6e1157ef0b 100644
--- a/lib/utildebug/build.gradle
+++ b/lib/utildebug/build.gradle
@@ -9,4 +9,8 @@ dependencies {
     testImplementation Config.depConfig.test_junit.dep
     testImplementation Config.depConfig.test_robolectric.dep
     testImplementation Config.depConfig.support_appcompat.dep
+}
+
+afterEvaluate {
+    verifyReleaseResources.enabled(false)
 }
\ No newline at end of file

From 96c45acb8eb47a58c84bb467e6b126500765f5b2 Mon Sep 17 00:00:00 2001
From: Blankj 
Date: Tue, 7 Apr 2020 17:21:35 +0800
Subject: [PATCH 09/49] see 04/07 log

---
 .../src/test/java/com/blankj/utilcode/util/BaseTest.java  | 8 +++++---
 .../java/com/blankj/utilcode/util/UiMessageUtilsTest.java | 3 ++-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/lib/utilcode/src/test/java/com/blankj/utilcode/util/BaseTest.java b/lib/utilcode/src/test/java/com/blankj/utilcode/util/BaseTest.java
index 6e097938bf..ebaa83564d 100644
--- a/lib/utilcode/src/test/java/com/blankj/utilcode/util/BaseTest.java
+++ b/lib/utilcode/src/test/java/com/blankj/utilcode/util/BaseTest.java
@@ -1,7 +1,5 @@
 package com.blankj.utilcode.util;
 
-import android.support.annotation.NonNull;
-import java.util.concurrent.Executor;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -9,6 +7,10 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLog;
 
+import java.util.concurrent.Executor;
+
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
@@ -18,7 +20,7 @@
  * 
*/ @RunWith(RobolectricTestRunner.class) -@Config(manifest = Config.NONE,shadows = { ShadowLog.class }) +@Config(manifest = Config.NONE, shadows = {ShadowLog.class}) public class BaseTest { @BusUtils.Bus(tag = "base") diff --git a/lib/utilcode/src/test/java/com/blankj/utilcode/util/UiMessageUtilsTest.java b/lib/utilcode/src/test/java/com/blankj/utilcode/util/UiMessageUtilsTest.java index 1ef00ee586..140dd77683 100644 --- a/lib/utilcode/src/test/java/com/blankj/utilcode/util/UiMessageUtilsTest.java +++ b/lib/utilcode/src/test/java/com/blankj/utilcode/util/UiMessageUtilsTest.java @@ -1,9 +1,10 @@ package com.blankj.utilcode.util; -import android.support.annotation.NonNull; import org.junit.Test; +import androidx.annotation.NonNull; + /** *
  *     author: blankj

From 7145da0408a6f5ed8f0bbd531245750eb1a1c75d Mon Sep 17 00:00:00 2001
From: Blankj 
Date: Tue, 5 May 2020 02:24:34 +0800
Subject: [PATCH 10/49] see 05/05 log

---
 buildSrc/src/main/groovy/Config.groovy | 8 ++++----
 lib/base/build.gradle                  | 8 ++++----
 lib/subutil/build.gradle               | 4 ++--
 lib/utilcode/build.gradle              | 8 ++++----
 lib/utildebug/build.gradle             | 6 +++---
 5 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy
index d8e41b3ca2..88b8eb9a5a 100644
--- a/buildSrc/src/main/groovy/Config.groovy
+++ b/buildSrc/src/main/groovy/Config.groovy
@@ -60,10 +60,10 @@ class Config {
             //./gradlew clean plugin:plugin_bus-gradle-plugin:mavenLocal     // 上传到本地 mavenLocal
             //./gradlew clean plugin:plugin_bus-gradle-plugin:bintrayUpload  // 上传到 jcenter
 
-            support_appcompat          : new DepConfig("androidx.appcompat:appcompat:$androidxVersion"),
-            support_material           : new DepConfig("com.google.android.material:material:$androidxVersion"),
-            support_multidex           : new DepConfig("com.android.support:multidex:1.0.2"),
-            support_constraint         : new DepConfig("com.android.support.constraint:constraint-layout:1.1.3"),
+            androidx_appcompat          : new DepConfig("androidx.appcompat:appcompat:$androidxVersion"),
+            androidx_material           : new DepConfig("com.google.android.material:material:$androidxVersion"),
+            androidx_multidex           : new DepConfig("androidx.multidex:multidex:2.0.0"),
+            androidx_constraint         : new DepConfig("androidx.constraintlayout:constraintlayout:1.1.3"),
 
             kotlin                     : new DepConfig("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"),
 
diff --git a/lib/base/build.gradle b/lib/base/build.gradle
index 9a1ac7b329..bb7fa31573 100644
--- a/lib/base/build.gradle
+++ b/lib/base/build.gradle
@@ -3,10 +3,10 @@ dependencies {
     api Config.depConfig.lib_subutil.dep
     api Config.depConfig.lib_utilcode.dep
 
-    api Config.depConfig.support_appcompat.dep
-    api Config.depConfig.support_material.dep
-    api Config.depConfig.support_multidex.dep
-    api Config.depConfig.support_constraint.dep
+    api Config.depConfig.androidx_appcompat.dep
+    api Config.depConfig.androidx_material.dep
+    api Config.depConfig.androidx_multidex.dep
+    api Config.depConfig.androidx_constraint.dep
     api Config.depConfig.kotlin.dep
     api Config.depConfig.free_proguard.dep
     api Config.depConfig.swipe_panel.dep
diff --git a/lib/subutil/build.gradle b/lib/subutil/build.gradle
index a8798fea1b..a561916f3e 100644
--- a/lib/subutil/build.gradle
+++ b/lib/subutil/build.gradle
@@ -9,8 +9,8 @@ readme {
 }
 
 dependencies {
-    compileOnly Config.depConfig.support_appcompat.dep
-    compileOnly Config.depConfig.support_material.dep
+    compileOnly Config.depConfig.androidx_appcompat.dep
+    compileOnly Config.depConfig.androidx_material.dep
     compileOnly Config.depConfig.lib_utilcode.dep
     api(Config.depConfig.glide.dep) {
         exclude group: "com.android.support"
diff --git a/lib/utilcode/build.gradle b/lib/utilcode/build.gradle
index a3ed94861c..891f7dbf40 100644
--- a/lib/utilcode/build.gradle
+++ b/lib/utilcode/build.gradle
@@ -29,13 +29,13 @@ android {
 dependencies {
     implementation Config.depConfig.gson.dep
 
-    compileOnly Config.depConfig.support_appcompat.dep
-    compileOnly Config.depConfig.support_material.dep
+    compileOnly Config.depConfig.androidx_appcompat.dep
+    compileOnly Config.depConfig.androidx_material.dep
 
     testImplementation Config.depConfig.test_junit.dep
     testImplementation Config.depConfig.test_robolectric.dep
-    testImplementation Config.depConfig.support_appcompat.dep
-    testImplementation Config.depConfig.support_material.dep
+    testImplementation Config.depConfig.androidx_appcompat.dep
+    testImplementation Config.depConfig.androidx_material.dep
     testImplementation Config.depConfig.eventbus_lib.dep
 }
 
diff --git a/lib/utildebug/build.gradle b/lib/utildebug/build.gradle
index 6e1157ef0b..82b55495b0 100644
--- a/lib/utildebug/build.gradle
+++ b/lib/utildebug/build.gradle
@@ -1,6 +1,6 @@
 dependencies {
-    compileOnly Config.depConfig.support_appcompat.dep
-    compileOnly Config.depConfig.support_material.dep
+    compileOnly Config.depConfig.androidx_appcompat.dep
+    compileOnly Config.depConfig.androidx_material.dep
 
     implementation Config.depConfig.lib_utilcode.dep
     implementation Config.depConfig.swipe_panel.dep
@@ -8,7 +8,7 @@ dependencies {
 
     testImplementation Config.depConfig.test_junit.dep
     testImplementation Config.depConfig.test_robolectric.dep
-    testImplementation Config.depConfig.support_appcompat.dep
+    testImplementation Config.depConfig.androidx_appcompat.dep
 }
 
 afterEvaluate {

From c7190639ec44b9ff4b5b35f5580458b77abd79c7 Mon Sep 17 00:00:00 2001
From: Blankj 
Date: Tue, 5 May 2020 02:26:00 +0800
Subject: [PATCH 11/49] see 05/05 log

---
 buildApp.gradle                        |  2 +-
 buildSrc/src/main/groovy/Config.groovy | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/buildApp.gradle b/buildApp.gradle
index 2220ed6947..8cb7de95fe 100644
--- a/buildApp.gradle
+++ b/buildApp.gradle
@@ -68,7 +68,7 @@ android {
 
 dependencies {
     // LeakCanary
-    debugImplementation Config.depConfig.leakcanary_android.dep
+    debugImplementation Config.depConfig.leakcanary.dep
 
     debugImplementation Config.depConfig.lib_utildebug.dep
     releaseImplementation Config.depConfig.lib_utildebug_no_op.dep
diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy
index 88b8eb9a5a..6074cf4d2e 100644
--- a/buildSrc/src/main/groovy/Config.groovy
+++ b/buildSrc/src/main/groovy/Config.groovy
@@ -20,7 +20,7 @@ class Config {
     // lib version
     static gradlePluginVersion = '3.5.2'
     static kotlinVersion = '1.3.50'
-    static androidxVersion = '1.0.0'
+    static androidxVersion = '1.1.0'
 
     static depConfig = [
             /*Never delete this line*/
@@ -60,14 +60,14 @@ class Config {
             //./gradlew clean plugin:plugin_bus-gradle-plugin:mavenLocal     // 上传到本地 mavenLocal
             //./gradlew clean plugin:plugin_bus-gradle-plugin:bintrayUpload  // 上传到 jcenter
 
-            androidx_appcompat          : new DepConfig("androidx.appcompat:appcompat:$androidxVersion"),
-            androidx_material           : new DepConfig("com.google.android.material:material:$androidxVersion"),
-            androidx_multidex           : new DepConfig("androidx.multidex:multidex:2.0.0"),
-            androidx_constraint         : new DepConfig("androidx.constraintlayout:constraintlayout:1.1.3"),
+            androidx_appcompat         : new DepConfig("androidx.appcompat:appcompat:$androidxVersion"),
+            androidx_material          : new DepConfig("com.google.android.material:material:$androidxVersion"),
+            androidx_multidex          : new DepConfig("androidx.multidex:multidex:2.0.0"),
+            androidx_constraint        : new DepConfig("androidx.constraintlayout:constraintlayout:1.1.3"),
 
             kotlin                     : new DepConfig("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"),
 
-            leakcanary_android         : new DepConfig("com.squareup.leakcanary:leakcanary-android:2.1"),
+            leakcanary                 : new DepConfig("com.squareup.leakcanary:leakcanary-android:2.1"),
 
             free_proguard              : new DepConfig("com.blankj:free-proguard:1.0.2"),
             swipe_panel                : new DepConfig("com.blankj:swipe-panel:1.2"),

From c351507a082875429db451bef2a818aead420077 Mon Sep 17 00:00:00 2001
From: Blankj 
Date: Sun, 25 Oct 2020 02:53:58 +0800
Subject: [PATCH 12/49] see 10/25 log

---
 .../com/blankj/utilcode/pkg/feature/mvp/MvpActivity.java   | 2 --
 lib/base/src/main/java/com/blankj/base/mvp/BaseModel.java  | 7 ++++---
 lib/base/src/main/java/com/blankj/base/mvp/BaseView.java   | 2 ++
 .../java/com/blankj/utilcode/util/DebouncingUtils.java     | 3 ++-
 .../src/main/java/com/blankj/utilcode/util/ViewUtils.java  | 3 ++-
 5 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/mvp/MvpActivity.java b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/mvp/MvpActivity.java
index 05ae20c92d..7fff29f4a7 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/mvp/MvpActivity.java
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/mvp/MvpActivity.java
@@ -1,7 +1,5 @@
 package com.blankj.utilcode.pkg.feature.mvp;
 
-import android.arch.lifecycle.ViewModel;
-import android.arch.lifecycle.ViewModelProvider;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
diff --git a/lib/base/src/main/java/com/blankj/base/mvp/BaseModel.java b/lib/base/src/main/java/com/blankj/base/mvp/BaseModel.java
index 84c930fd74..2f2b81d6e0 100644
--- a/lib/base/src/main/java/com/blankj/base/mvp/BaseModel.java
+++ b/lib/base/src/main/java/com/blankj/base/mvp/BaseModel.java
@@ -1,10 +1,11 @@
 package com.blankj.base.mvp;
 
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.MutableLiveData;
-import android.support.annotation.CallSuper;
 import android.util.Log;
 
+import androidx.annotation.CallSuper;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+
 /**
  * 
  *     author: blankj
diff --git a/lib/base/src/main/java/com/blankj/base/mvp/BaseView.java b/lib/base/src/main/java/com/blankj/base/mvp/BaseView.java
index 94f36bcdaa..a68909d01f 100644
--- a/lib/base/src/main/java/com/blankj/base/mvp/BaseView.java
+++ b/lib/base/src/main/java/com/blankj/base/mvp/BaseView.java
@@ -5,10 +5,12 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import androidx.annotation.CallSuper;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
 
 /**
  * 
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/DebouncingUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/DebouncingUtils.java
index c9f2c8ff79..889ac86090 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/DebouncingUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/DebouncingUtils.java
@@ -1,7 +1,6 @@
 package com.blankj.utilcode.util;
 
 import android.os.SystemClock;
-import android.support.annotation.NonNull;
 import android.text.TextUtils;
 import android.view.View;
 
@@ -9,6 +8,8 @@
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import androidx.annotation.NonNull;
+
 /**
  * 
  *     author: Blankj
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ViewUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ViewUtils.java
index a06e3503bf..f0ef043322 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ViewUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ViewUtils.java
@@ -2,7 +2,6 @@
 
 import android.content.Context;
 import android.os.Build;
-import android.support.annotation.LayoutRes;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -10,6 +9,8 @@
 
 import java.util.Locale;
 
+import androidx.annotation.LayoutRes;
+
 /**
  * 
  *     author: Blankj

From 7402e364000fd053b7ee08650a04a8559977ba41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A9=AC=E6=AD=87=E5=B0=94?= 
Date: Sun, 10 Jan 2021 16:54:25 +0430
Subject: [PATCH 13/49] Added new methods (features)

Added 6 new very useful methods.
1. getScreenXDpi() which returns the Width (X) density in DPI.
2. getScreenYDpi() which returns the Height (Y) density in DPI.
3. calculateDistanceByX() which returns the distance between the given View's X (start point of View's width) and the screen width.
4. calculateDistanceByY() which returns the distance between the given View's Y (start point of View's height) and the screen height.
5. getViewX() which returns the X coordinate of the given View on the screen.
6. getViewY() which returns the Y coordinate of the given View on the screen.
---
 .../com/blankj/utilcode/util/ScreenUtils.java | 68 +++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
index b5cad7ef99..cb742b7a7d 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
@@ -112,6 +112,74 @@ public static float getScreenDensity() {
     public static int getScreenDensityDpi() {
         return Resources.getSystem().getDisplayMetrics().densityDpi;
     }
+    
+    
+    
+    
+    /**
+     * Return X (width) of the screen expressed as dots-per-inch.
+     *
+     * @return the width of screen density expressed as dots-per-inch
+     */
+    public static int getScreenXDpi() {
+        return Resources.getSystem().getDisplayMetrics().xdpi;
+    }
+    
+    /**
+     * Return Y (height) of the screen expressed as dots-per-inch.
+     *
+     * @return the height of screen density expressed as dots-per-inch
+     */
+    public static int getScreenYDpi() {
+        return Resources.getSystem().getDisplayMetrics().ydpi;
+    }
+    
+   
+    
+    /**
+     * Return the distance between the given View's X (start point of View's width) and the screen width.
+     *
+     * @return the distance between the given View's X (start point of View's width) and the screen width.
+     */
+    public float calculateDistanceByX(View view) {
+        int[] point = new int[0];
+        view.getLocationOnScreen(point);
+        return (getScreenWidth() - point[0]).toFloat();
+    }
+
+    /**
+     * Return the distance between the given View's Y (start point of View's height) and the screen height.
+     *
+     * @return the distance between the given View's Y (start point of View's height) and the screen height.
+     */
+    public float calculateDistanceByY(View view) {
+        int[] point = new int[0];
+        view.getLocationOnScreen(point);
+        return (getScreenHeight() - point[1]).toFloat();
+    }
+
+    /**
+     * Return the X coordinate of the given View on the screen.
+     *
+     * @return X coordinate of the given View on the screen.
+     */
+    public int getViewX(View view){
+        int[] point = new int[0];
+        view.getLocationOnScreen(point);
+        return point[0];
+    }
+    
+    /**
+     * Return the Y coordinate of the given View on the screen.
+     *
+     * @return Y coordinate of the given View on the screen.
+     */
+    public int getViewY(View view){
+        int[] point = new int[0];
+        view.getLocationOnScreen(point);
+        return point[1];
+    }
+    
 
     /**
      * Set full screen.

From fd2d59aa451d0a1c038757d68e5387ef5c7d4230 Mon Sep 17 00:00:00 2001
From: yuruxuan <544324974@qq.com>
Date: Mon, 1 Feb 2021 13:43:30 +0800
Subject: [PATCH 14/49] add environment variable

---
 .../com/blankj/utilcode/util/ShellUtils.java  | 88 ++++++++++++++++++-
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ShellUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ShellUtils.java
index 1f2d50888b..a4f1e4fa81 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ShellUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ShellUtils.java
@@ -133,6 +133,21 @@ public static CommandResult execCmd(final String command, final boolean isRooted
         return execCmd(new String[]{command}, isRooted, true);
     }
 
+    /**
+     * Execute the command.
+     *
+     * @param command  The command.
+     * @param envp     The environment variable settings.
+     * @param isRooted True to use root, false otherwise.
+     * @return the single {@link CommandResult} instance
+     */
+    public static CommandResult execCmd(final String command, final List envp, final boolean isRooted) {
+        return execCmd(new String[]{command},
+                envp == null ? null : envp.toArray(new String[]{}),
+                isRooted,
+                true);
+    }
+
     /**
      * Execute the command.
      *
@@ -144,6 +159,23 @@ public static CommandResult execCmd(final List commands, final boolean i
         return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRooted, true);
     }
 
+    /**
+     * Execute the command.
+     *
+     * @param commands The commands.
+     * @param envp     The environment variable settings.
+     * @param isRooted True to use root, false otherwise.
+     * @return the single {@link CommandResult} instance
+     */
+    public static CommandResult execCmd(final List commands,
+                                        final List envp,
+                                        final boolean isRooted) {
+        return execCmd(commands == null ? null : commands.toArray(new String[]{}),
+                envp == null ? null : envp.toArray(new String[]{}),
+                isRooted,
+                true);
+    }
+
     /**
      * Execute the command.
      *
@@ -169,6 +201,40 @@ public static CommandResult execCmd(final String command,
         return execCmd(new String[]{command}, isRooted, isNeedResultMsg);
     }
 
+    /**
+     * Execute the command.
+     *
+     * @param command         The command.
+     * @param envp            The environment variable settings.
+     * @param isRooted        True to use root, false otherwise.
+     * @param isNeedResultMsg True to return the message of result, false otherwise.
+     * @return the single {@link CommandResult} instance
+     */
+    public static CommandResult execCmd(final String command,
+                                        final List envp,
+                                        final boolean isRooted,
+                                        final boolean isNeedResultMsg) {
+        return execCmd(new String[]{command}, envp == null ? null : envp.toArray(new String[]{}),
+                isRooted,
+                isNeedResultMsg);
+    }
+
+    /**
+     * Execute the command.
+     *
+     * @param command         The command.
+     * @param envp            The environment variable settings array.
+     * @param isRooted        True to use root, false otherwise.
+     * @param isNeedResultMsg True to return the message of result, false otherwise.
+     * @return the single {@link CommandResult} instance
+     */
+    public static CommandResult execCmd(final String command,
+                                        final String[] envp,
+                                        final boolean isRooted,
+                                        final boolean isNeedResultMsg) {
+        return execCmd(new String[]{command}, envp, isRooted, isNeedResultMsg);
+    }
+
     /**
      * Execute the command.
      *
@@ -196,6 +262,26 @@ public static CommandResult execCmd(final List commands,
     public static CommandResult execCmd(final String[] commands,
                                         final boolean isRooted,
                                         final boolean isNeedResultMsg) {
+        return execCmd(commands, null, isRooted, isNeedResultMsg);
+    }
+
+    /**
+     * Execute the command.
+     *
+     * @param commands        The commands.
+     * @param envp            Array of strings, each element of which
+     *                        has environment variable settings in the format
+     *                        name=value, or
+     *                        null if the subprocess should inherit
+     *                        the environment of the current process.
+     * @param isRooted        True to use root, false otherwise.
+     * @param isNeedResultMsg True to return the message of result, false otherwise.
+     * @return the single {@link CommandResult} instance
+     */
+    public static CommandResult execCmd(final String[] commands,
+                                        final String[] envp,
+                                        final boolean isRooted,
+                                        final boolean isNeedResultMsg) {
         int result = -1;
         if (commands == null || commands.length == 0) {
             return new CommandResult(result, "", "");
@@ -207,7 +293,7 @@ public static CommandResult execCmd(final String[] commands,
         StringBuilder errorMsg = null;
         DataOutputStream os = null;
         try {
-            process = Runtime.getRuntime().exec(isRooted ? "su" : "sh");
+            process = Runtime.getRuntime().exec(isRooted ? "su" : "sh", envp, null);
             os = new DataOutputStream(process.getOutputStream());
             for (String command : commands) {
                 if (command == null) continue;

From 28f24faf597ef92771d97780eac7d8e69ad145a4 Mon Sep 17 00:00:00 2001
From: Blankj 
Date: Mon, 22 Feb 2021 00:07:51 +0800
Subject: [PATCH 15/49] see 02/22 log

---
 CHANGELOG.md                                  |   2 +
 buildSrc/src/main/groovy/Config.groovy        |   4 +-
 .../launcher/app/src/main/AndroidManifest.xml |   1 +
 .../java/com/blankj/main/pkg/MainActivity.kt  |   4 +-
 .../utilcode/pkg/feature/api/ApiActivity.kt   |   4 +-
 .../pkg/feature/clean/CleanActivity.kt        |   7 +-
 .../pkg/feature/keyboard/KeyboardActivity.kt  |   3 +-
 .../pkg/feature/language/LanguageActivity.kt  |   3 +
 .../pkg/feature/phone/PhoneActivity.kt        |   4 +-
 .../pkg/feature/toast/ToastActivity.kt        |   3 +
 .../src/main/res/values-en-rUS/strings.xml    |   1 +
 .../src/main/res/values-zh-rCN/strings.xml    |   1 +
 .../pkg/src/main/res/values/strings.xml       |   4 +
 .../java/com/blankj/base/BaseFragment.java    |   2 +-
 .../com/blankj/subutil/util/BatteryUtils.java |  30 +-
 lib/utilcode/README-CN.md                     |   4 +-
 lib/utilcode/README.md                        |   4 +-
 .../utilcode/constant/RegexConstants.java     |  11 +-
 .../blankj/utilcode/util/ActivityUtils.java   |  29 +-
 .../utilcode/util/AdaptScreenUtils.java       |  17 +-
 .../com/blankj/utilcode/util/ApiUtils.java    |   6 +-
 .../com/blankj/utilcode/util/AppUtils.java    |  56 +-
 .../com/blankj/utilcode/util/ArrayUtils.java  | 529 +++++++++++-------
 .../com/blankj/utilcode/util/BarUtils.java    |  20 +-
 .../blankj/utilcode/util/BrightnessUtils.java |   2 +-
 .../com/blankj/utilcode/util/BusUtils.java    |  16 +-
 .../utilcode/util/CacheDiskStaticUtils.java   | 100 ++--
 .../utilcode/util/CacheDoubleUtils.java       |  56 +-
 .../blankj/utilcode/util/FragmentUtils.java   |   1 +
 .../com/blankj/utilcode/util/ImageUtils.java  | 103 +++-
 .../com/blankj/utilcode/util/IntentUtils.java |  13 +-
 .../com/blankj/utilcode/util/PhoneUtils.java  |   7 +-
 .../com/blankj/utilcode/util/RomUtils.java    |   2 +-
 .../blankj/utilcode/util/SnackbarUtils.java   |  16 +-
 .../com/blankj/utilcode/util/SpanUtils.java   |  16 +-
 .../com/blankj/utilcode/util/StringUtils.java |   3 +-
 .../com/blankj/utilcode/util/ThreadUtils.java |  14 +-
 .../com/blankj/utilcode/util/ToastUtils.java  | 145 +++--
 .../util/UtilsActivityLifecycleImpl.java      |   3 +
 .../com/blankj/utilcode/util/UtilsBridge.java |   7 +-
 .../main/res/xml/util_code_provider_paths.xml |   4 -
 .../utildebug/base/view/BaseContentView.java  |   2 +
 42 files changed, 854 insertions(+), 405 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 913ee7b7ad..14be8c6656 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+* `21/02/22` [add] Fix ToastUtils rtl bug. Publish v1.30.6.
+* `20/11/16` [add] Add ImageUtils#save2Album support param of dirName.
 * `20/11/13` [add] Fix MessengerUtils ANR. Add NetworkUtils#getWifiScanResult, [add|remove]OnWifiChangedConsumer. Publish v1.30.5.
 * `20/10/29` [add] Fix MessengerUtils startService IllegalStateException. Publish v1.30.4.
 * `20/10/28` [add] Fix BusUtils ConcurrentModificationException. Publish v1.30.3.
diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy
index 1d9b9cd6cd..fd23def7b1 100644
--- a/buildSrc/src/main/groovy/Config.groovy
+++ b/buildSrc/src/main/groovy/Config.groovy
@@ -14,8 +14,8 @@ class Config {
     static compileSdkVersion = 29
     static minSdkVersion = 14
     static targetSdkVersion = 29
-    static versionCode = 1_030_005
-    static versionName = '1.30.5'// E.g. 1.9.72 => 1,009,072
+    static versionCode = 1_030_006
+    static versionName = '1.30.6'// E.g. 1.9.72 => 1,009,072
 
     // lib version
     static gradlePluginVersion = '3.5.0'
diff --git a/feature/launcher/app/src/main/AndroidManifest.xml b/feature/launcher/app/src/main/AndroidManifest.xml
index 19f6313965..4f033c06a6 100644
--- a/feature/launcher/app/src/main/AndroidManifest.xml
+++ b/feature/launcher/app/src/main/AndroidManifest.xml
@@ -7,6 +7,7 @@
         android:allowBackup="false"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
+        android:supportsRtl="true"
         android:theme="@style/AppTheme">
 
         >(
                 CommonItemClick(R.string.core_util, true) {
-                    ApiUtils.getApi(UtilCodeApi::class.java).startUtilCodeActivity(this)
+                    ApiUtils.getApi(UtilCodeApi::class.java)?.startUtilCodeActivity(this)
                 },
                 CommonItemClick(R.string.sub_util, true) {
-                    ApiUtils.getApi(SubUtilApi::class.java).startSubUtilActivity(this)
+                    ApiUtils.getApi(SubUtilApi::class.java)?.startSubUtilActivity(this)
                 }
         ))
 
diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/api/ApiActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/api/ApiActivity.kt
index 0857ceaeac..8e11495b09 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/api/ApiActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/api/ApiActivity.kt
@@ -35,10 +35,10 @@ class ApiActivity : CommonActivity() {
     override fun bindItems(): MutableList> {
         return CollectionUtils.newArrayList(
                 CommonItemClick(R.string.api_invoke_with_params) {
-                    ApiUtils.getApi(OtherModuleApi::class.java).invokeWithParams(OtherModuleApi.ApiBean("params"))
+                    ApiUtils.getApi(OtherModuleApi::class.java)?.invokeWithParams(OtherModuleApi.ApiBean("params"))
                 },
                 CommonItemClick(R.string.api_invoke_with_return_value) {
-                    ToastUtils.showShort(ApiUtils.getApi(OtherModuleApi::class.java).invokeWithReturnValue().name)
+                    ToastUtils.showShort(ApiUtils.getApi(OtherModuleApi::class.java)?.invokeWithReturnValue()?.name)
                 }
         );
     }
diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/clean/CleanActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/clean/CleanActivity.kt
index 7185cc33cb..f0b8620eca 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/clean/CleanActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/clean/CleanActivity.kt
@@ -3,8 +3,6 @@ package com.blankj.utilcode.pkg.feature.clean
 import android.content.Context
 import android.content.Intent
 import com.blankj.common.activity.CommonActivity
-import com.blankj.common.activity.CommonActivityItemsView
-import com.blankj.common.activity.CommonActivityTitleView
 import com.blankj.common.item.CommonItem
 import com.blankj.common.item.CommonItemClick
 import com.blankj.utilcode.pkg.R
@@ -54,6 +52,11 @@ class CleanActivity : CommonActivity() {
                     showSnackbar(CleanUtils.cleanExternalCache(), externalCacheDir?.absolutePath)
                 })
             }
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
+                add(CommonItemClick(R.string.clean_app_user_data) {
+                    CleanUtils.cleanAppUserData()
+                })
+            }
         }
     }
 
diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/keyboard/KeyboardActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/keyboard/KeyboardActivity.kt
index b94f66876f..5ed25ae4fe 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/keyboard/KeyboardActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/keyboard/KeyboardActivity.kt
@@ -10,8 +10,7 @@ import com.blankj.common.item.CommonItemClick
 import com.blankj.common.item.CommonItemTitle
 import com.blankj.utilcode.pkg.R
 import com.blankj.utilcode.pkg.helper.DialogHelper
-import com.blankj.utilcode.util.CollectionUtils
-import com.blankj.utilcode.util.KeyboardUtils
+import com.blankj.utilcode.util.*
 import kotlinx.android.synthetic.main.keyboard_activity.*
 
 /**
diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/language/LanguageActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/language/LanguageActivity.kt
index 0e14482b91..c928da21fa 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/language/LanguageActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/language/LanguageActivity.kt
@@ -60,6 +60,9 @@ class LanguageActivity : CommonActivity() {
                 CommonItemClick(R.string.language_apply_english) {
                     LanguageUtils.applyLanguage(Locale.ENGLISH, isRelaunchApp())
                 },
+                CommonItemClick(R.string.language_apply_arabic) {
+                    LanguageUtils.applyLanguage(Locale("ar"), isRelaunchApp())
+                },
                 CommonItemClick(R.string.language_apply_system) {
                     LanguageUtils.applySystemLanguage(isRelaunchApp())
                 }
diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/phone/PhoneActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/phone/PhoneActivity.kt
index cb453b3b89..c9b748cdfa 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/phone/PhoneActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/phone/PhoneActivity.kt
@@ -54,8 +54,8 @@ class PhoneActivity : CommonActivity() {
                 CommonItemTitle("getSimOperatorName", PhoneUtils.getSimOperatorName()),
                 CommonItemTitle("getSimOperatorByMnc", PhoneUtils.getSimOperatorByMnc()),
 
-                CommonItemClick(R.string.phone_dial) { PhoneUtils.dial("10000") },
-                CommonItemClick(R.string.phone_call) { PhoneUtils.call("10000") },
+                CommonItemClick(R.string.phone_dial) { PhoneUtils.dial("*10000#haha") },
+                CommonItemClick(R.string.phone_call) { PhoneUtils.call("*10000#haha") },
                 CommonItemClick(R.string.phone_send_sms) { PhoneUtils.sendSms("10000", "sendSms") }
         )
     }
diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
index 5d55e3c754..bcb3eadfca 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/toast/ToastActivity.kt
@@ -79,6 +79,9 @@ class ToastActivity : CommonActivity() {
                 CommonItemClick(R.string.toast_show_middle) {
                     ToastUtils.make().setGravity(Gravity.CENTER, 0, 0).show(R.string.toast_middle)
                 },
+                CommonItemClick(R.string.toast_show_top) {
+                    ToastUtils.make().setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL, 0, 0).show(R.string.toast_top)
+                },
                 CommonItemClick(R.string.toast_show_custom_view) {
                     Thread(Runnable { CustomToast.showLong(R.string.toast_custom_view) }).start()
                 },
diff --git a/feature/utilcode/pkg/src/main/res/values-en-rUS/strings.xml b/feature/utilcode/pkg/src/main/res/values-en-rUS/strings.xml
index 414fa48424..20efc6c063 100644
--- a/feature/utilcode/pkg/src/main/res/values-en-rUS/strings.xml
+++ b/feature/utilcode/pkg/src/main/res/values-en-rUS/strings.xml
@@ -6,6 +6,7 @@
     Apply Simple Chinese
     Apply American
     Apply English
+    Apply Arabic
     Apply System
 
 
\ No newline at end of file
diff --git a/feature/utilcode/pkg/src/main/res/values-zh-rCN/strings.xml b/feature/utilcode/pkg/src/main/res/values-zh-rCN/strings.xml
index 5cab96988f..e06759a6d0 100644
--- a/feature/utilcode/pkg/src/main/res/values-zh-rCN/strings.xml
+++ b/feature/utilcode/pkg/src/main/res/values-zh-rCN/strings.xml
@@ -6,6 +6,7 @@
     设置简体中文
     设置美语
     设置英语
+    设置阿拉伯语
     设置系统语言
 
 
\ No newline at end of file
diff --git a/feature/utilcode/pkg/src/main/res/values/strings.xml b/feature/utilcode/pkg/src/main/res/values/strings.xml
index ed7e15412f..ccec698647 100644
--- a/feature/utilcode/pkg/src/main/res/values/strings.xml
+++ b/feature/utilcode/pkg/src/main/res/values/strings.xml
@@ -141,6 +141,7 @@
     Clean Internal Databases
     Clean Internal SP
     Clean External Cache
+    cleanAppUserData
 
     
     Click View Scale Default
@@ -233,6 +234,7 @@
     Apply Simple Chinese
     Apply American
     Apply English
+    Apply Arabic
     Apply System
 
     
@@ -341,6 +343,7 @@
     Show Custom View
     Custom View
     Show Middle
+    Show Top
     Cancel
     Show Toast Dialog
     Show Toast When Start Activity
@@ -351,6 +354,7 @@
     Custom Bg
     Spannable String
     Middle
+    Top
 
     
     Add Listener Id
diff --git a/lib/base/src/main/java/com/blankj/base/BaseFragment.java b/lib/base/src/main/java/com/blankj/base/BaseFragment.java
index 2ff0a90913..354cb0e839 100644
--- a/lib/base/src/main/java/com/blankj/base/BaseFragment.java
+++ b/lib/base/src/main/java/com/blankj/base/BaseFragment.java
@@ -89,7 +89,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
             } else {
                 ft.show(this);
             }
-            ft.commitAllowingStateLoss();
+            ft.commitNowAllowingStateLoss();
         }
         Bundle bundle = getArguments();
         initData(bundle);
diff --git a/lib/subutil/src/main/java/com/blankj/subutil/util/BatteryUtils.java b/lib/subutil/src/main/java/com/blankj/subutil/util/BatteryUtils.java
index 0e2fc571b4..56e3f36c76 100644
--- a/lib/subutil/src/main/java/com/blankj/subutil/util/BatteryUtils.java
+++ b/lib/subutil/src/main/java/com/blankj/subutil/util/BatteryUtils.java
@@ -1,12 +1,14 @@
 package com.blankj.subutil.util;
 
-import android.annotation.SuppressLint;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.BatteryManager;
+import android.os.Build;
+import android.os.PowerManager;
 import android.support.annotation.IntDef;
+import android.support.annotation.RequiresApi;
 
 import com.blankj.utilcode.util.ThreadUtils;
 import com.blankj.utilcode.util.Utils;
@@ -37,6 +39,32 @@ public final class BatteryUtils {
         int FULL         = BatteryManager.BATTERY_STATUS_FULL;
     }
 
+    /**
+     * Return whether the app is on the device's power whitelist.
+     *
+     * @return {@code true}: yes
{@code false}: no + */ + @RequiresApi(api = Build.VERSION_CODES.M) + public static boolean isIgnoringBatteryOptimizations() { + return isIgnoringBatteryOptimizations(Utils.getApp().getPackageName()); + } + + /** + * Return whether the app is on the device's power whitelist. + * + * @return {@code true}: yes
{@code false}: no + */ + @RequiresApi(api = Build.VERSION_CODES.M) + public static boolean isIgnoringBatteryOptimizations(String pkgName) { + try { + PowerManager pm = (PowerManager) Utils.getApp().getSystemService(Context.POWER_SERVICE); + //noinspection ConstantConditions + return pm.isIgnoringBatteryOptimizations(pkgName); + } catch (Exception e) { + return true; + } + } + /** * Register the status of battery changed listener. * diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md index a50fef56c8..e8edeb5927 100644 --- a/lib/utilcode/README-CN.md +++ b/lib/utilcode/README-CN.md @@ -2,10 +2,10 @@ Gradle: ```groovy -implementation 'com.blankj:utilcode:1.30.5' +implementation 'com.blankj:utilcode:1.30.6' // if u use AndroidX, use the following -implementation 'com.blankj:utilcodex:1.30.5' +implementation 'com.blankj:utilcodex:1.30.6' ``` diff --git a/lib/utilcode/README.md b/lib/utilcode/README.md index 55ad2d880a..63f7a83ba7 100644 --- a/lib/utilcode/README.md +++ b/lib/utilcode/README.md @@ -2,10 +2,10 @@ Gradle: ```groovy -implementation 'com.blankj:utilcode:1.30.5' +implementation 'com.blankj:utilcode:1.30.6' // if u use AndroidX, use the following -implementation 'com.blankj:utilcodex:1.30.5' +implementation 'com.blankj:utilcodex:1.30.6' ``` diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/constant/RegexConstants.java b/lib/utilcode/src/main/java/com/blankj/utilcode/constant/RegexConstants.java index 2c85bf835f..02618da72b 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/constant/RegexConstants.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/constant/RegexConstants.java @@ -16,13 +16,14 @@ public final class RegexConstants { public static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$"; /** * Regex of exact mobile. - *

china mobile: 134(0-8), 135, 136, 137, 138, 139, 147, 150, 151, 152, 157, 158, 159, 165, 172, 178, 182, 183, 184, 187, 188, 198

- *

china unicom: 130, 131, 132, 145, 155, 156, 166, 167, 171, 175, 176, 185, 186

- *

china telecom: 133, 153, 162, 173, 177, 180, 181, 189, 199, 191

+ *

china mobile: 134(0-8), 135, 136, 137, 138, 139, 147, 150, 151, 152, 157, 158, 159, 165, 172, 178, 182, 183, 184, 187, 188, 195, 197, 198

+ *

china unicom: 130, 131, 132, 145, 155, 156, 166, 167, 175, 176, 185, 186, 196

+ *

china telecom: 133, 149, 153, 162, 173, 177, 180, 181, 189, 190, 191, 199

+ *

china broadcasting: 192

*

global star: 1349

- *

virtual operator: 170

+ *

virtual operator: 170, 171

*/ - public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[57])|(15[0-35-9])|(16[2567])|(17[01235-8])|(18[0-9])|(19[189]))\\d{8}$"; + 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. */ diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java index 5a185d47a1..cf902f085a 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java @@ -44,7 +44,7 @@ private ActivityUtils() { * * @param callbacks The callbacks. */ - public static void addActivityLifecycleCallbacks(final Utils.ActivityLifecycleCallbacks callbacks) { + public static void addActivityLifecycleCallbacks(@Nullable final Utils.ActivityLifecycleCallbacks callbacks) { UtilsBridge.addActivityLifecycleCallbacks(callbacks); } @@ -54,8 +54,8 @@ public static void addActivityLifecycleCallbacks(final Utils.ActivityLifecycleCa * @param activity The activity. * @param callbacks The callbacks. */ - public static void addActivityLifecycleCallbacks(final Activity activity, - final Utils.ActivityLifecycleCallbacks callbacks) { + public static void addActivityLifecycleCallbacks(@Nullable final Activity activity, + @Nullable final Utils.ActivityLifecycleCallbacks callbacks) { UtilsBridge.addActivityLifecycleCallbacks(activity, callbacks); } @@ -64,7 +64,7 @@ public static void addActivityLifecycleCallbacks(final Activity activity, * * @param callbacks The callbacks. */ - public static void removeActivityLifecycleCallbacks(final Utils.ActivityLifecycleCallbacks callbacks) { + public static void removeActivityLifecycleCallbacks(@Nullable final Utils.ActivityLifecycleCallbacks callbacks) { UtilsBridge.removeActivityLifecycleCallbacks(callbacks); } @@ -73,7 +73,7 @@ public static void removeActivityLifecycleCallbacks(final Utils.ActivityLifecycl * * @param activity The activity. */ - public static void removeActivityLifecycleCallbacks(final Activity activity) { + public static void removeActivityLifecycleCallbacks(@Nullable final Activity activity) { UtilsBridge.removeActivityLifecycleCallbacks(activity); } @@ -83,8 +83,8 @@ public static void removeActivityLifecycleCallbacks(final Activity activity) { * @param activity The activity. * @param callbacks The callbacks. */ - public static void removeActivityLifecycleCallbacks(final Activity activity, - final Utils.ActivityLifecycleCallbacks callbacks) { + public static void removeActivityLifecycleCallbacks(@Nullable final Activity activity, + @Nullable final Utils.ActivityLifecycleCallbacks callbacks) { UtilsBridge.removeActivityLifecycleCallbacks(activity, callbacks); } @@ -94,13 +94,15 @@ public static void removeActivityLifecycleCallbacks(final Activity activity, * @param context The context. * @return the activity by context. */ - public static Activity getActivityByContext(Context context) { + @Nullable + public static Activity getActivityByContext(@NonNull Context context) { Activity activity = getActivityByContextInner(context); if (!isActivityAlive(activity)) return null; return activity; } - private static Activity getActivityByContextInner(Context context) { + @Nullable + private static Activity getActivityByContextInner(@Nullable Context context) { if (context == null) return null; List list = new ArrayList<>(); while (context instanceof ContextWrapper) { @@ -122,7 +124,8 @@ private static Activity getActivityByContextInner(Context context) { return null; } - private static Activity getActivityFromDecorContext(Context context) { + @Nullable + private static Activity getActivityFromDecorContext(@Nullable Context context) { if (context == null) return null; if (context.getClass().getName().equals("com.android.internal.policy.DecorContext")) { try { @@ -1906,6 +1909,7 @@ public static void finishAllActivitiesExceptNewest(@AnimRes final int enterAnim, * @param activity The activity. * @return the icon of activity */ + @Nullable public static Drawable getActivityIcon(@NonNull final Activity activity) { return getActivityIcon(activity.getComponentName()); } @@ -1916,6 +1920,7 @@ public static Drawable getActivityIcon(@NonNull final Activity activity) { * @param clz The activity class. * @return the icon of activity */ + @Nullable public static Drawable getActivityIcon(@NonNull final Class clz) { return getActivityIcon(new ComponentName(Utils.getApp(), clz)); } @@ -1926,6 +1931,7 @@ public static Drawable getActivityIcon(@NonNull final Class * @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 { @@ -1942,6 +1948,7 @@ public static Drawable getActivityIcon(@NonNull final ComponentName activityName * @param activity The activity. * @return the logo of activity */ + @Nullable public static Drawable getActivityLogo(@NonNull final Activity activity) { return getActivityLogo(activity.getComponentName()); } @@ -1952,6 +1959,7 @@ public static Drawable getActivityLogo(@NonNull final Activity activity) { * @param clz The activity class. * @return the logo of activity */ + @Nullable public static Drawable getActivityLogo(@NonNull final Class clz) { return getActivityLogo(new ComponentName(Utils.getApp(), clz)); } @@ -1962,6 +1970,7 @@ public static Drawable getActivityLogo(@NonNull final Class * @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 { diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AdaptScreenUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AdaptScreenUtils.java index 3a5ec1f12b..1bf781d5d4 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AdaptScreenUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AdaptScreenUtils.java @@ -1,6 +1,7 @@ package com.blankj.utilcode.util; import android.content.res.Resources; +import android.support.annotation.NonNull; import android.util.DisplayMetrics; import java.lang.reflect.Field; @@ -26,7 +27,8 @@ private AdaptScreenUtils() { /** * Adapt for the horizontal screen, and call it in {@link android.app.Activity#getResources()}. */ - public static Resources adaptWidth(final Resources resources, final int designWidth) { + @NonNull + public static Resources adaptWidth(@NonNull final Resources resources, final int designWidth) { float newXdpi = (resources.getDisplayMetrics().widthPixels * 72f) / designWidth; applyDisplayMetrics(resources, newXdpi); return resources; @@ -35,14 +37,16 @@ public static Resources adaptWidth(final Resources resources, final int designWi /** * Adapt for the vertical screen, and call it in {@link android.app.Activity#getResources()}. */ - public static Resources adaptHeight(final Resources resources, final int designHeight) { + @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()}. */ - public static Resources adaptHeight(final Resources resources, final int designHeight, final boolean includeNavBar) { + @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; @@ -50,7 +54,7 @@ public static Resources adaptHeight(final Resources resources, final int designH return resources; } - private static int getNavBarHeight(final Resources 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); @@ -63,7 +67,8 @@ private static int getNavBarHeight(final Resources resources) { * @param resources The resources. * @return the resource */ - public static Resources closeAdapt(final Resources resources) { + @NonNull + public static Resources closeAdapt(@NonNull final Resources resources) { float newXdpi = Resources.getSystem().getDisplayMetrics().density * 72f; applyDisplayMetrics(resources, newXdpi); return resources; @@ -91,7 +96,7 @@ public static int px2Pt(final float pxValue) { return (int) (pxValue * 72 / metrics.xdpi + 0.5); } - private static void applyDisplayMetrics(final Resources resources, final float newXdpi) { + private static void applyDisplayMetrics(@NonNull final Resources resources, final float newXdpi) { resources.getDisplayMetrics().xdpi = newXdpi; Utils.getApp().getResources().getDisplayMetrics().xdpi = newXdpi; applyOtherDisplayMetrics(resources, newXdpi); diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ApiUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ApiUtils.java index f99bc77f19..d2a08bd812 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ApiUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ApiUtils.java @@ -1,6 +1,7 @@ package com.blankj.utilcode.util; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.Log; import java.lang.annotation.ElementType; @@ -47,14 +48,17 @@ private void registerImpl(Class implClass) { * @param The type. * @return the api */ + @Nullable public static T getApi(@NonNull final Class apiClass) { return getInstance().getApiInner(apiClass); } - public static void register(Class implClass) { + public static void register(@Nullable Class implClass) { + if (implClass == null) return; getInstance().registerImpl(implClass); } + @NonNull public static String toString_() { return getInstance().toString(); } diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java index b4884a3442..a8b65dfecf 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java @@ -13,6 +13,7 @@ import android.net.Uri; import android.os.Build; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.Log; import java.io.File; @@ -143,8 +144,14 @@ public static boolean isAppDebug() { */ public static boolean isAppDebug(final String packageName) { if (UtilsBridge.isSpace(packageName)) return false; - ApplicationInfo ai = Utils.getApp().getApplicationInfo(); - return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + 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; + } } /** @@ -167,7 +174,7 @@ public static boolean isAppSystem(final String packageName) { try { PackageManager pm = Utils.getApp().getPackageManager(); ApplicationInfo ai = pm.getApplicationInfo(packageName, 0); - return ai != null && (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + return (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return false; @@ -203,8 +210,6 @@ public static boolean isAppForeground(@NonNull final String pkgName) { */ public static boolean isAppRunning(final String pkgName) { if (UtilsBridge.isSpace(pkgName)) return false; - ApplicationInfo ai = Utils.getApp().getApplicationInfo(); - int uid = ai.uid; ActivityManager am = (ActivityManager) Utils.getApp().getSystemService(Context.ACTIVITY_SERVICE); if (am != null) { List taskInfo = am.getRunningTasks(Integer.MAX_VALUE); @@ -220,7 +225,7 @@ public static boolean isAppRunning(final String pkgName) { List serviceInfo = am.getRunningServices(Integer.MAX_VALUE); if (serviceInfo != null && serviceInfo.size() > 0) { for (ActivityManager.RunningServiceInfo aInfo : serviceInfo) { - if (uid == aInfo.uid) { + if (pkgName.equals(aInfo.service.getPackageName())) { return true; } } @@ -328,6 +333,7 @@ public static void exitApp() { * * @return the application's icon */ + @Nullable public static Drawable getAppIcon() { return getAppIcon(Utils.getApp().getPackageName()); } @@ -338,6 +344,7 @@ public static Drawable getAppIcon() { * @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 { @@ -382,6 +389,7 @@ public static int getAppIconId(final String packageName) { * * @return the application's package name */ + @NonNull public static String getAppPackageName() { return Utils.getApp().getPackageName(); } @@ -391,6 +399,7 @@ public static String getAppPackageName() { * * @return the application's name */ + @NonNull public static String getAppName() { return getAppName(Utils.getApp().getPackageName()); } @@ -401,12 +410,13 @@ public static String getAppName() { * @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 ? null : pi.applicationInfo.loadLabel(pm).toString(); + return pi == null ? "" : pi.applicationInfo.loadLabel(pm).toString(); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return ""; @@ -418,6 +428,7 @@ public static String getAppName(final String packageName) { * * @return the application's path */ + @NonNull public static String getAppPath() { return getAppPath(Utils.getApp().getPackageName()); } @@ -428,12 +439,13 @@ public static String getAppPath() { * @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 ? null : pi.applicationInfo.sourceDir; + return pi == null ? "" : pi.applicationInfo.sourceDir; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return ""; @@ -445,6 +457,7 @@ public static String getAppPath(final String packageName) { * * @return the application's version name */ + @NonNull public static String getAppVersionName() { return getAppVersionName(Utils.getApp().getPackageName()); } @@ -455,12 +468,13 @@ public static String getAppVersionName() { * @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 ? null : pi.versionName; + return pi == null ? "" : pi.versionName; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return ""; @@ -499,6 +513,7 @@ public static int getAppVersionCode(final String packageName) { * * @return the application's signature */ + @Nullable public static Signature[] getAppSignatures() { return getAppSignatures(Utils.getApp().getPackageName()); } @@ -509,6 +524,7 @@ public static Signature[] getAppSignatures() { * @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 { @@ -541,6 +557,7 @@ public static Signature[] getAppSignatures(final String packageName) { * @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(); @@ -567,6 +584,7 @@ public static Signature[] getAppSignatures(final File file) { * * @return the application's signature for SHA1 value */ + @NonNull public static List getAppSignaturesSHA1() { return getAppSignaturesSHA1(Utils.getApp().getPackageName()); } @@ -577,6 +595,7 @@ public static List getAppSignaturesSHA1() { * @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"); } @@ -586,6 +605,7 @@ public static List getAppSignaturesSHA1(final String packageName) { * * @return the application's signature for SHA256 value */ + @NonNull public static List getAppSignaturesSHA256() { return getAppSignaturesSHA256(Utils.getApp().getPackageName()); } @@ -596,6 +616,7 @@ public static List getAppSignaturesSHA256() { * @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"); } @@ -605,6 +626,7 @@ public static List getAppSignaturesSHA256(final String packageName) { * * @return the application's signature for MD5 value */ + @NonNull public static List getAppSignaturesMD5() { return getAppSignaturesMD5(Utils.getApp().getPackageName()); } @@ -615,6 +637,7 @@ public static List getAppSignaturesMD5() { * @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"); } @@ -670,6 +693,7 @@ private static List getAppSignaturesHash(final String packageName, final * * @return the application's information */ + @Nullable public static AppInfo getAppInfo() { return getAppInfo(Utils.getApp().getPackageName()); } @@ -689,6 +713,7 @@ public static AppInfo getAppInfo() { * @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(); @@ -705,6 +730,7 @@ public static AppInfo getAppInfo(final String packageName) { * * @return the applications' information */ + @NonNull public static List getAppsInfo() { List list = new ArrayList<>(); PackageManager pm = Utils.getApp().getPackageManager(); @@ -723,6 +749,7 @@ public static List getAppsInfo() { * * @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()); @@ -733,6 +760,7 @@ public static AppUtils.AppInfo getApkInfo(final File apkFile) { * * @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(); @@ -747,13 +775,16 @@ public static AppUtils.AppInfo getApkInfo(final String apkFilePath) { private static AppInfo getBean(final PackageManager pm, final PackageInfo pi) { if (pi == null) return null; - ApplicationInfo ai = pi.applicationInfo; + 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, false); + } String name = ai.loadLabel(pm).toString(); Drawable icon = ai.loadIcon(pm); String packagePath = ai.sourceDir; - String versionName = pi.versionName; - int versionCode = pi.versionCode; boolean isSystem = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != 0; return new AppInfo(packageName, name, icon, packagePath, versionName, versionCode, isSystem); } @@ -839,6 +870,7 @@ public AppInfo(String packageName, String name, Drawable icon, String packagePat } @Override + @NonNull public String toString() { return "{" + "\n pkg name: " + getPackageName() + diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ArrayUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ArrayUtils.java index 08b6142276..5ab5c431fd 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ArrayUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ArrayUtils.java @@ -1,5 +1,8 @@ package com.blankj.utilcode.util; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; @@ -30,39 +33,47 @@ private ArrayUtils() { * @param array The array. * @return a new array only of those given elements. */ - @SafeVarargs + @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; } @@ -73,7 +84,7 @@ public static boolean[] newBooleanArray(boolean... array) { * @param array The array. * @return {@code true}: yes
{@code false}: no */ - public static boolean isEmpty(Object array) { + public static boolean isEmpty(@Nullable Object array) { return getLength(array) == 0; } @@ -83,12 +94,12 @@ public static boolean isEmpty(Object array) { * @param array The array. * @return the size of array */ - public static int getLength(Object array) { + public static int getLength(@Nullable Object array) { if (array == null) return 0; return Array.getLength(array); } - public static boolean isSameLength(Object array1, Object array2) { + public static boolean isSameLength(@Nullable Object array1, @Nullable Object array2) { return getLength(array1) == getLength(array2); } @@ -99,7 +110,8 @@ public static boolean isSameLength(Object array1, Object array2) { * @param index The index into the array. * @return the value of the specified index of the array */ - public static Object get(Object array, int index) { + @Nullable + public static Object get(@Nullable Object array, int index) { return get(array, index, null); } @@ -111,7 +123,8 @@ public static Object get(Object array, int index) { * @param defaultValue The default value. * @return the value of the specified index of the array */ - public static Object get(Object array, int index, Object defaultValue) { + @Nullable + public static Object get(@Nullable Object array, int index, @Nullable Object defaultValue) { if (array == null) return defaultValue; try { return Array.get(array, index); @@ -127,7 +140,7 @@ public static Object get(Object array, int index, Object defaultValue) { * @param index The index into the array. * @param value The new value of the indexed component. */ - public static void set(Object array, int index, Object value) { + public static void set(@Nullable Object array, int index, @Nullable Object value) { if (array == null) return; Array.set(array, index, value); } @@ -139,7 +152,7 @@ public static void set(Object array, int index, Object value) { * @param a2 The other array. * @return {@code true}: yes
{@code false}: no */ - public static boolean equals(Object[] a, Object[] a2) { + public static boolean equals(@Nullable Object[] a, @Nullable Object[] a2) { return Arrays.deepEquals(a, a2); } @@ -344,52 +357,62 @@ public static void reverse(boolean[] array) { * @param array the array to shallow clone, may be null * @return the cloned array, null if null input */ - public static T[] copy(T[] array) { + @Nullable + public static T[] copy(@Nullable T[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static long[] copy(long[] array) { + @Nullable + public static long[] copy(@Nullable long[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static int[] copy(int[] array) { + @Nullable + public static int[] copy(@Nullable int[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static short[] copy(short[] array) { + @Nullable + public static short[] copy(@Nullable short[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static char[] copy(char[] array) { + @Nullable + public static char[] copy(@Nullable char[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static byte[] copy(byte[] array) { + @Nullable + public static byte[] copy(@Nullable byte[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static double[] copy(double[] array) { + @Nullable + public static double[] copy(@Nullable double[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static float[] copy(float[] array) { + @Nullable + public static float[] copy(@Nullable float[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - public static boolean[] copy(boolean[] array) { + @Nullable + public static boolean[] copy(@Nullable boolean[] array) { if (array == null) return null; return subArray(array, 0, array.length); } - private static Object realCopy(Object array) { + @Nullable + private static Object realCopy(@Nullable Object array) { if (array == null) return null; return realSubArray(array, 0, getLength(array)); } @@ -398,44 +421,54 @@ private static Object realCopy(Object array) { // subArray /////////////////////////////////////////////////////////////////////////// - public static T[] subArray(T[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static T[] subArray(@Nullable T[] array, int startIndexInclusive, int endIndexExclusive) { //noinspection unchecked return (T[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static long[] subArray(long[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static long[] subArray(@Nullable long[] array, int startIndexInclusive, int endIndexExclusive) { return (long[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static int[] subArray(int[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static int[] subArray(@Nullable int[] array, int startIndexInclusive, int endIndexExclusive) { return (int[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static short[] subArray(short[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static short[] subArray(@Nullable short[] array, int startIndexInclusive, int endIndexExclusive) { return (short[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static char[] subArray(char[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static char[] subArray(@Nullable char[] array, int startIndexInclusive, int endIndexExclusive) { return (char[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static byte[] subArray(byte[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static byte[] subArray(@Nullable byte[] array, int startIndexInclusive, int endIndexExclusive) { return (byte[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static double[] subArray(double[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static double[] subArray(@Nullable double[] array, int startIndexInclusive, int endIndexExclusive) { return (double[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static float[] subArray(float[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static float[] subArray(@Nullable float[] array, int startIndexInclusive, int endIndexExclusive) { return (float[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - public static boolean[] subArray(boolean[] array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + public static boolean[] subArray(@Nullable boolean[] array, int startIndexInclusive, int endIndexExclusive) { return (boolean[]) realSubArray(array, startIndexInclusive, endIndexExclusive); } - private static Object realSubArray(Object array, int startIndexInclusive, int endIndexExclusive) { + @Nullable + private static Object realSubArray(@Nullable Object array, int startIndexInclusive, int endIndexExclusive) { if (array == null) { return null; } @@ -482,44 +515,54 @@ private static Object realSubArray(Object array, int startIndexInclusive, int en * @param element the object to realAdd * @return A new array containing the existing elements plus the new element */ - public static T[] add(T[] array, T 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); } - public static boolean[] add(boolean[] array, boolean element) { + @NonNull + public static boolean[] add(@Nullable boolean[] array, boolean element) { return (boolean[]) realAddOne(array, element, Boolean.TYPE); } - public static byte[] add(byte[] array, byte element) { + @NonNull + public static byte[] add(@Nullable byte[] array, byte element) { return (byte[]) realAddOne(array, element, Byte.TYPE); } - public static char[] add(char[] array, char element) { + @NonNull + public static char[] add(@Nullable char[] array, char element) { return (char[]) realAddOne(array, element, Character.TYPE); } - public static double[] add(double[] array, double element) { + @NonNull + public static double[] add(@Nullable double[] array, double element) { return (double[]) realAddOne(array, element, Double.TYPE); } - public static float[] add(float[] array, float element) { + @NonNull + public static float[] add(@Nullable float[] array, float element) { return (float[]) realAddOne(array, element, Float.TYPE); } - public static int[] add(int[] array, int element) { + @NonNull + public static int[] add(@Nullable int[] array, int element) { return (int[]) realAddOne(array, element, Integer.TYPE); } - public static long[] add(long[] array, long element) { + @NonNull + public static long[] add(@Nullable long[] array, long element) { return (long[]) realAddOne(array, element, Long.TYPE); } - public static short[] add(short[] array, short element) { + @NonNull + public static short[] add(@Nullable short[] array, short element) { return (short[]) realAddOne(array, element, Short.TYPE); } - private static Object realAddOne(Object array, Object element, Class newArrayComponentType) { + @NonNull + private static Object realAddOne(@Nullable Object array, @Nullable Object element, Class newArrayComponentType) { Object newArray; int arrayLength = 0; if (array != null) { @@ -553,43 +596,52 @@ private static Object realAddOne(Object array, Object element, Class newArrayCom * @return The new array, null if null array inputs. * The type of the new array is the type of the first array. */ - public static T[] add(T[] array1, T[] array2) { + @Nullable + public static T[] add(@Nullable T[] array1, @Nullable T[] array2) { return (T[]) realAddArr(array1, array2); } - public static boolean[] add(boolean[] array1, boolean[] array2) { + @Nullable + public static boolean[] add(@Nullable boolean[] array1, @Nullable boolean[] array2) { return (boolean[]) realAddArr(array1, array2); } - public static char[] add(char[] array1, char[] array2) { + @Nullable + public static char[] add(@Nullable char[] array1, @Nullable char[] array2) { return (char[]) realAddArr(array1, array2); } - public static byte[] add(byte[] array1, byte[] array2) { + @Nullable + public static byte[] add(@Nullable byte[] array1, @Nullable byte[] array2) { return (byte[]) realAddArr(array1, array2); } - public static short[] add(short[] array1, short[] array2) { + @Nullable + public static short[] add(@Nullable short[] array1, @Nullable short[] array2) { return (short[]) realAddArr(array1, array2); } - public static int[] add(int[] array1, int[] array2) { + @Nullable + public static int[] add(@Nullable int[] array1, @Nullable int[] array2) { return (int[]) realAddArr(array1, array2); } - public static long[] add(long[] array1, long[] array2) { + @Nullable + public static long[] add(@Nullable long[] array1, @Nullable long[] array2) { return (long[]) realAddArr(array1, array2); } - public static float[] add(float[] array1, float[] array2) { + @Nullable + public static float[] add(@Nullable float[] array1, @Nullable float[] array2) { return (float[]) realAddArr(array1, array2); } - public static double[] add(double[] array1, double[] array2) { + @Nullable + public static double[] add(@Nullable double[] array1, @Nullable double[] array2) { return (double[]) realAddArr(array1, array2); } - private static Object realAddArr(Object array1, Object array2) { + private static Object realAddArr(@Nullable Object array1, @Nullable Object array2) { if (array1 == null && array2 == null) return null; if (array1 == null) { return realCopy(array2); @@ -619,11 +671,11 @@ private static Object realAddArr(Object array1, Object array2) { * whose component type is the same as the element.

* *
-     * ArrayUtils.add(null, 0, null)      = [null]
-     * ArrayUtils.add(null, 0, "a")       = ["a"]
-     * ArrayUtils.add(["a"], 1, null)     = ["a", null]
-     * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
-     * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
+     * ArrayUtils.add(null, 0, null)        = null
+     * ArrayUtils.add(null, 0, ["a"])       = ["a"]
+     * ArrayUtils.add(["a"], 1, null)       = ["a"]
+     * ArrayUtils.add(["a"], 1, ["b"])      = ["a", "b"]
+     * ArrayUtils.add(["a", "b"], 2, ["c"]) = ["a", "b", "c"]
      * 
* * @param array1 the array to realAdd the element to, may be null @@ -633,51 +685,76 @@ private static Object realAddArr(Object array1, Object array2) { * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index > array.length). */ - public static T[] add(T[] array1, int index, T[] array2) { + @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 (T[]) new Object[]{null}; + return null; } return (T[]) realAddArr(array1, index, array2, clss); } - public static boolean[] add(boolean[] array1, int index, boolean[] array2) { - return (boolean[]) realAddArr(array1, index, array2, Boolean.TYPE); + @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(char[] array1, int index, char[] array2) { - return (char[]) realAddArr(array1, index, array2, Character.TYPE); + 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; } - public static byte[] add(byte[] array1, int index, byte[] array2) { - return (byte[]) realAddArr(array1, index, array2, Byte.TYPE); + @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; } - public static short[] add(short[] array1, int index, short[] array2) { - return (short[]) realAddArr(array1, index, array2, Short.TYPE); + @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; } - public static int[] add(int[] array1, int index, int[] array2) { - return (int[]) realAddArr(array1, index, array2, Integer.TYPE); + @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; } - public static long[] add(long[] array1, int index, long[] array2) { - return (long[]) realAddArr(array1, index, array2, Long.TYPE); + @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; } - public static float[] add(float[] array1, int index, float[] array2) { - return (float[]) realAddArr(array1, index, array2, Float.TYPE); + @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; } - public static double[] add(double[] array1, int index, double[] array2) { - return (double[]) realAddArr(array1, index, array2, Double.TYPE); + @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; } - private static Object realAddArr(Object array1, int index, Object array2, Class clss) { + @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); @@ -736,7 +813,8 @@ private static Object realAddArr(Object array1, int index, Object array2, Class * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index > array.length). */ - public static T[] add(T[] array, int index, T element) { + @NonNull + public static T[] add(@Nullable T[] array, int index, @Nullable T element) { Class clss; if (array != null) { clss = array.getClass().getComponentType(); @@ -748,39 +826,48 @@ public static T[] add(T[] array, int index, T element) { return (T[]) realAdd(array, index, element, clss); } - public static boolean[] add(boolean[] array, int index, boolean element) { + @NonNull + public static boolean[] add(@Nullable boolean[] array, int index, boolean element) { return (boolean[]) realAdd(array, index, element, Boolean.TYPE); } - public static char[] add(char[] array, int index, char element) { + @NonNull + public static char[] add(@Nullable char[] array, int index, char element) { return (char[]) realAdd(array, index, element, Character.TYPE); } - public static byte[] add(byte[] array, int index, byte element) { + @NonNull + public static byte[] add(@Nullable byte[] array, int index, byte element) { return (byte[]) realAdd(array, index, element, Byte.TYPE); } - public static short[] add(short[] array, int index, short element) { + @NonNull + public static short[] add(@Nullable short[] array, int index, short element) { return (short[]) realAdd(array, index, element, Short.TYPE); } - public static int[] add(int[] array, int index, int element) { + @NonNull + public static int[] add(@Nullable int[] array, int index, int element) { return (int[]) realAdd(array, index, element, Integer.TYPE); } - public static long[] add(long[] array, int index, long element) { + @NonNull + public static long[] add(@Nullable long[] array, int index, long element) { return (long[]) realAdd(array, index, element, Long.TYPE); } - public static float[] add(float[] array, int index, float element) { + @NonNull + public static float[] add(@Nullable float[] array, int index, float element) { return (float[]) realAdd(array, index, element, Float.TYPE); } - public static double[] add(double[] array, int index, double element) { + @NonNull + public static double[] add(@Nullable double[] array, int index, double element) { return (double[]) realAdd(array, index, element, Double.TYPE); } - private static Object realAdd(Object array, int index, Object element, Class clss) { + @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"); @@ -826,15 +913,16 @@ private static Object realAdd(Object array, int index, Object element, Class cls * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"] *
* - * @param array the array to remove the element from, may not be null + * @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), or if the array is null. - * @since 2.1 + * (index < 0 || index >= array.length) */ - public static Object[] remove(Object[] array, int index) { + @Nullable + public static Object[] remove(@Nullable Object[] array, int index) { + if (array == null) return null; return (Object[]) remove((Object) array, index); } @@ -861,9 +949,9 @@ public static Object[] remove(Object[] array, int index) { * @param element the element to be removed * @return A new array containing the existing elements except the first * occurrence of the specified element. - * @since 2.1 */ - public static Object[] removeElement(Object[] array, Object 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); @@ -871,11 +959,14 @@ public static Object[] removeElement(Object[] array, Object element) { return remove(array, index); } - public static boolean[] remove(boolean[] array, int index) { + @Nullable + public static boolean[] remove(@Nullable boolean[] array, int index) { + if (array == null) return null; return (boolean[]) remove((Object) array, index); } - public static boolean[] removeElement(boolean[] array, boolean element) { + @Nullable + public static boolean[] removeElement(@Nullable boolean[] array, boolean element) { int index = indexOf(array, element); if (index == INDEX_NOT_FOUND) { return copy(array); @@ -883,11 +974,14 @@ public static boolean[] removeElement(boolean[] array, boolean element) { return remove(array, index); } - public static byte[] remove(byte[] array, int index) { + @Nullable + public static byte[] remove(@Nullable byte[] array, int index) { + if (array == null) return null; return (byte[]) remove((Object) array, index); } - public static byte[] removeElement(byte[] array, byte element) { + @Nullable + public static byte[] removeElement(@Nullable byte[] array, byte element) { int index = indexOf(array, element); if (index == INDEX_NOT_FOUND) { return copy(array); @@ -895,11 +989,14 @@ public static byte[] removeElement(byte[] array, byte element) { return remove(array, index); } - public static char[] remove(char[] array, int index) { + @Nullable + public static char[] remove(@Nullable char[] array, int index) { + if (array == null) return null; return (char[]) remove((Object) array, index); } - public static char[] removeElement(char[] array, char element) { + @Nullable + public static char[] removeElement(@Nullable char[] array, char element) { int index = indexOf(array, element); if (index == INDEX_NOT_FOUND) { return copy(array); @@ -907,23 +1004,30 @@ public static char[] removeElement(char[] array, char element) { return remove(array, index); } - public static double[] remove(double[] array, int index) { + @Nullable + public static double[] remove(@Nullable double[] array, int index) { + if (array == null) return null; return (double[]) remove((Object) array, index); } - public static double[] removeElement(double[] array, double element) { + @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); } - public static float[] remove(float[] array, int index) { + @Nullable + public static float[] remove(@Nullable float[] array, int index) { + if (array == null) return null; return (float[]) remove((Object) array, index); } - public static float[] removeElement(float[] array, float element) { + @Nullable + public static float[] removeElement(@Nullable float[] array, float element) { int index = indexOf(array, element); if (index == INDEX_NOT_FOUND) { return copy(array); @@ -931,11 +1035,14 @@ public static float[] removeElement(float[] array, float element) { return remove(array, index); } - public static int[] remove(int[] array, int index) { + @Nullable + public static int[] remove(@Nullable int[] array, int index) { + if (array == null) return null; return (int[]) remove((Object) array, index); } - public static int[] removeElement(int[] array, int element) { + @Nullable + public static int[] removeElement(@Nullable int[] array, int element) { int index = indexOf(array, element); if (index == INDEX_NOT_FOUND) { return copy(array); @@ -943,11 +1050,14 @@ public static int[] removeElement(int[] array, int element) { return remove(array, index); } - public static long[] remove(long[] array, int index) { + @Nullable + public static long[] remove(@Nullable long[] array, int index) { + if (array == null) return null; return (long[]) remove((Object) array, index); } - public static long[] removeElement(long[] array, long element) { + @Nullable + public static long[] removeElement(@Nullable long[] array, long element) { int index = indexOf(array, element); if (index == INDEX_NOT_FOUND) { return copy(array); @@ -955,11 +1065,14 @@ public static long[] removeElement(long[] array, long element) { return remove(array, index); } - public static short[] remove(short[] array, int index) { + @Nullable + public static short[] remove(@Nullable short[] array, int index) { + if (array == null) return null; return (short[]) remove((Object) array, index); } - public static short[] removeElement(short[] array, short element) { + @Nullable + public static short[] removeElement(@Nullable short[] array, short element) { int index = indexOf(array, element); if (index == INDEX_NOT_FOUND) { return copy(array); @@ -967,7 +1080,8 @@ public static short[] removeElement(short[] array, short element) { return remove(array, index); } - private static Object remove(Object array, int 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); @@ -986,11 +1100,11 @@ private static Object remove(Object array, int index) { // object indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(Object[] array, Object objectToFind) { + public static int indexOf(@Nullable Object[] array, @Nullable Object objectToFind) { return indexOf(array, objectToFind, 0); } - public static int indexOf(Object[] array, final Object objectToFind, int startIndex) { + public static int indexOf(@Nullable Object[] array, @Nullable final Object objectToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1013,11 +1127,11 @@ public static int indexOf(Object[] array, final Object objectToFind, int startIn return INDEX_NOT_FOUND; } - public static int lastIndexOf(Object[] array, Object objectToFind) { + public static int lastIndexOf(@Nullable Object[] array, @Nullable Object objectToFind) { return lastIndexOf(array, objectToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(Object[] array, Object objectToFind, int startIndex) { + public static int lastIndexOf(@Nullable Object[] array, @Nullable Object objectToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1042,7 +1156,7 @@ public static int lastIndexOf(Object[] array, Object objectToFind, int startInde return INDEX_NOT_FOUND; } - public static boolean contains(Object[] array, Object objectToFind) { + public static boolean contains(@Nullable Object[] array, @Nullable Object objectToFind) { return indexOf(array, objectToFind) != INDEX_NOT_FOUND; } @@ -1050,11 +1164,11 @@ public static boolean contains(Object[] array, Object objectToFind) { // long indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(long[] array, long valueToFind) { + public static int indexOf(@Nullable long[] array, long valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(long[] array, long valueToFind, int startIndex) { + public static int indexOf(@Nullable long[] array, long valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1069,11 +1183,11 @@ public static int indexOf(long[] array, long valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static int lastIndexOf(long[] array, long valueToFind) { + public static int lastIndexOf(@Nullable long[] array, long valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(long[] array, long valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable long[] array, long valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1090,7 +1204,7 @@ public static int lastIndexOf(long[] array, long valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static boolean contains(long[] array, long valueToFind) { + public static boolean contains(@Nullable long[] array, long valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } @@ -1098,11 +1212,11 @@ public static boolean contains(long[] array, long valueToFind) { // int indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(int[] array, int valueToFind) { + public static int indexOf(@Nullable int[] array, int valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(int[] array, int valueToFind, int startIndex) { + public static int indexOf(@Nullable int[] array, int valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1117,11 +1231,11 @@ public static int indexOf(int[] array, int valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static int lastIndexOf(int[] array, int valueToFind) { + public static int lastIndexOf(@Nullable int[] array, int valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(int[] array, int valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable int[] array, int valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1138,7 +1252,7 @@ public static int lastIndexOf(int[] array, int valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static boolean contains(int[] array, int valueToFind) { + public static boolean contains(@Nullable int[] array, int valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } @@ -1146,11 +1260,11 @@ public static boolean contains(int[] array, int valueToFind) { // short indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(short[] array, short valueToFind) { + public static int indexOf(@Nullable short[] array, short valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(short[] array, short valueToFind, int startIndex) { + public static int indexOf(@Nullable short[] array, short valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1165,11 +1279,11 @@ public static int indexOf(short[] array, short valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static int lastIndexOf(short[] array, short valueToFind) { + public static int lastIndexOf(@Nullable short[] array, short valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(short[] array, short valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable short[] array, short valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1186,7 +1300,7 @@ public static int lastIndexOf(short[] array, short valueToFind, int startIndex) return INDEX_NOT_FOUND; } - public static boolean contains(short[] array, short valueToFind) { + public static boolean contains(@Nullable short[] array, short valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } @@ -1194,11 +1308,11 @@ public static boolean contains(short[] array, short valueToFind) { // char indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(char[] array, char valueToFind) { + public static int indexOf(@Nullable char[] array, char valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(char[] array, char valueToFind, int startIndex) { + public static int indexOf(@Nullable char[] array, char valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1213,11 +1327,11 @@ public static int indexOf(char[] array, char valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static int lastIndexOf(char[] array, char valueToFind) { + public static int lastIndexOf(@Nullable char[] array, char valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(char[] array, char valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable char[] array, char valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1234,7 +1348,7 @@ public static int lastIndexOf(char[] array, char valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static boolean contains(char[] array, char valueToFind) { + public static boolean contains(@Nullable char[] array, char valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } @@ -1242,11 +1356,11 @@ public static boolean contains(char[] array, char valueToFind) { // byte indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(byte[] array, byte valueToFind) { + public static int indexOf(@Nullable byte[] array, byte valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(byte[] array, byte valueToFind, int startIndex) { + public static int indexOf(@Nullable byte[] array, byte valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1261,11 +1375,11 @@ public static int indexOf(byte[] array, byte valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static int lastIndexOf(byte[] array, byte valueToFind) { + public static int lastIndexOf(@Nullable byte[] array, byte valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(byte[] array, byte valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable byte[] array, byte valueToFind, int startIndex) { if (array == null) { return INDEX_NOT_FOUND; } @@ -1282,7 +1396,7 @@ public static int lastIndexOf(byte[] array, byte valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static boolean contains(byte[] array, byte valueToFind) { + public static boolean contains(@Nullable byte[] array, byte valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } @@ -1290,15 +1404,15 @@ public static boolean contains(byte[] array, byte valueToFind) { // double indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(double[] array, double valueToFind) { + public static int indexOf(@Nullable double[] array, double valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(double[] array, double valueToFind, double tolerance) { + public static int indexOf(@Nullable double[] array, double valueToFind, double tolerance) { return indexOf(array, valueToFind, 0, tolerance); } - public static int indexOf(double[] array, double valueToFind, int startIndex) { + public static int indexOf(@Nullable double[] array, double valueToFind, int startIndex) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1313,7 +1427,7 @@ public static int indexOf(double[] array, double valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static int indexOf(double[] array, double valueToFind, int startIndex, double tolerance) { + public static int indexOf(@Nullable double[] array, double valueToFind, int startIndex, double tolerance) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1330,15 +1444,15 @@ public static int indexOf(double[] array, double valueToFind, int startIndex, do return INDEX_NOT_FOUND; } - public static int lastIndexOf(double[] array, double valueToFind) { + public static int lastIndexOf(@Nullable double[] array, double valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(double[] array, double valueToFind, double tolerance) { + public static int lastIndexOf(@Nullable double[] array, double valueToFind, double tolerance) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance); } - public static int lastIndexOf(double[] array, double valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable double[] array, double valueToFind, int startIndex) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1355,7 +1469,7 @@ public static int lastIndexOf(double[] array, double valueToFind, int startIndex return INDEX_NOT_FOUND; } - public static int lastIndexOf(double[] array, double valueToFind, int startIndex, double tolerance) { + public static int lastIndexOf(@Nullable double[] array, double valueToFind, int startIndex, double tolerance) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1374,11 +1488,11 @@ public static int lastIndexOf(double[] array, double valueToFind, int startIndex return INDEX_NOT_FOUND; } - public static boolean contains(double[] array, double valueToFind) { + public static boolean contains(@Nullable double[] array, double valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } - public static boolean contains(double[] array, double valueToFind, double tolerance) { + public static boolean contains(@Nullable double[] array, double valueToFind, double tolerance) { return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND; } @@ -1386,11 +1500,11 @@ public static boolean contains(double[] array, double valueToFind, double tolera // float indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(float[] array, float valueToFind) { + public static int indexOf(@Nullable float[] array, float valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(float[] array, float valueToFind, int startIndex) { + public static int indexOf(@Nullable float[] array, float valueToFind, int startIndex) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1405,11 +1519,11 @@ public static int indexOf(float[] array, float valueToFind, int startIndex) { return INDEX_NOT_FOUND; } - public static int lastIndexOf(float[] array, float valueToFind) { + public static int lastIndexOf(@Nullable float[] array, float valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(float[] array, float valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable float[] array, float valueToFind, int startIndex) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1426,7 +1540,7 @@ public static int lastIndexOf(float[] array, float valueToFind, int startIndex) return INDEX_NOT_FOUND; } - public static boolean contains(float[] array, float valueToFind) { + public static boolean contains(@Nullable float[] array, float valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } @@ -1434,11 +1548,11 @@ public static boolean contains(float[] array, float valueToFind) { // bool indexOf /////////////////////////////////////////////////////////////////////////// - public static int indexOf(boolean[] array, boolean valueToFind) { + public static int indexOf(@Nullable boolean[] array, boolean valueToFind) { return indexOf(array, valueToFind, 0); } - public static int indexOf(boolean[] array, boolean valueToFind, int startIndex) { + public static int indexOf(@Nullable boolean[] array, boolean valueToFind, int startIndex) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1453,11 +1567,11 @@ public static int indexOf(boolean[] array, boolean valueToFind, int startIndex) return INDEX_NOT_FOUND; } - public static int lastIndexOf(boolean[] array, boolean valueToFind) { + public static int lastIndexOf(@Nullable boolean[] array, boolean valueToFind) { return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - public static int lastIndexOf(boolean[] array, boolean valueToFind, int startIndex) { + public static int lastIndexOf(@Nullable boolean[] array, boolean valueToFind, int startIndex) { if (ArrayUtils.isEmpty(array)) { return INDEX_NOT_FOUND; } @@ -1474,7 +1588,7 @@ public static int lastIndexOf(boolean[] array, boolean valueToFind, int startInd return INDEX_NOT_FOUND; } - public static boolean contains(boolean[] array, boolean valueToFind) { + public static boolean contains(@Nullable boolean[] array, boolean valueToFind) { return indexOf(array, valueToFind) != INDEX_NOT_FOUND; } @@ -1482,7 +1596,8 @@ public static boolean contains(boolean[] array, boolean valueToFind) { // char converters /////////////////////////////////////////////////////////////////////////// - public static char[] toPrimitive(Character[] array) { + @Nullable + public static char[] toPrimitive(@Nullable Character[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1495,7 +1610,8 @@ public static char[] toPrimitive(Character[] array) { return result; } - public static char[] toPrimitive(Character[] array, char valueForNull) { + @Nullable + public static char[] toPrimitive(@Nullable Character[] array, char valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1509,7 +1625,8 @@ public static char[] toPrimitive(Character[] array, char valueForNull) { return result; } - public static Character[] toObject(char[] array) { + @Nullable + public static Character[] toObject(@Nullable char[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1526,7 +1643,8 @@ public static Character[] toObject(char[] array) { // long converters /////////////////////////////////////////////////////////////////////////// - public static long[] toPrimitive(Long[] array) { + @Nullable + public static long[] toPrimitive(@Nullable Long[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1539,7 +1657,8 @@ public static long[] toPrimitive(Long[] array) { return result; } - public static long[] toPrimitive(Long[] array, long valueForNull) { + @Nullable + public static long[] toPrimitive(@Nullable Long[] array, long valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1553,7 +1672,8 @@ public static long[] toPrimitive(Long[] array, long valueForNull) { return result; } - public static Long[] toObject(long[] array) { + @Nullable + public static Long[] toObject(@Nullable long[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1570,7 +1690,8 @@ public static Long[] toObject(long[] array) { // int converters /////////////////////////////////////////////////////////////////////////// - public static int[] toPrimitive(Integer[] array) { + @Nullable + public static int[] toPrimitive(@Nullable Integer[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1583,7 +1704,8 @@ public static int[] toPrimitive(Integer[] array) { return result; } - public static int[] toPrimitive(Integer[] array, int valueForNull) { + @Nullable + public static int[] toPrimitive(@Nullable Integer[] array, int valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1597,7 +1719,8 @@ public static int[] toPrimitive(Integer[] array, int valueForNull) { return result; } - public static Integer[] toObject(int[] array) { + @Nullable + public static Integer[] toObject(@Nullable int[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1614,7 +1737,8 @@ public static Integer[] toObject(int[] array) { // short converters /////////////////////////////////////////////////////////////////////////// - public static short[] toPrimitive(Short[] array) { + @Nullable + public static short[] toPrimitive(@Nullable Short[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1627,7 +1751,8 @@ public static short[] toPrimitive(Short[] array) { return result; } - public static short[] toPrimitive(Short[] array, short valueForNull) { + @Nullable + public static short[] toPrimitive(@Nullable Short[] array, short valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1641,7 +1766,8 @@ public static short[] toPrimitive(Short[] array, short valueForNull) { return result; } - public static Short[] toObject(short[] array) { + @Nullable + public static Short[] toObject(@Nullable short[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1658,7 +1784,8 @@ public static Short[] toObject(short[] array) { // byte converters /////////////////////////////////////////////////////////////////////////// - public static byte[] toPrimitive(Byte[] array) { + @Nullable + public static byte[] toPrimitive(@Nullable Byte[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1671,7 +1798,8 @@ public static byte[] toPrimitive(Byte[] array) { return result; } - public static byte[] toPrimitive(Byte[] array, byte valueForNull) { + @Nullable + public static byte[] toPrimitive(@Nullable Byte[] array, byte valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1685,7 +1813,8 @@ public static byte[] toPrimitive(Byte[] array, byte valueForNull) { return result; } - public static Byte[] toObject(byte[] array) { + @Nullable + public static Byte[] toObject(@Nullable byte[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1702,7 +1831,8 @@ public static Byte[] toObject(byte[] array) { // double converters /////////////////////////////////////////////////////////////////////////// - public static double[] toPrimitive(Double[] array) { + @Nullable + public static double[] toPrimitive(@Nullable Double[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1715,7 +1845,8 @@ public static double[] toPrimitive(Double[] array) { return result; } - public static double[] toPrimitive(Double[] array, double valueForNull) { + @Nullable + public static double[] toPrimitive(@Nullable Double[] array, double valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1729,7 +1860,8 @@ public static double[] toPrimitive(Double[] array, double valueForNull) { return result; } - public static Double[] toObject(double[] array) { + @Nullable + public static Double[] toObject(@Nullable double[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1746,7 +1878,8 @@ public static Double[] toObject(double[] array) { // float converters /////////////////////////////////////////////////////////////////////////// - public static float[] toPrimitive(Float[] array) { + @Nullable + public static float[] toPrimitive(@Nullable Float[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1759,7 +1892,8 @@ public static float[] toPrimitive(Float[] array) { return result; } - public static float[] toPrimitive(Float[] array, float valueForNull) { + @Nullable + public static float[] toPrimitive(@Nullable Float[] array, float valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1773,7 +1907,8 @@ public static float[] toPrimitive(Float[] array, float valueForNull) { return result; } - public static Float[] toObject(float[] array) { + @Nullable + public static Float[] toObject(@Nullable float[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1790,7 +1925,8 @@ public static Float[] toObject(float[] array) { // boolean converters /////////////////////////////////////////////////////////////////////////// - public static boolean[] toPrimitive(Boolean[] array) { + @Nullable + public static boolean[] toPrimitive(@Nullable Boolean[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1803,7 +1939,8 @@ public static boolean[] toPrimitive(Boolean[] array) { return result; } - public static boolean[] toPrimitive(Boolean[] array, boolean valueForNull) { + @Nullable + public static boolean[] toPrimitive(@Nullable Boolean[] array, boolean valueForNull) { if (array == null) { return null; } else if (array.length == 0) { @@ -1817,7 +1954,8 @@ public static boolean[] toPrimitive(Boolean[] array, boolean valueForNull) { return result; } - public static Boolean[] toObject(boolean[] array) { + @Nullable + public static Boolean[] toObject(@Nullable boolean[] array) { if (array == null) { return null; } else if (array.length == 0) { @@ -1830,67 +1968,71 @@ public static Boolean[] toObject(boolean[] array) { return result; } - public static List asList(T... array) { + @NonNull + public static List asList(@Nullable T... array) { if (array == null || array.length == 0) { return Collections.emptyList(); } return Arrays.asList(array); } - public static List asUnmodifiableList(T... array) { + @NonNull + public static List asUnmodifiableList(@Nullable T... array) { return Collections.unmodifiableList(asList(array)); } - public static List asArrayList(T... 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; } - public static List asLinkedList(T... array) { + @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(T[] array, Comparator c) { + public static void sort(@Nullable T[] array, Comparator c) { if (array == null || array.length < 2) return; Arrays.sort(array, c); } - public static void sort(byte[] array) { + public static void sort(@Nullable byte[] array) { if (array == null || array.length < 2) return; Arrays.sort(array); } - public static void sort(char[] array) { + public static void sort(@Nullable char[] array) { if (array == null || array.length < 2) return; Arrays.sort(array); } - public static void sort(double[] array) { + public static void sort(@Nullable double[] array) { if (array == null || array.length < 2) return; Arrays.sort(array); } - public static void sort(float[] array) { + public static void sort(@Nullable float[] array) { if (array == null || array.length < 2) return; Arrays.sort(array); } - public static void sort(int[] array) { + public static void sort(@Nullable int[] array) { if (array == null || array.length < 2) return; Arrays.sort(array); } - public static void sort(long[] array) { + public static void sort(@Nullable long[] array) { if (array == null || array.length < 2) return; Arrays.sort(array); } - public static void sort(short[] array) { + public static void sort(@Nullable short[] array) { if (array == null || array.length < 2) return; Arrays.sort(array); } @@ -1903,7 +2045,7 @@ public static void sort(short[] array) { * @param array The array. * @param closure the closure to perform, may be null */ - public static void forAllDo(Object array, Closure closure) { + public static void forAllDo(@Nullable Object array, @Nullable Closure closure) { if (array == null || closure == null) return; if (array instanceof Object[]) { Object[] objects = (Object[]) array; @@ -1970,7 +2112,8 @@ public static void forAllDo(Object array, Closure closure) { * @param array The array. * @return the string of array */ - public static String toString(Object array) { + @NonNull + public static String toString(@Nullable Object array) { if (array == null) return "null"; if (array instanceof Object[]) { return Arrays.deepToString((Object[]) array); diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java index 0092763b12..90acac5882 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java @@ -194,14 +194,14 @@ public static void subtractMarginTopEqualStatusBarHeight(@NonNull View view) { view.setTag(KEY_OFFSET, false); } - private static void addMarginTopEqualStatusBarHeight(final Window window) { + 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(final Window window) { + 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; @@ -349,13 +349,13 @@ public static void setStatusBarColor4Drawer(@NonNull final DrawerLayout drawer, } } - private static View applyStatusBarColor(final Activity activity, + private static View applyStatusBarColor(@NonNull final Activity activity, final int color, boolean isDecor) { return applyStatusBarColor(activity.getWindow(), color, isDecor); } - private static View applyStatusBarColor(final Window window, + private static View applyStatusBarColor(@NonNull final Window window, final int color, boolean isDecor) { ViewGroup parent = isDecor ? @@ -374,25 +374,25 @@ private static View applyStatusBarColor(final Window window, return fakeStatusBarView; } - private static void hideStatusBarView(final Activity activity) { + private static void hideStatusBarView(@NonNull final Activity activity) { hideStatusBarView(activity.getWindow()); } - private static void hideStatusBarView(final Window window) { + 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(final Window window) { + 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(final Context context, + private static View createStatusBarView(@NonNull final Context context, final int color) { View statusBarView = new View(context); statusBarView.setLayoutParams(new ViewGroup.LayoutParams( @@ -402,11 +402,11 @@ private static View createStatusBarView(final Context context, return statusBarView; } - public static void transparentStatusBar(final Activity activity) { + public static void transparentStatusBar(@NonNull final Activity activity) { transparentStatusBar(activity.getWindow()); } - public static void transparentStatusBar(final Window window) { + 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); diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java index f9344b0a59..0a3dc27632 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BrightnessUtils.java @@ -105,7 +105,7 @@ public static void setWindowBrightness(@NonNull final Window window, * @param window 窗口 * @return 屏幕亮度 0-255 */ - public static int getWindowBrightness(final Window window) { + public static int getWindowBrightness(@NonNull final Window window) { WindowManager.LayoutParams lp = window.getAttributes(); float brightness = lp.screenBrightness; if (brightness < 0) return getBrightness(); diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BusUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BusUtils.java index 0eb9ec86fa..c06f86fae8 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BusUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BusUtils.java @@ -1,5 +1,7 @@ package com.blankj.utilcode.util; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.Log; import java.lang.annotation.ElementType; @@ -61,27 +63,27 @@ private void registerBus(String tag, busInfoList.add(new BusInfo(tag, className, funName, paramType, paramName, sticky, threadMode, priority)); } - public static void register(final Object bus) { + public static void register(@Nullable final Object bus) { getInstance().registerInner(bus); } - public static void unregister(final Object bus) { + public static void unregister(@Nullable final Object bus) { getInstance().unregisterInner(bus); } - public static void post(final String tag) { + public static void post(@NonNull final String tag) { post(tag, NULL); } - public static void post(final String tag, final Object arg) { + public static void post(@NonNull final String tag, @NonNull final Object arg) { getInstance().postInner(tag, arg); } - public static void postSticky(final String tag) { + public static void postSticky(@NonNull final String tag) { postSticky(tag, NULL); } - public static void postSticky(final String tag, final Object arg) { + public static void postSticky(@NonNull final String tag, final Object arg) { getInstance().postStickyInner(tag, arg); } @@ -102,7 +104,7 @@ private static BusUtils getInstance() { return LazyHolder.INSTANCE; } - private void registerInner(final Object bus) { + private void registerInner(@Nullable final Object bus) { if (bus == null) return; Class aClass = bus.getClass(); String className = aClass.getName(); diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java index bb48a4b5cf..7a1a1f199d 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDiskStaticUtils.java @@ -4,6 +4,7 @@ import android.graphics.drawable.Drawable; import android.os.Parcelable; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import org.json.JSONArray; import org.json.JSONObject; @@ -27,7 +28,7 @@ public final class CacheDiskStaticUtils { * * @param cacheDiskUtils The default instance of {@link CacheDiskUtils}. */ - public static void setDefaultCacheDiskUtils(final CacheDiskUtils cacheDiskUtils) { + public static void setDefaultCacheDiskUtils(@Nullable final CacheDiskUtils cacheDiskUtils) { sDefaultCacheDiskUtils = cacheDiskUtils; } @@ -37,7 +38,7 @@ public static void setDefaultCacheDiskUtils(final CacheDiskUtils cacheDiskUtils) * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final byte[] value) { + public static void put(@NonNull final String key, @Nullable final byte[] value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -48,7 +49,7 @@ public static void put(@NonNull final String key, final byte[] value) { * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ - public static void put(@NonNull final String key, final byte[] value, final int saveTime) { + public static void put(@NonNull final String key, @Nullable final byte[] value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -69,7 +70,7 @@ public static byte[] getBytes(@NonNull final String key) { * @param defaultValue The default value if the cache doesn't exist. * @return the bytes if cache exists or defaultValue otherwise */ - public static byte[] getBytes(@NonNull final String key, final byte[] defaultValue) { + public static byte[] getBytes(@NonNull final String key, @Nullable final byte[] defaultValue) { return getBytes(key, defaultValue, getDefaultCacheDiskUtils()); } @@ -83,7 +84,7 @@ public static byte[] getBytes(@NonNull final String key, final byte[] defaultVal * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final String value) { + public static void put(@NonNull final String key, @Nullable final String value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -94,7 +95,7 @@ public static void put(@NonNull final String key, final String value) { * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ - public static void put(@NonNull final String key, final String value, final int saveTime) { + public static void put(@NonNull final String key, @Nullable final String value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -115,7 +116,7 @@ public static String getString(@NonNull final String key) { * @param defaultValue The default value if the cache doesn't exist. * @return the string value if cache exists or defaultValue otherwise */ - public static String getString(@NonNull final String key, final String defaultValue) { + public static String getString(@NonNull final String key, @Nullable final String defaultValue) { return getString(key, defaultValue, getDefaultCacheDiskUtils()); } @@ -129,7 +130,7 @@ public static String getString(@NonNull final String key, final String defaultVa * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final JSONObject value) { + public static void put(@NonNull final String key, @Nullable final JSONObject value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -141,7 +142,7 @@ public static void put(@NonNull final String key, final JSONObject value) { * @param saveTime The save time of cache, in seconds. */ public static void put(@NonNull final String key, - final JSONObject value, + @Nullable final JSONObject value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -163,7 +164,7 @@ public static JSONObject getJSONObject(@NonNull final String key) { * @param defaultValue The default value if the cache doesn't exist. * @return the JSONObject if cache exists or defaultValue otherwise */ - public static JSONObject getJSONObject(@NonNull final String key, final JSONObject defaultValue) { + public static JSONObject getJSONObject(@NonNull final String key, @Nullable final JSONObject defaultValue) { return getJSONObject(key, defaultValue, getDefaultCacheDiskUtils()); } @@ -178,7 +179,7 @@ public static JSONObject getJSONObject(@NonNull final String key, final JSONObje * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final JSONArray value) { + public static void put(@NonNull final String key, @Nullable final JSONArray value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -189,7 +190,7 @@ public static void put(@NonNull final String key, final JSONArray value) { * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ - public static void put(@NonNull final String key, final JSONArray value, final int saveTime) { + public static void put(@NonNull final String key, @Nullable final JSONArray value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -210,7 +211,7 @@ public static JSONArray getJSONArray(@NonNull final String key) { * @param defaultValue The default value if the cache doesn't exist. * @return the JSONArray if cache exists or defaultValue otherwise */ - public static JSONArray getJSONArray(@NonNull final String key, final JSONArray defaultValue) { + public static JSONArray getJSONArray(@NonNull final String key, @Nullable final JSONArray defaultValue) { return getJSONArray(key, defaultValue, getDefaultCacheDiskUtils()); } @@ -225,7 +226,7 @@ public static JSONArray getJSONArray(@NonNull final String key, final JSONArray * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final Bitmap value) { + public static void put(@NonNull final String key, @Nullable final Bitmap value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -236,7 +237,7 @@ public static void put(@NonNull final String key, final Bitmap value) { * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ - public static void put(@NonNull final String key, final Bitmap value, final int saveTime) { + public static void put(@NonNull final String key, @Nullable final Bitmap value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -257,7 +258,7 @@ public static Bitmap getBitmap(@NonNull final String key) { * @param defaultValue The default value if the cache doesn't exist. * @return the bitmap if cache exists or defaultValue otherwise */ - public static Bitmap getBitmap(@NonNull final String key, final Bitmap defaultValue) { + public static Bitmap getBitmap(@NonNull final String key, @Nullable final Bitmap defaultValue) { return getBitmap(key, defaultValue, getDefaultCacheDiskUtils()); } @@ -271,7 +272,7 @@ public static Bitmap getBitmap(@NonNull final String key, final Bitmap defaultVa * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final Drawable value) { + public static void put(@NonNull final String key, @Nullable final Drawable value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -282,7 +283,7 @@ public static void put(@NonNull final String key, final Drawable value) { * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ - public static void put(@NonNull final String key, final Drawable value, final int saveTime) { + public static void put(@NonNull final String key, @Nullable final Drawable value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -303,7 +304,7 @@ public static Drawable getDrawable(@NonNull final String key) { * @param defaultValue The default value if the cache doesn't exist. * @return the drawable if cache exists or defaultValue otherwise */ - public static Drawable getDrawable(@NonNull final String key, final Drawable defaultValue) { + public static Drawable getDrawable(@NonNull final String key, final @Nullable Drawable defaultValue) { return getDrawable(key, defaultValue, getDefaultCacheDiskUtils()); } @@ -317,7 +318,7 @@ public static Drawable getDrawable(@NonNull final String key, final Drawable def * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final Parcelable value) { + public static void put(@NonNull final String key, @Nullable final Parcelable value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -328,7 +329,7 @@ public static void put(@NonNull final String key, final Parcelable value) { * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ - public static void put(@NonNull final String key, final Parcelable value, final int saveTime) { + public static void put(@NonNull final String key, @Nullable final Parcelable value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -356,7 +357,7 @@ public static T getParcelable(@NonNull final String key, */ public static T getParcelable(@NonNull final String key, @NonNull final Parcelable.Creator creator, - final T defaultValue) { + @Nullable final T defaultValue) { return getParcelable(key, creator, defaultValue, getDefaultCacheDiskUtils()); } @@ -370,7 +371,7 @@ public static T getParcelable(@NonNull final String key, * @param key The key of cache. * @param value The value of cache. */ - public static void put(@NonNull final String key, final Serializable value) { + public static void put(@NonNull final String key, @Nullable final Serializable value) { put(key, value, getDefaultCacheDiskUtils()); } @@ -381,7 +382,7 @@ public static void put(@NonNull final String key, final Serializable value) { * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ - public static void put(@NonNull final String key, final Serializable value, final int saveTime) { + public static void put(@NonNull final String key, @Nullable final Serializable value, final int saveTime) { put(key, value, saveTime, getDefaultCacheDiskUtils()); } @@ -402,7 +403,7 @@ public static Object getSerializable(@NonNull final String key) { * @param defaultValue The default value if the cache doesn't exist. * @return the bitmap if cache exists or defaultValue otherwise */ - public static Object getSerializable(@NonNull final String key, final Object defaultValue) { + public static Object getSerializable(@NonNull final String key, @Nullable final Object defaultValue) { return getSerializable(key, defaultValue, getDefaultCacheDiskUtils()); } @@ -455,7 +456,7 @@ public static boolean clear() { * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final byte[] value, + @Nullable final byte[] value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -469,7 +470,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final byte[] value, + @Nullable final byte[] value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -495,7 +496,7 @@ public static byte[] getBytes(@NonNull final String key, @NonNull final CacheDis * @return the bytes if cache exists or defaultValue otherwise */ public static byte[] getBytes(@NonNull final String key, - final byte[] defaultValue, + @Nullable final byte[] defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getBytes(key, defaultValue); } @@ -512,7 +513,7 @@ public static byte[] getBytes(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final String value, + @Nullable final String value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -526,7 +527,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final String value, + @Nullable final String value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -552,7 +553,7 @@ public static String getString(@NonNull final String key, @NonNull final CacheDi * @return the string value if cache exists or defaultValue otherwise */ public static String getString(@NonNull final String key, - final String defaultValue, + @Nullable final String defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getString(key, defaultValue); } @@ -569,7 +570,7 @@ public static String getString(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final JSONObject value, + @Nullable final JSONObject value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -583,7 +584,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final JSONObject value, + @Nullable final JSONObject value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -609,7 +610,7 @@ public static JSONObject getJSONObject(@NonNull final String key, @NonNull final * @return the JSONObject if cache exists or defaultValue otherwise */ public static JSONObject getJSONObject(@NonNull final String key, - final JSONObject defaultValue, + @Nullable final JSONObject defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getJSONObject(key, defaultValue); } @@ -627,7 +628,7 @@ public static JSONObject getJSONObject(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final JSONArray value, + @Nullable final JSONArray value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -641,7 +642,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final JSONArray value, + @Nullable final JSONArray value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -667,7 +668,7 @@ public static JSONArray getJSONArray(@NonNull final String key, @NonNull final C * @return the JSONArray if cache exists or defaultValue otherwise */ public static JSONArray getJSONArray(@NonNull final String key, - final JSONArray defaultValue, + @Nullable final JSONArray defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getJSONArray(key, defaultValue); } @@ -685,7 +686,7 @@ public static JSONArray getJSONArray(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Bitmap value, + @Nullable final Bitmap value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -699,7 +700,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Bitmap value, + @Nullable final Bitmap value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -725,7 +726,7 @@ public static Bitmap getBitmap(@NonNull final String key, @NonNull final CacheDi * @return the bitmap if cache exists or defaultValue otherwise */ public static Bitmap getBitmap(@NonNull final String key, - final Bitmap defaultValue, + @Nullable final Bitmap defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getBitmap(key, defaultValue); } @@ -742,7 +743,7 @@ public static Bitmap getBitmap(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Drawable value, + @Nullable final Drawable value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -756,7 +757,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Drawable value, + @Nullable final Drawable value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -782,7 +783,7 @@ public static Drawable getDrawable(@NonNull final String key, @NonNull final Cac * @return the drawable if cache exists or defaultValue otherwise */ public static Drawable getDrawable(@NonNull final String key, - final Drawable defaultValue, + @Nullable final Drawable defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getDrawable(key, defaultValue); } @@ -799,7 +800,7 @@ public static Drawable getDrawable(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Parcelable value, + @Nullable final Parcelable value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -813,7 +814,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Parcelable value, + @Nullable final Parcelable value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -846,7 +847,7 @@ public static T getParcelable(@NonNull final String key, */ public static T getParcelable(@NonNull final String key, @NonNull final Parcelable.Creator creator, - final T defaultValue, + @Nullable final T defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getParcelable(key, creator, defaultValue); } @@ -863,7 +864,7 @@ public static T getParcelable(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Serializable value, + @Nullable final Serializable value, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value); } @@ -877,7 +878,7 @@ public static void put(@NonNull final String key, * @param cacheDiskUtils The instance of {@link CacheDiskUtils}. */ public static void put(@NonNull final String key, - final Serializable value, + @Nullable final Serializable value, final int saveTime, @NonNull final CacheDiskUtils cacheDiskUtils) { cacheDiskUtils.put(key, value, saveTime); @@ -903,7 +904,7 @@ public static Object getSerializable(@NonNull final String key, @NonNull final C * @return the bitmap if cache exists or defaultValue otherwise */ public static Object getSerializable(@NonNull final String key, - final Object defaultValue, + @Nullable final Object defaultValue, @NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.getSerializable(key, defaultValue); } @@ -949,6 +950,7 @@ public static boolean clear(@NonNull final CacheDiskUtils cacheDiskUtils) { return cacheDiskUtils.clear(); } + @NonNull private static CacheDiskUtils getDefaultCacheDiskUtils() { return sDefaultCacheDiskUtils != null ? sDefaultCacheDiskUtils : CacheDiskUtils.getInstance(); } diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java index c800423c78..1cc8324990 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/CacheDoubleUtils.java @@ -113,7 +113,12 @@ public byte[] getBytes(@NonNull final String key) { public byte[] getBytes(@NonNull final String key, final byte[] defaultValue) { byte[] obj = mCacheMemoryUtils.get(key); if (obj != null) return obj; - return mCacheDiskUtils.getBytes(key, defaultValue); + byte[] bytes = mCacheDiskUtils.getBytes(key); + if (bytes != null) { + mCacheMemoryUtils.put(key, bytes); + return bytes; + } + return defaultValue; } /////////////////////////////////////////////////////////////////////////// @@ -162,7 +167,12 @@ public String getString(@NonNull final String key) { public String getString(@NonNull final String key, final String defaultValue) { String obj = mCacheMemoryUtils.get(key); if (obj != null) return obj; - return mCacheDiskUtils.getString(key, defaultValue); + String string = mCacheDiskUtils.getString(key); + if (string != null) { + mCacheMemoryUtils.put(key, string); + return string; + } + return defaultValue; } /////////////////////////////////////////////////////////////////////////// @@ -213,7 +223,12 @@ public JSONObject getJSONObject(@NonNull final String key) { public JSONObject getJSONObject(@NonNull final String key, final JSONObject defaultValue) { JSONObject obj = mCacheMemoryUtils.get(key); if (obj != null) return obj; - return mCacheDiskUtils.getJSONObject(key, defaultValue); + JSONObject jsonObject = mCacheDiskUtils.getJSONObject(key); + if (jsonObject != null) { + mCacheMemoryUtils.put(key, jsonObject); + return jsonObject; + } + return defaultValue; } @@ -263,7 +278,12 @@ public JSONArray getJSONArray(@NonNull final String key) { public JSONArray getJSONArray(@NonNull final String key, final JSONArray defaultValue) { JSONArray obj = mCacheMemoryUtils.get(key); if (obj != null) return obj; - return mCacheDiskUtils.getJSONArray(key, defaultValue); + JSONArray jsonArray = mCacheDiskUtils.getJSONArray(key); + if (jsonArray != null) { + mCacheMemoryUtils.put(key, jsonArray); + return jsonArray; + } + return defaultValue; } /////////////////////////////////////////////////////////////////////////// @@ -312,7 +332,12 @@ public Bitmap getBitmap(@NonNull final String key) { public Bitmap getBitmap(@NonNull final String key, final Bitmap defaultValue) { Bitmap obj = mCacheMemoryUtils.get(key); if (obj != null) return obj; - return mCacheDiskUtils.getBitmap(key, defaultValue); + Bitmap bitmap = mCacheDiskUtils.getBitmap(key); + if (bitmap != null) { + mCacheMemoryUtils.put(key, bitmap); + return bitmap; + } + return defaultValue; } /////////////////////////////////////////////////////////////////////////// @@ -361,7 +386,12 @@ public Drawable getDrawable(@NonNull final String key) { public Drawable getDrawable(@NonNull final String key, final Drawable defaultValue) { Drawable obj = mCacheMemoryUtils.get(key); if (obj != null) return obj; - return mCacheDiskUtils.getDrawable(key, defaultValue); + Drawable drawable = mCacheDiskUtils.getDrawable(key); + if (drawable != null) { + mCacheMemoryUtils.put(key, drawable); + return drawable; + } + return defaultValue; } /////////////////////////////////////////////////////////////////////////// @@ -417,7 +447,12 @@ public T getParcelable(@NonNull final String key, final T defaultValue) { T value = mCacheMemoryUtils.get(key); if (value != null) return value; - return mCacheDiskUtils.getParcelable(key, creator, defaultValue); + T val = mCacheDiskUtils.getParcelable(key, creator); + if (val != null) { + mCacheMemoryUtils.put(key, val); + return val; + } + return defaultValue; } /////////////////////////////////////////////////////////////////////////// @@ -466,7 +501,12 @@ public Object getSerializable(@NonNull final String key) { public Object getSerializable(@NonNull final String key, final Object defaultValue) { Object obj = mCacheMemoryUtils.get(key); if (obj != null) return obj; - return mCacheDiskUtils.getSerializable(key, defaultValue); + Object serializable = mCacheDiskUtils.getSerializable(key); + if (serializable != null) { + mCacheMemoryUtils.put(key, serializable); + return serializable; + } + return defaultValue; } /** diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java index 3e56907eb2..8ddc4344a4 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java @@ -1525,6 +1525,7 @@ private static void operate(final int type, break; } ft.commitAllowingStateLoss(); + fm.executePendingTransactions(); } private static void addAnim(final FragmentTransaction ft, diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java index 242b9dcfd5..7df105a3bc 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java @@ -40,6 +40,8 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; +import android.support.v4.content.ContextCompat; +import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -85,7 +87,7 @@ public static byte[] bitmap2Bytes(final Bitmap bitmap) { * @param quality The quality. * @return bytes */ - public static byte[] bitmap2Bytes(final Bitmap bitmap, final CompressFormat format, int quality) { + public static byte[] bitmap2Bytes(@Nullable final Bitmap bitmap, @NonNull final CompressFormat format, int quality) { if (bitmap == null) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(format, quality, baos); @@ -98,7 +100,7 @@ public static byte[] bitmap2Bytes(final Bitmap bitmap, final CompressFormat form * @param bytes The bytes. * @return bitmap */ - public static Bitmap bytes2Bitmap(final byte[] bytes) { + public static Bitmap bytes2Bitmap(@Nullable final byte[] bytes) { return (bytes == null || bytes.length == 0) ? null : BitmapFactory.decodeByteArray(bytes, 0, bytes.length); @@ -110,7 +112,8 @@ public static Bitmap bytes2Bitmap(final byte[] bytes) { * @param drawable The drawable. * @return bitmap */ - public static Bitmap drawable2Bitmap(final Drawable drawable) { + public static Bitmap drawable2Bitmap(@Nullable final Drawable drawable) { + if (drawable == null) return null; if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; if (bitmapDrawable.getBitmap() != null) { @@ -142,7 +145,7 @@ public static Bitmap drawable2Bitmap(final Drawable drawable) { * @param bitmap The bitmap. * @return drawable */ - public static Drawable bitmap2Drawable(final Bitmap bitmap) { + public static Drawable bitmap2Drawable(@Nullable final Bitmap bitmap) { return bitmap == null ? null : new BitmapDrawable(Utils.getApp().getResources(), bitmap); } @@ -152,7 +155,7 @@ public static Drawable bitmap2Drawable(final Bitmap bitmap) { * @param drawable The drawable. * @return bytes */ - public static byte[] drawable2Bytes(final Drawable drawable) { + public static byte[] drawable2Bytes(@Nullable final Drawable drawable) { return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable)); } @@ -340,7 +343,18 @@ public static Bitmap getBitmap(final byte[] data, * @return bitmap */ public static Bitmap getBitmap(@DrawableRes final int resId) { - return BitmapFactory.decodeResource(Utils.getApp().getResources(), resId); + Drawable drawable = ContextCompat.getDrawable(Utils.getApp(), resId); + if (drawable == null) { + return null; + } + Canvas canvas = new Canvas(); + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + canvas.setBitmap(bitmap); + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + drawable.draw(canvas); + return bitmap; } /** @@ -1753,24 +1767,87 @@ public static boolean save(final Bitmap src, @Nullable public static File save2Album(final Bitmap src, final CompressFormat format) { - return save2Album(src, format, 100, false); + return save2Album(src, "", format, 100, false); + } + + /** + * @param src The source of bitmap. + * @param format The format of the image. + * @param recycle True to recycle the source of bitmap, false otherwise. + * @return the file if save success, otherwise return null. + */ + @Nullable + public static File save2Album(final Bitmap src, + final CompressFormat format, + final boolean recycle) { + return save2Album(src, "", format, 100, recycle); + } + + /** + * @param src The source of bitmap. + * @param format The format of the image. + * @param quality Hint to the compressor, 0-100. 0 meaning compress for + * small size, 100 meaning compress for max quality. Some + * formats, like PNG which is lossless, will ignore the + * quality setting + * @return the file if save success, otherwise return null. + */ + @Nullable + public static File save2Album(final Bitmap src, + final CompressFormat format, + final int quality) { + return save2Album(src, "", format, quality, false); + } + + /** + * @param src The source of bitmap. + * @param format The format of the image. + * @param quality Hint to the compressor, 0-100. 0 meaning compress for + * small size, 100 meaning compress for max quality. Some + * formats, like PNG which is lossless, will ignore the + * quality setting + * @param recycle True to recycle the source of bitmap, false otherwise. + * @return the file if save success, otherwise return null. + */ + @Nullable + public static File save2Album(final Bitmap src, + final CompressFormat format, + final int quality, + final boolean recycle) { + return save2Album(src, "", format, quality, recycle); + } + + /** + * @param src The source of bitmap. + * @param dirName The name of directory. + * @param format The format of the image. + * @return the file if save success, otherwise return null. + */ + @Nullable + public static File save2Album(final Bitmap src, + final String dirName, + final CompressFormat format) { + return save2Album(src, dirName, format, 100, false); } /** * @param src The source of bitmap. + * @param dirName The name of directory. * @param format The format of the image. * @param recycle True to recycle the source of bitmap, false otherwise. * @return the file if save success, otherwise return null. */ @Nullable public static File save2Album(final Bitmap src, + final String dirName, final CompressFormat format, final boolean recycle) { - return save2Album(src, format, 100, recycle); + return save2Album(src, dirName, format, 100, recycle); } /** * @param src The source of bitmap. + * @param dirName The name of directory. * @param format The format of the image. * @param quality Hint to the compressor, 0-100. 0 meaning compress for * small size, 100 meaning compress for max quality. Some @@ -1780,13 +1857,15 @@ public static File save2Album(final Bitmap src, */ @Nullable public static File save2Album(final Bitmap src, + final String dirName, final CompressFormat format, final int quality) { - return save2Album(src, format, quality, false); + return save2Album(src, dirName, format, quality, false); } /** * @param src The source of bitmap. + * @param dirName The name of directory. * @param format The format of the image. * @param quality Hint to the compressor, 0-100. 0 meaning compress for * small size, 100 meaning compress for max quality. Some @@ -1797,9 +1876,11 @@ public static File save2Album(final Bitmap src, */ @Nullable public static File save2Album(final Bitmap src, + final String dirName, final CompressFormat format, final int quality, final boolean recycle) { + String safeDirName = TextUtils.isEmpty(dirName) ? Utils.getApp().getPackageName() : dirName; String suffix = CompressFormat.JPEG.equals(format) ? "JPG" : format.name(); String fileName = System.currentTimeMillis() + "_" + quality + "." + suffix; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { @@ -1808,7 +1889,7 @@ public static File save2Album(final Bitmap src, return null; } File picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); - File destFile = new File(picDir, Utils.getApp().getPackageName() + "/" + fileName); + File destFile = new File(picDir, safeDirName + "/" + fileName); if (!save(src, destFile, format, quality, recycle)) { return null; } @@ -1824,7 +1905,7 @@ public static File save2Album(final Bitmap src, } else { contentUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI; } - contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/" + Utils.getApp().getPackageName()); + contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/" + safeDirName); contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1); Uri uri = Utils.getApp().getContentResolver().insert(contentUri, contentValues); if (uri == null) { diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java index 2364db719c..4a821458fa 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java @@ -8,6 +8,7 @@ import android.os.Bundle; import android.provider.MediaStore; import android.provider.Settings; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresPermission; import android.support.v4.content.FileProvider; @@ -402,8 +403,8 @@ public static Intent getShutdownIntent() { * @param phoneNumber The phone number. * @return the intent of dial */ - public static Intent getDialIntent(final String phoneNumber) { - Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)); + public static Intent getDialIntent(@NonNull final String phoneNumber) { + Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + Uri.encode(phoneNumber))); return getIntent(intent, true); } @@ -415,8 +416,8 @@ public static Intent getDialIntent(final String phoneNumber) { * @return the intent of call */ @RequiresPermission(CALL_PHONE) - public static Intent getCallIntent(final String phoneNumber) { - Intent intent = new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber)); + public static Intent getCallIntent(@NonNull final String phoneNumber) { + Intent intent = new Intent("android.intent.action.CALL", Uri.parse("tel:" + Uri.encode(phoneNumber))); return getIntent(intent, true); } @@ -427,8 +428,8 @@ public static Intent getCallIntent(final String phoneNumber) { * @param content The content of SMS. * @return the intent of send SMS */ - public static Intent getSendSmsIntent(final String phoneNumber, final String content) { - Uri uri = Uri.parse("smsto:" + phoneNumber); + public static Intent getSendSmsIntent(@NonNull final String phoneNumber, final String content) { + Uri uri = Uri.parse("smsto:" + Uri.encode(phoneNumber)); Intent intent = new Intent(Intent.ACTION_SENDTO, uri); intent.putExtra("sms_body", content); return getIntent(intent, true); diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/PhoneUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/PhoneUtils.java index 1e5e2982a3..972d804e16 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/PhoneUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/PhoneUtils.java @@ -3,6 +3,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.os.Build; +import android.support.annotation.NonNull; import android.support.annotation.RequiresPermission; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -288,7 +289,7 @@ public static String getSimOperatorByMnc() { * * @param phoneNumber The phone number. */ - public static void dial(final String phoneNumber) { + public static void dial(@NonNull final String phoneNumber) { Utils.getApp().startActivity(UtilsBridge.getDialIntent(phoneNumber)); } @@ -299,7 +300,7 @@ public static void dial(final String phoneNumber) { * @param phoneNumber The phone number. */ @RequiresPermission(CALL_PHONE) - public static void call(final String phoneNumber) { + public static void call(@NonNull final String phoneNumber) { Utils.getApp().startActivity(UtilsBridge.getCallIntent(phoneNumber)); } @@ -309,7 +310,7 @@ public static void call(final String phoneNumber) { * @param phoneNumber The phone number. * @param content The content. */ - public static void sendSms(final String phoneNumber, final String content) { + public static void sendSms(@NonNull final String phoneNumber, final String content) { Utils.getApp().startActivity(UtilsBridge.getSendSmsIntent(phoneNumber, content)); } diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/RomUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/RomUtils.java index 90f2255cf1..49e1cf6fcf 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/RomUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/RomUtils.java @@ -38,7 +38,7 @@ public final class RomUtils { private static final String[] ROM_SAMSUNG = {"samsung"}; private static final String[] ROM_MEIZU = {"meizu"}; private static final String[] ROM_LENOVO = {"lenovo"}; - private static final String[] ROM_SMARTISAN = {"smartisan"}; + private static final String[] ROM_SMARTISAN = {"smartisan", "deltainno"}; private static final String[] ROM_HTC = {"htc"}; private static final String[] ROM_SONY = {"sony"}; private static final String[] ROM_GIONEE = {"gionee", "amigo"}; diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java index fbc3ff02ff..ca14204dfc 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/SnackbarUtils.java @@ -47,7 +47,7 @@ public final class SnackbarUtils { private static final int COLOR_ERROR = 0xFFFF0000; private static final int COLOR_MESSAGE = 0xFFFFFFFF; - private static WeakReference sReference; + private static WeakReference sWeakSnackbar; private View view; private CharSequence message; @@ -223,11 +223,11 @@ public Snackbar show(boolean isShowTop) { spannableString.setSpan( colorSpan, 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE ); - sReference = new WeakReference<>(Snackbar.make(view, spannableString, duration)); + sWeakSnackbar = new WeakReference<>(Snackbar.make(view, spannableString, duration)); } else { - sReference = new WeakReference<>(Snackbar.make(view, message, duration)); + sWeakSnackbar = new WeakReference<>(Snackbar.make(view, message, duration)); } - final Snackbar snackbar = sReference.get(); + final Snackbar snackbar = sWeakSnackbar.get(); final Snackbar.SnackbarLayout snackbarView = (Snackbar.SnackbarLayout) snackbar.getView(); if (isShowTop) { for (int i = 0; i < snackbarView.getChildCount(); i++) { @@ -316,9 +316,9 @@ public void showError(boolean isShowTop) { * Dismiss the snackbar. */ public static void dismiss() { - if (sReference != null && sReference.get() != null) { - sReference.get().dismiss(); - sReference = null; + if (sWeakSnackbar != null && sWeakSnackbar.get() != null) { + sWeakSnackbar.get().dismiss(); + sWeakSnackbar = null; } } @@ -328,7 +328,7 @@ public static void dismiss() { * @return the view of snackbar */ public static View getView() { - Snackbar snackbar = sReference.get(); + Snackbar snackbar = sWeakSnackbar.get(); if (snackbar == null) return null; return snackbar.getView(); } diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/SpanUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/SpanUtils.java index 86141a8d56..f8eb9465bd 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/SpanUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/SpanUtils.java @@ -514,9 +514,7 @@ public SpanUtils setVerticalAlign(@Align final int align) { * @return the single {@link SpanUtils} instance */ public SpanUtils setClickSpan(@NonNull final ClickableSpan clickSpan) { - if (mTextView != null && mTextView.getMovementMethod() == null) { - mTextView.setMovementMethod(LinkMovementMethod.getInstance()); - } + setMovementMethodIfNeed(); this.clickSpan = clickSpan; return this; } @@ -533,9 +531,7 @@ public SpanUtils setClickSpan(@NonNull final ClickableSpan clickSpan) { public SpanUtils setClickSpan(@ColorInt final int color, final boolean underlineText, final View.OnClickListener listener) { - if (mTextView != null && mTextView.getMovementMethod() == null) { - mTextView.setMovementMethod(LinkMovementMethod.getInstance()); - } + setMovementMethodIfNeed(); this.clickSpan = new ClickableSpan() { @Override @@ -562,11 +558,15 @@ public void onClick(@NonNull View widget) { * @return the single {@link SpanUtils} instance */ public SpanUtils setUrl(@NonNull final String url) { + setMovementMethodIfNeed(); + this.url = url; + return this; + } + + private void setMovementMethodIfNeed() { if (mTextView != null && mTextView.getMovementMethod() == null) { mTextView.setMovementMethod(LinkMovementMethod.getInstance()); } - this.url = url; - return this; } /** diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/StringUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/StringUtils.java index 28efede8d4..f218ae5567 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/StringUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/StringUtils.java @@ -2,6 +2,7 @@ import android.content.res.Resources; import android.support.annotation.ArrayRes; +import android.support.annotation.Nullable; import android.support.annotation.StringRes; import java.util.IllegalFormatException; @@ -245,7 +246,7 @@ public static String[] getStringArray(@ArrayRes int id) { * @param args The args. * @return a formatted string. */ - public static String format(String str, Object... args) { + public static String format(@Nullable String str, Object... args) { String text = str; if (text != null) { if (args != null && args.length > 0) { diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ThreadUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ThreadUtils.java index b99dc4d21f..96830dd89f 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ThreadUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ThreadUtils.java @@ -1216,6 +1216,7 @@ public void run() { if (!isDone() && mTimeoutListener != null) { timeout(); mTimeoutListener.onTimeout(); + onDone(); } } }, mTimeoutMillis); @@ -1287,7 +1288,6 @@ private void timeout() { if (runner != null) { runner.interrupt(); } - onDone(); } @@ -1362,6 +1362,18 @@ public T getValue() { } return mValue; } + + public T getValue(long timeout, TimeUnit unit, T defaultValue) { + if (!mFlag.get()) { + try { + mLatch.await(timeout, unit); + } catch (InterruptedException e) { + e.printStackTrace(); + return defaultValue; + } + } + return mValue; + } } private static Executor getGlobalDeliver() { diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ToastUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ToastUtils.java index 69bce2594b..d08f2923bc 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ToastUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ToastUtils.java @@ -38,6 +38,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; import java.lang.reflect.Field; /** @@ -63,7 +64,7 @@ public final class ToastUtils { private static final String NOTHING = "toast nothing"; private static final ToastUtils DEFAULT_MAKER = make(); - private static IToast iToast; + private static WeakReference sWeakToast; private String mMode; private int mGravity = -1; @@ -82,6 +83,7 @@ public final class ToastUtils { * * @return the single {@link ToastUtils} instance */ + @NonNull public static ToastUtils make() { return new ToastUtils(); } @@ -90,6 +92,7 @@ public static ToastUtils make() { * @param mode The mode. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setMode(@MODE String mode) { mMode = mode; return this; @@ -103,6 +106,7 @@ public final ToastUtils setMode(@MODE String mode) { * @param yOffset Y-axis offset, in pixel. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setGravity(final int gravity, final int xOffset, final int yOffset) { mGravity = gravity; mXOffset = xOffset; @@ -116,6 +120,7 @@ public final ToastUtils setGravity(final int gravity, final int xOffset, final i * @param backgroundColor The color of background. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setBgColor(@ColorInt final int backgroundColor) { mBgColor = backgroundColor; return this; @@ -127,6 +132,7 @@ public final ToastUtils setBgColor(@ColorInt final int backgroundColor) { * @param bgResource The resource of background. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setBgResource(@DrawableRes final int bgResource) { mBgResource = bgResource; return this; @@ -138,6 +144,7 @@ public final ToastUtils setBgResource(@DrawableRes final int bgResource) { * @param msgColor The text color of toast. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setTextColor(@ColorInt final int msgColor) { mTextColor = msgColor; return this; @@ -149,6 +156,7 @@ public final ToastUtils setTextColor(@ColorInt final int msgColor) { * @param textSize The text size of toast. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setTextSize(final int textSize) { mTextSize = textSize; return this; @@ -159,6 +167,7 @@ public final ToastUtils setTextSize(final int textSize) { * * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setDurationIsLong(boolean isLong) { this.isLong = isLong; return this; @@ -170,6 +179,7 @@ public final ToastUtils setDurationIsLong(boolean isLong) { * @param resId The left icon resource identifier. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setLeftIcon(@DrawableRes int resId) { return setLeftIcon(ContextCompat.getDrawable(Utils.getApp(), resId)); } @@ -180,7 +190,8 @@ public final ToastUtils setLeftIcon(@DrawableRes int resId) { * @param drawable The left icon drawable. * @return the single {@link ToastUtils} instance */ - public final ToastUtils setLeftIcon(Drawable drawable) { + @NonNull + public final ToastUtils setLeftIcon(@Nullable Drawable drawable) { mIcons[0] = drawable; return this; } @@ -191,6 +202,7 @@ public final ToastUtils setLeftIcon(Drawable drawable) { * @param resId The top icon resource identifier. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setTopIcon(@DrawableRes int resId) { return setTopIcon(ContextCompat.getDrawable(Utils.getApp(), resId)); } @@ -201,7 +213,8 @@ public final ToastUtils setTopIcon(@DrawableRes int resId) { * @param drawable The top icon drawable. * @return the single {@link ToastUtils} instance */ - public final ToastUtils setTopIcon(Drawable drawable) { + @NonNull + public final ToastUtils setTopIcon(@Nullable Drawable drawable) { mIcons[1] = drawable; return this; } @@ -212,6 +225,7 @@ public final ToastUtils setTopIcon(Drawable drawable) { * @param resId The right icon resource identifier. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setRightIcon(@DrawableRes int resId) { return setRightIcon(ContextCompat.getDrawable(Utils.getApp(), resId)); } @@ -222,7 +236,8 @@ public final ToastUtils setRightIcon(@DrawableRes int resId) { * @param drawable The right icon drawable. * @return the single {@link ToastUtils} instance */ - public final ToastUtils setRightIcon(Drawable drawable) { + @NonNull + public final ToastUtils setRightIcon(@Nullable Drawable drawable) { mIcons[2] = drawable; return this; } @@ -233,6 +248,7 @@ public final ToastUtils setRightIcon(Drawable drawable) { * @param resId The bottom icon resource identifier. * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setBottomIcon(int resId) { return setBottomIcon(ContextCompat.getDrawable(Utils.getApp(), resId)); } @@ -243,7 +259,8 @@ public final ToastUtils setBottomIcon(int resId) { * @param drawable The bottom icon drawable. * @return the single {@link ToastUtils} instance */ - public final ToastUtils setBottomIcon(Drawable drawable) { + @NonNull + public final ToastUtils setBottomIcon(@Nullable Drawable drawable) { mIcons[3] = drawable; return this; } @@ -253,6 +270,7 @@ public final ToastUtils setBottomIcon(Drawable drawable) { * * @return the single {@link ToastUtils} instance */ + @NonNull public final ToastUtils setNotUseSystemToast() { isNotUseSystemToast = true; return this; @@ -263,6 +281,7 @@ public final ToastUtils setNotUseSystemToast() { * * @return the default {@link ToastUtils} instance */ + @NonNull public static ToastUtils getDefaultMaker() { return DEFAULT_MAKER; } @@ -272,7 +291,7 @@ public static ToastUtils getDefaultMaker() { * * @param text The text. */ - public final void show(final CharSequence text) { + public final void show(@Nullable final CharSequence text) { show(text, getDuration(), this); } @@ -301,14 +320,14 @@ public final void show(@StringRes final int resId, final Object... args) { * @param format The format. * @param args The args. */ - public final void show(final String format, final Object... args) { + public final void show(@Nullable final String format, final Object... args) { show(UtilsBridge.format(format, args), getDuration(), this); } /** * Show custom toast. */ - public final void show(final View view) { + public final void show(@NonNull final View view) { show(view, getDuration(), this); } @@ -359,7 +378,7 @@ private View tryApplyUtilsToastView(final CharSequence text) { * * @param text The text. */ - public static void showShort(final CharSequence text) { + public static void showShort(@Nullable final CharSequence text) { show(text, Toast.LENGTH_SHORT, DEFAULT_MAKER); } @@ -388,7 +407,7 @@ public static void showShort(@StringRes final int resId, final Object... args) { * @param format The format. * @param args The args. */ - public static void showShort(final String format, final Object... args) { + public static void showShort(@Nullable final String format, final Object... args) { show(UtilsBridge.format(format, args), Toast.LENGTH_SHORT, DEFAULT_MAKER); } @@ -397,7 +416,7 @@ public static void showShort(final String format, final Object... args) { * * @param text The text. */ - public static void showLong(final CharSequence text) { + public static void showLong(@Nullable final CharSequence text) { show(text, Toast.LENGTH_LONG, DEFAULT_MAKER); } @@ -426,7 +445,7 @@ public static void showLong(@StringRes final int resId, final Object... args) { * @param format The format. * @param args The args. */ - public static void showLong(final String format, final Object... args) { + public static void showLong(@Nullable final String format, final Object... args) { show(UtilsBridge.format(format, args), Toast.LENGTH_LONG, DEFAULT_MAKER); } @@ -434,26 +453,38 @@ public static void showLong(final String format, final Object... args) { * Cancel the toast. */ public static void cancel() { - if (iToast != null) { - iToast.cancel(); - iToast = null; - } + UtilsBridge.runOnUiThread(new Runnable() { + @Override + public void run() { + if (sWeakToast != null) { + final IToast iToast = ToastUtils.sWeakToast.get(); + if (iToast != null) { + iToast.cancel(); + } + sWeakToast = null; + } + } + }); } - private static void show(final CharSequence text, final int duration, final ToastUtils utils) { + private static void show(@Nullable final CharSequence text, final int duration, final ToastUtils utils) { show(null, getToastFriendlyText(text), duration, utils); } - private static void show(final View view, final int duration, final ToastUtils utils) { + private static void show(@NonNull final View view, final int duration, final ToastUtils utils) { show(view, null, duration, utils); } - private static void show(@Nullable final View view, final CharSequence text, final int duration, final ToastUtils utils) { + private static void show(@Nullable final View view, + @Nullable final CharSequence text, + final int duration, + @NonNull final ToastUtils utils) { UtilsBridge.runOnUiThread(new Runnable() { @Override public void run() { cancel(); - iToast = newToast(utils); + IToast iToast = newToast(utils); + ToastUtils.sWeakToast = new WeakReference<>(iToast); if (view != null) { iToast.setToastView(view); } else { @@ -491,9 +522,9 @@ private static IToast newToast(ToastUtils toastUtils) { return new WindowManagerToast(toastUtils, WindowManager.LayoutParams.TYPE_TOAST); } else if (UtilsBridge.isGrantedDrawOverlays()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - new WindowManagerToast(toastUtils, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); + return new WindowManagerToast(toastUtils, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else { - new WindowManagerToast(toastUtils, WindowManager.LayoutParams.TYPE_PHONE); + return new WindowManagerToast(toastUtils, WindowManager.LayoutParams.TYPE_PHONE); } } return new ActivityToast(toastUtils); @@ -553,11 +584,17 @@ static final class WindowManagerToast extends AbsToast { private WindowManager.LayoutParams mParams; - private Utils.ActivityLifecycleCallbacks mActivityLifecycleCallbacks; - WindowManagerToast(ToastUtils toastUtils, int type) { super(toastUtils); mParams = new WindowManager.LayoutParams(); + mWM = (WindowManager) Utils.getApp().getSystemService(Context.WINDOW_SERVICE); + mParams.type = type; + } + + WindowManagerToast(ToastUtils toastUtils, WindowManager wm, int type) { + super(toastUtils); + mParams = new WindowManager.LayoutParams(); + mWM = wm; mParams.type = type; } @@ -587,7 +624,6 @@ public void show(final int duration) { mParams.horizontalMargin = mToast.getHorizontalMargin(); mParams.verticalMargin = mToast.getVerticalMargin(); - mWM = (WindowManager) Utils.getApp().getSystemService(Context.WINDOW_SERVICE); try { if (mWM != null) { mWM.addView(mToastView, mParams); @@ -619,6 +655,7 @@ static final class ActivityToast extends AbsToast { private static int sShowingIndex = 0; private Utils.ActivityLifecycleCallbacks mActivityLifecycleCallbacks; + private IToast iToast; ActivityToast(ToastUtils toastUtils) { super(toastUtils); @@ -629,7 +666,7 @@ public void show(int duration) { if (mToast == null) return; if (!UtilsBridge.isAppForeground()) { // try to use system toast - showSystemToast(duration); + iToast = showSystemToast(duration); return; } boolean hasAliveActivity = false; @@ -637,8 +674,12 @@ public void show(int duration) { if (!UtilsBridge.isActivityAlive(activity)) { continue; } - hasAliveActivity = true; - showWithActivity(activity, sShowingIndex, true); + if (!hasAliveActivity) { + hasAliveActivity = true; + iToast = showWithActivityWindow(activity, duration); + } else { + showWithActivityView(activity, sShowingIndex, true); + } } if (hasAliveActivity) { registerLifecycleCallback(); @@ -652,7 +693,7 @@ public void run() { ++sShowingIndex; } else { // try to use system toast - showSystemToast(duration); + iToast = showSystemToast(duration); } } @@ -676,16 +717,29 @@ public void cancel() { } } } + if (iToast != null) { + iToast.cancel(); + iToast = null; + } super.cancel(); } - private void showSystemToast(int duration) { + private IToast showSystemToast(int duration) { SystemToast systemToast = new SystemToast(mToastUtils); systemToast.mToast = mToast; systemToast.show(duration); + return systemToast; } - private void showWithActivity(final Activity activity, final int index, boolean useAnim) { + private IToast showWithActivityWindow(Activity activity, int duration) { + WindowManagerToast wmToast = new WindowManagerToast(mToastUtils, activity.getWindowManager(), WindowManager.LayoutParams.LAST_APPLICATION_WINDOW); + wmToast.mToastView = getToastViewSnapshot(-1); + wmToast.mToast = mToast; + wmToast.show(duration); + return wmToast; + } + + private void showWithActivityView(final Activity activity, final int index, boolean useAnim) { final Window window = activity.getWindow(); if (window != null) { final ViewGroup decorView = (ViewGroup) window.getDecorView(); @@ -694,6 +748,7 @@ private void showWithActivity(final Activity activity, final int index, boolean ); lp.gravity = mToast.getGravity(); lp.bottomMargin = mToast.getYOffset() + UtilsBridge.getNavBarHeight(); + lp.topMargin = mToast.getYOffset() + UtilsBridge.getStatusBarHeight(); lp.leftMargin = mToast.getXOffset(); View toastViewSnapshot = getToastViewSnapshot(index); if (useAnim) { @@ -704,21 +759,13 @@ private void showWithActivity(final Activity activity, final int index, boolean } } - private View getToastViewSnapshot(final int index) { - Bitmap bitmap = UtilsBridge.view2Bitmap(mToastView); - ImageView toastIv = new ImageView(Utils.getApp()); - toastIv.setTag(TAG_TOAST + index); - toastIv.setImageBitmap(bitmap); - return toastIv; - } - private void registerLifecycleCallback() { final int index = sShowingIndex; mActivityLifecycleCallbacks = new Utils.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity) { if (isShowing()) { - showWithActivity(activity, index, false); + showWithActivityView(activity, index, false); } } }; @@ -761,6 +808,7 @@ public void setToastView(CharSequence text) { View utilsToastView = mToastUtils.tryApplyUtilsToastView(text); if (utilsToastView != null) { setToastView(utilsToastView); + processRtlIfNeed(); return; } @@ -778,9 +826,16 @@ public void setToastView(CharSequence text) { messageTv.setTextSize(mToastUtils.mTextSize); } setBg(messageTv); + processRtlIfNeed(); } - protected void setBg(final TextView msgTv) { + private void processRtlIfNeed() { + if (UtilsBridge.isLayoutRtl()) { + setToastView(getToastViewSnapshot(-1)); + } + } + + private void setBg(final TextView msgTv) { if (mToastUtils.mBgResource != -1) { mToastView.setBackgroundResource(mToastUtils.mBgResource); msgTv.setBackgroundColor(Color.TRANSPARENT); @@ -809,6 +864,14 @@ public void cancel() { mToast = null; mToastView = null; } + + View getToastViewSnapshot(final int index) { + Bitmap bitmap = UtilsBridge.view2Bitmap(mToastView); + ImageView toastIv = new ImageView(Utils.getApp()); + toastIv.setTag(TAG_TOAST + index); + toastIv.setImageBitmap(bitmap); + return toastIv; + } } interface IToast { diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsActivityLifecycleImpl.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsActivityLifecycleImpl.java index 272eddcb45..28414efd78 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsActivityLifecycleImpl.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsActivityLifecycleImpl.java @@ -201,6 +201,9 @@ public void onActivityPreCreated(@NonNull Activity activity, @Nullable Bundle sa @Override public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) { + if (mActivityList.size() == 0) { + postStatus(activity, true); + } LanguageUtils.applyLanguage(activity); setAnimatorsEnabled(); setTopActivity(activity); diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsBridge.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsBridge.java index 5361fdc1de..e920b53635 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsBridge.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/UtilsBridge.java @@ -12,6 +12,7 @@ import android.os.Parcelable; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.support.annotation.RequiresPermission; import android.support.annotation.StringRes; @@ -535,7 +536,7 @@ static String getString(@StringRes int id, Object... formatArgs) { return StringUtils.getString(id, formatArgs); } - static String format(String str, Object... args) { + static String format(@Nullable String str, Object... args) { return StringUtils.format(str, args); } @@ -606,6 +607,10 @@ static View layoutId2View(@LayoutRes final int layoutId) { return ViewUtils.layoutId2View(layoutId); } + static boolean isLayoutRtl() { + return ViewUtils.isLayoutRtl(); + } + /////////////////////////////////////////////////////////////////////////// // Common diff --git a/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml b/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml index ce405066c0..ed731a2299 100644 --- a/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml +++ b/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml @@ -1,9 +1,5 @@ - - diff --git a/lib/utildebug/src/main/java/com/blankj/utildebug/base/view/BaseContentView.java b/lib/utildebug/src/main/java/com/blankj/utildebug/base/view/BaseContentView.java index 246c011492..0af63e0fa8 100644 --- a/lib/utildebug/src/main/java/com/blankj/utildebug/base/view/BaseContentView.java +++ b/lib/utildebug/src/main/java/com/blankj/utildebug/base/view/BaseContentView.java @@ -10,6 +10,8 @@ import com.blankj.utildebug.base.view.listener.OnBackListener; import com.blankj.utildebug.base.view.listener.OnRefreshListener; +import java.util.Collections; + /** *
  *     author: blankj

From 66a4c0488ca6da273098058d70dabb0fe9b9bd8d Mon Sep 17 00:00:00 2001
From: Blankj 
Date: Mon, 22 Feb 2021 00:07:51 +0800
Subject: [PATCH 16/49] see 02/22 log

---
 .../blankj/subutil/util/CoordinateUtils.java  | 28 +++++++++++
 .../com/blankj/utilcode/util/IntentUtils.java |  4 +-
 .../com/blankj/utilcode/util/ScreenUtils.java | 46 ++++++++-----------
 3 files changed, 50 insertions(+), 28 deletions(-)

diff --git a/lib/subutil/src/main/java/com/blankj/subutil/util/CoordinateUtils.java b/lib/subutil/src/main/java/com/blankj/subutil/util/CoordinateUtils.java
index ee6d78a118..c205a52a75 100644
--- a/lib/subutil/src/main/java/com/blankj/subutil/util/CoordinateUtils.java
+++ b/lib/subutil/src/main/java/com/blankj/subutil/util/CoordinateUtils.java
@@ -121,6 +121,34 @@ public static double[] wgs84ToBd09(double lng, double lat) {
         return gcj02ToBd09(gcj[0], gcj[1]);
     }
 
+    /**
+     * Mercator 坐标转 WGS84 坐标
+     *
+     * @param lng Mercator 坐标经度
+     * @param lat Mercator 坐标纬度
+     * @return WGS84 坐标:[经度,纬度]
+     */
+    public static double[] mercatorToWGS84(double lng, double lat) {
+        double x = lng / 20037508.34d * 180.;
+        double y = lat / 20037508.34d * 180.;
+        y = 180 / PI * (2 * Math.atan(Math.exp(y * PI / 180.0)) - PI / 2);
+        return new double[]{x, y};
+    }
+
+    /**
+     * WGS84 坐标转 Mercator 坐标
+     *
+     * @param lng WGS84 坐标经度
+     * @param lat WGS84 坐标纬度
+     * @return Mercator 坐标:[经度,纬度]
+     */
+    public static double[] wgs84ToMercator(double lng, double lat) {
+        double x = lng * 20037508.34D / 180.0;
+        double y = Math.log(Math.tan((90.0 + lat) * PI / 360.0)) / (PI / 180.);
+        y = y * 20037508.34D / 180.0;
+        return new double[]{x, y};
+    }
+
     private static double transformLat(double lng, double lat) {
         double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
         ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java
index 4a821458fa..fccddd8d35 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java
@@ -389,9 +389,9 @@ public static Intent getComponentIntent(final String pkgName,
     public static Intent getShutdownIntent() {
         Intent intent;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            intent = new Intent(Intent.ACTION_SHUTDOWN);
-        } else {
             intent = new Intent("com.android.internal.intent.action.REQUEST_SHUTDOWN");
+        } else {
+            intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN");
         }
         intent.putExtra("android.intent.extra.KEY_CONFIRM", false);
         return intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
index cb742b7a7d..623e15518b 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ScreenUtils.java
@@ -112,39 +112,34 @@ public static float getScreenDensity() {
     public static int getScreenDensityDpi() {
         return Resources.getSystem().getDisplayMetrics().densityDpi;
     }
-    
-    
-    
-    
+
     /**
-     * Return X (width) of the screen expressed as dots-per-inch.
+     * Return the exact physical pixels per inch of the screen in the Y dimension.
      *
-     * @return the width of screen density expressed as dots-per-inch
+     * @return the exact physical pixels per inch of the screen in the Y dimension
      */
-    public static int getScreenXDpi() {
+    public static float getScreenXDpi() {
         return Resources.getSystem().getDisplayMetrics().xdpi;
     }
-    
+
     /**
-     * Return Y (height) of the screen expressed as dots-per-inch.
+     * Return the exact physical pixels per inch of the screen in the Y dimension.
      *
-     * @return the height of screen density expressed as dots-per-inch
+     * @return the exact physical pixels per inch of the screen in the Y dimension
      */
-    public static int getScreenYDpi() {
+    public static float getScreenYDpi() {
         return Resources.getSystem().getDisplayMetrics().ydpi;
     }
-    
-   
-    
+
     /**
      * Return the distance between the given View's X (start point of View's width) and the screen width.
      *
      * @return the distance between the given View's X (start point of View's width) and the screen width.
      */
-    public float calculateDistanceByX(View view) {
-        int[] point = new int[0];
+    public int calculateDistanceByX(View view) {
+        int[] point = new int[2];
         view.getLocationOnScreen(point);
-        return (getScreenWidth() - point[0]).toFloat();
+        return getScreenWidth() - point[0];
     }
 
     /**
@@ -152,10 +147,10 @@ public float calculateDistanceByX(View view) {
      *
      * @return the distance between the given View's Y (start point of View's height) and the screen height.
      */
-    public float calculateDistanceByY(View view) {
-        int[] point = new int[0];
+    public int calculateDistanceByY(View view) {
+        int[] point = new int[2];
         view.getLocationOnScreen(point);
-        return (getScreenHeight() - point[1]).toFloat();
+        return getScreenHeight() - point[1];
     }
 
     /**
@@ -163,23 +158,22 @@ public float calculateDistanceByY(View view) {
      *
      * @return X coordinate of the given View on the screen.
      */
-    public int getViewX(View view){
-        int[] point = new int[0];
+    public int getViewX(View view) {
+        int[] point = new int[2];
         view.getLocationOnScreen(point);
         return point[0];
     }
-    
+
     /**
      * Return the Y coordinate of the given View on the screen.
      *
      * @return Y coordinate of the given View on the screen.
      */
-    public int getViewY(View view){
-        int[] point = new int[0];
+    public int getViewY(View view) {
+        int[] point = new int[2];
         view.getLocationOnScreen(point);
         return point[1];
     }
-    
 
     /**
      * Set full screen.

From f14b404543d17cdba6680a78a15afdf7570a9248 Mon Sep 17 00:00:00 2001
From: jobs_xie 
Date: Thu, 22 Apr 2021 10:46:19 +0800
Subject: [PATCH 17/49] Fix: IllegalStateException: message is already in use

---
 .../src/main/java/com/blankj/utilcode/util/MessengerUtils.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
index a764eb50b6..d1d4669dbe 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
@@ -320,7 +320,7 @@ private void sendMsg2Client(final Message msg) {
             for (Messenger client : mClientMap.values()) {
                 try {
                     if (client != null) {
-                        client.send(msg);
+                        client.send(Message.obtain(msg));
                     }
                 } catch (RemoteException e) {
                     e.printStackTrace();

From e04bfdf9eff1cc82788a0255d38bdcb9f08180cc Mon Sep 17 00:00:00 2001
From: jobs_xie 
Date: Thu, 22 Apr 2021 10:58:44 +0800
Subject: [PATCH 18/49] Fix: IllegalStateException: message is already in use

---
 .../main/java/com/blankj/utilcode/util/MessengerUtils.java    | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
index d1d4669dbe..61aa8e2543 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
@@ -317,15 +317,17 @@ public int onStartCommand(Intent intent, int flags, int startId) {
         }
 
         private void sendMsg2Client(final Message msg) {
+           final Message obtain = Message.obtain(msg); //Copy the original
             for (Messenger client : mClientMap.values()) {
                 try {
                     if (client != null) {
-                        client.send(Message.obtain(msg));
+                        client.send(obtain);
                     }
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
             }
+            obtain.recycle(); //Recycled copy
         }
 
         private void consumeServerProcessCallback(final Message msg) {

From ab073b7a4d856771822c08fbdf2a13f300420ce1 Mon Sep 17 00:00:00 2001
From: xiexin52k <517436384@qq.com>
Date: Thu, 22 Apr 2021 14:28:21 +0800
Subject: [PATCH 19/49] Update MessengerUtils.java

---
 .../src/main/java/com/blankj/utilcode/util/MessengerUtils.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
index 61aa8e2543..71af539ab7 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
@@ -321,7 +321,7 @@ private void sendMsg2Client(final Message msg) {
             for (Messenger client : mClientMap.values()) {
                 try {
                     if (client != null) {
-                        client.send(obtain);
+                        client.send(Message.obtain(obtain));
                     }
                 } catch (RemoteException e) {
                     e.printStackTrace();

From 20290bb808058d92cf52a2632fc463faccc10ff6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A9=AC=E6=AD=87=E5=B0=94?= 
Date: Wed, 5 May 2021 02:51:15 +1000
Subject: [PATCH 20/49] Added 2 very useful methods

1. isFirstTimeInstall():
If you want to know whether this is the first time installation of this app in this device.
2. isAppUpgraded():
If you want to know whether the current version was installed over a previous version (update/upgrade) or if it is freshly installed (clean install).

Code:
/**
     * 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(this.getAppPackageName(), 0).firstInstallTime;
            Long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(this.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(this.getAppPackageName(), 0).firstInstallTime;
            Long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(this.getAppPackageName(), 0).lastUpdateTime;
            return firstInstallTime != lastUpdateTime;
        } catch (Exception e) {
            return false;
        }
    }
---
 .../com/blankj/utilcode/util/AppUtils.java    | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
index a8b65dfecf..1cc9112b16 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
@@ -384,6 +384,38 @@ public static int getAppIconId(final String packageName) {
         }
     }
 
+    
+    /**
+     * 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(this.getAppPackageName(), 0).firstInstallTime;
+            Long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(this.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(this.getAppPackageName(), 0).firstInstallTime;
+            Long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(this.getAppPackageName(), 0).lastUpdateTime;
+            return firstInstallTime != lastUpdateTime;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+    
+   
     /**
      * Return the application's package name.
      *

From cbea6b40658e04ee923c2e4c1d5fad0e18bae5ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A9=AC=E6=AD=87=E5=B0=94?= 
Date: Tue, 4 May 2021 18:56:24 +0200
Subject: [PATCH 21/49] Added yet another 2 very useful methods

1. isBehindProxy():
Returns true if device is connecting to the internet via a proxy, works for both Wi-Fi and Mobile Data.
2. isUsingVPN():
Returns true if device is connecting to the internet via a VPN.
---
 .../blankj/utilcode/util/NetworkUtils.java    | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
index 8f874dbf38..37104b1b43 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
@@ -261,6 +261,34 @@ public static boolean getMobileDataEnabled() {
         }
         return false;
     }
+    
+     /**
+     * Returns true if device is connecting to the internet via a proxy, works for both Wi-Fi and Mobile Data.
+     *
+     * @return true if using proxy to connect to the internet.
+     */
+    public static boolean isBehindProxy(){
+        return !(System.getProperty("http.proxyHost") == null || System.getProperty("http.proxyPort") == null);
+    }
+
+    /**
+     * Returns true if device is connecting to the internet via a VPN.
+     *
+     * @return true if using VPN to conncet to the internet.
+     */
+    public static boolean isUsingVPN(){
+        ConnectivityManager cm = (ConnectivityManager) com.blankj.utilcode.util.Utils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+            return cm.getNetworkInfo(ConnectivityManager.TYPE_VPN).isConnectedOrConnecting()
+        } else {
+            return cm.getNetworkInfo(NetworkCapabilities.TRANSPORT_VPN).isConnectedOrConnecting()
+        }
+    }
+
+    
+    
+    
+    
 
     /**
      * Return whether using mobile data.

From ebc64cd35122d1cba80822dd5942900d7fa507ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A9=AC=E6=AD=87=E5=B0=94?= 
Date: Mon, 10 May 2021 10:11:14 +0700
Subject: [PATCH 22/49] Added 4 useful methods

/**
     * Returns the domain part of a given Email address
     *
     * @param email The Email address. E.g Returns "protonmail.com" from the given Email "johnsmith@protonmail.com".
     * @return the domain part of a given Email address.
     */
    public static String extractEmailProvider(String email) {
        return email.substring(email.lastIndexOf("@") + 1);
    }

    /**
     * Returns the username part of a given Email address. E.g. Returns "johnsmith" from the given Email "johnsmith@protonmail.com".
     *
     * @param email The Email address.
     * @return the username part of a given Email address.
     */
    public static String extractEmailUsername(String email) {
        return email.substring(0, email.lastIndexOf("@"));
    }


    /**
     * Return whether a given Email address is on a specified Email provider. E.g. "johnsmith@protonmail.com" and "gmail.com" will return false.
     *
     * @param email The Email address.
     * @param emailProvider The Email provider to testify against.
     * @return {@code true}: yes
{@code false}: no */ public static boolean isFromEmailProvider(String email, String emailProvider) { return extractEmailProvider(email).equalsIgnoreCase(emailProvider); } /** * Return whether a given Email address is on any of the specified Email providers list (array). E.g. Useful if you pass it a list of real Email provider services and check if the Email is a disposable Email or a real one. * * @param email The Email address. * @param emailProviders The list of Email providers to testify against. * @return {@code true}: yes
{@code false}: no */ public static boolean isFromAnyOfEmailProviders(String email, String[] emailProviders) { return com.blankj.utilcode.util.ArrayUtils.contains(emailProviders, extractEmailProvider(email)); } --- .../com/blankj/utilcode/util/RegexUtils.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/RegexUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/RegexUtils.java index ae90e4ea5e..624a93511c 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/RegexUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/RegexUtils.java @@ -40,6 +40,54 @@ public static boolean isMobileSimple(final CharSequence input) { return isMatch(RegexConstants.REGEX_MOBILE_SIMPLE, input); } + + /** + * Returns the domain part of a given Email address + * + * @param email The Email address. E.g Returns "protonmail.com" from the given Email "johnsmith@protonmail.com". + * @return the domain part of a given Email address. + */ + public static String extractEmailProvider(String email) { + return email.substring(email.lastIndexOf("@") + 1); + } + + /** + * Returns the username part of a given Email address. E.g. Returns "johnsmith" from the given Email "johnsmith@protonmail.com". + * + * @param email The Email address. + * @return the username part of a given Email address. + */ + public static String extractEmailUsername(String email) { + return email.substring(0, email.lastIndexOf("@")); + } + + + /** + * Return whether a given Email address is on a specified Email provider. E.g. "johnsmith@protonmail.com" and "gmail.com" will return false. + * + * @param email The Email address. + * @param emailProvider The Email provider to testify against. + * @return {@code true}: yes
{@code false}: no + */ + public static boolean isFromEmailProvider(String email, String emailProvider) { + return extractEmailProvider(email).equalsIgnoreCase(emailProvider); + } + + /** + * Return whether a given Email address is on any of the specified Email providers list (array). E.g. Useful if you pass it a list of real Email provider services and check if the Email is a disposable Email or a real one. + * + * @param email The Email address. + * @param emailProviders The list of Email providers to testify against. + * @return {@code true}: yes
{@code false}: no + */ + public static boolean isFromAnyOfEmailProviders(String email, String[] emailProviders) { + return com.blankj.utilcode.util.ArrayUtils.contains(emailProviders, extractEmailProvider(email)); + } + + + + + /** * Return whether input matches regex of exact mobile. * From 402cc73a240a9527cea3180c6cf647223b3e6e91 Mon Sep 17 00:00:00 2001 From: caimengjie Date: Thu, 13 May 2021 01:09:26 +0800 Subject: [PATCH 23/49] add(publish): support publish mavenCentral --- CHANGELOG.md | 1 + build.gradle | 13 +- buildApp.gradle | 44 ++-- buildCommon.gradle | 16 -- buildSrc/src/main/groovy/Config.groovy | 6 +- config/flavor.gradle | 22 ++ config/publish.gradle | 237 ++++++++++++++++++ feature/utilcode/export/build.gradle | 14 +- gradle/publish.gradle | 237 ------------------ gradle/wrapper/gradle-wrapper.properties | 2 +- lib/subutil/build.gradle | 2 +- lib/utilcode/build.gradle | 15 +- lib/utilcode/src/main/AndroidManifest.xml | 2 +- .../com/blankj/utilcode/util/IntentUtils.java | 2 +- .../com/blankj/utilcode/util/ToastUtils.java | 2 +- .../com/blankj/utilcode/util/UriUtils.java | 2 +- lib/utildebug/build.gradle | 4 - plugin/api-gradle-plugin/build.gradle | 6 +- plugin/bus-gradle-plugin/build.gradle | 6 +- plugin/lib/base-transform/build.gradle | 6 +- script/clean.sh | 4 - script/gitHelp.sh | 45 ++++ script/runDevDebug.sh | 9 + script/runProductionRelease.sh | 9 + 24 files changed, 380 insertions(+), 326 deletions(-) create mode 100644 config/flavor.gradle create mode 100644 config/publish.gradle delete mode 100644 gradle/publish.gradle delete mode 100755 script/clean.sh create mode 100755 script/gitHelp.sh create mode 100755 script/runDevDebug.sh create mode 100755 script/runProductionRelease.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index db3e52985a..401a5071f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +* `21/05/13` [add] Support publish mavenCentral. * `21/02/22` [add] Fix ToastUtils rtl bug. Publish v1.30.6. * `20/11/16` [add] Add ImageUtils#save2Album support param of dirName. * `20/11/13` [add] Fix MessengerUtils ANR. Add NetworkUtils#getWifiScanResult, [add|remove]OnWifiChangedConsumer. Publish v1.30.5. diff --git a/build.gradle b/build.gradle index dd27b98617..133f032278 100644 --- a/build.gradle +++ b/build.gradle @@ -2,11 +2,9 @@ buildscript { ConfigUtils.init(gradle) repositories { - // use for debug plugin local - if (Config.depConfig.plugin_bus.useLocal || Config.depConfig.plugin_api.useLocal) { - maven() { url uri("${project.rootDir.path}/mavenLocal") } - } + mavenLocal() google() + mavenCentral() jcenter() } @@ -19,9 +17,10 @@ buildscript { allprojects { repositories { - maven() { url uri("${project.rootDir.path}/mavenLocal") } + mavenLocal() maven { url "https://jitpack.io/" } google() + mavenCentral() jcenter() } @@ -29,8 +28,8 @@ allprojects { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' resolutionStrategy.eachDependency { - if (it.requested.group == 'com.android.support' - && !it.requested.name.contains('multidex')) { + if (it.requested.group == 'com.android.support' && !it.requested.name.contains( + 'multidex')) { it.useVersion Config.supportVersion } } diff --git a/buildApp.gradle b/buildApp.gradle index 7aa523c466..d7ed2c75a3 100644 --- a/buildApp.gradle +++ b/buildApp.gradle @@ -1,6 +1,7 @@ apply { plugin "com.android.application" - from "${rootDir.path}/buildCommon.gradle" + from "${rootDir.path}/buildCommon.gradle" + from "${rootDir.path}/config/flavor.gradle" if (Config.depConfig.plugin_api.isApply) { plugin Config.depConfig.plugin_api.pluginId } @@ -32,19 +33,11 @@ android { } buildTypes { - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - applicationIdSuffix ".debug" - resValue "string", "app_name", Config.appName + suffix + ".debug" - } + debug {} release { - aaptOptions.cruncherEnabled = false - aaptOptions.useNewCruncher = false minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - resValue "string", "app_name", Config.appName + suffix } } @@ -58,8 +51,19 @@ android { maxProcessCount 8 dexInProcess = true } -} + productFlavors { + dev { + applicationIdSuffix ".dev" + versionNameSuffix "-dev" + resValue "string", "app_name", Config.appName + suffix + "-dev" + } + + production { + resValue "string", "app_name", Config.appName + suffix + } + } +} dependencies { // LeakCanary @@ -80,7 +84,9 @@ dependencies { def getSuffix() { if (project.name == "feature_launcher_app") return "" - return "." + project.name.substring("feature_".length(), project.name.length() - "_app".length()) + return "." + project. + name. + substring("feature_".length(), project.name.length() - "_app".length()) } def configSigning() { @@ -110,12 +116,14 @@ def configApkName() { if (variant.buildType.name != "debug") { def artifact = variant.getPackageApplicationProvider().get() artifact.outputDirectory = new File("${rootDir.path}/apk") - artifact.outputScope.apkDatas.forEach { apkData -> - apkData.outputFileName = "util" + suffix + - (variant.flavorName == "" ? "" : ("_" + variant.flavorName)) + - "_" + variant.versionName.replace(".", "_") + - "_" + variant.buildType.name + - ".apk" + variant.outputs.each { + it.outputFileName = "util" + suffix + + (variant.flavorName == "" ? "" : ("_" + variant.flavorName)) + + "_" + + variant.versionName.replace(".", "_") + + "_" + + variant.buildType.name + + ".apk" } } } diff --git a/buildCommon.gradle b/buildCommon.gradle index f83f74f52d..8cbcc26255 100644 --- a/buildCommon.gradle +++ b/buildCommon.gradle @@ -22,20 +22,4 @@ android { lintOptions { abortOnError false } - -// viewBinding { -// enabled = true -// } - -// flavorDimensions "region" -// -// productFlavors { -// china { -// dimension "region" -// } -// -// oversea { -// dimension "region" -// } -// } } \ No newline at end of file diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy index 9b6e55d3bb..4fb2b7ef2f 100644 --- a/buildSrc/src/main/groovy/Config.groovy +++ b/buildSrc/src/main/groovy/Config.groovy @@ -15,10 +15,10 @@ class Config { static minSdkVersion = 14 static targetSdkVersion = 29 static versionCode = 1_030_006 - static versionName = '1.30.6'// E.g. 1.9.72 => 1,009,072 + static versionName = '1.30.7-alpha1'// E.g. 1.9.72 => 1,009,072 // lib version - static gradlePluginVersion = '3.5.2' + static gradlePluginVersion = '4.1.0' static kotlinVersion = '1.3.72' static androidxVersion = '1.0.0' @@ -47,8 +47,6 @@ class Config { /*Never delete this line*/ plugin_gradle : new DepConfig(pluginPath: "com.android.tools.build:gradle:$gradlePluginVersion"), plugin_kotlin : new DepConfig(pluginPath: "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"), - plugin_maven : new DepConfig(pluginPath: "com.github.dcendents:android-maven-gradle-plugin:2.1", pluginId: "com.github.dcendents.android-maven"),// 上传到 maven - plugin_bintray : new DepConfig(pluginPath: "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4", pluginId: "com.jfrog.bintray"),// 上传到 bintray plugin_traute : new DepConfig(pluginPath: "tech.harmonysoft:traute-gradle:1.1.10", pluginId: "tech.harmonysoft.oss.traute"),// 注解转非空判断 // 上传新版本插件更新 pluginPath 中的版本号,并设置 isApply = false diff --git a/config/flavor.gradle b/config/flavor.gradle new file mode 100644 index 0000000000..25c1801983 --- /dev/null +++ b/config/flavor.gradle @@ -0,0 +1,22 @@ +android { + flavorDimensions "env" + productFlavors { + dev { + dimension "env" + } + + production { + dimension "env" + } + } + + variantFilter { variant -> + def flavorNames = variant.flavors*.name + def buildTypeName = variant.buildType.name + + // production 包不允许 debug 构建 + if (flavorNames.contains("production") && buildTypeName.contains("debug")) { + variant.setIgnore(true) + } + } +} \ No newline at end of file diff --git a/config/publish.gradle b/config/publish.gradle new file mode 100644 index 0000000000..af97da785b --- /dev/null +++ b/config/publish.gradle @@ -0,0 +1,237 @@ +/* + 1. add + signing.keyId=xx + signing.password=xx + signing.secretKeyRingFile=/Users/xx/secring.gpg + ossrhUsername=xx + ossrhPassword=xx + in root local.properties + + 2. copy the file to the directory of gradle, and apply the file in the module + ext { + groupId = Config.depConfig.lib_utilcode.groupId + artifactId = Config.depConfig.lib_utilcode.artifactId + version = Config.depConfig.lib_utilcode.version + website = "https://github.com/Blankj/AndroidUtilCode" +} + apply from: "${rootDir.path}/config/publish.gradle" + + 3. execute following command to publish + ./gradlew :xxmodule:publish2Local -> upload to mavenCentral + ./gradlew :xxmodule:publish2Remote -> upload to mavenLocal +*/ + +apply plugin: 'maven-publish' +apply plugin: 'signing' + +ext.multiPublishMode = true + +File localPropertiesFile = project.rootProject.file("local.properties"); +if (localPropertiesFile.exists()) { + Properties properties = new Properties() + properties.load(new FileInputStream(localPropertiesFile)) + properties.each { name, value -> ext[name] = value } +} else { + if (!ext["signing.keyId"] && !ext["signing.password"] && + !ext["signing.secretKeyRingFile"] && + !ext["ossrhUsername"] && + !ext["ossrhPassword"]) { + throw new NullPointerException("U should set MavenCentral params in local.properties") + } +} + +afterEvaluate { + def ext = project.ext + publishing { + publications { + release(MavenPublication) { + groupId ext.groupId + artifactId ext.artifactId + version ext.version + + if (isAndroidEnv(project)) { + if (project.ext.multiPublishMode) { + artifact("$buildDir/outputs/aar/${project.getName()}-release.aar") + artifact sourcesJar + } else { + from project.components.release + } + } else { + from project.components.java + } + + pom { + name = ext.artifactId + description = ext.artifactId + url = ext.website + + licenses { + license { + name = 'The Apache Software License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = ext.ossrhUsername + name = ext.ossrhUsername + } + } + scm { + url = ext.website + connection = ext.website + developerConnection = ext.website + ".git" + } + + if (project.ext.multiPublishMode) { + withXml { + def dependenciesNode = asNode().getAt('dependencies')[0] ?: + asNode().appendNode('dependencies') + + configurations. + api. + getDependencies(). + each { dep -> addDependency(project, dependenciesNode, dep, "compile") } + configurations. + implementation. + getDependencies(). + each { dep -> addDependency(project, dependenciesNode, dep, "runtime") } + } + } + } + } + } + + repositories { + maven { + // s01 is newest + def releasesUrl = "https://s01.oss.sonatype.org/content/repositories/releases/" + def snapshotUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" + url = version.toUpperCase().endsWith('SNAPSHOT') ? snapshotUrl : releasesUrl + + credentials { + username ossrhUsername + password ossrhPassword + } + } + } + } + + signing { + sign publishing.publications + } +} + +private void addDependency(Project project, def dependenciesNode, Dependency dep, String scope) { + if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified") { + return + } + + final dependencyNode = dependenciesNode.appendNode('dependency') + dependencyNode.appendNode('scope', scope) + + if (dep.version == 'unspecified') { + // 检测 module 中的 dependencies 是否有源码依赖 + // 如果是源码依赖,而且没有在 config 中配置 remotePath, + // 那么发布到仓库,其他地方依赖该库时会找不到源码的那个库 + println "publish -> module(unspecified) <${dep.group}:${dep.name}:${dep.version}>" + if (project.ext.groupId || project.ext.version) { + throw new GradleException( + "The module of <" + dep.name + "> should set groupId & version.") + } + // 源码依赖,但配置了 remotePath,让 pom 中写入 remotePath + println( + "publish -> module(wrapped) <${project.ext.groupId}:${name}:${project.ext.version}>") + + dependencyNode.appendNode('groupId', project.ext.pomGroupID) + dependencyNode.appendNode('artifactId', dep.name) + dependencyNode.appendNode('version', project.ext.pomVersion) + } else { + dependencyNode.appendNode('groupId', dep.group) + dependencyNode.appendNode('artifactId', dep.name) + dependencyNode.appendNode('version', dep.version) + println("publish -> library <${dep.group}:${dep.name}:${dep.version}>") + } + + if (!dep.transitive) { + // In case of non transitive dependency, + // all its dependencies should be force excluded from them POM file + final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion') + exclusionNode.appendNode('groupId', '*') + exclusionNode.appendNode('artifactId', '*') + } else if (!dep.properties.excludeRules.empty) { + // For transitive with exclusions, all exclude rules should be added to the POM file + final exclusions = dependencyNode.appendNode('exclusions') + dep.properties.excludeRules.each { ExcludeRule rule -> + final exclusionNode = exclusions.appendNode('exclusion') + exclusionNode.appendNode('groupId', rule.group ?: '*') + exclusionNode.appendNode('artifactId', rule.module ?: '*') + } + } +} + +if (isAndroidEnv(project)) { + // This generates sources.jar + task sourcesJar(type: Jar) { + classifier = 'sources' + from android.sourceSets.main.java.source + } + + task javadoc(type: Javadoc) { + source = android.sourceSets.main.java.source + classpath += configurations.compile + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } +} else { + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } +} + +if (project.hasProperty("kotlin")) { + // Disable creating javadocs + project.tasks.withType(Javadoc) { + enabled = false + } +} + +javadoc { + options { + encoding "UTF-8" + charSet 'UTF-8' + author true + version project.ext.version + links "http://docs.oracle.com/javase/7/docs/api" + title "${project.ext.artifactId} ${project.ext.version}" + } +} + +artifacts { + archives javadocJar + archives sourcesJar +} + +static def isAndroidEnv(Project project) { + return project.getPlugins().hasPlugin('com.android.application') || project. + getPlugins(). + hasPlugin('com.android.library') +} + +task publish2Local(type: GradleBuild) { + tasks = ['clean', 'assemble', 'publishReleasePublicationToMavenLocal'] +} + +task publish2Remote(type: GradleBuild) { + tasks = ['clean', 'assemble', 'publishReleasePublicationToMavenRepository'] +} \ No newline at end of file diff --git a/feature/utilcode/export/build.gradle b/feature/utilcode/export/build.gradle index cecc254461..815f9babe6 100644 --- a/feature/utilcode/export/build.gradle +++ b/feature/utilcode/export/build.gradle @@ -1,10 +1,8 @@ -apply from: "${rootDir.path}/gradle/publish.gradle" -publish { - def depConfig = Config.depConfig.feature_utilcode_export - name = "UtilCodeExport" - groupId = depConfig.groupId - artifactId = depConfig.artifactId - version = depConfig.version - website = "https://github.com/Blankj/UtilCodeExport" +ext { + groupId = Config.depConfig.feature_utilcode_export.groupId + artifactId = Config.depConfig.feature_utilcode_export.artifactId + version = Config.depConfig.feature_utilcode_export.version + website = "https://github.com/Blankj/AndroidUtilCode" } +apply from: "${rootDir.path}/config/publish.gradle" //./gradlew :feature_utilcode_export:mavenLocal // 上传到本地 mavenLocal \ No newline at end of file diff --git a/gradle/publish.gradle b/gradle/publish.gradle deleted file mode 100644 index 76bb5fea66..0000000000 --- a/gradle/publish.gradle +++ /dev/null @@ -1,237 +0,0 @@ -/* - 1. must add the following classpath in root build.gradle - classpath "com.github.dcendents:android-maven-gradle-plugin:2.1" - classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4" - - 2. add bintrayUser, bintrayKey in root local.properties - - 3. copy the file to the directory of gradle, and apply the file in the module - apply from: "${rootDir.path}/gradle/publish.gradle" - publish { - name = "UtilCode" - groupId = "com.blankj" - artifactId = "utilcode" - version = "xx.xx" - website = "https://github.com/Blankj/AndroidUtilCode" - } - - 4. execute following command to publish - ./gradlew bintrayUpload -> upload to bintray - ./gradlew mavenLocal -> upload to local maven -*/ - -apply plugin: "com.github.dcendents.android-maven" -apply plugin: "com.jfrog.bintray" - -extensions.create('publish', PublishExtension) - -afterEvaluate { - def ext = project['publish'] as PublishExtension - loadBintray(ext) - configMaven(project, ext) - configBintray(project, ext) - configJavadoc(project, ext) -} - -private void loadBintray(PublishExtension ext) { - Properties properties = new Properties() - File localPropertiesFile = project.rootProject.file("local.properties"); - if (localPropertiesFile.exists()) { - properties.load(localPropertiesFile.newDataInputStream()) - ext.bintrayUser = properties.getProperty("bintrayUser") - ext.bintrayKey = properties.getProperty("bintrayKey") - } -} - -def configMaven(Project project, PublishExtension ext) { - project.group = ext.groupId - project.version = ext.version - - project.install { - repositories.mavenInstaller { - configPom(pom, ext) - } - } - - project.tasks.create("mavenLocal", Upload) { - group("publishing") - configuration = project.configurations.archives - - repositories.mavenDeployer { - repository(url: uri("${project.rootDir.path}/mavenLocal")) - configPom(pom, ext) - } - - doFirst { - ext.check(false) - } - } - - project.tasks.findByName("bintrayUpload").doFirst { - ext.check(true) - } -} - -def configPom(pom, PublishExtension ext) { - pom.project { - name ext.name - groupId ext.groupId - artifactId ext.artifactId - version ext.version - packaging isAndroid() ? "aar" : "jar" - description ext.name - url ext.website - - scm { - url ext.website - connection ext.website - developerConnection ext.website + ".git" - } - - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - - developers { - developer { - id ext.bintrayUser - name ext.bintrayUser - } - } - } - - pom.whenConfigured { - // 检测 module 中的 dependencies 是否有源码依赖 - // 如果是源码依赖,而且没有在 config 中配置 remotePath,那么发布到仓库,其他地方依赖该库时会找不到源码的那个库 - it.dependencies.findAll { dep -> dep.version == "unspecified" }.collect { dep -> - DepConfig config = Config.depConfig.get(dep.artifactId) - if (config == null || config.version == null) { - // 源码依赖而且没有在 config 中配置 remotePath,直接报错 - System.err.println("The module of <" + dep.artifactId + "> should publish to maven first.") - throw new RuntimeException() - } - dep.groupId = config.groupId - dep.version = config.version - // 源码依赖,但配置了 remotePath,让 pom 中写入 remotePath - GLog.l("Please check <${dep.groupId}:${dep.artifactId}:${dep.version}> is published.") - } - } -} - -def configBintray(Project project, PublishExtension ext) { - project.bintray { - user = ext.bintrayUser - key = ext.bintrayKey - configurations = ['archives'] - override = false - publish = true - pkg { - repo = "maven" - name = ext.name - websiteUrl = ext.website - vcsUrl = ext.website + '.git' - licenses = ["Apache-2.0"] - } - } -} - -private void configJavadoc(Project project, PublishExtension ext) { - if (isAndroid()) { - // This generates sources.jar - task sourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.source - } - - task javadoc(type: Javadoc) { - source = android.sourceSets.main.java.source - classpath += configurations.compile - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - } - - task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir - } - } else { - task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource - } - - task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir - } - } - - if (project.hasProperty("kotlin")) { - // Disable creating javadocs - project.tasks.withType(Javadoc) { - enabled = false - } - } - - javadoc { - options { - encoding "UTF-8" - charSet 'UTF-8' - author true - version ext.version - links "http://docs.oracle.com/javase/7/docs/api" - title "${ext.name} ${ext.version}" - } - } - - artifacts { - archives javadocJar - archives sourcesJar - } -} - -def isAndroid() { - return project.getPlugins().hasPlugin('com.android.application') || - project.getPlugins().hasPlugin('com.android.library') -} - -class PublishExtension { - String name - String groupId - String artifactId - String version - String website - - String bintrayUser - String bintrayKey - - void check(boolean isBintray) { - checkField(name, "name") - checkField(groupId, "groupId") - checkField(artifactId, "artifactId") - checkField(version, "version") - checkField(website, "website") - - if (isBintray) { - if (isBintrayEmpty()) { - throw new NullPointerException("U should set bintrayUser and bintrayKey in local.properties") - } - } - } - - boolean isBintrayEmpty() { - return isEmpty(bintrayUser) || isEmpty(bintrayKey) - } - - static void checkField(String field, String fieldName) { - if (isEmpty(field)) { - throw new NullPointerException("$fieldName is empty!!") - } - } - - static boolean isEmpty(String str) { - return str == null || str.length() == 0 - } -} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e4718dff4d..1e0ae1a108 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip diff --git a/lib/subutil/build.gradle b/lib/subutil/build.gradle index a561916f3e..1d2b458537 100644 --- a/lib/subutil/build.gradle +++ b/lib/subutil/build.gradle @@ -1,5 +1,5 @@ apply { - plugin Config.depConfig.plugin_traute.pluginId +// plugin Config.depConfig.plugin_traute.pluginId plugin "readme-sub" } diff --git a/lib/utilcode/build.gradle b/lib/utilcode/build.gradle index 891f7dbf40..612969a45c 100644 --- a/lib/utilcode/build.gradle +++ b/lib/utilcode/build.gradle @@ -1,5 +1,5 @@ apply { - plugin Config.depConfig.plugin_traute.pluginId + // plugin Config.depConfig.plugin_traute.pluginId plugin "readme-core" } @@ -29,7 +29,7 @@ android { dependencies { implementation Config.depConfig.gson.dep - compileOnly Config.depConfig.androidx_appcompat.dep + implementation Config.depConfig.androidx_appcompat.dep compileOnly Config.depConfig.androidx_material.dep testImplementation Config.depConfig.test_junit.dep @@ -39,15 +39,10 @@ dependencies { testImplementation Config.depConfig.eventbus_lib.dep } -afterEvaluate { - verifyReleaseResources.enabled(false) -} - -apply from: "${rootDir.path}/gradle/publish.gradle" -publish { - name = "UtilCodeX" +ext { groupId = Config.depConfig.lib_utilcode.groupId artifactId = Config.depConfig.lib_utilcode.artifactId version = Config.depConfig.lib_utilcode.version website = "https://github.com/Blankj/AndroidUtilCode" -} \ No newline at end of file +} +apply from: "${rootDir.path}/config/publish.gradle" \ No newline at end of file diff --git a/lib/utilcode/src/main/AndroidManifest.xml b/lib/utilcode/src/main/AndroidManifest.xml index 4cf4fe1090..fc5b75e0e3 100644 --- a/lib/utilcode/src/main/AndroidManifest.xml +++ b/lib/utilcode/src/main/AndroidManifest.xml @@ -18,7 +18,7 @@ = Build.VERSION_CODES.N) { - String authority = Utils.getApp().getPackageName() + ".utilcode.provider"; + String authority = Utils.getApp().getPackageName() + ".utilcode.fileprovider"; return FileProvider.getUriForFile(Utils.getApp(), authority, file); } else { return Uri.fromFile(file); diff --git a/lib/utildebug/build.gradle b/lib/utildebug/build.gradle index 4dd4682f3c..22f1f7294b 100644 --- a/lib/utildebug/build.gradle +++ b/lib/utildebug/build.gradle @@ -1,7 +1,3 @@ -afterEvaluate { - verifyReleaseResources.enabled(false) -} - dependencies { compileOnly Config.depConfig.androidx_appcompat.dep compileOnly Config.depConfig.androidx_material.dep diff --git a/plugin/api-gradle-plugin/build.gradle b/plugin/api-gradle-plugin/build.gradle index 8b859f35a6..2f6b956ee0 100755 --- a/plugin/api-gradle-plugin/build.gradle +++ b/plugin/api-gradle-plugin/build.gradle @@ -31,14 +31,12 @@ sourceSets { } } -apply from: "${rootDir.path}/gradle/publish.gradle" -publish { - name = "ApiPlugin" +ext { groupId = Config.depConfig.plugin_api.groupId artifactId = Config.depConfig.plugin_api.artifactId version = Config.depConfig.plugin_api.version website = "https://github.com/Blankj/AndroidUtilCode" } - +apply from: "${rootDir.path}/config/publish.gradle" //./gradlew clean :plugin_api-gradle-plugin:mavenLocal // 上传到本地 mavenLocal //./gradlew clean :plugin_api-gradle-plugin:bintrayUpload // 上传到 jcenter diff --git a/plugin/bus-gradle-plugin/build.gradle b/plugin/bus-gradle-plugin/build.gradle index ec264eaf4e..7cd24042a7 100755 --- a/plugin/bus-gradle-plugin/build.gradle +++ b/plugin/bus-gradle-plugin/build.gradle @@ -31,14 +31,12 @@ sourceSets { } } -apply from: "${rootDir.path}/gradle/publish.gradle" -publish { - name = "BusPlugin" +ext { groupId = Config.depConfig.plugin_bus.groupId artifactId = Config.depConfig.plugin_bus.artifactId version = Config.depConfig.plugin_bus.version website = "https://github.com/Blankj/AndroidUtilCode" } - +apply from: "${rootDir.path}/config/publish.gradle" //./gradlew clean :plugin_bus-gradle-plugin:mavenLocal // 上传到本地 mavenLocal //./gradlew clean :plugin_bus-gradle-plugin:bintrayUpload // 上传到 jcenter \ No newline at end of file diff --git a/plugin/lib/base-transform/build.gradle b/plugin/lib/base-transform/build.gradle index 72d0abe453..3518481ebd 100755 --- a/plugin/lib/base-transform/build.gradle +++ b/plugin/lib/base-transform/build.gradle @@ -18,14 +18,12 @@ sourceSets { } } -apply from: "${rootDir.path}/gradle/publish.gradle" -publish { - name = "BaseTransform" +ext { groupId = Config.depConfig.plugin_lib_base_transform.groupId artifactId = Config.depConfig.plugin_lib_base_transform.artifactId version = Config.depConfig.plugin_lib_base_transform.version website = "https://github.com/Blankj/AndroidUtilCode" } - +apply from: "${rootDir.path}/config/publish.gradle" //./gradlew clean plugin:lib:plugin_lib_base-transform:mavenLocal // 上传到本地 mavenLocal //./gradlew clean plugin:lib:plugin_lib_base-transform:bintrayUpload // 上传到 gradle 插件库中 diff --git a/script/clean.sh b/script/clean.sh deleted file mode 100755 index 2ff72056bb..0000000000 --- a/script/clean.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -rm -rf .idea -find . -name "*.iml" -type f -exec rm -rf {} \; -find . -name "build" -type d -exec rm -rf {} \; \ No newline at end of file diff --git a/script/gitHelp.sh b/script/gitHelp.sh new file mode 100755 index 0000000000..af98ce2ac6 --- /dev/null +++ b/script/gitHelp.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +while true; do + echo " ############## input command code #################" + echo " # [1] Git Push #" + echo " # [2] Git Push And Merge to Master #" + echo " # [other] exit #" + echo " ###################################################" + + read which + + case $which in + 1) + curBranch=$(git symbolic-ref --short -q HEAD) + gitPush $curBranch + ;; + 2) + curBranch=$(git symbolic-ref --short -q HEAD) + gitPush $curBranch + echo "git checkout master" + echo $(git checkout master) + echo "git merge $branchName" + echo $(git merge $branchName) + echo "git push origin master" + echo $(git push origin master) + echo "git checkout $branchName" + echo $(git checkout $branchName) + ;; + *) + echo "88" + break + ;; + esac +done + +function gitPush() { + curBranch=$1 + echo "curBranch = $curBranch" + echo "git add -A" + echo $(git add -A) + date=$(date "+%m/%d") + echo "git commit -m \"see $date log\"" + echo $(git commit -m "see $date log") + echo "git push origin $curBranch" + echo $(git push origin $curBranch) +} diff --git a/script/runDevDebug.sh b/script/runDevDebug.sh new file mode 100755 index 0000000000..e42394e0c8 --- /dev/null +++ b/script/runDevDebug.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e + +# build dev debug apk +./gradlew --daemon installDevDebug + +# start main activity +adb shell am start -n "com.blankj.androidutilcode.dev/com.blankj.main.pkg.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER \ No newline at end of file diff --git a/script/runProductionRelease.sh b/script/runProductionRelease.sh new file mode 100755 index 0000000000..a3d44d5ede --- /dev/null +++ b/script/runProductionRelease.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e + +# build dev debug apk +./gradlew --daemon installProductionRelease + +# start main activity +adb shell am start -n "com.blankj.androidutilcode/com.blankj.main.pkg.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER \ No newline at end of file From 8faee0b382724d3579921672f8a5dbb9c9360f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=AD=87=E5=B0=94?= Date: Wed, 22 Sep 2021 13:39:01 -0600 Subject: [PATCH 24/49] isUsingNetworkProvidedTime() Useful in situations where you want to verify that the device has a correct time set, to avoid fraud, or if you want to prevent the user from messing with the time and abusing your "one-time" and "expiring" features. --- .../java/com/blankj/utilcode/util/TimeUtils.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java index 2ab5370c82..88887b621f 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java @@ -36,6 +36,19 @@ protected Map initialValue() { private static SimpleDateFormat getDefaultFormat() { return getSafeDateFormat("yyyy-MM-dd HH:mm:ss"); } + /** + * Checks whether the device is using Network Provided Time or not. + * Useful in situations where you want to verify that the device has a correct time set, to avoid fraud, or if you want to prevent the user from messing with the time and abusing your "one-time" and "expiring" features. + * @return {@code true}: yes
{@code false}: no + */ + public static boolean isUsingNetworkProvidedTime() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + return Settings.Global.getInt(Utils.getApp().getContentResolver(), Settings.Global.AUTO_TIME, 0) == 1; + } else { + return android.provider.Settings.System.getInt(Utils.getApp().getContentResolver(), android.provider.Settings.System.AUTO_TIME, 0) == 1; + } + } + @SuppressLint("SimpleDateFormat") public static SimpleDateFormat getSafeDateFormat(String pattern) { From fb1f0d0a616bbbb326e9c7665887365c5dd064f9 Mon Sep 17 00:00:00 2001 From: jikun2008 Date: Wed, 10 Nov 2021 16:52:17 +0800 Subject: [PATCH 25/49] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit //这里会发生内存泄漏 如果不设置为null contentView.setTag(TAG_ON_GLOBAL_LAYOUT_LISTENER, null); --- .../src/main/java/com/blankj/utilcode/util/KeyboardUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java index 7f95fdee75..fd70fef220 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java @@ -238,6 +238,8 @@ public static void unregisterSoftInputChangedListener(@NonNull final Window wind if (tag instanceof OnGlobalLayoutListener) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { contentView.getViewTreeObserver().removeOnGlobalLayoutListener((OnGlobalLayoutListener) tag); + //这里会发生内存泄漏 如果不设置为null + contentView.setTag(TAG_ON_GLOBAL_LAYOUT_LISTENER, null); } } } From 9df5d7e15b06109153d0499c3f1ed1a3080c94ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=AD=87=E5=B0=94?= Date: Tue, 23 Nov 2021 22:19:24 +0100 Subject: [PATCH 26/49] 2 new methods: isJSONObject() and isJSONArray() Check if a given input is a JSONObject or a JSONArray. --- .../com/blankj/utilcode/util/JsonUtils.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/JsonUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/JsonUtils.java index ea40ac3162..43046adf5a 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/JsonUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/JsonUtils.java @@ -26,6 +26,27 @@ private JsonUtils() { throw new UnsupportedOperationException("u can't instantiate me..."); } + + /** + * Checks if a given input is a JSONObject. + * + * @param input Anything. + * @return true if it is a JSONObject. + */ + public static boolean isJSONObject(final T input) { + return input instanceof JSONObject; + } + + /** + * Checks if a given input is a JSONArray + * + * @param input Anything. + * @return true if it is a JSONArray. + */ + public static boolean isJSONArray(final T input) { + return input instanceof JSONArray; + } + public static boolean getBoolean(final JSONObject jsonObject, final String key) { return getBoolean(jsonObject, key, false); From e40b6d40b55cfb3608cd954d6bdd1feac67b94ca Mon Sep 17 00:00:00 2001 From: caimengjie Date: Mon, 6 Dec 2021 00:00:20 +0800 Subject: [PATCH 27/49] opt: Config --- build.gradle | 4 +- buildApp.gradle | 43 ++-- buildCommon.gradle | 5 + buildLib.gradle | 2 +- buildSrc/settings.gradle | 8 + buildSrc/src/main/groovy/Config.groovy | 114 ++++----- buildSrc/src/main/groovy/ConfigUtils.groovy | 45 ++-- buildSrc/src/main/groovy/DepConfig.groovy | 93 ------- buildSrc/src/main/groovy/GitUtils.groovy | 111 --------- buildSrc/src/main/groovy/LibConfig.groovy | 29 +++ buildSrc/src/main/groovy/ModuleConfig.groovy | 35 +++ buildSrc/src/main/groovy/PluginConfig.groovy | 35 +++ buildSrc/src/main/groovy/ShellUtils.java | 228 ------------------ .../src/main/groovy/TaskDurationUtils.groovy | 5 + config.json | 28 --- config/publish.gradle | 52 ++-- feature/launcher/app/build.gradle | 2 +- feature/utilcode/export/build.gradle | 8 +- gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 55616 bytes gradlew | 88 ++++--- gradlew.bat | 190 ++++++++------- lib/base/build.gradle | 23 +- .../java/com/blankj/base/rv/BaseItem.java | 6 +- lib/common/build.gradle | 2 +- lib/subutil/build.gradle | 19 +- lib/utilcode/README-CN.md | 1 + lib/utilcode/build.gradle | 23 +- .../blankj/utilcode/util/ActivityUtils.java | 3 +- .../com/blankj/utilcode/util/AppUtils.java | 16 ++ .../com/blankj/utilcode/util/CrashUtils.java | 30 ++- .../blankj/utilcode/util/KeyboardUtils.java | 127 ++++++---- .../blankj/utilcode/util/MetaDataUtils.java | 2 +- .../com/blankj/utilcode/util/SpanUtils.java | 26 +- .../util/UtilsActivityLifecycleImpl.java | 19 +- lib/utildebug/build.gradle | 16 +- .../com/blankj/utildebug/menu/DebugMenu.java | 1 + module_config.gradle | 72 ++++++ module_config.json | 30 +++ module_config.yaml | 91 +++++++ plugin/api-gradle-plugin/build.gradle | 20 +- plugin/buildSrc-plugin/.gitignore | 1 + plugin/buildSrc-plugin/build.gradle | 37 +++ .../com/blankj/buildSrc/BuildSrcPlugin.groovy | 13 + .../java/com/blankj/buildSrc/ModuleCfg.groovy | 80 ++++++ plugin/bus-gradle-plugin/build.gradle | 18 +- plugin/lib/base-transform/build.gradle | 14 +- settings.gradle | 112 +++------ 47 files changed, 968 insertions(+), 959 deletions(-) create mode 100644 buildSrc/settings.gradle delete mode 100644 buildSrc/src/main/groovy/DepConfig.groovy delete mode 100644 buildSrc/src/main/groovy/GitUtils.groovy create mode 100644 buildSrc/src/main/groovy/LibConfig.groovy create mode 100644 buildSrc/src/main/groovy/ModuleConfig.groovy create mode 100644 buildSrc/src/main/groovy/PluginConfig.groovy delete mode 100644 buildSrc/src/main/groovy/ShellUtils.java delete mode 100644 config.json create mode 100644 module_config.gradle create mode 100644 module_config.json create mode 100644 module_config.yaml create mode 100755 plugin/buildSrc-plugin/.gitignore create mode 100755 plugin/buildSrc-plugin/build.gradle create mode 100644 plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/BuildSrcPlugin.groovy create mode 100644 plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/ModuleCfg.groovy diff --git a/build.gradle b/build.gradle index 133f032278..e0f0f36c87 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { dependencies { for (def entrySet : ConfigUtils.getApplyPlugins().entrySet()) { - classpath entrySet.value.dep + classpath entrySet.value.path } } } @@ -29,7 +29,7 @@ allprojects { resolutionStrategy.eachDependency { if (it.requested.group == 'com.android.support' && !it.requested.name.contains( - 'multidex')) { + 'multidex')) { it.useVersion Config.supportVersion } } diff --git a/buildApp.gradle b/buildApp.gradle index d7ed2c75a3..93f0b9b1d4 100644 --- a/buildApp.gradle +++ b/buildApp.gradle @@ -1,29 +1,30 @@ +apply plugin: "com.android.application" + apply { - plugin "com.android.application" from "${rootDir.path}/buildCommon.gradle" from "${rootDir.path}/config/flavor.gradle" - if (Config.depConfig.plugin_api.isApply) { - plugin Config.depConfig.plugin_api.pluginId + if (Config.plugins.plugin_api.isApply) { + plugin Config.plugins.plugin_api.id } - if (Config.depConfig.plugin_bus.isApply) { - plugin Config.depConfig.plugin_bus.pluginId + if (Config.plugins.plugin_bus.isApply) { + plugin Config.plugins.plugin_bus.id } } configSigning() configApkName() -if (Config.depConfig.plugin_bus.isApply) { - bus { - onlyScanLibRegex = '^([:]|(com\\.blankj)).+$' - } -} - -if (Config.depConfig.plugin_api.isApply) { - api { - onlyScanLibRegex = '^([:]|(com\\.blankj)).+$' - } -} +//if (PluginConfig.plugin_bus.isApply) { +// bus { +// onlyScanLibRegex = '^([:]|(com\\.blankj)).+$' +// } +//} +// +//if (PluginConfig.plugin_api.isApply) { +// api { +// onlyScanLibRegex = '^([:]|(com\\.blankj)).+$' +// } +//} android { defaultConfig { @@ -67,18 +68,18 @@ android { dependencies { // LeakCanary - debugImplementation Config.depConfig.leakcanary.dep + debugImplementation Config.libs.leakcanary.path - debugImplementation Config.depConfig.lib_utildebug.dep - releaseImplementation Config.depConfig.lib_utildebug_no_op.dep + debugImplementation Config.modules.lib_utildebug.dep + releaseImplementation Config.modules.lib_utildebug_no_op.dep // 根据 Config.pkgConfig 来依赖所有 pkg for (def entrySet : ConfigUtils.getApplyPkgs().entrySet()) { api entrySet.value.dep } - if (Config.depConfig.feature_mock.isApply) { - api Config.depConfig.feature_mock.dep + if (Config.modules.feature_mock.isApply) { + api ModuleConfig.modules.feature_mock.dep } } diff --git a/buildCommon.gradle b/buildCommon.gradle index 8cbcc26255..2cba3ffea2 100644 --- a/buildCommon.gradle +++ b/buildCommon.gradle @@ -19,6 +19,11 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + lintOptions { abortOnError false } diff --git a/buildLib.gradle b/buildLib.gradle index ac9c42ac1c..aed207cbee 100644 --- a/buildLib.gradle +++ b/buildLib.gradle @@ -8,6 +8,6 @@ dependencies { api entrySet.value.dep } } else if (project.name.endsWith("_export")) { - api Config.depConfig.lib_common.dep + api Config.modules.lib_common.dep } } \ No newline at end of file diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle new file mode 100644 index 0000000000..8a313c3b99 --- /dev/null +++ b/buildSrc/settings.gradle @@ -0,0 +1,8 @@ +//dependencyResolutionManagement { +// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) +// repositories { +// google() +// mavenCentral() +// jcenter() // Warning: this repository is going to shut down soon +// } +//} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy index 4fb2b7ef2f..4a0b27a980 100644 --- a/buildSrc/src/main/groovy/Config.groovy +++ b/buildSrc/src/main/groovy/Config.groovy @@ -1,11 +1,3 @@ -/** - *
- *     author: blankj
- *     blog  : http://blankj.com
- *     time  : 2019/07/13
- *     desc  :
- * 
- */ class Config { static applicationId = 'com.blankj.androidutilcode' @@ -14,74 +6,84 @@ class Config { static compileSdkVersion = 29 static minSdkVersion = 14 static targetSdkVersion = 29 - static versionCode = 1_030_006 - static versionName = '1.30.7-alpha1'// E.g. 1.9.72 => 1,009,072 + static versionCode = 1_030_007 + static versionName = '1.31.0'// E.g. 1.9.72 => 1,009,072 // lib version static gradlePluginVersion = '4.1.0' static kotlinVersion = '1.3.72' static androidxVersion = '1.0.0' - static depConfig = [ - /*Never delete this line*/ - /*Generated by "config.json"*/ - plugin_api_gradle_plugin : new DepConfig(true , true , ":plugin:api-gradle-plugin"), - plugin_bus_gradle_plugin : new DepConfig(true , true , ":plugin:bus-gradle-plugin"), - plugin_lib_base_transform : new DepConfig(true , false, ":plugin:lib:base-transform", "com.blankj:base-transform:1.0"), - feature_mock : new DepConfig(false, true , ":feature:mock"), - feature_launcher_app : new DepConfig(true , true , ":feature:launcher:app"), - feature_main_app : new DepConfig(false, true , ":feature:main:app"), - feature_main_pkg : new DepConfig(true , true , ":feature:main:pkg"), - feature_subutil_app : new DepConfig(false, true , ":feature:subutil:app"), - feature_subutil_pkg : new DepConfig(true , true , ":feature:subutil:pkg"), - feature_subutil_export : new DepConfig(true , true , ":feature:subutil:export"), - feature_utilcode_app : new DepConfig(false, true , ":feature:utilcode:app"), - feature_utilcode_pkg : new DepConfig(true , true , ":feature:utilcode:pkg"), - feature_utilcode_export : new DepConfig(true , true , ":feature:utilcode:export", "com.blankj:utilcode-export:1.1"), - lib_base : new DepConfig(true , true , ":lib:base"), - lib_common : new DepConfig(true , true , ":lib:common"), - lib_subutil : new DepConfig(true , true , ":lib:subutil"), - lib_utilcode : new DepConfig(true , true , ":lib:utilcode", "com.blankj:utilcodex:$versionName"), - lib_utildebug : new DepConfig(true , true , ":lib:utildebug"), - lib_utildebug_no_op : new DepConfig(true , true , ":lib:utildebug-no-op"), - /*Never delete this line*/ - plugin_gradle : new DepConfig(pluginPath: "com.android.tools.build:gradle:$gradlePluginVersion"), - plugin_kotlin : new DepConfig(pluginPath: "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"), - plugin_traute : new DepConfig(pluginPath: "tech.harmonysoft:traute-gradle:1.1.10", pluginId: "tech.harmonysoft.oss.traute"),// 注解转非空判断 + static modules = [ + /*Don't delete this line*/ + /*Generated by "module_config.json"*/ + plugin_api_gradle_plugin : new ModuleConfig(isApply: true , useLocal: true , localPath: "./plugin/api-gradle-plugin"), + plugin_bus_gradle_plugin : new ModuleConfig(isApply: true , useLocal: true , localPath: "./plugin/bus-gradle-plugin"), + plugin_lib_base_transform : new ModuleConfig(isApply: true , useLocal: true , localPath: "./plugin/lib/base-transform", remotePath: "com.blankj:base-transform:1.0"), + plugin_buildSrc_plugin : new ModuleConfig(isApply: true , useLocal: true , localPath: "./plugin/buildSrc-plugin"), + feature_mock : new ModuleConfig(isApply: false, useLocal: true , localPath: "./feature/mock"), + feature_launcher_app : new ModuleConfig(isApply: true , useLocal: true , localPath: "./feature/launcher/app"), + feature_main_app : new ModuleConfig(isApply: false, useLocal: true , localPath: "./feature/main/app"), + feature_main_pkg : new ModuleConfig(isApply: true , useLocal: true , localPath: "./feature/main/pkg"), + feature_subutil_app : new ModuleConfig(isApply: false, useLocal: true , localPath: "./feature/subutil/app"), + feature_subutil_pkg : new ModuleConfig(isApply: true , useLocal: true , localPath: "./feature/subutil/pkg"), + feature_subutil_export : new ModuleConfig(isApply: true , useLocal: true , localPath: "./feature/subutil/export"), + feature_utilcode_app : new ModuleConfig(isApply: false, useLocal: true , localPath: "./feature/utilcode/app"), + feature_utilcode_pkg : new ModuleConfig(isApply: true , useLocal: true , localPath: "./feature/utilcode/pkg"), + feature_utilcode_export : new ModuleConfig(isApply: true , useLocal: true , localPath: "./feature/utilcode/export", remotePath: "com.blankj:utilcode-export:1.1"), + lib_base : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/base"), + lib_common : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/common"), + lib_subutil : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/subutil"), + lib_utilcode : new ModuleConfig(isApply: true , useLocal: false, localPath: "./lib/utilcode", remotePath: "com.blankj:utilcode:$Config.versionName"), + lib_utildebug : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug"), + lib_utildebug_no_op : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug-no-op"), + /*Don't delete this line*/ + ] + + static plugins = [ + plugin_gradle : new PluginConfig(path: "com.android.tools.build:gradle:$gradlePluginVersion"), + plugin_kotlin : new PluginConfig(path: "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"), + // 上传到 maven + plugin_maven : new PluginConfig(path: "com.github.dcendents:android-maven-gradle-plugin:2.1", id: "com.github.dcendents.android-maven"), - // 上传新版本插件更新 pluginPath 中的版本号,并设置 isApply = false + // 上传新版本插件更新 path 中的版本号,并设置 isApply = false // 通过 mavenLocal 上传本地版本,设置 isApply = true 即可应用插件来调试,最后通过 bintrayUpload 来发布插件 - plugin_api : new DepConfig(isApply: true, useLocal: false, pluginPath: "com.blankj:api-gradle-plugin:1.5", pluginId: "com.blankj.api"), + plugin_api : new PluginConfig(isApply: true, useLocal: false, path: "com.blankj:api-gradle-plugin:1.5", id: "com.blankj.api"), //./gradlew clean :plugin_api-gradle-plugin:mavenLocal // 上传到本地 mavenLocal //./gradlew clean :plugin_api-gradle-plugin:bintrayUpload // 上传到 jcenter - plugin_bus : new DepConfig(isApply: true, useLocal: false, pluginPath: "com.blankj:bus-gradle-plugin:2.6", pluginId: "com.blankj.bus"), + plugin_bus : new PluginConfig(isApply: true, useLocal: false, path: "com.blankj:bus-gradle-plugin:2.6", id: "com.blankj.bus"), //./gradlew clean :plugin_bus-gradle-plugin:mavenLocal // 上传到本地 mavenLocal //./gradlew clean :plugin_bus-gradle-plugin:bintrayUpload // 上传到 jcenter + plugin_buildSrc: new PluginConfig(isApply: true, useLocal: false, path: "com.blankj:buildSrc-plugin:1.0", id: "com.blankj.buildSrc"), + //./gradlew clean :plugin_bus-gradle-plugin:mavenLocal // 上传到本地 mavenLocal + //./gradlew clean :plugin_bus-gradle-plugin:bintrayUpload // 上传到 jcenter + ] - androidx_appcompat : new DepConfig("androidx.appcompat:appcompat:$androidxVersion"), - androidx_material : new DepConfig("com.google.android.material:material:$androidxVersion"), - androidx_multidex : new DepConfig("androidx.multidex:multidex:2.0.0"), - androidx_constraint : new DepConfig("androidx.constraintlayout:constraintlayout:1.1.3"), + static libs = [ + androidx_appcompat : new LibConfig(path: "androidx.appcompat:appcompat:$androidxVersion"), + androidx_material : new LibConfig(path: "com.google.android.material:material:$androidxVersion"), + androidx_multidex : new LibConfig(path: "androidx.multidex:multidex:2.0.0"), + androidx_constraint: new LibConfig(path: "androidx.constraintlayout:constraintlayout:1.1.3"), - kotlin : new DepConfig("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"), + kotlin : new LibConfig(path: "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"), - leakcanary : new DepConfig("com.squareup.leakcanary:leakcanary-android:2.1"), + leakcanary : new LibConfig(path: "com.squareup.leakcanary:leakcanary-android:2.1"), - free_proguard : new DepConfig("com.blankj:free-proguard:1.0.2"), - swipe_panel : new DepConfig("com.blankj:swipe-panel:1.2"), + free_proguard : new LibConfig(path: "com.blankj:free-proguard:1.0.2"), + swipe_panel : new LibConfig(path: "com.blankj:swipe-panel:1.2"), - gson : new DepConfig("com.google.code.gson:gson:2.8.5"), - glide : new DepConfig("com.github.bumptech.glide:glide:4.7.1"), - retrofit : new DepConfig("com.squareup.retrofit2:retrofit:2.4.0"), - commons_io : new DepConfig("commons-io:commons-io:2.6"), + gson : new LibConfig(path: "com.google.code.gson:gson:2.8.5"), + glide : new LibConfig(path: "com.github.bumptech.glide:glide:4.7.1"), + retrofit : new LibConfig(path: "com.squareup.retrofit2:retrofit:2.4.0"), + commons_io : new LibConfig(path: "commons-io:commons-io:2.6"), - eventbus_lib : new DepConfig("org.greenrobot:eventbus:3.1.1"), - eventbus_processor : new DepConfig("org.greenrobot:eventbus-annotation-processor:3.0.1"), + eventbus_lib : new LibConfig(path: "org.greenrobot:eventbus:3.1.1"), + eventbus_processor : new LibConfig(path: "org.greenrobot:eventbus-annotation-processor:3.0.1"), - photo_view : new DepConfig("com.github.chrisbanes:PhotoView:2.0.0"), + photo_view : new LibConfig(path: "com.github.chrisbanes:PhotoView:2.0.0"), - test_junit : new DepConfig("junit:junit:4.12"), - test_robolectric : new DepConfig("org.robolectric:robolectric:4.3.1"), + test_junit : new LibConfig(path: "junit:junit:4.12"), + test_robolectric : new LibConfig(path: "org.robolectric:robolectric:4.3.1"), ] } //./gradlew clean :lib_utilcode:bintrayUpload \ No newline at end of file diff --git a/buildSrc/src/main/groovy/ConfigUtils.groovy b/buildSrc/src/main/groovy/ConfigUtils.groovy index d60518fac5..6a09d2f2d9 100644 --- a/buildSrc/src/main/groovy/ConfigUtils.groovy +++ b/buildSrc/src/main/groovy/ConfigUtils.groovy @@ -17,7 +17,6 @@ class ConfigUtils { generateDep(gradle) addCommonGradle(gradle) TaskDurationUtils.init(gradle) - GitUtils.init(gradle) } /** @@ -25,16 +24,12 @@ class ConfigUtils { */ private static void generateDep(Gradle gradle) { def configs = [:] - for (Map.Entry entry : Config.depConfig.entrySet()) { + for (Map.Entry entry : Config.modules.entrySet()) { def (name, config) = [entry.key, entry.value] - if (entry.value.pluginPath) { - config.dep = config.pluginPath + if (config.useLocal) { + config.dep = gradle.rootProject.findProject(name) } else { - if (config.useLocal) { - config.dep = gradle.rootProject.findProject(config.projectPath) - } else { - config.dep = config.remotePath - } + config.dep = config.remotePath } configs.put(name, config) } @@ -46,20 +41,18 @@ class ConfigUtils { @Override void beforeEvaluate(Project project) { // 在 project 的 build.gradle 前 do sth. - if (project.subprojects.isEmpty()) { - if (project.path.startsWith(":plugin")) { - return + if (project.name.contains("plugin")) { + return + } + if (project.name.endsWith("_app")) { + GLog.l(project.toString() + " applies buildApp.gradle") + project.apply { + from "${project.rootDir.path}/buildApp.gradle" } - if (project.name.endsWith("_app")) { - GLog.l(project.toString() + " applies buildApp.gradle") - project.apply { - from "${project.rootDir.path}/buildApp.gradle" - } - } else { - GLog.l(project.toString() + " applies buildLib.gradle") - project.apply { - from "${project.rootDir.path}/buildLib.gradle" - } + } else { + GLog.l(project.toString() + " applies buildLib.gradle") + project.apply { + from "${project.rootDir.path}/buildLib.gradle" } } } @@ -73,8 +66,8 @@ class ConfigUtils { static getApplyPlugins() { def plugins = [:] - for (Map.Entry entry : Config.depConfig.entrySet()) { - if (entry.value.isApply && entry.value.pluginPath) { + for (Map.Entry entry : Config.plugins.entrySet()) { + if (entry.value.isApply) { plugins.put(entry.key, entry.value) } } @@ -84,7 +77,7 @@ class ConfigUtils { static getApplyPkgs() { def pkgs = [:] - for (Map.Entry entry : Config.depConfig.entrySet()) { + for (Map.Entry entry : Config.modules.entrySet()) { if (entry.value.isApply && entry.key.endsWith("_pkg")) { pkgs.put(entry.key, entry.value) } @@ -95,7 +88,7 @@ class ConfigUtils { static getApplyExports() { def exports = [:] - for (Map.Entry entry : Config.depConfig.entrySet()) { + for (Map.Entry entry : Config.modules.entrySet()) { if (entry.value.isApply && entry.key.endsWith("_export")) { exports.put(entry.key, entry.value) } diff --git a/buildSrc/src/main/groovy/DepConfig.groovy b/buildSrc/src/main/groovy/DepConfig.groovy deleted file mode 100644 index 042b67036d..0000000000 --- a/buildSrc/src/main/groovy/DepConfig.groovy +++ /dev/null @@ -1,93 +0,0 @@ -/** - *
- *     author: blankj
- *     blog  : http://blankj.com
- *     time  : 2019/07/13
- *     desc  :
- * 
- */ -class DepConfig { - boolean isApply // 是否应用 - boolean useLocal // 是否使用本地的 - String localPath // 本地路径 - String remotePath// 远程路径 - String pluginPath// 插件路径 - String pluginId // 插件 ID - def dep // 根据条件生成项目最终的依赖项 - - DepConfig() { - isApply = true - } - - DepConfig(String path) { - this(true, path) - } - - DepConfig(boolean isApply, String path) { - if (path.startsWith(":")) { - this.useLocal = true - this.localPath = path - this.isApply = isApply - } else { - this.useLocal = false - this.remotePath = path - this.isApply = isApply - } - } - - DepConfig(boolean useLocal, String localPath, String remotePath) { - this(true, useLocal, localPath, remotePath) - } - - DepConfig(boolean isApply, boolean useLocal, String localPath) { - this(isApply, useLocal, localPath, null) - } - - DepConfig(boolean isApply, boolean useLocal, String localPath, String remotePath) { - this.isApply = isApply - this.useLocal = useLocal - this.localPath = localPath - this.remotePath = remotePath - } - - void setPluginPath(String pluginPath) { - this.pluginPath = pluginPath - this.remotePath = pluginPath - } - - String getPath() { - if (pluginPath != null) return pluginPath - return useLocal ? localPath : remotePath - } - - String getGroupId() { - String[] splits = remotePath.split(":") - return splits.length == 3 ? splits[0] : null - } - - String getArtifactId() { - String[] splits = remotePath.split(":") - return splits.length == 3 ? splits[1] : null - } - - String getVersion() { - String[] splits = remotePath.split(":") - return splits.length == 3 ? splits[2] : null - } - - String getProjectPath() { - return ":" + localPath.substring(1).replace(":", "_") - } - - @Override - String toString() { - return "{ isApply = ${getFlag(isApply)}" + - ", useLocal = ${getFlag(useLocal)}" + - (dep == null ? ", path = " + path : (", dep = " + dep)) + - " }" - } - - static String getFlag(boolean b) { - return b ? "✅" : "❌" - } -} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/GitUtils.groovy b/buildSrc/src/main/groovy/GitUtils.groovy deleted file mode 100644 index f525377a79..0000000000 --- a/buildSrc/src/main/groovy/GitUtils.groovy +++ /dev/null @@ -1,111 +0,0 @@ -import org.gradle.api.Action -import org.gradle.api.Project -import org.gradle.api.invocation.Gradle - -import java.text.SimpleDateFormat - -/** - *
- *     author: blankj
- *     blog  : http://blankj.com
- *     time  : 2019/08/16
- *     desc  :
- * 
- */ -class GitUtils { - - private static Project rootProject; - - static void init(Gradle gradle) { - rootProject = gradle.rootProject - addGitHelpTask() - } - - static def addGitHelpTask() { - rootProject.task("gitHelp").doLast { - def commands = [ - " ############## input command code #################", - " # [1] Git Push #", - " # [2] Git Push And Merge to Master #", - " # [3] Git New Branch #", - " # [0] exit #", - " ###################################################", - ] - String commandTips = String.join(System.getProperty("line.separator"), commands) - while (true) { - GLog.l(commandTips) - Scanner scanner = new Scanner(System.in) - def input = scanner.next() - GLog.l(input) - switch (input) { - case "1": - gitPush() - break - case "2": - gitPushAndMerge2Master() - break - case "3": - gitNewBranch() - break - case "0": - return - } - } - } - } - - static void gitPush() { - String branchName = getGitBranch() - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd") - String date = simpleDateFormat.format(new Date()) - exeCmd( - "git add -A", - "git commit -m \"see $date log\"", - "git push origin $branchName" - ) - } - - static void gitPushAndMerge2Master() { - String branchName = getGitBranch() - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd") - String date = simpleDateFormat.format(new Date()) - exeCmd( - "git add -A", - "git commit -m \"see $date log\"", - "git push origin $branchName", - "git checkout master", - "git merge $branchName", - "git push origin master", - "git checkout $branchName" - ) - } - - static void gitNewBranch() { - exeCmd( - "git checkout master", - "git checkout -b ${Config.versionName}", - "git push origin ${Config.versionName}:${Config.versionName}", - ) - } - - private static def getGitBranch() { - return exeCmd("git symbolic-ref --short -q HEAD") - } - - private static def exeCmd(String... cmds) { - String output = "" - for (def cmd in cmds) { - output = _exeCmd(cmd) - } - return output - } - - private static def _exeCmd(String cmd) { - def output = new StringBuilder() - GLog.l("Execute command: ${cmd}") - def cmdResult = ShellUtils.execCmd(cmd) - GLog.l("$cmdResult") - return cmdResult.successMsg - } -} -// ./gradlew gitHelp diff --git a/buildSrc/src/main/groovy/LibConfig.groovy b/buildSrc/src/main/groovy/LibConfig.groovy new file mode 100644 index 0000000000..6369553ba0 --- /dev/null +++ b/buildSrc/src/main/groovy/LibConfig.groovy @@ -0,0 +1,29 @@ +class LibConfig { + + String path + + String getGroupId() { + String[] splits = path.split(":") + return splits.length == 3 ? splits[0] : null + } + + String getArtifactId() { + String[] splits = path.split(":") + return splits.length == 3 ? splits[1] : null + } + + String getVersion() { + String[] splits = path.split(":") + return splits.length == 3 ? splits[2] : null + } + + @Override + String toString() { + return "LibConfig { path = $path }" + } + + static String getFlag(boolean b) { + return b ? "✅" : "❌" + } +} + diff --git a/buildSrc/src/main/groovy/ModuleConfig.groovy b/buildSrc/src/main/groovy/ModuleConfig.groovy new file mode 100644 index 0000000000..291abd8ffe --- /dev/null +++ b/buildSrc/src/main/groovy/ModuleConfig.groovy @@ -0,0 +1,35 @@ +class ModuleConfig { + + boolean isApply // 是否应用 + boolean useLocal // 是否使用本地的 + String localPath // 本地路径 + String remotePath // 远程路径 + def dep // 根据条件生成项目最终的依赖项 + + String getGroupId() { + String[] splits = remotePath.split(":") + return splits.length == 3 ? splits[0] : null + } + + String getArtifactId() { + String[] splits = remotePath.split(":") + return splits.length == 3 ? splits[1] : null + } + + String getVersion() { + String[] splits = remotePath.split(":") + return splits.length == 3 ? splits[2] : null + } + + @Override + String toString() { + return "ModuleConfig { isApply = ${getFlag(isApply)}" + + ", dep = " + dep + + " }" + } + + static String getFlag(boolean b) { + return b ? "✅" : "❌" + } +} + diff --git a/buildSrc/src/main/groovy/PluginConfig.groovy b/buildSrc/src/main/groovy/PluginConfig.groovy new file mode 100644 index 0000000000..3811c6a0ca --- /dev/null +++ b/buildSrc/src/main/groovy/PluginConfig.groovy @@ -0,0 +1,35 @@ +final class PluginConfig { + + boolean isApply = true // 是否应用 + boolean useLocal // 是否使用本地的 + String path // 插件路径 + String id // 插件 ID + + String getGroupId() { + String[] splits = path.split(":") + return splits.length == 3 ? splits[0] : null + } + + String getArtifactId() { + String[] splits = path.split(":") + return splits.length == 3 ? splits[1] : null + } + + String getVersion() { + String[] splits = path.split(":") + return splits.length == 3 ? splits[2] : null + } + + @Override + String toString() { + return "PluginConfig { isApply = ${getFlag(isApply)}" + + ", useLocal = ${getFlag(useLocal)}" + + ", path = " + path + + ", id = " + id + + " }" + } + + static String getFlag(boolean b) { + return b ? "✅" : "❌" + } +} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/ShellUtils.java b/buildSrc/src/main/groovy/ShellUtils.java deleted file mode 100644 index ef4917c68e..0000000000 --- a/buildSrc/src/main/groovy/ShellUtils.java +++ /dev/null @@ -1,228 +0,0 @@ -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.List; - -/** - *
- *     author: Blankj
- *     blog  : http://blankj.com
- *     time  : 2016/08/07
- *     desc  : utils about shell
- * 
- */ -public final class ShellUtils { - - private static final String LINE_SEP = System.getProperty("line.separator"); - - private ShellUtils() { - throw new UnsupportedOperationException("u can't instantiate me..."); - } - - /** - * Execute the command. - * - * @param command The command. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final String command) { - return execCmd(new String[]{command}, false, true); - } - - /** - * Execute the command. - * - * @param command The command. - * @param isRooted True to use root, false otherwise. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final String command, final boolean isRooted) { - return execCmd(new String[]{command}, isRooted, true); - } - - /** - * Execute the command. - * - * @param commands The commands. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final List commands) { - return execCmd(commands == null ? null : commands.toArray(new String[]{}), false, true); - } - - /** - * Execute the command. - * - * @param commands The commands. - * @param isRooted True to use root, false otherwise. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final List commands, final boolean isRooted) { - return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRooted, true); - } - - /** - * Execute the command. - * - * @param commands The commands. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final String[] commands) { - return execCmd(commands, false, true); - } - - /** - * Execute the command. - * - * @param commands The commands. - * @param isRooted True to use root, false otherwise. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final String[] commands, final boolean isRooted) { - return execCmd(commands, isRooted, true); - } - - /** - * Execute the command. - * - * @param command The command. - * @param isRooted True to use root, false otherwise. - * @param isNeedResultMsg True to return the message of result, false otherwise. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final String command, - final boolean isRooted, - final boolean isNeedResultMsg) { - return execCmd(new String[]{command}, isRooted, isNeedResultMsg); - } - - /** - * Execute the command. - * - * @param commands The commands. - * @param isRooted True to use root, false otherwise. - * @param isNeedResultMsg True to return the message of result, false otherwise. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final List commands, - final boolean isRooted, - final boolean isNeedResultMsg) { - return execCmd(commands == null ? null : commands.toArray(new String[]{}), - isRooted, - isNeedResultMsg); - } - - /** - * Execute the command. - * - * @param commands The commands. - * @param isRooted True to use root, false otherwise. - * @param isNeedResultMsg True to return the message of result, false otherwise. - * @return the single {@link CommandResult} instance - */ - public static CommandResult execCmd(final String[] commands, - final boolean isRooted, - final boolean isNeedResultMsg) { - int result = -1; - if (commands == null || commands.length == 0) { - return new CommandResult(result, "", ""); - } - Process process = null; - BufferedReader successResult = null; - BufferedReader errorResult = null; - StringBuilder successMsg = null; - StringBuilder errorMsg = null; - DataOutputStream os = null; - try { - process = Runtime.getRuntime().exec(isRooted ? "su" : "sh"); - os = new DataOutputStream(process.getOutputStream()); - for (String command : commands) { - if (command == null) continue; - os.write(command.getBytes()); - os.writeBytes(LINE_SEP); - os.flush(); - } - os.writeBytes("exit" + LINE_SEP); - os.flush(); - result = process.waitFor(); - if (isNeedResultMsg) { - successMsg = new StringBuilder(); - errorMsg = new StringBuilder(); - successResult = new BufferedReader( - new InputStreamReader(process.getInputStream(), "UTF-8") - ); - errorResult = new BufferedReader( - new InputStreamReader(process.getErrorStream(), "UTF-8") - ); - String line; - if ((line = successResult.readLine()) != null) { - successMsg.append(line); - while ((line = successResult.readLine()) != null) { - successMsg.append(LINE_SEP).append(line); - } - } - if ((line = errorResult.readLine()) != null) { - errorMsg.append(line); - while ((line = errorResult.readLine()) != null) { - errorMsg.append(LINE_SEP).append(line); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (os != null) { - os.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - try { - if (successResult != null) { - successResult.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - try { - if (errorResult != null) { - errorResult.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - if (process != null) { - process.destroy(); - } - } - return new CommandResult( - result, - successMsg == null ? "" : successMsg.toString(), - errorMsg == null ? "" : errorMsg.toString() - ); - } - - /** - * The result of command. - */ - public static class CommandResult { - public int result; - public String successMsg; - public String errorMsg; - - public CommandResult(final int result, final String successMsg, final String errorMsg) { - this.result = result; - this.successMsg = successMsg; - this.errorMsg = errorMsg; - } - - @Override - public String toString() { - return "result: " + result + "\n" + - "successMsg: " + successMsg + "\n" + - "errorMsg: " + errorMsg; - } - } -} diff --git a/buildSrc/src/main/groovy/TaskDurationUtils.groovy b/buildSrc/src/main/groovy/TaskDurationUtils.groovy index 9ff2722345..6aacfcf30f 100644 --- a/buildSrc/src/main/groovy/TaskDurationUtils.groovy +++ b/buildSrc/src/main/groovy/TaskDurationUtils.groovy @@ -38,6 +38,11 @@ class TaskDurationUtils { } }) grd.addBuildListener(new BuildListener() { + @Override + void beforeSettings(Settings settings) { + super.beforeSettings(settings) + } + @Override void buildStarted(Gradle gradle) {} diff --git a/config.json b/config.json deleted file mode 100644 index c4c025e27b..0000000000 --- a/config.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "appConfigDesc": "appConfig 配置的是可以跑 app 的模块,git 提交务必只包含 launcher", - "appConfig": ["launcher"], - "pkgConfigDesc": "pkgConfig 配置的是要依赖的功能包,为空则依赖全部,git 提交务必为空", - "pkgConfig": [], - "proConfigDesc": "proConfig 配置的是使用本地还是仓库,优先级低于 appConfig 和 pkgConfig", - "proConfig": [ - {"isApply": true, "useLocal": true, "localPath": ":plugin:api-gradle-plugin"}, - {"isApply": true, "useLocal": true, "localPath": ":plugin:bus-gradle-plugin"}, - {"isApply": true, "useLocal": false, "localPath": ":plugin:lib:base-transform", "remotePath": "com.blankj:base-transform:1.0"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:mock"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:launcher:app"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:main:app"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:main:pkg"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:subutil:app"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:subutil:pkg"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:subutil:export"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:utilcode:app"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:utilcode:pkg"}, - {"isApply": true, "useLocal": true, "localPath": ":feature:utilcode:export", "remotePath": "com.blankj:utilcode-export:1.1"}, - {"isApply": true, "useLocal": true, "localPath": ":lib:base"}, - {"isApply": true, "useLocal": true, "localPath": ":lib:common"}, - {"isApply": true, "useLocal": true, "localPath": ":lib:subutil"}, - {"isApply": true, "useLocal": true, "localPath": ":lib:utilcode", "remotePath": "com.blankj:utilcodex:$versionName"}, - {"isApply": true, "useLocal": true, "localPath": ":lib:utildebug"}, - {"isApply": true, "useLocal": true, "localPath": ":lib:utildebug-no-op"} - ] -} diff --git a/config/publish.gradle b/config/publish.gradle index af97da785b..fa8a449f3c 100644 --- a/config/publish.gradle +++ b/config/publish.gradle @@ -9,16 +9,16 @@ 2. copy the file to the directory of gradle, and apply the file in the module ext { - groupId = Config.depConfig.lib_utilcode.groupId - artifactId = Config.depConfig.lib_utilcode.artifactId - version = Config.depConfig.lib_utilcode.version + groupId = Config.modules.lib_utilcode.groupId + artifactId = Config.modules.lib_utilcode.artifactId + version = Config.modules.lib_utilcode.version website = "https://github.com/Blankj/AndroidUtilCode" } apply from: "${rootDir.path}/config/publish.gradle" 3. execute following command to publish - ./gradlew :xxmodule:publish2Local -> upload to mavenCentral - ./gradlew :xxmodule:publish2Remote -> upload to mavenLocal + ./gradlew :xxmodule:publish2Local -> upload to mavenLocal + ./gradlew :xxmodule:publish2Remote -> upload to mavenCentral */ apply plugin: 'maven-publish' @@ -32,10 +32,8 @@ if (localPropertiesFile.exists()) { properties.load(new FileInputStream(localPropertiesFile)) properties.each { name, value -> ext[name] = value } } else { - if (!ext["signing.keyId"] && !ext["signing.password"] && - !ext["signing.secretKeyRingFile"] && - !ext["ossrhUsername"] && - !ext["ossrhPassword"]) { + if (!ext["signing.keyId"] && !ext["signing.password"] && !ext["signing.secretKeyRingFile"] + && !ext["ossrhUsername"] && !ext["ossrhPassword"]) { throw new NullPointerException("U should set MavenCentral params in local.properties") } } @@ -86,16 +84,14 @@ afterEvaluate { if (project.ext.multiPublishMode) { withXml { def dependenciesNode = asNode().getAt('dependencies')[0] ?: - asNode().appendNode('dependencies') - - configurations. - api. - getDependencies(). - each { dep -> addDependency(project, dependenciesNode, dep, "compile") } - configurations. - implementation. - getDependencies(). - each { dep -> addDependency(project, dependenciesNode, dep, "runtime") } + asNode().appendNode('dependencies') + + configurations.api.getDependencies().each { + dep -> addDependency(project, dependenciesNode, dep, "compile") + } + configurations.implementation.getDependencies().each { + dep -> addDependency(project, dependenciesNode, dep, "runtime") + } } } } @@ -136,12 +132,10 @@ private void addDependency(Project project, def dependenciesNode, Dependency dep // 那么发布到仓库,其他地方依赖该库时会找不到源码的那个库 println "publish -> module(unspecified) <${dep.group}:${dep.name}:${dep.version}>" if (project.ext.groupId || project.ext.version) { - throw new GradleException( - "The module of <" + dep.name + "> should set groupId & version.") + throw new GradleException("The module of <" + dep.name + "> should set groupId & version.") } // 源码依赖,但配置了 remotePath,让 pom 中写入 remotePath - println( - "publish -> module(wrapped) <${project.ext.groupId}:${name}:${project.ext.version}>") + println("publish -> module(wrapped) <${project.ext.groupId}:${name}:${project.ext.version}>") dependencyNode.appendNode('groupId', project.ext.pomGroupID) dependencyNode.appendNode('artifactId', dep.name) @@ -223,15 +217,9 @@ artifacts { } static def isAndroidEnv(Project project) { - return project.getPlugins().hasPlugin('com.android.application') || project. - getPlugins(). - hasPlugin('com.android.library') + return project.getPlugins().hasPlugin('com.android.application') || project.getPlugins().hasPlugin('com.android.library') } -task publish2Local(type: GradleBuild) { - tasks = ['clean', 'assemble', 'publishReleasePublicationToMavenLocal'] -} +task publish2Local(type: GradleBuild, dependsOn: ['clean', 'assemble', 'publishReleasePublicationToMavenLocal']) {} -task publish2Remote(type: GradleBuild) { - tasks = ['clean', 'assemble', 'publishReleasePublicationToMavenRepository'] -} \ No newline at end of file +task publish2Remote(type: GradleBuild, dependsOn: ['clean', 'assemble', 'publishReleasePublicationToMavenRepository']) {} \ No newline at end of file diff --git a/feature/launcher/app/build.gradle b/feature/launcher/app/build.gradle index 408db62a67..8f2b6d205d 100644 --- a/feature/launcher/app/build.gradle +++ b/feature/launcher/app/build.gradle @@ -1,5 +1,5 @@ apply plugin: 'kotlin-kapt' dependencies { - kapt Config.depConfig.eventbus_processor.dep + kapt Config.libs.eventbus_processor.path } \ No newline at end of file diff --git a/feature/utilcode/export/build.gradle b/feature/utilcode/export/build.gradle index 815f9babe6..30e59272ee 100644 --- a/feature/utilcode/export/build.gradle +++ b/feature/utilcode/export/build.gradle @@ -1,8 +1,8 @@ ext { - groupId = Config.depConfig.feature_utilcode_export.groupId - artifactId = Config.depConfig.feature_utilcode_export.artifactId - version = Config.depConfig.feature_utilcode_export.version + groupId = Config.modules.feature_utilcode_export.groupId + artifactId = Config.modules.feature_utilcode_export.artifactId + version = Config.modules.feature_utilcode_export.version website = "https://github.com/Blankj/AndroidUtilCode" } -apply from: "${rootDir.path}/config/publish.gradle" +//apply from: "${rootDir.path}/config/publish.gradle" //./gradlew :feature_utilcode_export:mavenLocal // 上传到本地 mavenLocal \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 13372aef5e24af05341d49695ee84e5f9b594659..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch literal 55616 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�J+L&6O)2CL%pxI@Gv&XXKx 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 V&}jHG \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +75,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +105,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +170,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 8a0b282aa6..15e1ee37a7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,100 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lib/base/build.gradle b/lib/base/build.gradle index bb7fa31573..b7eb9d588c 100644 --- a/lib/base/build.gradle +++ b/lib/base/build.gradle @@ -1,15 +1,14 @@ dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - api Config.depConfig.lib_subutil.dep - api Config.depConfig.lib_utilcode.dep + api Config.modules.lib_subutil.dep + api Config.modules.lib_utilcode.dep - api Config.depConfig.androidx_appcompat.dep - api Config.depConfig.androidx_material.dep - api Config.depConfig.androidx_multidex.dep - api Config.depConfig.androidx_constraint.dep - api Config.depConfig.kotlin.dep - api Config.depConfig.free_proguard.dep - api Config.depConfig.swipe_panel.dep - api Config.depConfig.eventbus_lib.dep - compileOnly Config.depConfig.lib_utildebug_no_op.dep + api Config.libs.androidx_appcompat.path + api Config.libs.androidx_material.path + api Config.libs.androidx_multidex.path + api Config.libs.androidx_constraint.path + api Config.libs.kotlin.path + api Config.libs.free_proguard.path + api Config.libs.swipe_panel.path + api Config.libs.eventbus_lib.path + compileOnly Config.modules.lib_utildebug_no_op.dep } \ No newline at end of file diff --git a/lib/base/src/main/java/com/blankj/base/rv/BaseItem.java b/lib/base/src/main/java/com/blankj/base/rv/BaseItem.java index 885fe1a6a5..b0d6de04fa 100644 --- a/lib/base/src/main/java/com/blankj/base/rv/BaseItem.java +++ b/lib/base/src/main/java/com/blankj/base/rv/BaseItem.java @@ -24,6 +24,7 @@ public abstract class BaseItem { private static final SparseIntArray LAYOUT_SPARSE_ARRAY = new SparseIntArray(); private static final SparseArray VIEW_SPARSE_ARRAY = new SparseArray<>(); + public boolean isBindViewHolder = false; static ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { int layoutByType = LAYOUT_SPARSE_ARRAY.get(viewType, -1); @@ -43,6 +44,7 @@ public void partialUpdate(List payloads) { } void bindViewHolder(@NonNull final ItemViewHolder holder, final int position) { + isBindViewHolder = true; if (mOnItemClickListener != null) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override @@ -73,7 +75,9 @@ public boolean onLongClick(View v) { bind(holder, position); } - public void onViewRecycled(@NonNull final ItemViewHolder holder, final int position) {/**/} + public void onViewRecycled(@NonNull final ItemViewHolder holder, final int position) { + isBindViewHolder = false; + } public long getItemId() { return RecyclerView.NO_ID; diff --git a/lib/common/build.gradle b/lib/common/build.gradle index c4bb45fba5..4993b43792 100644 --- a/lib/common/build.gradle +++ b/lib/common/build.gradle @@ -1,4 +1,4 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - api Config.depConfig.lib_base.dep + api Config.modules.lib_base.dep } \ No newline at end of file diff --git a/lib/subutil/build.gradle b/lib/subutil/build.gradle index 1d2b458537..8a697c5a1e 100644 --- a/lib/subutil/build.gradle +++ b/lib/subutil/build.gradle @@ -1,5 +1,4 @@ apply { -// plugin Config.depConfig.plugin_traute.pluginId plugin "readme-sub" } @@ -9,16 +8,16 @@ readme { } dependencies { - compileOnly Config.depConfig.androidx_appcompat.dep - compileOnly Config.depConfig.androidx_material.dep - compileOnly Config.depConfig.lib_utilcode.dep - api(Config.depConfig.glide.dep) { + compileOnly Config.libs.androidx_appcompat.path + compileOnly Config.libs.androidx_material.path + compileOnly Config.modules.lib_utilcode.dep + api(Config.libs.glide.path) { exclude group: "com.android.support" } - api Config.depConfig.retrofit.dep - api Config.depConfig.gson.dep + api Config.libs.retrofit.path + api Config.libs.gson.path - testImplementation Config.depConfig.lib_utilcode.dep - testImplementation Config.depConfig.test_junit.dep - testImplementation Config.depConfig.test_robolectric.dep + testImplementation Config.modules.lib_utilcode.dep + testImplementation Config.libs.test_junit.path + testImplementation Config.libs.test_robolectric.path } \ No newline at end of file diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md index e8edeb5927..79b18eef15 100644 --- a/lib/utilcode/README-CN.md +++ b/lib/utilcode/README-CN.md @@ -78,6 +78,7 @@ getAppSignaturesMD5 : 获取应用签名的的 MD5 值 getAppInfo : 获取 App 信息 getAppsInfo : 获取所有已安装 App 信息 getApkInfo : 获取 Apk 信息 +isFirstTimeInstalled : 判断应用是否首次安装 ``` * ### 数组相关 -> [ArrayUtils.java][array.java] -> [Test][array.test] diff --git a/lib/utilcode/build.gradle b/lib/utilcode/build.gradle index 612969a45c..37a43b0a66 100644 --- a/lib/utilcode/build.gradle +++ b/lib/utilcode/build.gradle @@ -1,5 +1,4 @@ apply { - // plugin Config.depConfig.plugin_traute.pluginId plugin "readme-core" } @@ -27,22 +26,22 @@ android { } dependencies { - implementation Config.depConfig.gson.dep + implementation Config.libs.gson.path - implementation Config.depConfig.androidx_appcompat.dep - compileOnly Config.depConfig.androidx_material.dep + implementation Config.libs.androidx_appcompat.path + compileOnly Config.libs.androidx_material.path - testImplementation Config.depConfig.test_junit.dep - testImplementation Config.depConfig.test_robolectric.dep - testImplementation Config.depConfig.androidx_appcompat.dep - testImplementation Config.depConfig.androidx_material.dep - testImplementation Config.depConfig.eventbus_lib.dep + testImplementation Config.libs.test_junit.path + testImplementation Config.libs.test_robolectric.path + testImplementation Config.libs.androidx_appcompat.path + testImplementation Config.libs.androidx_material.path + testImplementation Config.libs.eventbus_lib.path } ext { - groupId = Config.depConfig.lib_utilcode.groupId - artifactId = Config.depConfig.lib_utilcode.artifactId - version = Config.depConfig.lib_utilcode.version + groupId = Config.modules.lib_utilcode.groupId + artifactId = Config.modules.lib_utilcode.artifactId + version = Config.modules.lib_utilcode.version website = "https://github.com/Blankj/AndroidUtilCode" } apply from: "${rootDir.path}/config/publish.gradle" \ No newline at end of file diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java index 8191618118..10858f75f4 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java @@ -96,7 +96,8 @@ public static void removeActivityLifecycleCallbacks(@Nullable final Activity act * @return the activity by context. */ @Nullable - public static Activity getActivityByContext(@NonNull Context context) { + public static Activity getActivityByContext(@Nullable Context context) { + if (context == null) return null; Activity activity = getActivityByContextInner(context); if (!isActivityAlive(activity)) return null; return activity; diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java index 2a5b2ed4ef..8848cbd193 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java @@ -774,6 +774,22 @@ public static AppUtils.AppInfo getApkInfo(final String 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; diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/CrashUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/CrashUtils.java index 69ae961662..598f7fdbac 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/CrashUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/CrashUtils.java @@ -1,15 +1,12 @@ package com.blankj.utilcode.util; -import android.annotation.SuppressLint; - +import androidx.annotation.NonNull; import java.io.File; import java.lang.Thread.UncaughtExceptionHandler; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; -import androidx.annotation.NonNull; - /** *
  *     author: Blankj
@@ -22,7 +19,8 @@ public final class CrashUtils {
 
     private static final String FILE_SEP = System.getProperty("file.separator");
 
-    private static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
+    private static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER =
+        Thread.getDefaultUncaughtExceptionHandler();
 
     private CrashUtils() {
         throw new UnsupportedOperationException("u can't instantiate me...");
@@ -65,7 +63,7 @@ public static void init(final OnCrashListener onCrashListener) {
     /**
      * Initialization
      *
-     * @param crashDir        The directory of saving crash information.
+     * @param crashDir The directory of saving crash information.
      * @param onCrashListener The crash listener.
      */
     public static void init(@NonNull final File crashDir, final OnCrashListener onCrashListener) {
@@ -75,22 +73,23 @@ public static void init(@NonNull final File crashDir, final OnCrashListener onCr
     /**
      * Initialization
      *
-     * @param crashDirPath    The directory's path of saving crash information.
+     * @param crashDirPath The directory's path of saving crash information.
      * @param onCrashListener The crash listener.
      */
     public static void init(final String crashDirPath, final OnCrashListener onCrashListener) {
         String dirPath;
         if (UtilsBridge.isSpace(crashDirPath)) {
             if (UtilsBridge.isSDCardEnableByEnvironment()
-                    && Utils.getApp().getExternalFilesDir(null) != null)
+                && Utils.getApp().getExternalFilesDir(null) != null) {
                 dirPath = Utils.getApp().getExternalFilesDir(null) + FILE_SEP + "crash" + FILE_SEP;
-            else {
+            } else {
                 dirPath = Utils.getApp().getFilesDir() + FILE_SEP + "crash" + FILE_SEP;
             }
         } else {
             dirPath = crashDirPath.endsWith(FILE_SEP) ? crashDirPath : crashDirPath + FILE_SEP;
         }
-        Thread.setDefaultUncaughtExceptionHandler(getUncaughtExceptionHandler(dirPath, onCrashListener));
+        Thread.setDefaultUncaughtExceptionHandler(
+            getUncaughtExceptionHandler(dirPath, onCrashListener));
     }
 
     private static UncaughtExceptionHandler getUncaughtExceptionHandler(final String dirPath,
@@ -100,15 +99,15 @@ private static UncaughtExceptionHandler getUncaughtExceptionHandler(final String
             public void uncaughtException(@NonNull final Thread t, @NonNull final Throwable e) {
                 final String time = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss").format(new Date());
                 CrashInfo info = new CrashInfo(time, e);
-                if (onCrashListener != null) {
-                    onCrashListener.onCrash(info);
-                }
                 final String crashFile = dirPath + time + ".txt";
                 UtilsBridge.writeFileFromString(crashFile, info.toString(), true);
 
                 if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) {
                     DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(t, e);
                 }
+                if (onCrashListener != null) {
+                    onCrashListener.onCrash(info);
+                }
             }
         };
     }
@@ -123,7 +122,7 @@ public interface OnCrashListener {
 
     public static final class CrashInfo {
         private UtilsBridge.FileHead mFileHeadProvider;
-        private Throwable            mThrowable;
+        private Throwable mThrowable;
 
         private CrashInfo(String time, Throwable throwable) {
             mThrowable = throwable;
@@ -145,8 +144,7 @@ public final Throwable getThrowable() {
 
         @Override
         public String toString() {
-            return mFileHeadProvider.toString() +
-                    UtilsBridge.getFullStackTrace(mThrowable);
+            return mFileHeadProvider.toString() + UtilsBridge.getFullStackTrace(mThrowable);
         }
     }
 }
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java
index f2511e831f..c87687f8a1 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/KeyboardUtils.java
@@ -17,10 +17,9 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 import android.widget.FrameLayout;
-
-import java.lang.reflect.Field;
-
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import java.lang.reflect.Field;
 
 /**
  * 
@@ -42,7 +41,8 @@ private KeyboardUtils() {
      * Show the soft input.
      */
     public static void showSoftInput() {
-        InputMethodManager imm = (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
+        InputMethodManager imm =
+            (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
         if (imm == null) {
             return;
         }
@@ -52,7 +52,10 @@ public static void showSoftInput() {
     /**
      * Show the soft input.
      */
-    public static void showSoftInput(@NonNull Activity activity) {
+    public static void showSoftInput(@Nullable Activity activity) {
+        if (activity == null) {
+            return;
+        }
         if (!isSoftInputVisible(activity)) {
             toggleSoftInput();
         }
@@ -70,14 +73,16 @@ public static void showSoftInput(@NonNull final View view) {
     /**
      * Show the soft input.
      *
-     * @param view  The view.
+     * @param view The view.
      * @param flags Provides additional operating flags.  Currently may be
-     *              0 or have the {@link InputMethodManager#SHOW_IMPLICIT} bit set.
+     * 0 or have the {@link InputMethodManager#SHOW_IMPLICIT} bit set.
      */
     public static void showSoftInput(@NonNull final View view, final int flags) {
         InputMethodManager imm =
-                (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
-        if (imm == null) return;
+            (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (imm == null) {
+            return;
+        }
         view.setFocusable(true);
         view.setFocusableInTouchMode(true);
         view.requestFocus();
@@ -85,7 +90,7 @@ public static void showSoftInput(@NonNull final View view, final int flags) {
             @Override
             protected void onReceiveResult(int resultCode, Bundle resultData) {
                 if (resultCode == InputMethodManager.RESULT_UNCHANGED_HIDDEN
-                        || resultCode == InputMethodManager.RESULT_HIDDEN) {
+                    || resultCode == InputMethodManager.RESULT_HIDDEN) {
                     toggleSoftInput();
                 }
             }
@@ -98,7 +103,10 @@ protected void onReceiveResult(int resultCode, Bundle resultData) {
      *
      * @param activity The activity.
      */
-    public static void hideSoftInput(@NonNull final Activity activity) {
+    public static void hideSoftInput(@Nullable final Activity activity) {
+        if (activity == null) {
+            return;
+        }
         hideSoftInput(activity.getWindow());
     }
 
@@ -107,7 +115,10 @@ public static void hideSoftInput(@NonNull final Activity activity) {
      *
      * @param window The window.
      */
-    public static void hideSoftInput(@NonNull final Window window) {
+    public static void hideSoftInput(@Nullable final Window window) {
+        if (window == null) {
+            return;
+        }
         View view = window.getCurrentFocus();
         if (view == null) {
             View decorView = window.getDecorView();
@@ -131,8 +142,10 @@ public static void hideSoftInput(@NonNull final Window window) {
      */
     public static void hideSoftInput(@NonNull final View view) {
         InputMethodManager imm =
-                (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
-        if (imm == null) return;
+            (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (imm == null) {
+            return;
+        }
         imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
     }
 
@@ -143,7 +156,10 @@ public static void hideSoftInput(@NonNull final View view) {
      *
      * @param activity The activity.
      */
-    public static void hideSoftInputByToggle(final Activity activity) {
+    public static void hideSoftInputByToggle(@Nullable final Activity activity) {
+        if (activity == null) {
+            return;
+        }
         long nowMillis = SystemClock.elapsedRealtime();
         long delta = nowMillis - millis;
         if (Math.abs(delta) > 500 && KeyboardUtils.isSoftInputVisible(activity)) {
@@ -157,8 +173,10 @@ public static void hideSoftInputByToggle(final Activity activity) {
      */
     public static void toggleSoftInput() {
         InputMethodManager imm =
-                (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
-        if (imm == null) return;
+            (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (imm == null) {
+            return;
+        }
         imm.toggleSoftInput(0, 0);
     }
 
@@ -178,8 +196,8 @@ private static int getDecorViewInvisibleHeight(@NonNull final Window window) {
         final View decorView = window.getDecorView();
         final Rect outRect = new Rect();
         decorView.getWindowVisibleDisplayFrame(outRect);
-        Log.d("KeyboardUtils", "getDecorViewInvisibleHeight: "
-                + (decorView.getBottom() - outRect.bottom));
+        Log.d("KeyboardUtils",
+            "getDecorViewInvisibleHeight: " + (decorView.getBottom() - outRect.bottom));
         int delta = Math.abs(decorView.getBottom() - outRect.bottom);
         if (delta <= UtilsBridge.getNavBarHeight() + UtilsBridge.getStatusBarHeight()) {
             sDecorViewDelta = delta;
@@ -195,24 +213,26 @@ private static int getDecorViewInvisibleHeight(@NonNull final Window window) {
      * @param listener The soft input changed listener.
      */
     public static void registerSoftInputChangedListener(@NonNull final Activity activity,
-                                                        @NonNull final OnSoftInputChangedListener listener) {
+                                                        @NonNull
+                                                        final OnSoftInputChangedListener listener) {
         registerSoftInputChangedListener(activity.getWindow(), listener);
     }
 
     /**
      * Register soft input changed listener.
      *
-     * @param window   The window.
+     * @param window The window.
      * @param listener The soft input changed listener.
      */
     public static void registerSoftInputChangedListener(@NonNull final Window window,
-                                                        @NonNull final OnSoftInputChangedListener listener) {
+                                                        @NonNull
+                                                        final OnSoftInputChangedListener listener) {
         final int flags = window.getAttributes().flags;
         if ((flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) != 0) {
             window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
         }
         final FrameLayout contentView = window.findViewById(android.R.id.content);
-        final int[] decorViewInvisibleHeightPre = {getDecorViewInvisibleHeight(window)};
+        final int[] decorViewInvisibleHeightPre = { getDecorViewInvisibleHeight(window) };
         OnGlobalLayoutListener onGlobalLayoutListener = new OnGlobalLayoutListener() {
             @Override
             public void onGlobalLayout() {
@@ -234,11 +254,14 @@ public void onGlobalLayout() {
      */
     public static void unregisterSoftInputChangedListener(@NonNull final Window window) {
         final View contentView = window.findViewById(android.R.id.content);
-        if (contentView == null) return;
+        if (contentView == null) {
+            return;
+        }
         Object tag = contentView.getTag(TAG_ON_GLOBAL_LAYOUT_LISTENER);
         if (tag instanceof OnGlobalLayoutListener) {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-                contentView.getViewTreeObserver().removeOnGlobalLayoutListener((OnGlobalLayoutListener) tag);
+                contentView.getViewTreeObserver()
+                    .removeOnGlobalLayoutListener((OnGlobalLayoutListener) tag);
             }
         }
     }
@@ -261,36 +284,35 @@ public static void fixAndroidBug5497(@NonNull final Activity activity) {
      */
     public static void fixAndroidBug5497(@NonNull final Window window) {
         int softInputMode = window.getAttributes().softInputMode;
-        window.setSoftInputMode(softInputMode & ~WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+        window.setSoftInputMode(
+            softInputMode & ~WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
         final FrameLayout contentView = window.findViewById(android.R.id.content);
         final View contentViewChild = contentView.getChildAt(0);
         final int paddingBottom = contentViewChild.getPaddingBottom();
-        final int[] contentViewInvisibleHeightPre5497 = {getContentViewInvisibleHeight(window)};
-        contentView.getViewTreeObserver()
-                .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-                    @Override
-                    public void onGlobalLayout() {
-                        int height = getContentViewInvisibleHeight(window);
-                        if (contentViewInvisibleHeightPre5497[0] != height) {
-                            contentViewChild.setPadding(
-                                    contentViewChild.getPaddingLeft(),
-                                    contentViewChild.getPaddingTop(),
-                                    contentViewChild.getPaddingRight(),
-                                    paddingBottom + getDecorViewInvisibleHeight(window)
-                            );
-                            contentViewInvisibleHeightPre5497[0] = height;
-                        }
-                    }
-                });
+        final int[] contentViewInvisibleHeightPre5497 = { getContentViewInvisibleHeight(window) };
+        contentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+            @Override
+            public void onGlobalLayout() {
+                int height = getContentViewInvisibleHeight(window);
+                if (contentViewInvisibleHeightPre5497[0] != height) {
+                    contentViewChild.setPadding(contentViewChild.getPaddingLeft(),
+                        contentViewChild.getPaddingTop(), contentViewChild.getPaddingRight(),
+                        paddingBottom + getDecorViewInvisibleHeight(window));
+                    contentViewInvisibleHeightPre5497[0] = height;
+                }
+            }
+        });
     }
 
     private static int getContentViewInvisibleHeight(final Window window) {
         final View contentView = window.findViewById(android.R.id.content);
-        if (contentView == null) return 0;
+        if (contentView == null) {
+            return 0;
+        }
         final Rect outRect = new Rect();
         contentView.getWindowVisibleDisplayFrame(outRect);
-        Log.d("KeyboardUtils", "getContentViewInvisibleHeight: "
-                + (contentView.getBottom() - outRect.bottom));
+        Log.d("KeyboardUtils",
+            "getContentViewInvisibleHeight: " + (contentView.getBottom() - outRect.bottom));
         int delta = Math.abs(contentView.getBottom() - outRect.bottom);
         if (delta <= UtilsBridge.getStatusBarHeight() + UtilsBridge.getNavBarHeight()) {
             return 0;
@@ -314,9 +336,12 @@ public static void fixSoftInputLeaks(@NonNull final Activity activity) {
      */
     public static void fixSoftInputLeaks(@NonNull final Window window) {
         InputMethodManager imm =
-                (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
-        if (imm == null) return;
-        String[] leakViews = new String[]{"mLastSrvView", "mCurRootView", "mServedView", "mNextServedView"};
+            (InputMethodManager) Utils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (imm == null) {
+            return;
+        }
+        String[] leakViews =
+            new String[] { "mLastSrvView", "mCurRootView", "mServedView", "mNextServedView" };
         for (String leakView : leakViews) {
             try {
                 Field leakViewField = InputMethodManager.class.getDeclaredField(leakView);
@@ -324,7 +349,9 @@ public static void fixSoftInputLeaks(@NonNull final Window window) {
                     leakViewField.setAccessible(true);
                 }
                 Object obj = leakViewField.get(imm);
-                if (!(obj instanceof View)) continue;
+                if (!(obj instanceof View)) {
+                    continue;
+                }
                 View view = (View) obj;
                 if (view.getRootView() == window.getDecorView().getRootView()) {
                     leakViewField.set(imm, null);
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
index bd4b8da935..0ff8fa8798 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/MetaDataUtils.java
@@ -118,7 +118,7 @@ public static String getMetaDataInService(@NonNull final Class getActivitiesByReflect() {
         Activity topActivity = null;
         try {
             Object activityThread = getActivityThread();
+            if (activityThread == null) return list;
             Field mActivitiesField = activityThread.getClass().getDeclaredField("mActivities");
             mActivitiesField.setAccessible(true);
             Object mActivities = mActivitiesField.get(activityThread);
@@ -388,10 +381,10 @@ private List getActivitiesByReflect() {
                     if (!pausedField.getBoolean(activityRecord)) {
                         topActivity = activity;
                     } else {
-                        list.add(activity);
+                        list.addFirst(activity);
                     }
                 } else {
-                    list.add(activity);
+                    list.addFirst(activity);
                 }
             }
         } catch (Exception e) {
diff --git a/lib/utildebug/build.gradle b/lib/utildebug/build.gradle
index 22f1f7294b..d1c5a67273 100644
--- a/lib/utildebug/build.gradle
+++ b/lib/utildebug/build.gradle
@@ -1,12 +1,12 @@
 dependencies {
-    compileOnly Config.depConfig.androidx_appcompat.dep
-    compileOnly Config.depConfig.androidx_material.dep
+    compileOnly Config.libs.androidx_appcompat.path
+    compileOnly Config.libs.androidx_material.path
 
-    implementation Config.depConfig.lib_utilcode.dep
-    implementation Config.depConfig.swipe_panel.dep
-    implementation Config.depConfig.photo_view.dep
+    implementation Config.modules.lib_utilcode.dep
+    implementation Config.libs.swipe_panel.path
+    implementation Config.libs.photo_view.path
 
-    testImplementation Config.depConfig.test_junit.dep
-    testImplementation Config.depConfig.test_robolectric.dep
-    testImplementation Config.depConfig.androidx_appcompat.dep
+    testImplementation Config.libs.test_junit.path
+    testImplementation Config.libs.test_robolectric.path
+    testImplementation Config.libs.androidx_appcompat.path
 }
\ No newline at end of file
diff --git a/lib/utildebug/src/main/java/com/blankj/utildebug/menu/DebugMenu.java b/lib/utildebug/src/main/java/com/blankj/utildebug/menu/DebugMenu.java
index 37c53b89cb..8a0ac4f0f0 100644
--- a/lib/utildebug/src/main/java/com/blankj/utildebug/menu/DebugMenu.java
+++ b/lib/utildebug/src/main/java/com/blankj/utildebug/menu/DebugMenu.java
@@ -56,6 +56,7 @@ protected void onAttachedToWindow() {
 
     @Override
     protected void onDetachedFromWindow() {
+        int a = 0xe1;
         DebugIcon.setVisibility(true);
         super.onDetachedFromWindow();
     }
diff --git a/module_config.gradle b/module_config.gradle
new file mode 100644
index 0000000000..6be8429bd7
--- /dev/null
+++ b/module_config.gradle
@@ -0,0 +1,72 @@
+import groovy.json.JsonSlurper
+
+/**
+ * 在 module_config.json 中 根据 appConfig 和 pkgConfig 来 include 本地模块
+ * 可以考虑写成插件来更方便 apply
+ */
+
+def json = new JsonSlurper().parse(file("./module_config.json"))
+
+for (def module in json.moduleConfig) {
+    String moduleName = module.name
+
+    if (moduleName == "feature_mock") {
+        if (json.pkgConfig.isEmpty()) {
+            module.isApply = false
+        }
+    } else if (moduleName.endsWith("_app")) {
+        if (!json.appConfig.contains(moduleName)) {
+            module.isApply = false
+        }
+    } else if (moduleName.endsWith("_pkg")) {
+        if (!json.pkgConfig.isEmpty()) {
+            if (!json.pkgConfig.contains(moduleName)) {
+                module.isApply = false
+            }
+        }
+    }
+
+    if (module.useLocal && module.isApply) {
+        include moduleName
+        project(":$moduleName").projectDir = file(module.localPath)
+    }
+}
+
+def ls = System.getProperty("line.separator")
+
+List modules = []
+for (def module in json.moduleConfig) {
+    String name = module.name
+    boolean isApply = module.isApply
+    boolean useLocal = module.useLocal
+    String localPath = module.localPath
+    String remotePath = module.remotePath
+    if (localPath != null) localPath = "\"$localPath\""
+    if (remotePath != null) remotePath = "\"$remotePath\""
+    modules.add(String.format("%-12s%-27s: new ModuleConfig(isApply: %-5s, useLocal: %-5s, localPath: $localPath%s),",
+            "", name, isApply, useLocal, remotePath == null ? "" : ", remotePath: $remotePath"))
+}
+
+def configFile = file('./buildSrc/src/main/groovy/Config.groovy')
+def lines = configFile.readLines("utf8")
+def configContent = new StringBuilder()
+
+boolean enterNeverFlag = false
+for (def line : lines) {
+    if (enterNeverFlag) {
+        if (line.contains("/*Don't delete this line*/")) {
+            configContent.append(ls).append(line)
+            enterNeverFlag = false
+        }
+        continue
+    }
+    configContent.append(ls).append(line)
+    if (line.contains("/*Don't delete this line*/")) {
+        configContent.append(ls).append(String.format("%-12s/*Generated by \"module_config.json\"*/", ""))
+        enterNeverFlag = true
+        for (String m : modules) {
+            configContent.append(ls).append(m)
+        }
+    }
+}
+configFile.write(configContent.substring(ls.length()).toString())
\ No newline at end of file
diff --git a/module_config.json b/module_config.json
new file mode 100644
index 0000000000..18f416382a
--- /dev/null
+++ b/module_config.json
@@ -0,0 +1,30 @@
+{
+  "desc": "提交 git 时需要检查下配置是否正确!!!",
+  "appConfigDesc": "appConfig 配置的是可以跑 app 的模块",
+  "appConfig": ["feature_launcher_app"],
+  "pkgConfigDesc": "pkgConfig 配置的是要依赖的功能包,为空则依赖全部",
+  "pkgConfig": [],
+  "moduleConfigDesc": "moduleConfig 配置的是使用本地还是仓库,优先级低于 appConfig 和 pkgConfig",
+  "moduleConfig": [
+    {"name": "plugin_api_gradle_plugin",  "isApply": true, "useLocal": true, "localPath": "./plugin/api-gradle-plugin"},
+    {"name": "plugin_bus_gradle_plugin",  "isApply": true, "useLocal": true, "localPath": "./plugin/bus-gradle-plugin"},
+    {"name": "plugin_lib_base_transform", "isApply": true, "useLocal": true, "localPath": "./plugin/lib/base-transform", "remotePath": "com.blankj:base-transform:1.0"},
+    {"name": "plugin_buildSrc_plugin",    "isApply": true, "useLocal": true, "localPath": "./plugin/buildSrc-plugin"},
+    {"name": "feature_mock",              "isApply": true, "useLocal": true, "localPath": "./feature/mock"},
+    {"name": "feature_launcher_app",      "isApply": true, "useLocal": true, "localPath": "./feature/launcher/app"},
+    {"name": "feature_main_app",          "isApply": true, "useLocal": true, "localPath": "./feature/main/app"},
+    {"name": "feature_main_pkg",          "isApply": true, "useLocal": true, "localPath": "./feature/main/pkg"},
+    {"name": "feature_subutil_app",       "isApply": true, "useLocal": true, "localPath": "./feature/subutil/app"},
+    {"name": "feature_subutil_pkg",       "isApply": true, "useLocal": true, "localPath": "./feature/subutil/pkg"},
+    {"name": "feature_subutil_export",    "isApply": true, "useLocal": true, "localPath": "./feature/subutil/export"},
+    {"name": "feature_utilcode_app",      "isApply": true, "useLocal": true, "localPath": "./feature/utilcode/app"},
+    {"name": "feature_utilcode_pkg",      "isApply": true, "useLocal": true, "localPath": "./feature/utilcode/pkg"},
+    {"name": "feature_utilcode_export",   "isApply": true, "useLocal": true, "localPath": "./feature/utilcode/export", "remotePath": "com.blankj:utilcode-export:1.1"},
+    {"name": "lib_base",                  "isApply": true, "useLocal": true, "localPath": "./lib/base"},
+    {"name": "lib_common",                "isApply": true, "useLocal": true, "localPath": "./lib/common"},
+    {"name": "lib_subutil",               "isApply": true, "useLocal": true, "localPath": "./lib/subutil"},
+    {"name": "lib_utilcode",              "isApply": true, "useLocal": false, "localPath": "./lib/utilcode", "remotePath": "com.blankj:utilcodex:$Config.versionName"},
+    {"name": "lib_utildebug",             "isApply": true, "useLocal": true, "localPath": "./lib/utildebug"},
+    {"name": "lib_utildebug_no_op",       "isApply": true, "useLocal": true, "localPath": "./lib/utildebug-no-op"}
+  ]
+}
diff --git a/module_config.yaml b/module_config.yaml
new file mode 100644
index 0000000000..b10ce808e6
--- /dev/null
+++ b/module_config.yaml
@@ -0,0 +1,91 @@
+desc: 提交 git 时需要检查下配置是否正确!!!
+appConfigDesc: appConfig 配置的是可以跑 app 的模块
+appConfig:
+  - feature_launcher_app
+pkgConfigDesc: pkgConfig 配置的是要依赖的功能包,为空则依赖全部
+pkgConfig: [ ]
+moduleConfigDesc: moduleConfig 配置的是使用本地还是仓库,优先级低于 appConfig 和 pkgConfig
+moduleConfig:
+  - name: plugin_api_gradle_plugin
+      isApply: true
+      useLocal: true
+      localPath: ./plugin/api-gradle-plugin
+  - name: plugin_bus_gradle_plugin
+    isApply: true
+    useLocal: true
+    localPath: ./plugin/bus-gradle-plugin
+  - name: plugin_lib_base_transform
+    isApply: true
+    useLocal: true
+    localPath: ./plugin/lib/base-transform
+    remotePath: 'com.blankj:base-transform:1.0'
+  - name: plugin_buildSrc_plugin
+    isApply: true
+    useLocal: true
+    localPath: ./plugin/buildSrc-plugin
+  - name: feature_mock
+    isApply: true
+    useLocal: true
+    localPath: ./feature/mock
+  - name: feature_launcher_app
+    isApply: true
+    useLocal: true
+    localPath: ./feature/launcher/app
+  - name: feature_main_app
+    isApply: true
+    useLocal: true
+    localPath: ./feature/main/app
+  - name: feature_main_pkg
+    isApply: true
+    useLocal: true
+    localPath: ./feature/main/pkg
+  - name: feature_subutil_app
+    isApply: true
+    useLocal: true
+    localPath: ./feature/subutil/app
+  - name: feature_subutil_pkg
+    isApply: true
+    useLocal: true
+    localPath: ./feature/subutil/pkg
+  - name: feature_subutil_export
+    isApply: true
+    useLocal: true
+    localPath: ./feature/subutil/export
+  - name: feature_utilcode_app
+    isApply: true
+    useLocal: true
+    localPath: ./feature/utilcode/app
+  - name: feature_utilcode_pkg
+    isApply: true
+    useLocal: true
+    localPath: ./feature/utilcode/pkg
+  - name: feature_utilcode_export
+    isApply: true
+    useLocal: true
+    localPath: ./feature/utilcode/export
+    remotePath: 'com.blankj:utilcode-export:1.1'
+  - name: lib_base
+    isApply: true
+    useLocal: true
+    localPath: ./lib/base
+  - name: lib_common
+    isApply: true
+    useLocal: true
+    localPath: ./lib/common
+  - name: lib_subutil
+    isApply: true
+    useLocal: true
+    localPath: ./lib/subutil
+  - name: lib_utilcode
+    isApply: true
+    useLocal: true
+    localPath: ./lib/utilcode
+    remotePath: 'com.blankj:utilcode:$Config.versionName'
+  - name: lib_utildebug
+    isApply: true
+    useLocal: true
+    localPath: ./lib/utildebug
+  - name: lib_utildebug_no_op
+    isApply: true
+    useLocal: true
+    localPath: ./lib/utildebug-no-op
diff --git a/plugin/api-gradle-plugin/build.gradle b/plugin/api-gradle-plugin/build.gradle
index 2f6b956ee0..8a559c213d 100755
--- a/plugin/api-gradle-plugin/build.gradle
+++ b/plugin/api-gradle-plugin/build.gradle
@@ -6,21 +6,21 @@ apply {
 gradlePlugin {
     plugins {
         apiPlugin {
-            id = 'com.blankj.api'
+            id = Config.plugins.plugin_api.id
             implementationClass = 'com.blankj.api.ApiPlugin'
         }
     }
 }
 
 dependencies {
-    compileOnly Config.depConfig.plugin_gradle.dep
-    implementation Config.depConfig.commons_io.dep
-    implementation Config.depConfig.plugin_lib_base_transform.dep
+    compileOnly Config.plugins.plugin_gradle.path
+    implementation Config.libs.commons_io.path
+    implementation Config.modules.plugin_lib_base_transform.remotePath
     implementation gradleApi()
     implementation localGroovy()
 
-    testImplementation Config.depConfig.test_junit.dep
-    testImplementation Config.depConfig.plugin_gradle.dep
+    testImplementation Config.libs.test_junit.path
+    testImplementation Config.plugins.plugin_gradle.path
 }
 
 sourceSets {
@@ -32,11 +32,9 @@ sourceSets {
 }
 
 ext {
-    groupId = Config.depConfig.plugin_api.groupId
-    artifactId = Config.depConfig.plugin_api.artifactId
-    version = Config.depConfig.plugin_api.version
+    groupId = Config.plugins.plugin_api.groupId
+    artifactId = Config.plugins.plugin_api.artifactId
+    version = Config.plugins.plugin_api.version
     website = "https://github.com/Blankj/AndroidUtilCode"
 }
 apply from: "${rootDir.path}/config/publish.gradle"
-//./gradlew clean :plugin_api-gradle-plugin:mavenLocal     // 上传到本地 mavenLocal
-//./gradlew clean :plugin_api-gradle-plugin:bintrayUpload  // 上传到 jcenter
diff --git a/plugin/buildSrc-plugin/.gitignore b/plugin/buildSrc-plugin/.gitignore
new file mode 100755
index 0000000000..42afabfd2a
--- /dev/null
+++ b/plugin/buildSrc-plugin/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/plugin/buildSrc-plugin/build.gradle b/plugin/buildSrc-plugin/build.gradle
new file mode 100755
index 0000000000..567fbcef2d
--- /dev/null
+++ b/plugin/buildSrc-plugin/build.gradle
@@ -0,0 +1,37 @@
+apply {
+    plugin "groovy"
+    plugin "java-gradle-plugin"
+}
+
+gradlePlugin {
+    plugins {
+        apiPlugin {
+            id = 'com.blankj.buildSrc'
+            implementationClass = 'com.blankj.buildSrc.BuildSrcPlugin'
+        }
+    }
+}
+
+dependencies {
+    compileOnly Config.plugins.plugin_gradle.path
+    implementation Config.libs.commons_io.path
+    implementation gradleApi()
+    implementation localGroovy()
+}
+
+sourceSets {
+    main {
+        groovy {
+            srcDirs += 'src/main/java'
+        }
+    }
+}
+
+ext {
+    groupId = Config.plugins.plugin_buildSrc.groupId
+    artifactId = Config.plugins.plugin_buildSrc.artifactId
+    version = Config.plugins.plugin_buildSrc.version
+    website = "https://github.com/Blankj/AndroidUtilCode"
+}
+apply from: "${rootDir.path}/config/publish.gradle"
+//./gradlew clean plugin:plugin_buildSrc-plugin:publish2Local     // 上传到本地 mavenLocal
diff --git a/plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/BuildSrcPlugin.groovy b/plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/BuildSrcPlugin.groovy
new file mode 100644
index 0000000000..2915b3ffe1
--- /dev/null
+++ b/plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/BuildSrcPlugin.groovy
@@ -0,0 +1,13 @@
+package com.blankj.buildSrc;
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class BuildSrcPlugin implements Plugin {
+
+    @Override
+    void apply(Project project) {
+        println 'apply BuildSrcPlugin'
+        ModuleCfg.main()
+    }
+}
\ No newline at end of file
diff --git a/plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/ModuleCfg.groovy b/plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/ModuleCfg.groovy
new file mode 100644
index 0000000000..d52675d158
--- /dev/null
+++ b/plugin/buildSrc-plugin/src/main/java/com/blankj/buildSrc/ModuleCfg.groovy
@@ -0,0 +1,80 @@
+package com.blankj.buildSrc
+
+import groovy.json.JsonSlurper
+
+
+/**
+ * 在 config.json 中 根据 appConfig 和 pkgConfig 来 include 本地模块
+ * 可以考虑写成插件来更方便 apply
+ */
+
+println 'exe ModuleCfg.groovy'
+
+def config = new JsonSlurper().parse(file("./config.json"))
+
+for (def pro in config.proConfig) {
+    String localPath = pro.localPath
+
+    if (localPath == ":feature:mock") {
+        if (config.pkgConfig.isEmpty()) {
+            pro.isApply = false
+        }
+    } else if (localPath.endsWith(":app")) {
+        def appName = localPath.substring(":feature:".length(), localPath.length() - 4)
+        if (!config.appConfig.contains(appName)) {
+            pro.isApply = false
+        }
+    } else if (localPath.endsWith(":pkg")) {
+        if (!config.pkgConfig.isEmpty()) {
+            def pkgName = localPath.substring(":feature:".length(), localPath.length() - 4)
+            if (!config.pkgConfig.contains(pkgName)) {
+                pro.isApply = false
+            }
+        }
+    }
+
+    if (pro.useLocal && pro.isApply) {
+        def projectPath = ":" + localPath.substring(1).replace(":", "_")
+        include projectPath
+        project(projectPath).projectDir = file(localPath.substring(1).replace(":", "/"))
+    }
+}
+
+def ls = System.getProperty("line.separator")
+
+List proDeps = []
+for (def pro in config.proConfig) {
+    boolean useLocal = pro.useLocal
+    String localPath = pro.localPath
+    String remotePath = pro.remotePath
+    String name = localPath.replace(":", "_").replace("-", "_").substring(1)
+    if (localPath != null) localPath = "\"$localPath\""
+    if (remotePath != null) remotePath = "\"$remotePath\""
+    boolean isApply = pro.isApply
+    proDeps.add(String.format("%-12s%-27s: new DepConfig(%-5s, %-5s, $localPath%s),",
+            "", name, isApply, useLocal, remotePath == null ? "" : ", $remotePath"))
+}
+
+def configFile = file('./buildSrc/src/main/groovy/ModuleConfig.groovy')
+def lines = configFile.readLines("utf8")
+def configContent = new StringBuilder()
+
+boolean enterNeverFlag = false
+for (def line : lines) {
+    if (enterNeverFlag) {
+        if (line.contains("/*Never")) {
+            configContent.append(ls).append(line)
+            enterNeverFlag = false
+        }
+        continue
+    }
+    configContent.append(ls).append(line)
+    if (line.contains("/*Never")) {
+        configContent.append(ls).append(String.format("%-12s/*Generated by \"config.json\"*/", ""))
+        enterNeverFlag = true
+        for (String dep : proDeps) {
+            configContent.append(ls).append(dep)
+        }
+    }
+}
+configFile.write(configContent.substring(ls.length()).toString())
\ No newline at end of file
diff --git a/plugin/bus-gradle-plugin/build.gradle b/plugin/bus-gradle-plugin/build.gradle
index 7cd24042a7..68e43c6867 100755
--- a/plugin/bus-gradle-plugin/build.gradle
+++ b/plugin/bus-gradle-plugin/build.gradle
@@ -6,21 +6,21 @@ apply {
 gradlePlugin {
     plugins {
         busPlugin {
-            id = 'com.blankj.bus'
+            id = Config.plugins.plugin_bus.id
             implementationClass = 'com.blankj.bus.BusPlugin'
         }
     }
 }
 
 dependencies {
-    compileOnly Config.depConfig.plugin_gradle.dep
-    implementation Config.depConfig.commons_io.dep
-    implementation Config.depConfig.plugin_lib_base_transform.dep
+    compileOnly Config.plugins.plugin_gradle.path
+    implementation Config.modules.plugin_lib_base_transform.remotePath
+    implementation Config.libs.commons_io.path
     implementation gradleApi()
     implementation localGroovy()
 
-    testImplementation Config.depConfig.test_junit.dep
-    testImplementation Config.depConfig.plugin_gradle.dep
+    testImplementation Config.libs.test_junit.path
+    testImplementation Config.plugins.plugin_gradle.path
 }
 
 sourceSets {
@@ -32,9 +32,9 @@ sourceSets {
 }
 
 ext {
-    groupId = Config.depConfig.plugin_bus.groupId
-    artifactId = Config.depConfig.plugin_bus.artifactId
-    version = Config.depConfig.plugin_bus.version
+    groupId = Config.plugins.plugin_bus.groupId
+    artifactId = Config.plugins.plugin_bus.artifactId
+    version = Config.plugins.plugin_bus.version
     website = "https://github.com/Blankj/AndroidUtilCode"
 }
 apply from: "${rootDir.path}/config/publish.gradle"
diff --git a/plugin/lib/base-transform/build.gradle b/plugin/lib/base-transform/build.gradle
index 3518481ebd..8eac0ab6d3 100755
--- a/plugin/lib/base-transform/build.gradle
+++ b/plugin/lib/base-transform/build.gradle
@@ -4,8 +4,8 @@ apply {
 }
 
 dependencies {
-    compileOnly Config.depConfig.plugin_gradle.dep
-    implementation Config.depConfig.commons_io.dep
+    compileOnly Config.plugins.plugin_gradle.path
+    implementation Config.libs.commons_io.path
     implementation gradleApi()
     implementation localGroovy()
 }
@@ -19,11 +19,11 @@ sourceSets {
 }
 
 ext {
-    groupId = Config.depConfig.plugin_lib_base_transform.groupId
-    artifactId = Config.depConfig.plugin_lib_base_transform.artifactId
-    version = Config.depConfig.plugin_lib_base_transform.version
+    groupId = Config.modules.plugin_lib_base_transform.groupId
+    artifactId = Config.modules.plugin_lib_base_transform.artifactId
+    version = Config.modules.plugin_lib_base_transform.version
     website = "https://github.com/Blankj/AndroidUtilCode"
 }
 apply from: "${rootDir.path}/config/publish.gradle"
-//./gradlew clean plugin:lib:plugin_lib_base-transform:mavenLocal     // 上传到本地 mavenLocal
-//./gradlew clean plugin:lib:plugin_lib_base-transform:bintrayUpload  // 上传到 gradle 插件库中
+//./gradlew clean :plugin_lib_base-transform:mavenLocal     // 上传到本地 mavenLocal
+//./gradlew clean :plugin_lib_base-transform:bintrayUpload  // 上传到 gradle 插件库中
diff --git a/settings.gradle b/settings.gradle
index 2d1b907aca..3fb2a0a2be 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,73 +1,39 @@
-import groovy.json.JsonSlurper
-
-/**
- * 在 config.json 中 根据 appConfig 和 pkgConfig 来 include 本地模块
- */
-def config = new JsonSlurper().parse(file("./config.json"))
-
-for (def pro in config.proConfig) {
-    String localPath = pro.localPath
-
-    if (localPath == ":feature:mock") {
-        if (config.pkgConfig.isEmpty()) {
-            pro.isApply = false
-        }
-    } else if (localPath.endsWith(":app")) {
-        def appName = localPath.substring(":feature:".length(), localPath.length() - 4)
-        if (!config.appConfig.contains(appName)) {
-            pro.isApply = false
-        }
-    } else if (localPath.endsWith(":pkg")) {
-        if (!config.pkgConfig.isEmpty()) {
-            def pkgName = localPath.substring(":feature:".length(), localPath.length() - 4)
-            if (!config.pkgConfig.contains(pkgName)) {
-                pro.isApply = false
-            }
-        }
-    }
-
-    if (pro.useLocal && pro.isApply) {
-        def projectPath = ":" + localPath.substring(1).replace(":", "_")
-        include projectPath
-        project(projectPath).projectDir = file(localPath.substring(1).replace(":", "/"))
-    }
-}
-
-def ls = System.getProperty("line.separator")
-
-List proDeps = []
-for (def pro in config.proConfig) {
-    boolean useLocal = pro.useLocal
-    String localPath = pro.localPath
-    String remotePath = pro.remotePath
-    String name = localPath.replace(":", "_").replace("-", "_").substring(1)
-    if (localPath != null) localPath = "\"$localPath\""
-    if (remotePath != null) remotePath = "\"$remotePath\""
-    boolean isApply = pro.isApply
-    proDeps.add(String.format("%-12s%-27s: new DepConfig(%-5s, %-5s, $localPath%s),",
-            "", name, isApply, useLocal, remotePath == null ? "" : ", $remotePath"))
-}
-
-def configFile = file('./buildSrc/src/main/groovy/Config.groovy')
-def lines = configFile.readLines("utf8")
-def configContent = new StringBuilder()
-
-boolean enterNeverFlag = false
-for (def line : lines) {
-    if (enterNeverFlag) {
-        if (line.contains("/*Never")) {
-            configContent.append(ls).append(line)
-            enterNeverFlag = false
-        }
-        continue
-    }
-    configContent.append(ls).append(line)
-    if (line.contains("/*Never")) {
-        configContent.append(ls).append(String.format("%-12s/*Generated by \"config.json\"*/", ""))
-        enterNeverFlag = true
-        for (String dep : proDeps) {
-            configContent.append(ls).append(dep)
-        }
-    }
-}
-configFile.write(configContent.substring(ls.length()).toString())
\ No newline at end of file
+//includeBuild 'configPlugin'
+
+//buildscript {
+////    ConfigUtils.init(gradle)
+//    repositories {
+//        mavenLocal()
+//        mavenCentral()
+//    }
+//
+//    dependencies {
+//        classpath 'com.blankj:buildSrc-plugin:1.0'
+//    }
+//}
+
+//apply plugin: "com.blankj.buildSrc"
+
+
+//dependencyResolutionManagement {
+//    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+//    repositories {
+//        google()
+//        mavenCentral()
+//        jcenter() // Warning: this repository is going to shut down soon
+//        maven {url 'https://jetpack.io/'} // Warning: this repository is going to shut down soon
+//    }
+//
+////    configurations.all {
+////        resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
+////
+////        resolutionStrategy.eachDependency {
+////            if (it.requested.group == 'com.android.support' && !it.requested.name.contains(
+////                    'multidex')) {
+////                it.useVersion Config.supportVersion
+////            }
+////        }
+////    }
+//}
+
+apply from: 'module_config.gradle'

From d0b890e106be3658d259ca7ec52e232b991f67f1 Mon Sep 17 00:00:00 2001
From: caimengjie 
Date: Mon, 6 Dec 2021 01:45:43 +0800
Subject: [PATCH 28/49] opt: publish v1.31.0

---
 module_config.yaml | 91 ----------------------------------------------
 1 file changed, 91 deletions(-)
 delete mode 100644 module_config.yaml

diff --git a/module_config.yaml b/module_config.yaml
deleted file mode 100644
index b10ce808e6..0000000000
--- a/module_config.yaml
+++ /dev/null
@@ -1,91 +0,0 @@
-desc: 提交 git 时需要检查下配置是否正确!!!
-appConfigDesc: appConfig 配置的是可以跑 app 的模块
-appConfig:
-  - feature_launcher_app
-pkgConfigDesc: pkgConfig 配置的是要依赖的功能包,为空则依赖全部
-pkgConfig: [ ]
-moduleConfigDesc: moduleConfig 配置的是使用本地还是仓库,优先级低于 appConfig 和 pkgConfig
-moduleConfig:
-  - name: plugin_api_gradle_plugin
-      isApply: true
-      useLocal: true
-      localPath: ./plugin/api-gradle-plugin
-  - name: plugin_bus_gradle_plugin
-    isApply: true
-    useLocal: true
-    localPath: ./plugin/bus-gradle-plugin
-  - name: plugin_lib_base_transform
-    isApply: true
-    useLocal: true
-    localPath: ./plugin/lib/base-transform
-    remotePath: 'com.blankj:base-transform:1.0'
-  - name: plugin_buildSrc_plugin
-    isApply: true
-    useLocal: true
-    localPath: ./plugin/buildSrc-plugin
-  - name: feature_mock
-    isApply: true
-    useLocal: true
-    localPath: ./feature/mock
-  - name: feature_launcher_app
-    isApply: true
-    useLocal: true
-    localPath: ./feature/launcher/app
-  - name: feature_main_app
-    isApply: true
-    useLocal: true
-    localPath: ./feature/main/app
-  - name: feature_main_pkg
-    isApply: true
-    useLocal: true
-    localPath: ./feature/main/pkg
-  - name: feature_subutil_app
-    isApply: true
-    useLocal: true
-    localPath: ./feature/subutil/app
-  - name: feature_subutil_pkg
-    isApply: true
-    useLocal: true
-    localPath: ./feature/subutil/pkg
-  - name: feature_subutil_export
-    isApply: true
-    useLocal: true
-    localPath: ./feature/subutil/export
-  - name: feature_utilcode_app
-    isApply: true
-    useLocal: true
-    localPath: ./feature/utilcode/app
-  - name: feature_utilcode_pkg
-    isApply: true
-    useLocal: true
-    localPath: ./feature/utilcode/pkg
-  - name: feature_utilcode_export
-    isApply: true
-    useLocal: true
-    localPath: ./feature/utilcode/export
-    remotePath: 'com.blankj:utilcode-export:1.1'
-  - name: lib_base
-    isApply: true
-    useLocal: true
-    localPath: ./lib/base
-  - name: lib_common
-    isApply: true
-    useLocal: true
-    localPath: ./lib/common
-  - name: lib_subutil
-    isApply: true
-    useLocal: true
-    localPath: ./lib/subutil
-  - name: lib_utilcode
-    isApply: true
-    useLocal: true
-    localPath: ./lib/utilcode
-    remotePath: 'com.blankj:utilcode:$Config.versionName'
-  - name: lib_utildebug
-    isApply: true
-    useLocal: true
-    localPath: ./lib/utildebug
-  - name: lib_utildebug_no_op
-    isApply: true
-    useLocal: true
-    localPath: ./lib/utildebug-no-op

From ccba200fd83bc6479b8b8065a4824cd0e5fd67c2 Mon Sep 17 00:00:00 2001
From: caimengjie 
Date: Mon, 6 Dec 2021 01:47:28 +0800
Subject: [PATCH 29/49] opt: publish v1.31.0

---
 CHANGELOG.md                                   |  1 +
 buildSrc/src/main/groovy/Config.groovy         |  2 +-
 config/publish.gradle                          |  8 ++++++--
 lib/utilcode/README-CN.md                      |  7 ++++---
 lib/utilcode/README.md                         |  7 ++++---
 .../com/blankj/utilcode/util/AppUtils.java     | 18 +++++++++---------
 .../com/blankj/utilcode/util/NetworkUtils.java |  5 +++--
 .../com/blankj/utilcode/util/TimeUtils.java    |  2 ++
 module_config.json                             |  2 +-
 9 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 401a5071f8..c4bcc19c85 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,4 @@
+* `21/12/06` [add] Publish v1.31.0
 * `21/05/13` [add] Support publish mavenCentral.
 * `21/02/22` [add] Fix ToastUtils rtl bug. Publish v1.30.6.
 * `20/11/16` [add] Add ImageUtils#save2Album support param of dirName.
diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy
index 4a0b27a980..2465570d82 100644
--- a/buildSrc/src/main/groovy/Config.groovy
+++ b/buildSrc/src/main/groovy/Config.groovy
@@ -34,7 +34,7 @@ class Config {
             lib_base                   : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/base"),
             lib_common                 : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/common"),
             lib_subutil                : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/subutil"),
-            lib_utilcode               : new ModuleConfig(isApply: true , useLocal: false, localPath: "./lib/utilcode", remotePath: "com.blankj:utilcode:$Config.versionName"),
+            lib_utilcode               : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utilcode", remotePath: "com.blankj:utilcodex:$Config.versionName"),
             lib_utildebug              : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug"),
             lib_utildebug_no_op        : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug-no-op"),
             /*Don't delete this line*/
diff --git a/config/publish.gradle b/config/publish.gradle
index fa8a449f3c..91f749a86d 100644
--- a/config/publish.gradle
+++ b/config/publish.gradle
@@ -220,6 +220,10 @@ static def isAndroidEnv(Project project) {
     return project.getPlugins().hasPlugin('com.android.application') || project.getPlugins().hasPlugin('com.android.library')
 }
 
-task publish2Local(type: GradleBuild, dependsOn: ['clean', 'assemble', 'publishReleasePublicationToMavenLocal']) {}
+task publish2Local(type: GradleBuild) {
+    tasks = ['assemble', 'publishReleasePublicationToMavenLocal']
+}
 
-task publish2Remote(type: GradleBuild, dependsOn: ['clean', 'assemble', 'publishReleasePublicationToMavenRepository']) {}
\ No newline at end of file
+task publish2Remote(type: GradleBuild) {
+    tasks = ['assemble', 'publishReleasePublicationToMavenRepository']
+}
\ No newline at end of file
diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
index 79b18eef15..0e4e93f3a0 100644
--- a/lib/utilcode/README-CN.md
+++ b/lib/utilcode/README-CN.md
@@ -2,10 +2,11 @@
 
 Gradle:
 ```groovy
-implementation 'com.blankj:utilcode:1.30.6'
-
 // if u use AndroidX, use the following
-implementation 'com.blankj:utilcodex:1.30.6'
+implementation 'com.blankj:utilcodex:1.31.0'
+
+// Not in maintenance
+implementation 'com.blankj:utilcode:1.30.6'
 ```
 
 
diff --git a/lib/utilcode/README.md b/lib/utilcode/README.md
index 63f7a83ba7..cdabfba45a 100644
--- a/lib/utilcode/README.md
+++ b/lib/utilcode/README.md
@@ -2,10 +2,11 @@
 
 Gradle:
 ```groovy
-implementation 'com.blankj:utilcode:1.30.6'
-
 // if u use AndroidX, use the following
-implementation 'com.blankj:utilcodex:1.30.6'
+implementation 'com.blankj:utilcodex:1.31.0'
+
+// Not in maintenance
+implementation 'com.blankj:utilcode:1.30.6'
 ```
 
 
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
index fe8301f9ec..8f03e1cf1f 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
@@ -385,16 +385,16 @@ public static int getAppIconId(final String packageName) {
         }
     }
 
-    
+
     /**
      * 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(){
+    public static boolean isFirstTimeInstall() {
         try {
-            Long firstInstallTime = Utils.getApp().getPackageManager().getPackageInfo(this.getAppPackageName(), 0).firstInstallTime;
-            Long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(this.getAppPackageName(), 0).lastUpdateTime;
+            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;
@@ -406,17 +406,17 @@ public static boolean isFirstTimeInstall(){
      *
      * @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(){
+    public static boolean isAppUpgraded() {
         try {
-            Long firstInstallTime = Utils.getApp().getPackageManager().getPackageInfo(this.getAppPackageName(), 0).firstInstallTime;
-            Long lastUpdateTime = Utils.getApp().getPackageManager().getPackageInfo(this.getAppPackageName(), 0).lastUpdateTime;
+            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.
      *
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
index b2c64a6416..e73b6487db 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/NetworkUtils.java
@@ -6,6 +6,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiInfo;
@@ -280,9 +281,9 @@ public static boolean isBehindProxy(){
     public static boolean isUsingVPN(){
         ConnectivityManager cm = (ConnectivityManager) com.blankj.utilcode.util.Utils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
-            return cm.getNetworkInfo(ConnectivityManager.TYPE_VPN).isConnectedOrConnecting()
+            return cm.getNetworkInfo(ConnectivityManager.TYPE_VPN).isConnectedOrConnecting();
         } else {
-            return cm.getNetworkInfo(NetworkCapabilities.TRANSPORT_VPN).isConnectedOrConnecting()
+            return cm.getNetworkInfo(NetworkCapabilities.TRANSPORT_VPN).isConnectedOrConnecting();
         }
     }
 
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java
index 8a38efd195..ee700cbeb7 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/TimeUtils.java
@@ -1,6 +1,8 @@
 package com.blankj.utilcode.util;
 
 import android.annotation.SuppressLint;
+import android.os.Build;
+import android.provider.Settings;
 
 import com.blankj.utilcode.constant.TimeConstants;
 
diff --git a/module_config.json b/module_config.json
index 18f416382a..87233122b9 100644
--- a/module_config.json
+++ b/module_config.json
@@ -23,7 +23,7 @@
     {"name": "lib_base",                  "isApply": true, "useLocal": true, "localPath": "./lib/base"},
     {"name": "lib_common",                "isApply": true, "useLocal": true, "localPath": "./lib/common"},
     {"name": "lib_subutil",               "isApply": true, "useLocal": true, "localPath": "./lib/subutil"},
-    {"name": "lib_utilcode",              "isApply": true, "useLocal": false, "localPath": "./lib/utilcode", "remotePath": "com.blankj:utilcodex:$Config.versionName"},
+    {"name": "lib_utilcode",              "isApply": true, "useLocal": true, "localPath": "./lib/utilcode", "remotePath": "com.blankj:utilcodex:$Config.versionName"},
     {"name": "lib_utildebug",             "isApply": true, "useLocal": true, "localPath": "./lib/utildebug"},
     {"name": "lib_utildebug_no_op",       "isApply": true, "useLocal": true, "localPath": "./lib/utildebug-no-op"}
   ]

From ac872f8fb52d569d252e5fe136b0f7af14798f5a Mon Sep 17 00:00:00 2001
From: caimengjie 
Date: Mon, 6 Dec 2021 01:51:47 +0800
Subject: [PATCH 30/49] fix: ci

---
 buildSrc/src/main/groovy/Config.groovy |  4 ++--
 config/publish.gradle                  | 15 ++++++---------
 module_config.json                     |  2 +-
 3 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy
index 2465570d82..268ec666ce 100644
--- a/buildSrc/src/main/groovy/Config.groovy
+++ b/buildSrc/src/main/groovy/Config.groovy
@@ -34,7 +34,7 @@ class Config {
             lib_base                   : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/base"),
             lib_common                 : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/common"),
             lib_subutil                : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/subutil"),
-            lib_utilcode               : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utilcode", remotePath: "com.blankj:utilcodex:$Config.versionName"),
+            lib_utilcode               : new ModuleConfig(isApply: true , useLocal: false, localPath: "./lib/utilcode", remotePath: "com.blankj:utilcodex:$Config.versionName"),
             lib_utildebug              : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug"),
             lib_utildebug_no_op        : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug-no-op"),
             /*Don't delete this line*/
@@ -54,7 +54,7 @@ class Config {
             plugin_bus     : new PluginConfig(isApply: true, useLocal: false, path: "com.blankj:bus-gradle-plugin:2.6", id: "com.blankj.bus"),
             //./gradlew clean :plugin_bus-gradle-plugin:mavenLocal     // 上传到本地 mavenLocal
             //./gradlew clean :plugin_bus-gradle-plugin:bintrayUpload  // 上传到 jcenter
-            plugin_buildSrc: new PluginConfig(isApply: true, useLocal: false, path: "com.blankj:buildSrc-plugin:1.0", id: "com.blankj.buildSrc"),
+            plugin_buildSrc: new PluginConfig(isApply: false, useLocal: false, path: "com.blankj:buildSrc-plugin:1.0", id: "com.blankj.buildSrc"),
             //./gradlew clean :plugin_bus-gradle-plugin:mavenLocal     // 上传到本地 mavenLocal
             //./gradlew clean :plugin_bus-gradle-plugin:bintrayUpload  // 上传到 jcenter
     ]
diff --git a/config/publish.gradle b/config/publish.gradle
index 91f749a86d..7608215123 100644
--- a/config/publish.gradle
+++ b/config/publish.gradle
@@ -27,17 +27,14 @@ apply plugin: 'signing'
 ext.multiPublishMode = true
 
 File localPropertiesFile = project.rootProject.file("local.properties");
-if (localPropertiesFile.exists()) {
-    Properties properties = new Properties()
-    properties.load(new FileInputStream(localPropertiesFile))
-    properties.each { name, value -> ext[name] = value }
-} else {
-    if (!ext["signing.keyId"] && !ext["signing.password"] && !ext["signing.secretKeyRingFile"]
-            && !ext["ossrhUsername"] && !ext["ossrhPassword"]) {
-        throw new NullPointerException("U should set MavenCentral params in local.properties")
-    }
+if (!localPropertiesFile.exists()) {
+    return
 }
 
+Properties properties = new Properties()
+properties.load(new FileInputStream(localPropertiesFile))
+properties.each { name, value -> ext[name] = value }
+
 afterEvaluate {
     def ext = project.ext
     publishing {
diff --git a/module_config.json b/module_config.json
index 87233122b9..18f416382a 100644
--- a/module_config.json
+++ b/module_config.json
@@ -23,7 +23,7 @@
     {"name": "lib_base",                  "isApply": true, "useLocal": true, "localPath": "./lib/base"},
     {"name": "lib_common",                "isApply": true, "useLocal": true, "localPath": "./lib/common"},
     {"name": "lib_subutil",               "isApply": true, "useLocal": true, "localPath": "./lib/subutil"},
-    {"name": "lib_utilcode",              "isApply": true, "useLocal": true, "localPath": "./lib/utilcode", "remotePath": "com.blankj:utilcodex:$Config.versionName"},
+    {"name": "lib_utilcode",              "isApply": true, "useLocal": false, "localPath": "./lib/utilcode", "remotePath": "com.blankj:utilcodex:$Config.versionName"},
     {"name": "lib_utildebug",             "isApply": true, "useLocal": true, "localPath": "./lib/utildebug"},
     {"name": "lib_utildebug_no_op",       "isApply": true, "useLocal": true, "localPath": "./lib/utildebug-no-op"}
   ]

From f9a1dbf0dfa8ad5bd20fe4f72bb72a4470b248db Mon Sep 17 00:00:00 2001
From: Absinthe 
Date: Sat, 11 Dec 2021 11:59:28 +0800
Subject: [PATCH 31/49] Explicitly specify `android:exported` to make
 compatible with Android 12.

---
 lib/utilcode/src/main/AndroidManifest.xml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/utilcode/src/main/AndroidManifest.xml b/lib/utilcode/src/main/AndroidManifest.xml
index fc5b75e0e3..d45dd57787 100644
--- a/lib/utilcode/src/main/AndroidManifest.xml
+++ b/lib/utilcode/src/main/AndroidManifest.xml
@@ -5,12 +5,14 @@
 
         
 
         
Date: Wed, 25 May 2022 11:18:02 +0800
Subject: [PATCH 32/49] fix bug

---
 lib/utilcode/src/main/res/xml/util_code_provider_paths.xml | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml b/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml
index ed731a2299..b88716480c 100644
--- a/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml
+++ b/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml
@@ -23,4 +23,9 @@
     
-
\ No newline at end of file
+      
+    
+

From 8dc01389ee5599c44c7ae26a8c26411b63bfa564 Mon Sep 17 00:00:00 2001
From: Justson 
Date: Wed, 8 Jun 2022 10:55:22 +0800
Subject: [PATCH 33/49] Update README-CN.md

---
 lib/utilcode/README-CN.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
index 0e4e93f3a0..260cabac24 100644
--- a/lib/utilcode/README-CN.md
+++ b/lib/utilcode/README-CN.md
@@ -6,7 +6,7 @@ Gradle:
 implementation 'com.blankj:utilcodex:1.31.0'
 
 // Not in maintenance
-implementation 'com.blankj:utilcode:1.30.6'
+implementation 'com.blankj:utilcode:1.30.7'
 ```
 
 

From ed848ebd638507a492946e6300b057fb621b5dba Mon Sep 17 00:00:00 2001
From: NH002 
Date: Thu, 9 Jun 2022 09:06:11 +0200
Subject: [PATCH 34/49] Added uri2FileNoCacheCopy

---
 .../main/java/com/blankj/utilcode/util/UriUtils.java  | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/UriUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/UriUtils.java
index 322b9d1190..c22d1bba38 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/UriUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/UriUtils.java
@@ -77,6 +77,17 @@ public static File uri2File(final Uri uri) {
         return copyUri2Cache(uri);
     }
 
+    /**
+     * Uri to file, without creating the cache copy if the path cannot be resolved.
+     *
+     * @param uri The uri.
+     * @return file
+     */
+    public static File uri2FileNoCacheCopy(final Uri uri) {
+        if (uri == null) return null;
+        return uri2FileReal(uri);
+    }
+    
     /**
      * Uri to file.
      *

From da8b04946981398dfb217825946af55cba3b3444 Mon Sep 17 00:00:00 2001
From: taochen <935612713@qq.com>
Date: Mon, 18 Jul 2022 16:12:33 +0800
Subject: [PATCH 35/49] =?UTF-8?q?[M]=20BarUtils=E6=B7=BB=E5=8A=A0transpare?=
 =?UTF-8?q?ntNavBar=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../pkg/feature/bar/nav/BarNavActivity.kt     | 42 +++++++++++++------
 .../com/blankj/utilcode/util/BarUtils.java    | 32 +++++++++++---
 2 files changed, 57 insertions(+), 17 deletions(-)

diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt
index 1b3032974f..48a738ecd7 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt
@@ -12,7 +12,6 @@ import com.blankj.utilcode.pkg.R
 import com.blankj.utilcode.util.BarUtils
 import com.blankj.utilcode.util.CollectionUtils
 import com.blankj.utilcode.util.ColorUtils
-import com.blankj.utilcode.util.Utils
 
 /**
  * ```
@@ -41,24 +40,43 @@ class BarNavActivity : CommonActivity() {
             add(CommonItemTitle("isSupportNavBar", BarUtils.isSupportNavBar().toString()))
             if (BarUtils.isSupportNavBar()) {
                 add(CommonItemSwitch(
-                        R.string.bar_nav_visibility,
-                        { BarUtils.isNavBarVisible(this@BarNavActivity) },
-                        { BarUtils.setNavBarVisibility(this@BarNavActivity, it) }
+                    R.string.bar_nav_visibility,
+                    { BarUtils.isNavBarVisible(this@BarNavActivity) },
+                    { BarUtils.setNavBarVisibility(this@BarNavActivity, it) }
                 ))
 
                 add(CommonItemSwitch(
-                        R.string.bar_nav_light_mode,
-                        { BarUtils.isNavBarLightMode(this@BarNavActivity) },
-                        { BarUtils.setNavBarLightMode(this@BarNavActivity, it) }
+                    R.string.bar_nav_light_mode,
+                    { BarUtils.isNavBarLightMode(this@BarNavActivity) },
+                    { BarUtils.setNavBarLightMode(this@BarNavActivity, it) }
                 ))
 
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-                    add(CommonItemClick("getNavBarColor: ${ColorUtils.int2ArgbString(BarUtils.getNavBarColor(this@BarNavActivity))}").setOnItemClickListener() { _, item, _ ->
-                        BarUtils.setNavBarColor(this@BarNavActivity, ColorUtils.getRandomColor())
-                        itemsView.updateItems(bindItems())
-                        item.title = "getNavBarColor: ${ColorUtils.int2ArgbString(BarUtils.getNavBarColor(this@BarNavActivity))}"
-                    })
+                    add(
+                        CommonItemClick(
+                            "getNavBarColor: ${
+                                ColorUtils.int2ArgbString(
+                                    BarUtils.getNavBarColor(
+                                        this@BarNavActivity
+                                    )
+                                )
+                            }"
+                        ).setOnItemClickListener() { _, item, _ ->
+                            BarUtils.setNavBarColor(
+                                this@BarNavActivity,
+                                ColorUtils.getRandomColor()
+                            )
+                            itemsView.updateItems(bindItems())
+                            item.title = "getNavBarColor: ${
+                                ColorUtils.int2ArgbString(
+                                    BarUtils.getNavBarColor(this@BarNavActivity)
+                                )
+                            }"
+                        })
                 }
+                add(CommonItemClick("transparentNavBar").setOnItemClickListener() { _, item, _ ->
+                    BarUtils.transparentNavBar(this@BarNavActivity)
+                })
             }
         }
     }
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
index af9dbc4fcd..ece4f7faba 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
@@ -1,5 +1,7 @@
 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;
@@ -19,15 +21,13 @@
 import android.view.Window;
 import android.view.WindowManager;
 
-import java.lang.reflect.Method;
-
 import androidx.annotation.ColorInt;
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RequiresPermission;
 import androidx.drawerlayout.widget.DrawerLayout;
 
-import static android.Manifest.permission.EXPAND_STATUS_BAR;
+import java.lang.reflect.Method;
 
 /**
  * 
@@ -44,8 +44,8 @@ public final class BarUtils {
     ///////////////////////////////////////////////////////////////////////////
 
     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 static final String TAG_OFFSET = "TAG_OFFSET";
+    private static final int KEY_OFFSET = -123;
 
     private BarUtils() {
         throw new UnsupportedOperationException("u can't instantiate me...");
@@ -715,4 +715,26 @@ public static boolean isNavBarLightMode(@NonNull final Window window) {
         }
         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);
+    }
 }

From 0a1be7ec672053012b2bdae6259037765ff0af14 Mon Sep 17 00:00:00 2001
From: taochen <935612713@qq.com>
Date: Mon, 18 Jul 2022 17:02:24 +0800
Subject: [PATCH 36/49] =?UTF-8?q?[M]=20=E4=BF=AE=E6=94=B9BarUtils=E6=96=B9?=
 =?UTF-8?q?=E6=B3=95=E5=88=97=E8=A1=A8=E5=8F=8A=E6=8F=8F=E8=BF=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/utilcode/README-CN.md | 1 +
 lib/utilcode/README.md    | 1 +
 2 files changed, 2 insertions(+)

diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
index 0e4e93f3a0..f7523783f9 100644
--- a/lib/utilcode/README-CN.md
+++ b/lib/utilcode/README-CN.md
@@ -141,6 +141,7 @@ getNavBarColor                       : 获取导航栏颜色
 isSupportNavBar                      : 判断是否支持导航栏
 setNavBarLightMode                   : 设置导航栏是否为浅色模式
 isNavBarLightMode                    : 判断导航栏是否为浅色模式
+transparentNavBar                    : 透明导航栏
 ```
 
 * ### 亮度相关 -> [BrightnessUtils.java][brightness.java] -> [Demo][brightness.demo]
diff --git a/lib/utilcode/README.md b/lib/utilcode/README.md
index cdabfba45a..9d2025ebb0 100644
--- a/lib/utilcode/README.md
+++ b/lib/utilcode/README.md
@@ -140,6 +140,7 @@ getNavBarColor
 isSupportNavBar
 setNavBarLightMode
 isNavBarLightMode
+transparentNavBar
 ```
 
 * ### About Brightness -> [BrightnessUtils.java][brightness.java] -> [Demo][brightness.demo]

From cf983059a82e0306ea1bdaa773f9fec0ed03ad22 Mon Sep 17 00:00:00 2001
From: taochen <935612713@qq.com>
Date: Tue, 19 Jul 2022 12:00:46 +0800
Subject: [PATCH 37/49] =?UTF-8?q?[F]=20TargetSdkVersion=2030=20AppUtils.is?=
 =?UTF-8?q?AppInstalled=E8=BF=94=E5=9B=9E=E9=94=99=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/utilcode/src/main/AndroidManifest.xml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lib/utilcode/src/main/AndroidManifest.xml b/lib/utilcode/src/main/AndroidManifest.xml
index fc5b75e0e3..4d2b38e471 100644
--- a/lib/utilcode/src/main/AndroidManifest.xml
+++ b/lib/utilcode/src/main/AndroidManifest.xml
@@ -1,6 +1,15 @@
 
 
+    
+        
+            
+        
+        
+            
+        
+    
+
     
 
         
Date: Tue, 19 Jul 2022 17:31:46 +0800
Subject: [PATCH 38/49] =?UTF-8?q?[M]=20AppUtils=E5=A2=9E=E5=8A=A0getAppMin?=
 =?UTF-8?q?SdkVersion,=20getAppTargetSdkVersion=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../utilcode/pkg/feature/app/AppActivity.kt   | 108 ++++++++--------
 lib/utilcode/README-CN.md                     |   2 +
 lib/utilcode/README.md                        |   2 +
 .../com/blankj/utilcode/util/AppUtils.java    | 115 ++++++++++++++++--
 .../debug/tool/appInfo/AppInfoItem.java       |  15 ++-
 5 files changed, 173 insertions(+), 69 deletions(-)

diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt
index 175fa1bc3b..21eb351146 100644
--- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt
+++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt
@@ -54,7 +54,10 @@ class AppActivity : CommonActivity(), Utils.OnAppStatusChangedListener {
 
     override fun bindItems(): MutableList> {
         return CollectionUtils.newArrayList(
-                CommonItemSwitch("registerAppStatusChangedListener", { isRegisterAppStatusChangedListener }, {
+            CommonItemSwitch(
+                "registerAppStatusChangedListener",
+                { isRegisterAppStatusChangedListener },
+                {
                     isRegisterAppStatusChangedListener = it
                     if (it) {
                         AppUtils.registerAppStatusChangedListener(this)
@@ -62,55 +65,63 @@ class AppActivity : CommonActivity(), Utils.OnAppStatusChangedListener {
                         AppUtils.unregisterAppStatusChangedListener(this)
                     }
                 }),
-                CommonItemTitle("isAppRoot", AppUtils.isAppRoot().toString()),
-                CommonItemTitle("isAppDebug", AppUtils.isAppDebug().toString()),
-                CommonItemTitle("isAppSystem", AppUtils.isAppSystem().toString()),
-                CommonItemTitle("isAppForeground", AppUtils.isAppForeground(AppUtils.getAppPackageName()).toString()),
-                CommonItemTitle("isAppRunning", AppUtils.isAppRunning(AppUtils.getAppPackageName()).toString()),
-                CommonItemImage("getAppIcon") {
-                    it.setImageDrawable(AppUtils.getAppIcon())
-                },
-                CommonItemTitle("getAppPackageName", AppUtils.getAppPackageName()),
-                CommonItemTitle("getAppName", AppUtils.getAppName()),
-                CommonItemTitle("getAppPath", AppUtils.getAppPath()),
-                CommonItemTitle("getAppVersionName", AppUtils.getAppVersionName()),
-                CommonItemTitle("getAppVersionCode", AppUtils.getAppVersionCode().toString()),
-                CommonItemTitle("getAppSignaturesSHA1", AppUtils.getAppSignaturesSHA1().toString()),
-                CommonItemTitle("getAppSignaturesSHA256", AppUtils.getAppSignaturesSHA256().toString()),
-                CommonItemTitle("getAppSignaturesMD5", AppUtils.getAppSignaturesMD5().toString()),
-                CommonItemTitle("getAppUid", AppUtils.getAppUid().toString()),
-                CommonItemTitle("getApkInfo", AppUtils.getApkInfo(AppUtils.getAppPath()).toString()),
-
-                CommonItemClick(R.string.app_install) {
-                    if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
-                        ToastUtils.showShort(R.string.app_install_tips)
+            CommonItemTitle("isAppRoot", AppUtils.isAppRoot().toString()),
+            CommonItemTitle("isAppDebug", AppUtils.isAppDebug().toString()),
+            CommonItemTitle("isAppSystem", AppUtils.isAppSystem().toString()),
+            CommonItemTitle(
+                "isAppForeground",
+                AppUtils.isAppForeground(AppUtils.getAppPackageName()).toString()
+            ),
+            CommonItemTitle(
+                "isAppRunning",
+                AppUtils.isAppRunning(AppUtils.getAppPackageName()).toString()
+            ),
+            CommonItemImage("getAppIcon") {
+                it.setImageDrawable(AppUtils.getAppIcon())
+            },
+            CommonItemTitle("getAppPackageName", AppUtils.getAppPackageName()),
+            CommonItemTitle("getAppName", AppUtils.getAppName()),
+            CommonItemTitle("getAppPath", AppUtils.getAppPath()),
+            CommonItemTitle("getAppVersionName", AppUtils.getAppVersionName()),
+            CommonItemTitle("getAppVersionCode", AppUtils.getAppVersionCode().toString()),
+            CommonItemTitle("getAppMinSdkVersion", AppUtils.getAppMinSdkVersion().toString()),
+            CommonItemTitle("getAppTargetSdkVersion", AppUtils.getAppTargetSdkVersion().toString()),
+            CommonItemTitle("getAppSignaturesSHA1", AppUtils.getAppSignaturesSHA1().toString()),
+            CommonItemTitle("getAppSignaturesSHA256", AppUtils.getAppSignaturesSHA256().toString()),
+            CommonItemTitle("getAppSignaturesMD5", AppUtils.getAppSignaturesMD5().toString()),
+            CommonItemTitle("getAppUid", AppUtils.getAppUid().toString()),
+            CommonItemTitle("getApkInfo", AppUtils.getApkInfo(AppUtils.getAppPath()).toString()),
+
+            CommonItemClick(R.string.app_install) {
+                if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
+                    ToastUtils.showShort(R.string.app_install_tips)
+                } else {
+                    if (!FileUtils.isFileExists(Config.TEST_APK_PATH)) {
+                        ReleaseInstallApkTask(listener).execute()
                     } else {
-                        if (!FileUtils.isFileExists(Config.TEST_APK_PATH)) {
-                            ReleaseInstallApkTask(listener).execute()
-                        } else {
-                            listener.onReleased()
-                        }
+                        listener.onReleased()
                     }
-                },
-                CommonItemClick(R.string.app_uninstall) {
-                    if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
-                        AppUtils.uninstallApp(Config.TEST_PKG)
-                    } else {
-                        ToastUtils.showShort(R.string.app_uninstall_tips)
-                    }
-                },
-                CommonItemClick(R.string.app_launch) {
-                    AppUtils.launchApp(this.packageName)
-                },
-                CommonItemClick(R.string.app_relaunch) {
-                    AppUtils.relaunchApp()
-                },
-                CommonItemClick(R.string.app_launch_details_settings, true) {
-                    AppUtils.launchAppDetailsSettings()
-                },
-                CommonItemClick(R.string.app_exit) {
-                    AppUtils.exitApp()
                 }
+            },
+            CommonItemClick(R.string.app_uninstall) {
+                if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
+                    AppUtils.uninstallApp(Config.TEST_PKG)
+                } else {
+                    ToastUtils.showShort(R.string.app_uninstall_tips)
+                }
+            },
+            CommonItemClick(R.string.app_launch) {
+                AppUtils.launchApp(this.packageName)
+            },
+            CommonItemClick(R.string.app_relaunch) {
+                AppUtils.relaunchApp()
+            },
+            CommonItemClick(R.string.app_launch_details_settings, true) {
+                AppUtils.launchAppDetailsSettings()
+            },
+            CommonItemClick(R.string.app_exit) {
+                AppUtils.exitApp()
+            }
         )
     }
 
@@ -130,7 +141,8 @@ class AppActivity : CommonActivity(), Utils.OnAppStatusChangedListener {
     }
 }
 
-class ReleaseInstallApkTask(private val mListener: OnReleasedListener) : ThreadUtils.SimpleTask() {
+class ReleaseInstallApkTask(private val mListener: OnReleasedListener) :
+    ThreadUtils.SimpleTask() {
 
     override fun doInBackground() {
         ResourceUtils.copyFileFromAssets("test_install", Config.TEST_APK_PATH)
diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
index f7523783f9..641e96ff1d 100644
--- a/lib/utilcode/README-CN.md
+++ b/lib/utilcode/README-CN.md
@@ -72,6 +72,8 @@ getAppName                        : 获取 App 名称
 getAppPath                        : 获取 App 路径
 getAppVersionName                 : 获取 App 版本号
 getAppVersionCode                 : 获取 App 版本码
+getAppMinSdkVersion               : 获取 App 支持最低系统版本号
+getAppTargetSdkVersion            : 获取 App 目标系统版本号
 getAppSignatures                  : 获取 App 签名
 getAppSignaturesSHA1              : 获取应用签名的的 SHA1 值
 getAppSignaturesSHA256            : 获取应用签名的的 SHA256 值
diff --git a/lib/utilcode/README.md b/lib/utilcode/README.md
index 9d2025ebb0..b88bcbcfbd 100644
--- a/lib/utilcode/README.md
+++ b/lib/utilcode/README.md
@@ -72,6 +72,8 @@ getAppName
 getAppPath
 getAppVersionName
 getAppVersionCode
+getAppMinSdkVersion
+getAppTargetSdkVersion
 getAppSignatures
 getAppSignaturesSHA1
 getAppSignaturesSHA256
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
index 8f03e1cf1f..3a07653fb0 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
@@ -14,13 +14,13 @@
 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;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
 /**
  * 
  *     author: Blankj
@@ -541,6 +541,65 @@ public static int getAppVersionCode(final String packageName) {
         }
     }
 
+    /**
+     * 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.
      *
@@ -721,6 +780,8 @@ private static List getAppSignaturesHash(final String packageName, final
      * 
  • path of package
  • *
  • version name
  • *
  • version code
  • + *
  • minimum sdk version code
  • + *
  • target sdk version code
  • *
  • is system
  • * * @@ -740,6 +801,8 @@ public static AppInfo getAppInfo() { *
  • path of package
  • *
  • version name
  • *
  • version code
  • + *
  • minimum sdk version code
  • + *
  • target sdk version code
  • *
  • is system
  • * * @@ -829,13 +892,18 @@ private static AppInfo getBean(final PackageManager pm, final PackageInfo pi) { String packageName = pi.packageName; ApplicationInfo ai = pi.applicationInfo; if (ai == null) { - return new AppInfo(packageName, "", null, "", versionName, versionCode, false); + 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, isSystem); + return new AppInfo(packageName, name, icon, packagePath, versionName, versionCode, minSdkVersion, targetSdkVersion, isSystem); } /** @@ -843,13 +911,15 @@ private static AppInfo getBean(final PackageManager pm, final PackageInfo pi) { */ public static class AppInfo { - private String packageName; - private String name; + private String packageName; + private String name; private Drawable icon; - private String packagePath; - private String versionName; - private int versionCode; - private boolean isSystem; + private String packagePath; + private String versionName; + private int versionCode; + private int minSdkVersion; + private int targetSdkVersion; + private boolean isSystem; public Drawable getIcon() { return icon; @@ -907,14 +977,31 @@ public void setVersionName(final String versionName) { this.versionName = versionName; } - public AppInfo(String packageName, String name, Drawable icon, String packagePath, - String versionName, int versionCode, boolean isSystem) { + 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); } @@ -928,6 +1015,8 @@ public String toString() { "\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/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java b/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java index 76351e4b10..54895ee71f 100644 --- a/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java +++ b/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java @@ -5,10 +5,12 @@ import android.view.View.OnClickListener; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + import com.blankj.utilcode.util.AppUtils; import com.blankj.utilcode.util.ClickUtils; import com.blankj.utilcode.util.StringUtils; -import com.blankj.utildebug.DebugUtils; import com.blankj.utildebug.R; import com.blankj.utildebug.base.rv.BaseItem; import com.blankj.utildebug.base.rv.ItemViewHolder; @@ -16,9 +18,6 @@ import java.util.ArrayList; import java.util.List; -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; - /** *
      *     author: blankj
    @@ -29,8 +28,8 @@
      */
     public class AppInfoItem extends BaseItem {
     
    -    private String          mTitle;
    -    private String          mContent;
    +    private String mTitle;
    +    private String mContent;
         private OnClickListener mListener;
     
         private TextView titleTv;
    @@ -71,9 +70,9 @@ public static List getAppInfoItems() {
             appInfoItems.add(new AppInfoItem(R.string.du_app_info_version_name, AppUtils.getAppVersionName()));
             appInfoItems.add(new AppInfoItem(R.string.du_app_info_version_code, String.valueOf(AppUtils.getAppVersionCode())));
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    -            appInfoItems.add(new AppInfoItem(R.string.du_app_info_min_sdk_version, String.valueOf(DebugUtils.getApp().getApplicationInfo().minSdkVersion)));
    +            appInfoItems.add(new AppInfoItem(R.string.du_app_info_min_sdk_version, String.valueOf(AppUtils.getAppMinSdkVersion())));
             }
    -        appInfoItems.add(new AppInfoItem(R.string.du_app_info_target_sdk_version, String.valueOf(DebugUtils.getApp().getApplicationInfo().targetSdkVersion)));
    +        appInfoItems.add(new AppInfoItem(R.string.du_app_info_target_sdk_version, String.valueOf(AppUtils.getAppTargetSdkVersion())));
             appInfoItems.add(new AppInfoItem(R.string.du_app_info_open_app_info_page, "", new OnClickListener() {
                 @Override
                 public void onClick(View v) {
    
    From 718f281a3da9d4e4e6c3298faf4da9e4563e7d50 Mon Sep 17 00:00:00 2001
    From: taochen <935612713@qq.com>
    Date: Mon, 18 Jul 2022 16:12:33 +0800
    Subject: [PATCH 39/49] =?UTF-8?q?[M]=20BarUtils=E6=B7=BB=E5=8A=A0transpare?=
     =?UTF-8?q?ntNavBar=E5=AE=9E=E7=8E=B0?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    ---
     .../pkg/feature/bar/nav/BarNavActivity.kt     | 42 +++++++++++++------
     .../com/blankj/utilcode/util/BarUtils.java    | 32 +++++++++++---
     2 files changed, 57 insertions(+), 17 deletions(-)
    
    diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt
    index 1b3032974f..48a738ecd7 100644
    --- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt
    +++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/bar/nav/BarNavActivity.kt
    @@ -12,7 +12,6 @@ import com.blankj.utilcode.pkg.R
     import com.blankj.utilcode.util.BarUtils
     import com.blankj.utilcode.util.CollectionUtils
     import com.blankj.utilcode.util.ColorUtils
    -import com.blankj.utilcode.util.Utils
     
     /**
      * ```
    @@ -41,24 +40,43 @@ class BarNavActivity : CommonActivity() {
                 add(CommonItemTitle("isSupportNavBar", BarUtils.isSupportNavBar().toString()))
                 if (BarUtils.isSupportNavBar()) {
                     add(CommonItemSwitch(
    -                        R.string.bar_nav_visibility,
    -                        { BarUtils.isNavBarVisible(this@BarNavActivity) },
    -                        { BarUtils.setNavBarVisibility(this@BarNavActivity, it) }
    +                    R.string.bar_nav_visibility,
    +                    { BarUtils.isNavBarVisible(this@BarNavActivity) },
    +                    { BarUtils.setNavBarVisibility(this@BarNavActivity, it) }
                     ))
     
                     add(CommonItemSwitch(
    -                        R.string.bar_nav_light_mode,
    -                        { BarUtils.isNavBarLightMode(this@BarNavActivity) },
    -                        { BarUtils.setNavBarLightMode(this@BarNavActivity, it) }
    +                    R.string.bar_nav_light_mode,
    +                    { BarUtils.isNavBarLightMode(this@BarNavActivity) },
    +                    { BarUtils.setNavBarLightMode(this@BarNavActivity, it) }
                     ))
     
                     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    -                    add(CommonItemClick("getNavBarColor: ${ColorUtils.int2ArgbString(BarUtils.getNavBarColor(this@BarNavActivity))}").setOnItemClickListener() { _, item, _ ->
    -                        BarUtils.setNavBarColor(this@BarNavActivity, ColorUtils.getRandomColor())
    -                        itemsView.updateItems(bindItems())
    -                        item.title = "getNavBarColor: ${ColorUtils.int2ArgbString(BarUtils.getNavBarColor(this@BarNavActivity))}"
    -                    })
    +                    add(
    +                        CommonItemClick(
    +                            "getNavBarColor: ${
    +                                ColorUtils.int2ArgbString(
    +                                    BarUtils.getNavBarColor(
    +                                        this@BarNavActivity
    +                                    )
    +                                )
    +                            }"
    +                        ).setOnItemClickListener() { _, item, _ ->
    +                            BarUtils.setNavBarColor(
    +                                this@BarNavActivity,
    +                                ColorUtils.getRandomColor()
    +                            )
    +                            itemsView.updateItems(bindItems())
    +                            item.title = "getNavBarColor: ${
    +                                ColorUtils.int2ArgbString(
    +                                    BarUtils.getNavBarColor(this@BarNavActivity)
    +                                )
    +                            }"
    +                        })
                     }
    +                add(CommonItemClick("transparentNavBar").setOnItemClickListener() { _, item, _ ->
    +                    BarUtils.transparentNavBar(this@BarNavActivity)
    +                })
                 }
             }
         }
    diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
    index af9dbc4fcd..ece4f7faba 100644
    --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
    +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
    @@ -1,5 +1,7 @@
     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;
    @@ -19,15 +21,13 @@
     import android.view.Window;
     import android.view.WindowManager;
     
    -import java.lang.reflect.Method;
    -
     import androidx.annotation.ColorInt;
     import androidx.annotation.NonNull;
     import androidx.annotation.RequiresApi;
     import androidx.annotation.RequiresPermission;
     import androidx.drawerlayout.widget.DrawerLayout;
     
    -import static android.Manifest.permission.EXPAND_STATUS_BAR;
    +import java.lang.reflect.Method;
     
     /**
      * 
    @@ -44,8 +44,8 @@ public final class BarUtils {
         ///////////////////////////////////////////////////////////////////////////
     
         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 static final String TAG_OFFSET = "TAG_OFFSET";
    +    private static final int KEY_OFFSET = -123;
     
         private BarUtils() {
             throw new UnsupportedOperationException("u can't instantiate me...");
    @@ -715,4 +715,26 @@ public static boolean isNavBarLightMode(@NonNull final Window window) {
             }
             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);
    +    }
     }
    
    From afaea3eb6b29d24c18cfbcb4a103310fd380b16e Mon Sep 17 00:00:00 2001
    From: Justson 
    Date: Wed, 8 Jun 2022 10:55:22 +0800
    Subject: [PATCH 40/49] Update README-CN.md
    
    ---
     lib/utilcode/README-CN.md | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
    index 0e4e93f3a0..260cabac24 100644
    --- a/lib/utilcode/README-CN.md
    +++ b/lib/utilcode/README-CN.md
    @@ -6,7 +6,7 @@ Gradle:
     implementation 'com.blankj:utilcodex:1.31.0'
     
     // Not in maintenance
    -implementation 'com.blankj:utilcode:1.30.6'
    +implementation 'com.blankj:utilcode:1.30.7'
     ```
     
     
    
    From 555cca99df44edc2025db0a3cbe9dc1b4b65db31 Mon Sep 17 00:00:00 2001
    From: sth0409 <97033765@qq.com>
    Date: Wed, 25 May 2022 11:18:02 +0800
    Subject: [PATCH 41/49] fix bug
    
    ---
     lib/utilcode/src/main/res/xml/util_code_provider_paths.xml | 7 ++++++-
     1 file changed, 6 insertions(+), 1 deletion(-)
    
    diff --git a/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml b/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml
    index ed731a2299..b88716480c 100644
    --- a/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml
    +++ b/lib/utilcode/src/main/res/xml/util_code_provider_paths.xml
    @@ -23,4 +23,9 @@
         
    -
    \ No newline at end of file
    +      
    +    
    +
    
    From 862088e4b85a0621f184f6ecea71367d05f9ba72 Mon Sep 17 00:00:00 2001
    From: Absinthe 
    Date: Sat, 11 Dec 2021 11:59:28 +0800
    Subject: [PATCH 42/49] Explicitly specify `android:exported` to make
     compatible with Android 12.
    
    ---
     lib/utilcode/src/main/AndroidManifest.xml | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/lib/utilcode/src/main/AndroidManifest.xml b/lib/utilcode/src/main/AndroidManifest.xml
    index fc5b75e0e3..d45dd57787 100644
    --- a/lib/utilcode/src/main/AndroidManifest.xml
    +++ b/lib/utilcode/src/main/AndroidManifest.xml
    @@ -5,12 +5,14 @@
     
             
     
             
    Date: Mon, 18 Jul 2022 17:02:24 +0800
    Subject: [PATCH 43/49] =?UTF-8?q?[M]=20=E4=BF=AE=E6=94=B9BarUtils=E6=96=B9?=
     =?UTF-8?q?=E6=B3=95=E5=88=97=E8=A1=A8=E5=8F=8A=E6=8F=8F=E8=BF=B0?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    ---
     lib/utilcode/README-CN.md | 1 +
     lib/utilcode/README.md    | 1 +
     2 files changed, 2 insertions(+)
    
    diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
    index 260cabac24..a6ab4b3d09 100644
    --- a/lib/utilcode/README-CN.md
    +++ b/lib/utilcode/README-CN.md
    @@ -141,6 +141,7 @@ getNavBarColor                       : 获取导航栏颜色
     isSupportNavBar                      : 判断是否支持导航栏
     setNavBarLightMode                   : 设置导航栏是否为浅色模式
     isNavBarLightMode                    : 判断导航栏是否为浅色模式
    +transparentNavBar                    : 透明导航栏
     ```
     
     * ### 亮度相关 -> [BrightnessUtils.java][brightness.java] -> [Demo][brightness.demo]
    diff --git a/lib/utilcode/README.md b/lib/utilcode/README.md
    index cdabfba45a..9d2025ebb0 100644
    --- a/lib/utilcode/README.md
    +++ b/lib/utilcode/README.md
    @@ -140,6 +140,7 @@ getNavBarColor
     isSupportNavBar
     setNavBarLightMode
     isNavBarLightMode
    +transparentNavBar
     ```
     
     * ### About Brightness -> [BrightnessUtils.java][brightness.java] -> [Demo][brightness.demo]
    
    From 62bf1646bf43427de4f30ff0653a3dfe6da90634 Mon Sep 17 00:00:00 2001
    From: taochen <935612713@qq.com>
    Date: Tue, 19 Jul 2022 12:00:46 +0800
    Subject: [PATCH 44/49] =?UTF-8?q?[F]=20TargetSdkVersion=2030=20AppUtils.is?=
     =?UTF-8?q?AppInstalled=E8=BF=94=E5=9B=9E=E9=94=99=E8=AF=AF?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    ---
     lib/utilcode/src/main/AndroidManifest.xml | 9 +++++++++
     1 file changed, 9 insertions(+)
    
    diff --git a/lib/utilcode/src/main/AndroidManifest.xml b/lib/utilcode/src/main/AndroidManifest.xml
    index d45dd57787..ab497595d4 100644
    --- a/lib/utilcode/src/main/AndroidManifest.xml
    +++ b/lib/utilcode/src/main/AndroidManifest.xml
    @@ -1,6 +1,15 @@
     
     
    +    
    +        
    +            
    +        
    +        
    +            
    +        
    +    
    +
         
     
             
    Date: Tue, 19 Jul 2022 17:31:46 +0800
    Subject: [PATCH 45/49] =?UTF-8?q?[M]=20AppUtils=E5=A2=9E=E5=8A=A0getAppMin?=
     =?UTF-8?q?SdkVersion,=20getAppTargetSdkVersion=E6=94=AF=E6=8C=81?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    ---
     .../utilcode/pkg/feature/app/AppActivity.kt   | 108 ++++++++--------
     lib/utilcode/README-CN.md                     |   2 +
     lib/utilcode/README.md                        |   2 +
     .../com/blankj/utilcode/util/AppUtils.java    | 115 ++++++++++++++++--
     .../debug/tool/appInfo/AppInfoItem.java       |  15 ++-
     5 files changed, 173 insertions(+), 69 deletions(-)
    
    diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt
    index 175fa1bc3b..21eb351146 100644
    --- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt
    +++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/app/AppActivity.kt
    @@ -54,7 +54,10 @@ class AppActivity : CommonActivity(), Utils.OnAppStatusChangedListener {
     
         override fun bindItems(): MutableList> {
             return CollectionUtils.newArrayList(
    -                CommonItemSwitch("registerAppStatusChangedListener", { isRegisterAppStatusChangedListener }, {
    +            CommonItemSwitch(
    +                "registerAppStatusChangedListener",
    +                { isRegisterAppStatusChangedListener },
    +                {
                         isRegisterAppStatusChangedListener = it
                         if (it) {
                             AppUtils.registerAppStatusChangedListener(this)
    @@ -62,55 +65,63 @@ class AppActivity : CommonActivity(), Utils.OnAppStatusChangedListener {
                             AppUtils.unregisterAppStatusChangedListener(this)
                         }
                     }),
    -                CommonItemTitle("isAppRoot", AppUtils.isAppRoot().toString()),
    -                CommonItemTitle("isAppDebug", AppUtils.isAppDebug().toString()),
    -                CommonItemTitle("isAppSystem", AppUtils.isAppSystem().toString()),
    -                CommonItemTitle("isAppForeground", AppUtils.isAppForeground(AppUtils.getAppPackageName()).toString()),
    -                CommonItemTitle("isAppRunning", AppUtils.isAppRunning(AppUtils.getAppPackageName()).toString()),
    -                CommonItemImage("getAppIcon") {
    -                    it.setImageDrawable(AppUtils.getAppIcon())
    -                },
    -                CommonItemTitle("getAppPackageName", AppUtils.getAppPackageName()),
    -                CommonItemTitle("getAppName", AppUtils.getAppName()),
    -                CommonItemTitle("getAppPath", AppUtils.getAppPath()),
    -                CommonItemTitle("getAppVersionName", AppUtils.getAppVersionName()),
    -                CommonItemTitle("getAppVersionCode", AppUtils.getAppVersionCode().toString()),
    -                CommonItemTitle("getAppSignaturesSHA1", AppUtils.getAppSignaturesSHA1().toString()),
    -                CommonItemTitle("getAppSignaturesSHA256", AppUtils.getAppSignaturesSHA256().toString()),
    -                CommonItemTitle("getAppSignaturesMD5", AppUtils.getAppSignaturesMD5().toString()),
    -                CommonItemTitle("getAppUid", AppUtils.getAppUid().toString()),
    -                CommonItemTitle("getApkInfo", AppUtils.getApkInfo(AppUtils.getAppPath()).toString()),
    -
    -                CommonItemClick(R.string.app_install) {
    -                    if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
    -                        ToastUtils.showShort(R.string.app_install_tips)
    +            CommonItemTitle("isAppRoot", AppUtils.isAppRoot().toString()),
    +            CommonItemTitle("isAppDebug", AppUtils.isAppDebug().toString()),
    +            CommonItemTitle("isAppSystem", AppUtils.isAppSystem().toString()),
    +            CommonItemTitle(
    +                "isAppForeground",
    +                AppUtils.isAppForeground(AppUtils.getAppPackageName()).toString()
    +            ),
    +            CommonItemTitle(
    +                "isAppRunning",
    +                AppUtils.isAppRunning(AppUtils.getAppPackageName()).toString()
    +            ),
    +            CommonItemImage("getAppIcon") {
    +                it.setImageDrawable(AppUtils.getAppIcon())
    +            },
    +            CommonItemTitle("getAppPackageName", AppUtils.getAppPackageName()),
    +            CommonItemTitle("getAppName", AppUtils.getAppName()),
    +            CommonItemTitle("getAppPath", AppUtils.getAppPath()),
    +            CommonItemTitle("getAppVersionName", AppUtils.getAppVersionName()),
    +            CommonItemTitle("getAppVersionCode", AppUtils.getAppVersionCode().toString()),
    +            CommonItemTitle("getAppMinSdkVersion", AppUtils.getAppMinSdkVersion().toString()),
    +            CommonItemTitle("getAppTargetSdkVersion", AppUtils.getAppTargetSdkVersion().toString()),
    +            CommonItemTitle("getAppSignaturesSHA1", AppUtils.getAppSignaturesSHA1().toString()),
    +            CommonItemTitle("getAppSignaturesSHA256", AppUtils.getAppSignaturesSHA256().toString()),
    +            CommonItemTitle("getAppSignaturesMD5", AppUtils.getAppSignaturesMD5().toString()),
    +            CommonItemTitle("getAppUid", AppUtils.getAppUid().toString()),
    +            CommonItemTitle("getApkInfo", AppUtils.getApkInfo(AppUtils.getAppPath()).toString()),
    +
    +            CommonItemClick(R.string.app_install) {
    +                if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
    +                    ToastUtils.showShort(R.string.app_install_tips)
    +                } else {
    +                    if (!FileUtils.isFileExists(Config.TEST_APK_PATH)) {
    +                        ReleaseInstallApkTask(listener).execute()
                         } else {
    -                        if (!FileUtils.isFileExists(Config.TEST_APK_PATH)) {
    -                            ReleaseInstallApkTask(listener).execute()
    -                        } else {
    -                            listener.onReleased()
    -                        }
    +                        listener.onReleased()
                         }
    -                },
    -                CommonItemClick(R.string.app_uninstall) {
    -                    if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
    -                        AppUtils.uninstallApp(Config.TEST_PKG)
    -                    } else {
    -                        ToastUtils.showShort(R.string.app_uninstall_tips)
    -                    }
    -                },
    -                CommonItemClick(R.string.app_launch) {
    -                    AppUtils.launchApp(this.packageName)
    -                },
    -                CommonItemClick(R.string.app_relaunch) {
    -                    AppUtils.relaunchApp()
    -                },
    -                CommonItemClick(R.string.app_launch_details_settings, true) {
    -                    AppUtils.launchAppDetailsSettings()
    -                },
    -                CommonItemClick(R.string.app_exit) {
    -                    AppUtils.exitApp()
                     }
    +            },
    +            CommonItemClick(R.string.app_uninstall) {
    +                if (AppUtils.isAppInstalled(Config.TEST_PKG)) {
    +                    AppUtils.uninstallApp(Config.TEST_PKG)
    +                } else {
    +                    ToastUtils.showShort(R.string.app_uninstall_tips)
    +                }
    +            },
    +            CommonItemClick(R.string.app_launch) {
    +                AppUtils.launchApp(this.packageName)
    +            },
    +            CommonItemClick(R.string.app_relaunch) {
    +                AppUtils.relaunchApp()
    +            },
    +            CommonItemClick(R.string.app_launch_details_settings, true) {
    +                AppUtils.launchAppDetailsSettings()
    +            },
    +            CommonItemClick(R.string.app_exit) {
    +                AppUtils.exitApp()
    +            }
             )
         }
     
    @@ -130,7 +141,8 @@ class AppActivity : CommonActivity(), Utils.OnAppStatusChangedListener {
         }
     }
     
    -class ReleaseInstallApkTask(private val mListener: OnReleasedListener) : ThreadUtils.SimpleTask() {
    +class ReleaseInstallApkTask(private val mListener: OnReleasedListener) :
    +    ThreadUtils.SimpleTask() {
     
         override fun doInBackground() {
             ResourceUtils.copyFileFromAssets("test_install", Config.TEST_APK_PATH)
    diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
    index a6ab4b3d09..d8b9591fe7 100644
    --- a/lib/utilcode/README-CN.md
    +++ b/lib/utilcode/README-CN.md
    @@ -72,6 +72,8 @@ getAppName                        : 获取 App 名称
     getAppPath                        : 获取 App 路径
     getAppVersionName                 : 获取 App 版本号
     getAppVersionCode                 : 获取 App 版本码
    +getAppMinSdkVersion               : 获取 App 支持最低系统版本号
    +getAppTargetSdkVersion            : 获取 App 目标系统版本号
     getAppSignatures                  : 获取 App 签名
     getAppSignaturesSHA1              : 获取应用签名的的 SHA1 值
     getAppSignaturesSHA256            : 获取应用签名的的 SHA256 值
    diff --git a/lib/utilcode/README.md b/lib/utilcode/README.md
    index 9d2025ebb0..b88bcbcfbd 100644
    --- a/lib/utilcode/README.md
    +++ b/lib/utilcode/README.md
    @@ -72,6 +72,8 @@ getAppName
     getAppPath
     getAppVersionName
     getAppVersionCode
    +getAppMinSdkVersion
    +getAppTargetSdkVersion
     getAppSignatures
     getAppSignaturesSHA1
     getAppSignaturesSHA256
    diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
    index 8f03e1cf1f..3a07653fb0 100644
    --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
    +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/AppUtils.java
    @@ -14,13 +14,13 @@
     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;
     
    -import androidx.annotation.NonNull;
    -import androidx.annotation.Nullable;
    -
     /**
      * 
      *     author: Blankj
    @@ -541,6 +541,65 @@ public static int getAppVersionCode(final String packageName) {
             }
         }
     
    +    /**
    +     * 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.
          *
    @@ -721,6 +780,8 @@ private static List getAppSignaturesHash(final String packageName, final
          * 
  • path of package
  • *
  • version name
  • *
  • version code
  • + *
  • minimum sdk version code
  • + *
  • target sdk version code
  • *
  • is system
  • * * @@ -740,6 +801,8 @@ public static AppInfo getAppInfo() { *
  • path of package
  • *
  • version name
  • *
  • version code
  • + *
  • minimum sdk version code
  • + *
  • target sdk version code
  • *
  • is system
  • * * @@ -829,13 +892,18 @@ private static AppInfo getBean(final PackageManager pm, final PackageInfo pi) { String packageName = pi.packageName; ApplicationInfo ai = pi.applicationInfo; if (ai == null) { - return new AppInfo(packageName, "", null, "", versionName, versionCode, false); + 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, isSystem); + return new AppInfo(packageName, name, icon, packagePath, versionName, versionCode, minSdkVersion, targetSdkVersion, isSystem); } /** @@ -843,13 +911,15 @@ private static AppInfo getBean(final PackageManager pm, final PackageInfo pi) { */ public static class AppInfo { - private String packageName; - private String name; + private String packageName; + private String name; private Drawable icon; - private String packagePath; - private String versionName; - private int versionCode; - private boolean isSystem; + private String packagePath; + private String versionName; + private int versionCode; + private int minSdkVersion; + private int targetSdkVersion; + private boolean isSystem; public Drawable getIcon() { return icon; @@ -907,14 +977,31 @@ public void setVersionName(final String versionName) { this.versionName = versionName; } - public AppInfo(String packageName, String name, Drawable icon, String packagePath, - String versionName, int versionCode, boolean isSystem) { + 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); } @@ -928,6 +1015,8 @@ public String toString() { "\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/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java b/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java index 76351e4b10..54895ee71f 100644 --- a/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java +++ b/lib/utildebug/src/main/java/com/blankj/utildebug/debug/tool/appInfo/AppInfoItem.java @@ -5,10 +5,12 @@ import android.view.View.OnClickListener; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + import com.blankj.utilcode.util.AppUtils; import com.blankj.utilcode.util.ClickUtils; import com.blankj.utilcode.util.StringUtils; -import com.blankj.utildebug.DebugUtils; import com.blankj.utildebug.R; import com.blankj.utildebug.base.rv.BaseItem; import com.blankj.utildebug.base.rv.ItemViewHolder; @@ -16,9 +18,6 @@ import java.util.ArrayList; import java.util.List; -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; - /** *
      *     author: blankj
    @@ -29,8 +28,8 @@
      */
     public class AppInfoItem extends BaseItem {
     
    -    private String          mTitle;
    -    private String          mContent;
    +    private String mTitle;
    +    private String mContent;
         private OnClickListener mListener;
     
         private TextView titleTv;
    @@ -71,9 +70,9 @@ public static List getAppInfoItems() {
             appInfoItems.add(new AppInfoItem(R.string.du_app_info_version_name, AppUtils.getAppVersionName()));
             appInfoItems.add(new AppInfoItem(R.string.du_app_info_version_code, String.valueOf(AppUtils.getAppVersionCode())));
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    -            appInfoItems.add(new AppInfoItem(R.string.du_app_info_min_sdk_version, String.valueOf(DebugUtils.getApp().getApplicationInfo().minSdkVersion)));
    +            appInfoItems.add(new AppInfoItem(R.string.du_app_info_min_sdk_version, String.valueOf(AppUtils.getAppMinSdkVersion())));
             }
    -        appInfoItems.add(new AppInfoItem(R.string.du_app_info_target_sdk_version, String.valueOf(DebugUtils.getApp().getApplicationInfo().targetSdkVersion)));
    +        appInfoItems.add(new AppInfoItem(R.string.du_app_info_target_sdk_version, String.valueOf(AppUtils.getAppTargetSdkVersion())));
             appInfoItems.add(new AppInfoItem(R.string.du_app_info_open_app_info_page, "", new OnClickListener() {
                 @Override
                 public void onClick(View v) {
    
    From 5f739314d9eadeb5cad7f0e6876d2606480fc1f5 Mon Sep 17 00:00:00 2001
    From: Blankj 
    Date: Sat, 15 Oct 2022 00:45:11 +0800
    Subject: [PATCH 46/49] fix: some bugs
    
    ---
     CHANGELOG.md                                  |  1 +
     buildSrc/src/main/groovy/Config.groovy        |  6 +--
     lib/utilcode/README-CN.md                     | 11 +++--
     lib/utilcode/README.md                        |  3 +-
     .../blankj/utilcode/util/ActivityUtils.java   |  9 ++--
     .../com/blankj/utilcode/util/BarUtils.java    |  4 +-
     .../com/blankj/utilcode/util/DeviceUtils.java | 46 +++++++++++++++++--
     module_config.json                            |  2 +-
     8 files changed, 63 insertions(+), 19 deletions(-)
    
    diff --git a/CHANGELOG.md b/CHANGELOG.md
    index c4bcc19c85..73e8145bf1 100644
    --- a/CHANGELOG.md
    +++ b/CHANGELOG.md
    @@ -1,3 +1,4 @@
    +* `22/10/15` [add] Fix some issue. Publish v1.31.1
     * `21/12/06` [add] Publish v1.31.0
     * `21/05/13` [add] Support publish mavenCentral.
     * `21/02/22` [add] Fix ToastUtils rtl bug. Publish v1.30.6.
    diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy
    index 268ec666ce..9a8d69d659 100644
    --- a/buildSrc/src/main/groovy/Config.groovy
    +++ b/buildSrc/src/main/groovy/Config.groovy
    @@ -6,8 +6,8 @@ class Config {
         static compileSdkVersion = 29
         static minSdkVersion = 14
         static targetSdkVersion = 29
    -    static versionCode = 1_030_007
    -    static versionName = '1.31.0'// E.g. 1.9.72 => 1,009,072
    +    static versionCode = 1_031_001
    +    static versionName = '1.31.1'// E.g. 1.9.72 => 1,009,072
     
         // lib version
         static gradlePluginVersion = '4.1.0'
    @@ -34,7 +34,7 @@ class Config {
                 lib_base                   : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/base"),
                 lib_common                 : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/common"),
                 lib_subutil                : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/subutil"),
    -            lib_utilcode               : new ModuleConfig(isApply: true , useLocal: false, localPath: "./lib/utilcode", remotePath: "com.blankj:utilcodex:$Config.versionName"),
    +            lib_utilcode               : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utilcode", remotePath: "com.blankj:utilcodex:$Config.versionName"),
                 lib_utildebug              : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug"),
                 lib_utildebug_no_op        : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug-no-op"),
                 /*Don't delete this line*/
    diff --git a/lib/utilcode/README-CN.md b/lib/utilcode/README-CN.md
    index d8b9591fe7..6610b3be99 100644
    --- a/lib/utilcode/README-CN.md
    +++ b/lib/utilcode/README-CN.md
    @@ -3,7 +3,7 @@
     Gradle:
     ```groovy
     // if u use AndroidX, use the following
    -implementation 'com.blankj:utilcodex:1.31.0'
    +implementation 'com.blankj:utilcodex:1.31.1'
     
     // Not in maintenance
     implementation 'com.blankj:utilcode:1.30.7'
    @@ -1210,10 +1210,11 @@ removeListener: 移除消息监听器
     
     * ### URI 相关 -> [UriUtils.java][uri.java]
     ```
    -res2Uri  : res 转 uri
    -file2Uri : file 转 uri
    -uri2File : uri 转 file
    -uri2Bytes: uri 转 bytes
    +res2Uri            : res 转 uri
    +file2Uri           : file 转 uri
    +uri2File           : uri 转 file
    +uri2FileNoCacheCopy: uri 转 file 不拷贝缓存
    +uri2Bytes          : uri 转 bytes
     ```
     
     * ### UtilsTransActivity -> [UtilsTransActivity.java][trans.java]
    diff --git a/lib/utilcode/README.md b/lib/utilcode/README.md
    index b88bcbcfbd..570f58fc46 100644
    --- a/lib/utilcode/README.md
    +++ b/lib/utilcode/README.md
    @@ -3,7 +3,7 @@
     Gradle:
     ```groovy
     // if u use AndroidX, use the following
    -implementation 'com.blankj:utilcodex:1.31.0'
    +implementation 'com.blankj:utilcodex:1.31.1'
     
     // Not in maintenance
     implementation 'com.blankj:utilcode:1.30.6'
    @@ -1212,6 +1212,7 @@ removeListener
     res2Uri
     file2Uri
     uri2File
    +uri2FileNoCacheCopy
     uri2Bytes
     ```
     
    diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
    index 10858f75f4..056668652c 100644
    --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
    +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java
    @@ -2013,10 +2013,11 @@ private static boolean startActivity(final Intent intent,
         }
     
         private static boolean isIntentAvailable(final Intent intent) {
    -        return Utils.getApp()
    -                .getPackageManager()
    -                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
    -                .size() > 0;
    +//        return Utils.getApp()
    +//                .getPackageManager()
    +//                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
    +//                .size() > 0;
    +        return true;
         }
     
         private static boolean startActivityForResult(final Activity activity,
    diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
    index ece4f7faba..e8cacc5f0c 100644
    --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
    +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/BarUtils.java
    @@ -57,7 +57,7 @@ private BarUtils() {
          * @return the status bar's height
          */
         public static int getStatusBarHeight() {
    -        Resources resources = Utils.getApp().getResources();
    +        Resources resources = Resources.getSystem();
             int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
             return resources.getDimensionPixelSize(resourceId);
         }
    @@ -483,7 +483,7 @@ private static void invokePanels(final String methodName) {
          * @return the navigation bar's height
          */
         public static int getNavBarHeight() {
    -        Resources res = Utils.getApp().getResources();
    +        Resources res = Resources.getSystem();
             int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
             if (resourceId != 0) {
                 return res.getDimensionPixelSize(resourceId);
    diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/DeviceUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
    index e6feb5fdaa..9cd01108e1 100644
    --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
    +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/DeviceUtils.java
    @@ -13,16 +13,19 @@
     import android.telephony.TelephonyManager;
     import android.text.TextUtils;
     
    -import androidx.annotation.RequiresApi;
    -import androidx.annotation.RequiresPermission;
    -
    +import java.io.BufferedReader;
     import java.io.File;
    +import java.io.IOException;
    +import java.io.InputStreamReader;
     import java.net.InetAddress;
     import java.net.NetworkInterface;
     import java.net.SocketException;
     import java.util.Enumeration;
     import java.util.UUID;
     
    +import androidx.annotation.RequiresApi;
    +import androidx.annotation.RequiresPermission;
    +
     import static android.Manifest.permission.ACCESS_WIFI_STATE;
     import static android.Manifest.permission.CHANGE_WIFI_STATE;
     import static android.Manifest.permission.INTERNET;
    @@ -382,6 +385,7 @@ public static boolean isEmulator() {
             intent.setAction(Intent.ACTION_DIAL);
             boolean checkDial = intent.resolveActivity(Utils.getApp().getPackageManager()) == null;
             if (checkDial) return true;
    +        if (isEmulatorByCpu()) return true;
     
     //        boolean checkDebuggerConnected = Debug.isDebuggerConnected();
     //        if (checkDebuggerConnected) return true;
    @@ -389,6 +393,42 @@ public static boolean isEmulator() {
             return false;
         }
     
    +    /**
    +     * Returns whether is emulator by check cpu info.
    +     * by function of {@link #readCpuInfo}, obtain the device cpu information.
    +     * then compare whether it is intel or amd (because intel and amd are generally not mobile phone cpu), to determine whether it is a real mobile phone
    +     *
    +     * @return {@code true}: yes
    {@code false}: no + */ + private static boolean isEmulatorByCpu() { + String cpuInfo = readCpuInfo(); + return cpuInfo.contains("intel") || cpuInfo.contains("amd"); + } + + /** + * Return Cpu information + * + * @return Cpu info + */ + private static String readCpuInfo() { + String result = ""; + try { + String[] args = {"/system/bin/cat", "/proc/cpuinfo"}; + ProcessBuilder cmd = new ProcessBuilder(args); + Process process = cmd.start(); + StringBuilder sb = new StringBuilder(); + String readLine; + BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8")); + while ((readLine = responseReader.readLine()) != null) { + sb.append(readLine); + } + responseReader.close(); + result = sb.toString().toLowerCase(); + } catch (IOException ignored) { + } + return result; + } + /** * Whether user has enabled development settings. * diff --git a/module_config.json b/module_config.json index 18f416382a..87233122b9 100644 --- a/module_config.json +++ b/module_config.json @@ -23,7 +23,7 @@ {"name": "lib_base", "isApply": true, "useLocal": true, "localPath": "./lib/base"}, {"name": "lib_common", "isApply": true, "useLocal": true, "localPath": "./lib/common"}, {"name": "lib_subutil", "isApply": true, "useLocal": true, "localPath": "./lib/subutil"}, - {"name": "lib_utilcode", "isApply": true, "useLocal": false, "localPath": "./lib/utilcode", "remotePath": "com.blankj:utilcodex:$Config.versionName"}, + {"name": "lib_utilcode", "isApply": true, "useLocal": true, "localPath": "./lib/utilcode", "remotePath": "com.blankj:utilcodex:$Config.versionName"}, {"name": "lib_utildebug", "isApply": true, "useLocal": true, "localPath": "./lib/utildebug"}, {"name": "lib_utildebug_no_op", "isApply": true, "useLocal": true, "localPath": "./lib/utildebug-no-op"} ] From 99be3102e1b5dce8bf051721008811eed3dae0a0 Mon Sep 17 00:00:00 2001 From: taochen <935612713@qq.com> Date: Fri, 21 Oct 2022 15:42:20 +0800 Subject: [PATCH 47/49] =?UTF-8?q?[F]=20=E9=83=A8=E5=88=86=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E5=B8=82=E5=9C=BA=E4=BB=A5=E6=89=80=E8=B0=93ActivityU?= =?UTF-8?q?tils=E9=9A=90=E7=A7=81=E5=90=88=E8=A7=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E6=8B=92=E7=BB=9D=E5=BA=94=E7=94=A8=E4=B8=8A=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blankj/utilcode/util/ActivityUtils.java | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java index 056668652c..d49ce6ff06 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ActivityUtils.java @@ -1997,29 +1997,22 @@ private static void startActivity(final Context context, 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); + try { + if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + context.startActivity(intent, options); + } else { + context.startActivity(intent); + } + } catch (Exception e) { + Log.e("ActivityUtils", "An exception occurred in startActivity, error message: " + e.getLocalizedMessage()); + return false; } 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, @@ -2036,15 +2029,16 @@ 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"); + try { + if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + activity.startActivityForResult(intent, requestCode, options); + } else { + activity.startActivityForResult(intent, requestCode); + } + } catch (Exception e) { + Log.e("ActivityUtils", "An exception occurred in startActivityForResult, error message: " + e.getLocalizedMessage()); 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; } @@ -2079,18 +2073,19 @@ 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); + try { + if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + fragment.startActivityForResult(intent, requestCode, options); + } else { + fragment.startActivityForResult(intent, requestCode); + } + } catch (Exception e) { + Log.e("ActivityUtils", "An exception occurred in fragment.startActivityForResult, error message: " + e.getLocalizedMessage()); + return false; } return true; } From 19349b9998224f04385c37f643fc96e69faf33bd Mon Sep 17 00:00:00 2001 From: simple <383559698@qq.com> Date: Wed, 24 Apr 2024 19:22:35 +0800 Subject: [PATCH 48/49] update VibrateUtils --- buildSrc/src/main/groovy/Config.groovy | 2 +- .../pkg/feature/vibrate/VibrateActivity.kt | 22 +++++- .../pkg/src/main/res/values/strings.xml | 1 + .../blankj/utilcode/util/VibrateUtils.java | 79 +++++++++++++++++++ 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/groovy/Config.groovy b/buildSrc/src/main/groovy/Config.groovy index a69b8907c7..9a8d69d659 100644 --- a/buildSrc/src/main/groovy/Config.groovy +++ b/buildSrc/src/main/groovy/Config.groovy @@ -34,7 +34,7 @@ class Config { lib_base : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/base"), lib_common : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/common"), lib_subutil : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/subutil"), - lib_utilcode : new ModuleConfig(isApply: true , useLocal: false, localPath: "./lib/utilcode", remotePath: "com.blankj:utilcodex:$Config.versionName"), + lib_utilcode : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utilcode", remotePath: "com.blankj:utilcodex:$Config.versionName"), lib_utildebug : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug"), lib_utildebug_no_op : new ModuleConfig(isApply: true , useLocal: true , localPath: "./lib/utildebug-no-op"), /*Don't delete this line*/ diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt index d2cd9bc147..ee88dab0fa 100644 --- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt +++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt @@ -32,11 +32,22 @@ class VibrateActivity : CommonActivity() { override fun bindItems(): MutableList> { return CollectionUtils.newArrayList( - CommonItemClick(R.string.vibrate_1000ms) { VibrateUtils.vibrate(1000) }, + CommonItemClick(R.string.vibrate_1000ms) { + VibrateUtils.vibrate(1000) + }, CommonItemClick(R.string.vibrate_custom) { VibrateUtils.vibrate(longArrayOf(0, 1000, 1000, 2000, 2000, 1000), 1) }, - CommonItemClick(R.string.vibrate_cancel) { VibrateUtils.cancel() } + CommonItemClick(R.string.vibrate_background) { + backHome() + mContentView.postDelayed({ + VibrateUtils.vibrateCompat(longArrayOf(0, 1000, 1000, 2000, 2000, 1000), 1) +// VibrateUtils.vibrateCompat(1000) + }, 1000) + }, + CommonItemClick(R.string.vibrate_cancel) { + VibrateUtils.cancel() + } ) } @@ -44,4 +55,11 @@ class VibrateActivity : CommonActivity() { super.onDestroy() VibrateUtils.cancel() } + + private fun backHome() { + val intent = Intent(Intent.ACTION_MAIN).apply { + addCategory(Intent.CATEGORY_HOME) + } + startActivity(intent) + } } diff --git a/feature/utilcode/pkg/src/main/res/values/strings.xml b/feature/utilcode/pkg/src/main/res/values/strings.xml index ccec698647..551f9adbaf 100644 --- a/feature/utilcode/pkg/src/main/res/values/strings.xml +++ b/feature/utilcode/pkg/src/main/res/values/strings.xml @@ -366,5 +366,6 @@ Vibrate 1000ms Vibrate Custom + Vibrate Background Cancel diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java index 622d657817..8d2ab055e4 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java @@ -1,7 +1,11 @@ package com.blankj.utilcode.util; import android.content.Context; +import android.media.AudioAttributes; +import android.os.Build; import android.os.Vibrator; + +import androidx.annotation.RequiresApi; import androidx.annotation.RequiresPermission; import static android.Manifest.permission.VIBRATE; @@ -35,6 +39,39 @@ public static void vibrate(final long milliseconds) { vibrator.vibrate(milliseconds); } + /** + * Vibrate. + *

    Must hold {@code }

    + * + * @param milliseconds The number of milliseconds to vibrate. + * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, + * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or + * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for + * vibrations associated with incoming calls. + */ + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @RequiresPermission(VIBRATE) + public static void vibrate(final long milliseconds, AudioAttributes attributes) { + Vibrator vibrator = getVibrator(); + if (vibrator == null) return; + vibrator.vibrate(milliseconds, attributes); + } + + /** + * VibrateCompat + *

    Must hold {@code }

    + * + * @param milliseconds he number of milliseconds to vibrate. + */ + @RequiresPermission(VIBRATE) + public static void vibrateCompat(final long milliseconds) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + vibrate(milliseconds, getAudioAttributes()); + } else { + vibrate(milliseconds); + } + } + /** * Vibrate. *

    Must hold {@code }

    @@ -49,6 +86,41 @@ public static void vibrate(final long[] pattern, final int repeat) { vibrator.vibrate(pattern, repeat); } + /** + * Vibrate. + *

    Must hold {@code }

    + * + * @param pattern An array of longs of times for which to turn the vibrator on or off. + * @param repeat The index into pattern at which to repeat, or -1 if you don't want to repeat. + * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, + * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or + * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for + * vibrations associated with incoming calls. + */ + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @RequiresPermission(VIBRATE) + public static void vibrate(final long[] pattern, final int repeat, AudioAttributes attributes) { + Vibrator vibrator = getVibrator(); + if (vibrator == null) return; + vibrator.vibrate(pattern, repeat, attributes); + } + + /** + * VibrateCompat + *

    Must hold {@code }

    + * + * @param pattern An array of longs of times for which to turn the vibrator on or off. + * @param repeat The index into pattern at which to repeat, or -1 if you don't want to repeat. + */ + @RequiresPermission(VIBRATE) + public static void vibrateCompat(final long[] pattern, final int repeat) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + vibrate(pattern, repeat, getAudioAttributes()); + } else { + vibrate(pattern, repeat); + } + } + /** * Cancel vibrate. *

    Must hold {@code }

    @@ -66,4 +138,11 @@ private static Vibrator getVibrator() { } return vibrator; } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private static AudioAttributes getAudioAttributes() { + return new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_ALARM) + .build(); + } } From c7ebceb6675670080389472445d0bcb3c71f8bc9 Mon Sep 17 00:00:00 2001 From: simple <383559698@qq.com> Date: Thu, 25 Apr 2024 10:36:38 +0800 Subject: [PATCH 49/49] add VibrateUtils comment --- .../blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt | 1 + .../src/main/java/com/blankj/utilcode/util/VibrateUtils.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt index ee88dab0fa..5dc337bc5b 100644 --- a/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt +++ b/feature/utilcode/pkg/src/main/java/com/blankj/utilcode/pkg/feature/vibrate/VibrateActivity.kt @@ -41,6 +41,7 @@ class VibrateActivity : CommonActivity() { CommonItemClick(R.string.vibrate_background) { backHome() mContentView.postDelayed({ +// VibrateUtils.vibrate(1000) -- can not vibrate in background VibrateUtils.vibrateCompat(longArrayOf(0, 1000, 1000, 2000, 2000, 1000), 1) // VibrateUtils.vibrateCompat(1000) }, 1000) diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java index 8d2ab055e4..164810381a 100644 --- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java +++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/VibrateUtils.java @@ -58,7 +58,7 @@ public static void vibrate(final long milliseconds, AudioAttributes attributes) } /** - * VibrateCompat + * VibrateCompat - Can vibrate in background *

    Must hold {@code }

    * * @param milliseconds he number of milliseconds to vibrate. @@ -106,7 +106,7 @@ public static void vibrate(final long[] pattern, final int repeat, AudioAttribut } /** - * VibrateCompat + * VibrateCompat - Can vibrate in background *

    Must hold {@code }

    * * @param pattern An array of longs of times for which to turn the vibrator on or off.