├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── render.experimental.xml ├── runConfigurations.xml └── vcs.xml ├── .svn └── pristine │ └── 96 │ └── 96e650c5285528ac68052ac4a64de7bc4747b3fd.svn-base ├── LICENSE ├── README.md ├── androidutilskt ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lindroid │ │ └── androidutilskt │ │ ├── app │ │ └── AndUtil.kt │ │ ├── extension │ │ ├── ActivityUtil.kt │ │ ├── AppUtil.kt │ │ ├── BitmapUtil.kt │ │ ├── BrightnessUtil.kt │ │ ├── ClipboardUtil.kt │ │ ├── DensityUtil.kt │ │ ├── KeyboarStatusWatcher.kt │ │ ├── KeyboardUtil.kt │ │ ├── NavBarStatusWatcher.kt │ │ ├── NavigationBarUtil.kt │ │ ├── NetworkUtil.kt │ │ ├── NumberUtil.kt │ │ ├── RegexUtil.kt │ │ ├── ResourceUtil.kt │ │ ├── SDCardUtil.kt │ │ ├── ScreenUtil.kt │ │ ├── SpUtil.kt │ │ ├── SpanUtil.kt │ │ ├── TimeUtil.kt │ │ ├── ToastUtil.kt │ │ ├── ViewUtil.kt │ │ ├── logcat │ │ │ ├── DiskConfig.kt │ │ │ ├── LogConfig.kt │ │ │ ├── LogLevel.kt │ │ │ ├── LogUtil.kt │ │ │ ├── formatstrategy │ │ │ │ ├── AndroidFormatStrategy.kt │ │ │ │ ├── CsvFormatStrategy.kt │ │ │ │ └── FormatStrategy.kt │ │ │ ├── logadapter │ │ │ │ ├── AndroidLogAdapter.kt │ │ │ │ ├── DiskLogAdapter.kt │ │ │ │ └── LogAdapter.kt │ │ │ ├── logstrategy │ │ │ │ ├── DiskLogStrategy.kt │ │ │ │ ├── LogStrategy.kt │ │ │ │ └── LogcatLogStrategy.kt │ │ │ └── printer │ │ │ │ ├── LogPrinter.kt │ │ │ │ └── Printer.kt │ │ └── statusbar │ │ │ ├── DeviceUtil.kt │ │ │ └── StatusBarUtil.kt │ │ └── statics │ │ ├── AppManager.kt │ │ ├── IntentUtil.kt │ │ └── VibratorUtil.kt │ └── res │ └── values │ └── strings.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lindroid │ │ └── androidutilsktdemo │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launch-web.png │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── lindroid │ │ │ └── androidutilsktdemo │ │ │ ├── JavaActivity.java │ │ │ ├── activity │ │ │ ├── AppInfoActivity.kt │ │ │ ├── BrightnessActivity.kt │ │ │ ├── CatalogActivity.kt │ │ │ ├── IntentActivity.kt │ │ │ ├── KeyboardActivity.kt │ │ │ ├── LogActivity.kt │ │ │ ├── NavigationBarActivity.kt │ │ │ ├── RegexActivity.kt │ │ │ ├── SDCardActivity.kt │ │ │ ├── ScreenActivity.kt │ │ │ ├── SpannableActivity.kt │ │ │ ├── TimeActivity.kt │ │ │ ├── ToastActivity.kt │ │ │ ├── VibratorActivity.kt │ │ │ ├── ViewActivity.kt │ │ │ └── statusbar │ │ │ │ ├── StatusBarActivity.kt │ │ │ │ ├── StatusBarChangeColorActivity.kt │ │ │ │ ├── StatusBarImageActivity.kt │ │ │ │ └── StatusBarSlideActivity.kt │ │ │ ├── app │ │ │ └── App.kt │ │ │ ├── base │ │ │ └── BaseActivity.kt │ │ │ ├── receiver │ │ │ └── ScreenActionReceiver.kt │ │ │ └── util │ │ │ └── PermissionUtil.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_build.xml │ │ ├── ic_launcher_background.xml │ │ ├── img_android.jpeg │ │ └── shape_gradient_bar.xml │ │ ├── layout │ │ ├── activity_app_info.xml │ │ ├── activity_brightness.xml │ │ ├── activity_catalog.xml │ │ ├── activity_intent.xml │ │ ├── activity_java.xml │ │ ├── activity_keyboard.xml │ │ ├── activity_log.xml │ │ ├── activity_navigation_bar.xml │ │ ├── activity_regex.xml │ │ ├── activity_screen.xml │ │ ├── activity_sdcard.xml │ │ ├── activity_spannable.xml │ │ ├── activity_status_bar.xml │ │ ├── activity_status_bar_change_color.xml │ │ ├── activity_status_bar_image.xml │ │ ├── activity_status_bar_slide.xml │ │ ├── activity_time.xml │ │ ├── activity_toast.xml │ │ ├── activity_vibrator.xml │ │ ├── activity_view.xml │ │ └── toolbar.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lindroid │ └── androidutilsktdemo │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | /.idea/caches 6 | /.idea/libraries 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | /.idea/navEditor.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | /.svn -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/render.experimental.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.svn/pristine/96/96e650c5285528ac68052ac4a64de7bc4747b3fd.svn-base: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.Activity 5 | import android.content.Context 6 | import android.content.Intent 7 | import android.net.Uri 8 | import android.provider.MediaStore 9 | import android.provider.Settings 10 | import com.lindroid.androidutilskt.app.AndUtil 11 | 12 | /** 13 | * @author Lin 14 | * @date 2019/2/28 15 | * @function 16 | * @Description 17 | */ 18 | object IntentUtil { 19 | /** 20 | * 打开系统设置界面 21 | */ 22 | @JvmStatic 23 | fun launchSystemSetting(context: Context) { 24 | context.startActivity(Intent(Settings.ACTION_SETTINGS)) 25 | } 26 | 27 | /** 28 | * 打开wifi设置界面 29 | */ 30 | @JvmStatic 31 | fun launchWifiSetting(context: Context) { 32 | context.startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) 33 | } 34 | 35 | /** 36 | * 打开拨号面板 37 | */ 38 | @JvmStatic 39 | fun launchDialPage(context: Context) { 40 | context.startActivity(Intent(Intent.ACTION_DIAL)) 41 | } 42 | 43 | /** 44 | * 直接拨打电话 45 | */ 46 | @JvmStatic 47 | @SuppressLint("MissingPermission") 48 | fun callPhone(context: Context, phoneNumber: String) { 49 | context.startActivity(Intent(Intent.ACTION_CALL, Uri.parse("tel:$phoneNumber"))) 50 | } 51 | 52 | /** 53 | * 调用浏览器并打开一个网页 54 | * 为了避免手机上面没有安装浏览器引发崩溃,应弹出选择面板 55 | * @param url : 网页地址 56 | * @param browserListener : 是否成功打开浏览器选择面板的监听 57 | */ 58 | @JvmStatic 59 | fun launchBrowse( 60 | context: Context, 61 | url: String, 62 | title: String = AndUtil.appContext.getString(R.string.util_intent_choose_browser), 63 | browserListener: ((isSuccess: Boolean) -> Unit)? = null 64 | ) { 65 | val intentWeb = with(Intent(Intent.ACTION_VIEW)) { 66 | addCategory(Intent.CATEGORY_BROWSABLE) 67 | data = Uri.parse(url) 68 | this 69 | } 70 | if (intentWeb.resolveActivity(context.packageManager) != null) { 71 | browserListener?.invoke(true) 72 | context.startActivity(Intent.createChooser(intentWeb, title)) 73 | } else { 74 | //手机上没有安装浏览器 75 | browserListener?.invoke(false) 76 | } 77 | } 78 | 79 | 80 | /** 81 | * 启动系统相机 82 | */ 83 | @JvmStatic 84 | fun launchCamera(activity: Activity, requestCode: Int) { 85 | activity.startActivityForResult(Intent(MediaStore.ACTION_IMAGE_CAPTURE), requestCode) 86 | } 87 | 88 | /** 89 | * 发送短信 90 | * @param phoneNumber 手机号码 91 | * @param message 短信内容 92 | */ 93 | @JvmStatic 94 | fun sendSMS(context: Context, phoneNumber: String = "", message: String = "") { 95 | val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:$phoneNumber")) 96 | intent.putExtra("sms_body", message) 97 | context.startActivity(intent) 98 | } 99 | 100 | } 101 | 102 | -------------------------------------------------------------------------------- /androidutilskt/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /androidutilskt/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lindroy/AndroidUtilsKt/5d6832813a4a0dba7290ad5ef92959f638ea51ab/androidutilskt/build.gradle -------------------------------------------------------------------------------- /androidutilskt/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /androidutilskt/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/app/AndUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.app 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.support.annotation.ColorRes 6 | import android.support.annotation.StringRes 7 | import android.support.v4.content.ContextCompat 8 | import com.lindroid.androidutilskt.extension.defTimeZone 9 | import com.lindroid.androidutilskt.extension.logcat.DiskConfig 10 | import com.lindroid.androidutilskt.extension.logcat.LogConfig 11 | import com.lindroid.androidutilskt.extension.serverFormat 12 | import com.lindroid.androidutilskt.extension.setSpDefaultFile 13 | import java.util.* 14 | 15 | /** 16 | * @author Lin 17 | * @date 2019/2/27 18 | * @function 初始化类 19 | * @Description 20 | */ 21 | object AndUtil { 22 | private lateinit var application: Application 23 | 24 | @JvmStatic 25 | fun init(application: Application): Config { 26 | this.application = application 27 | return Config.build() 28 | } 29 | 30 | @JvmStatic 31 | internal val appContext: Context 32 | get() = application.applicationContext 33 | 34 | @JvmStatic 35 | internal fun getString(@StringRes strId: Int): String = appContext.getString(strId) 36 | 37 | @JvmStatic 38 | internal fun getColor(@ColorRes colorId: Int): Int = ContextCompat.getColor(appContext, colorId) 39 | 40 | class Config { 41 | companion object { 42 | fun build() = Config() 43 | } 44 | 45 | /** 46 | * 设置默认的SharePreference表名 47 | */ 48 | fun setDefaultSpFile(fileName: String) = this.apply { setSpDefaultFile(fileName) } 49 | 50 | /** 51 | * 设置全局的服务器时间格式 52 | */ 53 | fun setServerTimeFormat(timeFormat: String) = this.apply { serverFormat = timeFormat } 54 | 55 | /** 56 | * 设置默认时区 57 | */ 58 | fun setTimeZone(timeZone: TimeZone) = this.apply { defTimeZone = timeZone } 59 | 60 | /** 61 | * 设置LogUtil配置 62 | */ 63 | fun setLogGlobalConfig(init: LogConfig.() -> Unit) = this.apply { 64 | LogConfig(false, init) 65 | } 66 | 67 | /** 68 | * 设置LogUtil输出到磁盘的配置 69 | */ 70 | fun setLogDiskConfig(init:DiskConfig.()->Unit) = this.apply { 71 | DiskConfig(init) 72 | } 73 | } 74 | 75 | 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/AppUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("AppUtil") 2 | package com.lindroid.androidutilskt.extension 3 | 4 | import android.content.Context 5 | import android.content.pm.PackageManager 6 | import android.graphics.drawable.Drawable 7 | import java.io.File 8 | 9 | /** 10 | * @author Lin 11 | * @date 2018/10/26 12 | * @function App信息工具类 13 | * @Description 14 | */ 15 | 16 | private const val UNKOWN = "unKnown" 17 | 18 | /** 19 | * 获取应用版本名称,默认为本应用 20 | * @return 失败时返回unKnown 21 | */ 22 | fun Context.getAppVersionName(packageName: String = this.packageName): String { 23 | return try { 24 | if (packageName.isBlank()) { 25 | return UNKOWN 26 | } else { 27 | val pi = packageManager.getPackageInfo(packageName, 0) 28 | pi?.versionName ?: UNKOWN 29 | } 30 | } catch (e: PackageManager.NameNotFoundException) { 31 | UNKOWN 32 | } 33 | } 34 | 35 | /** 36 | * 获取应用版本号,默认为本应用 37 | * @return 失败时返回-1 38 | */ 39 | fun Context.getAppVersionCode(packageName: String = this.packageName): Int { 40 | return try { 41 | if (packageName.isBlank()) { 42 | -1 43 | } else { 44 | val pi = packageManager.getPackageInfo(packageName, 0) 45 | pi?.versionCode ?: -1 46 | } 47 | } catch (e: PackageManager.NameNotFoundException) { 48 | -1 49 | } 50 | } 51 | 52 | /** 53 | * 获取应用大小,单位为b,默认为本应用 54 | * @return 失败时返回-1 55 | */ 56 | fun Context.getAppSize(packageName: String = this.packageName): Long { 57 | return try { 58 | if (packageName.isBlank()) { 59 | -1 60 | } else { 61 | val applicationInfo = packageManager.getApplicationInfo(packageName, 0) 62 | File(applicationInfo.sourceDir).length() 63 | } 64 | } catch (e: PackageManager.NameNotFoundException) { 65 | -1 66 | } 67 | } 68 | 69 | /** 70 | * 获取应用图标,默认为本应用 71 | * @return 失败时返回null 72 | */ 73 | fun Context.getAppIcon(packageName: String = this.packageName): Drawable? { 74 | return try { 75 | if (packageName.isBlank()) { 76 | null 77 | } else { 78 | val applicationInfo = packageManager.getApplicationInfo(packageName, 0) 79 | applicationInfo.loadIcon(packageManager) 80 | } 81 | } catch (e: PackageManager.NameNotFoundException) { 82 | null 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/BitmapUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("BitmapUtil") 2 | 3 | package com.lindroid.androidutilskt.extension 4 | 5 | import android.graphics.Bitmap 6 | import android.graphics.Canvas 7 | import android.graphics.Color 8 | import android.graphics.drawable.BitmapDrawable 9 | import android.graphics.drawable.Drawable 10 | import android.view.View 11 | import android.widget.ImageView 12 | 13 | /** 14 | * @author Lin 15 | * @date 2019/4/9 16 | * @function Bitmap工具类 17 | * @Description 18 | */ 19 | /** 20 | * 安全创建Bitmap,如果产生了OOM,可以主动GC后再尝试。 21 | * https://github.com/QMUI/QMUI_Android 22 | * @param width : Bitmap宽度 23 | * @param height : Bitmap高度度 24 | * @param retryCount : 重试次数,默认一次 25 | * @param config : Bitmap.Config,默认为ARGB_8888 26 | * @return 创建Bitmap成功返回Bitmap,否则返回null。 27 | */ 28 | fun createBitmapSafely( 29 | width: Int, 30 | height: Int, 31 | retryCount: Int = 1, 32 | config: Bitmap.Config = Bitmap.Config.ARGB_8888 33 | ): Bitmap? = try { 34 | Bitmap.createBitmap(width, height, config) 35 | } catch (e: OutOfMemoryError) { 36 | e.printStackTrace() 37 | when (retryCount > 0) { 38 | true -> { 39 | System.gc() 40 | createBitmapSafely(width, height, retryCount, config) 41 | } 42 | false -> null 43 | } 44 | } 45 | 46 | /** 47 | * 将View转换为Bitmap 48 | * @param scale: 生成的Bitmap相对于原View的大小比例,范围为0~1.0 49 | */ 50 | fun viewToBitmap(view: View, scale: Float = 1.0F): Bitmap? = when (view) { 51 | is ImageView -> { 52 | val drawable: Drawable = view.drawable 53 | (drawable as BitmapDrawable).bitmap 54 | } 55 | else -> { 56 | view.clearFocus() 57 | val bitmap = 58 | createBitmapSafely((view.width * scale).toInt(), (view.height * scale).toInt()) 59 | if (bitmap != null) { 60 | val canvas = Canvas() 61 | synchronized(canvas) { 62 | with(canvas) { 63 | setBitmap(bitmap) 64 | save() 65 | drawColor(Color.WHITE) 66 | scale(scale, scale) 67 | view.draw(canvas) 68 | restore() 69 | setBitmap(null) 70 | } 71 | } 72 | } 73 | bitmap 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/BrightnessUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("BrightnessUtil") 2 | package com.lindroid.androidutilskt.extension 3 | 4 | import android.Manifest 5 | import android.app.Activity 6 | import android.provider.Settings 7 | import android.support.annotation.IntRange 8 | import android.support.annotation.RequiresPermission 9 | import com.lindroid.androidutilskt.app.AndUtil 10 | 11 | /** 12 | * @author Lin 13 | * @date 2019/3/9 14 | * @function 屏幕亮度工具类 15 | * @Description 16 | */ 17 | 18 | /** 19 | * 是否开启了自动亮度 20 | */ 21 | val isAutoBrightness: Boolean 22 | get() = try { 23 | Settings.System.getInt( 24 | AndUtil.appContext.contentResolver, 25 | Settings.System.SCREEN_BRIGHTNESS_MODE 26 | ) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC 27 | } catch (e: Settings.SettingNotFoundException) { 28 | e.printStackTrace() 29 | false 30 | } 31 | 32 | 33 | /** 34 | * 设置是否开启自动亮度 35 | * @param enable : 为true时开启,false时关闭 36 | * @return 设置成功返回true 37 | */ 38 | fun setAutoBrightness(enable: Boolean) = Settings.System.putInt( 39 | AndUtil.appContext.contentResolver, Settings.System.SCREEN_BRIGHTNESS_MODE, 40 | if (enable) Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC else Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL 41 | ) 42 | 43 | 44 | /** 45 | * 系统屏幕亮度,需要WRITE_SETTINGS权限,并在代码中申请系统设置权限 46 | * 范围为0~255 47 | */ 48 | var systemBrightness 49 | get() = try { 50 | Settings.System.getInt(AndUtil.appContext.contentResolver, Settings.System.SCREEN_BRIGHTNESS) 51 | } catch (e: Settings.SettingNotFoundException) { 52 | e.printStackTrace() 53 | -1 54 | } 55 | @RequiresPermission(Manifest.permission.WRITE_SETTINGS) 56 | set(@IntRange(from = 0, to = 255) brightness) { 57 | if (isAutoBrightness) { 58 | //如果当前是自动亮度,则关闭自动亮度 59 | setAutoBrightness(false) 60 | } 61 | val uri = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS) 62 | Settings.System.putInt(AndUtil.appContext.contentResolver, Settings.System.SCREEN_BRIGHTNESS, brightness) 63 | AndUtil.appContext.contentResolver.notifyChange(uri, null) 64 | } 65 | 66 | /** 67 | * 当前窗口亮度 68 | * 范围为0~1.0,1.0时为最亮,-1为系统默认设置 69 | */ 70 | var Activity.windowBrightness 71 | get() = window.attributes.screenBrightness 72 | set(brightness) { 73 | //小于0或大于1.0默认为系统亮度 74 | window.attributes = window.attributes.apply { 75 | screenBrightness = if (brightness > 1.0 || brightness < 0) -1.0F else brightness 76 | } 77 | } 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/ClipboardUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("ClipboardUtil") 2 | package com.lindroid.androidutilskt.extension 3 | 4 | import android.content.ClipData 5 | import android.content.ClipboardManager 6 | import android.content.Context 7 | import com.lindroid.androidutilskt.app.AndUtil 8 | 9 | /** 10 | * @author Lin 11 | * @date 2018/11/21 12 | * @function 复制工具类 13 | * @Description 14 | */ 15 | 16 | /** 17 | * 复制纯文本 18 | * @param text: 需要复制的文本 19 | * @param label: 用户可见的对复制数据的描述 20 | * @return 是否复制成功 21 | */ 22 | @JvmOverloads 23 | fun clipPlainText(text: CharSequence, label: CharSequence = ""): Boolean { 24 | val cm = AndUtil.appContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager 25 | val clipData = ClipData.newPlainText(label, text) 26 | cm.primaryClip = clipData 27 | return cm.hasPrimaryClip() 28 | } 29 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/DensityUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DensityUtil") 2 | package com.lindroid.androidutilskt.extension 3 | 4 | import android.content.res.Resources 5 | 6 | /** 7 | * @author Lin 8 | * @date 2018/10/18 9 | * @function 单位转换工具类 10 | * @Description 11 | */ 12 | 13 | fun dp2px(dpValue: Float): Float { 14 | val scale = Resources.getSystem().displayMetrics.density 15 | return (dpValue * scale + 0.5F) 16 | } 17 | 18 | fun dp2px(dpValue: Int) = dp2px(dpValue.toFloat()).toInt() 19 | 20 | fun px2dp(pxValue: Float): Float { 21 | val scale = Resources.getSystem().displayMetrics.density 22 | return (pxValue / scale + 0.5F) 23 | } 24 | 25 | fun px2dp(pxValue: Int) = px2dp(pxValue.toFloat()).toInt() 26 | 27 | fun sp2px(spValue: Float): Float { 28 | val fontScale = Resources.getSystem().displayMetrics.density 29 | return (spValue * fontScale + 0.5F) 30 | } 31 | 32 | fun sp2px(spValue: Int) = sp2px(spValue.toFloat()).toInt() 33 | 34 | fun px2sp(pxValue: Float): Float { 35 | val fontScale = Resources.getSystem().displayMetrics.density 36 | return (pxValue / fontScale + 0.5F) 37 | } 38 | 39 | fun px2sp(pxValue: Int) = px2sp(pxValue.toFloat()).toInt() 40 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/KeyboarStatusWatcher.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension 2 | 3 | import android.app.Activity 4 | import android.graphics.Rect 5 | import android.view.View 6 | import android.view.ViewTreeObserver 7 | import com.lindroid.androidutilskt.extension.statusbar.statusBarHeight 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/6/1 12 | * @function 监听软键盘显示和隐藏,并获取其高度 13 | * @Description 14 | */ 15 | 16 | class KeyboardStatusWatcher(val view: View) : ViewTreeObserver.OnGlobalLayoutListener { 17 | 18 | private val mContext = view.context 19 | 20 | private val rootView = view.rootView 21 | 22 | private val watchers: HashMap Unit)> = HashMap() 23 | 24 | /** 25 | * 可见区域高度 26 | */ 27 | private var visibleHeight = 0 28 | 29 | /** 30 | * 软键盘是否显示 31 | */ 32 | var isKeyboardShowed = false 33 | private set(value) { 34 | field = value 35 | } 36 | 37 | /** 38 | * 软键盘是否隐藏 39 | */ 40 | val isKeyboardHidden 41 | get() = !isKeyboardShowed 42 | 43 | /** 44 | * 最近一次弹出的软键盘高度 45 | */ 46 | var keyboardHeight = 0 47 | 48 | init { 49 | if (!watchers.containsKey(view)) { 50 | view.viewTreeObserver.addOnGlobalLayoutListener(this) 51 | } 52 | } 53 | 54 | /** 55 | * Callback method to be invoked when the global layout state or the visibility of views 56 | * within the view tree changes 57 | */ 58 | override fun onGlobalLayout() { 59 | val rect = Rect() 60 | rootView.getWindowVisibleDisplayFrame(rect) 61 | if (visibleHeight == (rect.bottom - rect.top)) { 62 | //可见区域高度不变时不必执行下面代码,避免重复监听 63 | return 64 | } else { 65 | visibleHeight = (rect.bottom - rect.top) 66 | } 67 | val heightDiff = rootView.height - visibleHeight 68 | if (heightDiff > screenHeight / 3) { 69 | isKeyboardShowed = true 70 | //计算软键盘高度 71 | when (mContext) { 72 | is Activity -> { 73 | //非全屏时减去状态栏高度 74 | keyboardHeight = if (mContext.isFullScreen) heightDiff else heightDiff - statusBarHeight 75 | //导航栏显示时减去其高度 76 | if (hasNavBar && mContext.isNavBarShowed) { 77 | keyboardHeight -= navBarHeight 78 | } 79 | } 80 | else -> keyboardHeight = heightDiff 81 | } 82 | } else { 83 | //软键盘隐藏时键盘高度为0 84 | isKeyboardShowed = false 85 | keyboardHeight = 0 86 | } 87 | 88 | watchers.forEach { 89 | it.value.invoke(isKeyboardShowed, keyboardHeight) 90 | } 91 | } 92 | 93 | /** 94 | * 监听软键盘状态 95 | */ 96 | fun addKeyboardStatusWatcher(watcher: ((isShowed: Boolean, keyboardHeight: Int) -> Unit)) { 97 | watchers[view] = watcher 98 | } 99 | 100 | /** 101 | * 移除软键盘状态监听事件 102 | */ 103 | fun removeKeyboardStatusWatcher(view: View): Boolean = watchers.remove(view) != null 104 | 105 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/KeyboardUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("KeyboardUtil") 2 | 3 | package com.lindroid.androidutilskt.extension 4 | 5 | import android.content.Context 6 | import android.view.View 7 | import android.view.inputmethod.InputMethodManager 8 | 9 | /** 10 | * @author Lin 11 | * @date 2018/10/26 12 | * @function 软键盘工具类 13 | * @Description 14 | */ 15 | 16 | /** 17 | * 打开软键盘 18 | */ 19 | fun View.showKeyboard(): Boolean { 20 | val imm = context 21 | .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager 22 | requestFocus() 23 | return imm.showSoftInput(this, InputMethodManager.RESULT_UNCHANGED_SHOWN) 24 | } 25 | 26 | /** 27 | * 关闭软键盘 28 | */ 29 | fun View.hideKeyboard(): Boolean { 30 | val imm = context 31 | .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager 32 | return imm.hideSoftInputFromWindow(this.windowToken, InputMethodManager.RESULT_UNCHANGED_SHOWN) 33 | } 34 | 35 | /** 36 | * 根据当前软键盘的状态做取反操作 37 | */ 38 | fun View.toggleKeyboard() { 39 | val imm = context 40 | .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager 41 | imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.RESULT_UNCHANGED_SHOWN) 42 | } 43 | 44 | /** 45 | * 设置软键盘的显示和隐藏监听事件 46 | */ 47 | /* 48 | fun View.addKeyboardStatusWatcher(callback: ((isShowed: Boolean, keyboardHeight: Int) -> Unit)) = 49 | with(KeyboardStatusWatcher(this)) { 50 | addKeyboardStatusWatcher(callback) 51 | this 52 | } 53 | 54 | fun View.removeKeyboardStatusWatcher(){ 55 | KeyboardStatusWatcher(this).removeKeyboardStatusWatcher(this) 56 | }*/ 57 | 58 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/NavBarStatusWatcher.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension 2 | 3 | import android.app.Activity 4 | import android.graphics.Rect 5 | import android.view.View 6 | import android.view.ViewTreeObserver 7 | import com.lindroid.androidutilskt.extension.statusbar.statusBarHeight 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/6/14 12 | * @function 监听虚拟导航栏的显示和隐藏 13 | * @Description 14 | */ 15 | class NavBarStatusWatcher(val view: View) : ViewTreeObserver.OnGlobalLayoutListener { 16 | private val mContext = view.context 17 | 18 | private val rootView = view.rootView 19 | 20 | private val watchers: HashMap Unit)> = HashMap() 21 | 22 | init { 23 | if (hasNavBar && !watchers.containsKey(view)) { 24 | rootView.viewTreeObserver.addOnGlobalLayoutListener(this) 25 | } 26 | } 27 | 28 | /** 29 | * Callback method to be invoked when the global layout state or the visibility of views 30 | * within the view tree changes 31 | */ 32 | override fun onGlobalLayout() { 33 | val rect = Rect() 34 | rootView.getWindowVisibleDisplayFrame(rect) 35 | val heightDiff = rootView.height - (rect.bottom - rect.top) 36 | val barHeight = when (mContext) { 37 | is Activity -> { 38 | if (mContext.isFullScreen) heightDiff else heightDiff - statusBarHeight 39 | } 40 | else -> heightDiff 41 | } 42 | watchers.forEach { 43 | it.value.invoke(barHeight == navBarHeight) 44 | } 45 | } 46 | 47 | fun addNavBarStatusWatcher(watcher: (isShowed: Boolean) -> Unit) { 48 | watchers[view] = watcher 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/NavigationBarUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("BarUtil") 2 | 3 | package com.lindroid.androidutilskt.extension 4 | 5 | import android.app.Activity 6 | import android.os.Build 7 | import android.support.annotation.ColorInt 8 | import android.support.annotation.ColorRes 9 | import android.support.annotation.RequiresApi 10 | import android.view.View 11 | import android.view.ViewGroup 12 | import android.view.Window 13 | import com.lindroid.androidutilskt.app.AndUtil 14 | 15 | 16 | /** 17 | * @author Lin 18 | * @date 2019/6/11 19 | * @function 虚拟导航栏工具类 20 | * @Description 21 | */ 22 | 23 | /** 24 | * 手机是否有虚拟导航栏 25 | */ 26 | val hasNavBar 27 | @JvmName("hasNavBar") 28 | get() = navBarResId != 0 29 | 30 | /*fun Window.setOnNavBarStatusWatcher(callback: (isShowed: Boolean) -> Unit) { 31 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH && hasNavBar) { 32 | val navigationBarHeight = navBarHeight 33 | decorView.setOnApplyWindowInsetsListener { v, insets -> 34 | if (insets != null) { 35 | callback.invoke(insets.systemWindowInsetBottom == navigationBarHeight) 36 | } 37 | insets 38 | } 39 | } 40 | } 41 | 42 | fun Activity.setOnNavBarStatusWatcher(callback: (isShowed: Boolean) -> Unit) { 43 | window.setOnNavBarStatusWatcher(callback) 44 | }*/ 45 | 46 | /** 47 | * 当前虚拟导航栏是否显示 48 | */ 49 | val Activity.isNavBarShowed: Boolean 50 | get() = this.window.isNavBarShowed 51 | 52 | /** 53 | * 当前虚拟导航栏是否显示 54 | */ 55 | val Window.isNavBarShowed: Boolean 56 | get() { 57 | val viewGroup = decorView as ViewGroup? ?: return false 58 | return (0 until viewGroup.childCount).firstOrNull { 59 | viewGroup.getChildAt(it).id != View.NO_ID 60 | && AndUtil.appContext.resources.getResourceEntryName(viewGroup.getChildAt(it).id) == RES_NAME_NAV_BAR 61 | } != null 62 | } 63 | 64 | /** 65 | * 当前虚拟导航栏是否隐藏 66 | */ 67 | val Window.isNavBarHidden: Boolean 68 | get() = !isNavBarShowed 69 | 70 | /** 71 | * 当前虚拟导航栏是否隐藏 72 | */ 73 | val Activity.isNavBarHidden: Boolean 74 | get() = window.isNavBarHidden 75 | 76 | /*fun Window.hideNavBar() { 77 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 78 | return 79 | } 80 | *//* val viewGroup = decorView as ViewGroup? ?: return false 81 | (0 until viewGroup.childCount).forEach { 82 | val childId = viewGroup.getChildAt(it).id 83 | if (childId != View.NO_ID){ 84 | val resourceEntryName = AndUtil.appContext.resources.getResourceEntryName(childId) 85 | }else{ 86 | return 87 | } 88 | }*//* 89 | val uiOptions = 90 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 91 | }*/ 92 | 93 | /*fun Window.setShowNavBar(isShow: Boolean) { 94 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || !hasNavBar) { 95 | return 96 | } 97 | val viewGroup = decorView as ViewGroup? ?: return 98 | for (i in (0 until viewGroup.childCount)) { 99 | val childId = viewGroup.getChildAt(i).id 100 | if (childId != View.NO_ID) { 101 | val resourceEntryName = AndUtil.appContext.resources.getResourceEntryName(childId) 102 | if (RES_NAME_NAV_BAR == resourceEntryName) { 103 | viewGroup.getChildAt(i).visibility = if (isShow) View.VISIBLE else View.INVISIBLE 104 | } 105 | } else { 106 | break 107 | } 108 | } 109 | val uiOptions = 110 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 111 | if (isShow) { 112 | decorView.systemUiVisibility = decorView.systemUiVisibility and uiOptions.inv() 113 | } else { 114 | decorView.systemUiVisibility = decorView.systemUiVisibility or uiOptions 115 | } 116 | }*/ 117 | 118 | 119 | /** 120 | * 获取虚拟导航栏的高度,必须在布局绘制完成之后调用才能获取到正确的值(可以在onWindowFocusChanged()中调用) 121 | * 单位为px 122 | */ 123 | val navBarHeight: Int 124 | get() { 125 | val resourceId = navBarResId 126 | return if (resourceId != 0) { 127 | getResDimenPx(resourceId) 128 | } else 0 129 | } 130 | 131 | /** 132 | * 设置导航栏颜色 133 | */ 134 | var Window.navBarColor: Int 135 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP) 136 | get() = navigationBarColor 137 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP) 138 | set(@ColorInt value) { 139 | navigationBarColor = value 140 | } 141 | 142 | /** 143 | * 设置导航栏颜色 144 | */ 145 | var Activity.navBarColor: Int 146 | get() = window.navBarColor 147 | set(@ColorInt value) { 148 | window.navBarColor = value 149 | } 150 | 151 | /** 152 | * 设置导航栏颜色 153 | */ 154 | fun Window.setNavBarColorRes(@ColorRes colorId: Int) { 155 | navBarColor = getResColor(colorId) 156 | } 157 | 158 | /** 159 | * 设置导航栏颜色 160 | */ 161 | fun Activity.setNavBarColorRes(@ColorRes colorId: Int) { 162 | navBarColor = getResColor(colorId) 163 | } 164 | 165 | private const val RES_NAME_NAV_BAR = "navigationBarBackground" 166 | 167 | private val navBarResId 168 | get() = AndUtil.appContext.resources.getIdentifier( 169 | "navigation_bar_height", 170 | "dimen", "android" 171 | ) -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/NetworkUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("NetworkUtil") 2 | 3 | package com.lindroid.androidutilskt.extension 4 | 5 | import android.content.Context 6 | import android.net.ConnectivityManager 7 | import com.lindroid.androidutilskt.app.AndUtil 8 | 9 | /** 10 | * @author Lin 11 | * @date 2018/10/19 12 | * @function 网络相关工具类 13 | * @Description 14 | */ 15 | 16 | /**没有网络**/ 17 | const val NETWORK_NONE = -1 18 | /**网络连接**/ 19 | //const val NETWORK_CONNECTED = 0 20 | /**移动网络**/ 21 | const val NETWORK_MOBILE = 1 22 | /**无线网络**/ 23 | const val NETWORK_WIFI = 2 24 | /**未知网络**/ 25 | const val NETWORK_UNKNOWN = -2 26 | 27 | /** 28 | * 获取当前的网络状态 29 | */ 30 | val networkState: Int 31 | get() { 32 | //得到连接管理器对象 33 | val cm = AndUtil.appContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 34 | val networkInfo = cm.activeNetworkInfo 35 | 36 | //如果网络连接,判断该网络类型 37 | return when (networkInfo != null && networkInfo.isAvailable) { 38 | true -> when (networkInfo.type) { 39 | ConnectivityManager.TYPE_WIFI -> NETWORK_WIFI 40 | ConnectivityManager.TYPE_MOBILE -> NETWORK_MOBILE 41 | else -> { 42 | NETWORK_UNKNOWN 43 | } 44 | } 45 | false -> NETWORK_NONE 46 | } 47 | } 48 | 49 | /**是否是wifi**/ 50 | val isWifi 51 | get() = networkState == NETWORK_WIFI 52 | 53 | /**是否是移动网络**/ 54 | val isMobileNet 55 | get() = networkState == NETWORK_MOBILE 56 | 57 | /**网络是否连接**/ 58 | val isNetworkConnect 59 | get() = when (networkState) { 60 | NETWORK_MOBILE, NETWORK_WIFI -> true 61 | NETWORK_NONE -> false 62 | else -> { 63 | false 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/NumberUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension 2 | 3 | import java.text.NumberFormat 4 | 5 | /** 6 | * @author Lin 7 | * @date 2019/6/1 8 | * @function 9 | * @Description 10 | */ 11 | /** 12 | * 去除小数点后面的0 13 | * @see removeLastZero 14 | */ 15 | fun String?.removeLastZero(isGroupingUsed: Boolean = false) = when (isNullOrEmpty()) { 16 | true -> "" 17 | false ->this!!.toDouble().removeLastZero(isGroupingUsed) 18 | } 19 | 20 | /** 21 | * 去除小数点后面的0 22 | * @param isGroupingUsed:是否使用千分分隔符,默认为false不使用 23 | */ 24 | fun Double?.removeLastZero(isGroupingUsed: Boolean = false) = when (this == null) { 25 | true -> "" 26 | false -> { 27 | NumberFormat.getInstance().let { 28 | it.isGroupingUsed = isGroupingUsed 29 | it.format(this) ?: "" 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/RegexUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("RegexUtil") 2 | package com.lindroid.androidutilskt.extension 3 | 4 | import android.util.Patterns 5 | 6 | /** 7 | * @author Lin 8 | * @date 2019/3/14 9 | * @function 正则表达式工具类 10 | * @Description 11 | */ 12 | 13 | private fun String.checkWithRegex(pattern: String): Boolean { 14 | return Regex(pattern).matches(this) 15 | } 16 | 17 | /**校验内地手机号码**/ 18 | val String.isMobile: Boolean 19 | get() = checkWithRegex("^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(16[6])|(17[0,1,3,5-8])|(18[0-9])|(19[8,9]))\\d{8}$") 20 | 21 | /**校验电子邮箱**/ 22 | val String.isEmail: Boolean 23 | get() = checkWithRegex(Patterns.EMAIL_ADDRESS.pattern()) 24 | 25 | /**校验网络链接**/ 26 | val String.isWebUrl: Boolean 27 | // get() = checkWithRegex(Patterns.WEB_URL.pattern()) 28 | get() = checkWithRegex("[a-zA-z]+://[^\\s]*") 29 | 30 | /**校验数字**/ 31 | val String.isNumber: Boolean 32 | get() = checkWithRegex("^[0-9]*$") 33 | 34 | /**校验正整数**/ 35 | val String.isPositiveInt: Boolean 36 | get() = checkWithRegex("""^[1-9]\d*${'$'}""") 37 | 38 | /**校验负整数**/ 39 | val String.isNegativeInt: Boolean 40 | get() = checkWithRegex("""^-[1-9]\d*${'$'}""") 41 | 42 | /**校验字母(无关大小写)**/ 43 | val String.isLetter: Boolean 44 | get() = checkWithRegex("^[A-Za-z]+$") 45 | 46 | /**校验大写字母**/ 47 | val String.isUpperCaseLetter: Boolean 48 | get() = checkWithRegex("^[A-Z]+$") 49 | 50 | /**校验小写字母**/ 51 | val String.isLowerCaseLetter: Boolean 52 | get() = checkWithRegex("^[a-z]+$") 53 | 54 | /**校验汉字**/ 55 | val String.isChinese: Boolean 56 | get() = checkWithRegex("^[\\u4e00-\\u9fa5]+$") 57 | 58 | /**校验QQ号码**/ 59 | val String.isQQ: Boolean 60 | get() = checkWithRegex("[1-9][0-9]{4,14}") 61 | 62 | /**校验澳门手机号码**/ 63 | val String.isMacaoMobile: Boolean 64 | get() = checkWithRegex("[6]\\d{7}") -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/ResourceUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("ResUtil") 2 | 3 | package com.lindroid.androidutilskt.extension 4 | 5 | import android.support.annotation.* 6 | import android.support.v4.content.ContextCompat 7 | import com.lindroid.androidutilskt.app.AndUtil 8 | 9 | /** 10 | * @author Lin 11 | * @date 2018/11/9 12 | * @function 资源相关工具类 13 | * @Description 获取字符、图片、颜色等资源 14 | */ 15 | 16 | /** 17 | * 获取颜色 18 | */ 19 | @JvmName("getColor") 20 | fun getResColor(@ColorRes colorRes: Int) = ContextCompat.getColor(AndUtil.appContext, colorRes) 21 | 22 | /** 23 | * 获取图片资源 24 | */ 25 | @JvmName("getDrawable") 26 | fun getResDrawable(@DrawableRes drawableRes: Int) = 27 | ContextCompat.getDrawable(AndUtil.appContext, drawableRes) 28 | 29 | /** 30 | * 获取字符资源 31 | */ 32 | @JvmName("getString") 33 | fun getResString(@StringRes stringId: Int, vararg formatArgs: Any) = 34 | AndUtil.appContext.getString(stringId, *formatArgs) 35 | 36 | /** 37 | * 获取String数组 38 | */ 39 | @JvmName("getStringArray") 40 | fun getResStringArray(@ArrayRes arrayId: Int): Array = 41 | AndUtil.appContext.resources.getStringArray(arrayId) 42 | 43 | /** 44 | * 获取Int数组 45 | */ 46 | @JvmName("getIntArray") 47 | fun getResIntArray(@ArrayRes arrayId: Int) = AndUtil.appContext.resources.getIntArray(arrayId) 48 | 49 | /** 50 | * 获取Char数组 51 | */ 52 | @JvmName("getTextArray") 53 | fun getResTextArray(@ArrayRes arrayId: Int): Array = AndUtil.appContext.resources.getTextArray(arrayId) 54 | 55 | /** 56 | * 获取dimens资源 57 | * 单位为px 58 | */ 59 | @JvmName("getDimenPx") 60 | fun getResDimenPx(@DimenRes dimenRes: Int) = 61 | AndUtil.appContext.resources.getDimensionPixelSize(dimenRes) 62 | 63 | /** 64 | * 获取dimens中单位为dp的资源 65 | */ 66 | @JvmName("getDimenDp") 67 | fun getResDimenDp(@DimenRes dimenRes: Int) = 68 | px2dp(AndUtil.appContext.resources.getDimensionPixelSize(dimenRes)) 69 | 70 | /** 71 | * 获取dimens中单位为Sp的资源 72 | */ 73 | @JvmName("getDimenSp") 74 | fun getResDimenSp(@DimenRes dimenRes: Int) = 75 | px2sp(AndUtil.appContext.resources.getDimensionPixelSize(dimenRes)) -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/SDCardUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("SDCardUtil") 2 | 3 | package com.lindroid.androidutilskt.extension 4 | 5 | import android.os.Environment 6 | import android.os.StatFs 7 | 8 | /** 9 | * @author Lin 10 | * @date 2019/3/19 11 | * @function SD卡工具类 12 | * @Description 13 | */ 14 | 15 | /** 16 | * SD卡是否已挂载 17 | */ 18 | val isSDCardMounted 19 | get() = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED 20 | 21 | /** 22 | * 获取SD卡路径 23 | */ 24 | val sdCardPath: String 25 | get() = if (isSDCardMounted) Environment.getExternalStorageDirectory().absolutePath else "" 26 | 27 | /** 28 | * 获取SD卡的总大小 29 | * 失败时返回-1 30 | */ 31 | val sdCardTotalSize: Long 32 | get() = when (isSDCardMounted) { 33 | true -> { 34 | val statFs = StatFs(Environment.getExternalStorageDirectory().path) 35 | statFs.blockSizeLong * statFs.blockCountLong 36 | } 37 | false -> -1 38 | } 39 | 40 | /** 41 | * 获取SD卡可用空间大小 42 | * 失败时返回-1 43 | */ 44 | val sdCardAvailableSize: Long 45 | get() = when (isSDCardMounted) { 46 | true -> { 47 | val statFs = StatFs(Environment.getExternalStorageDirectory().path) 48 | statFs.blockSizeLong * statFs.availableBlocksLong 49 | } 50 | false -> -1 51 | } 52 | 53 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/SpUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("SpUtil") 2 | package com.lindroid.androidutilskt.extension 3 | 4 | import android.annotation.SuppressLint 5 | import android.content.Context.MODE_PRIVATE 6 | import com.lindroid.androidutilskt.app.AndUtil 7 | 8 | /** 9 | * @author Lin 10 | * @date 2018/10/18 11 | * @function SharedPreferences工具类 12 | * @Description 13 | * 1、get和put方法均是成对的,且put方法会返回布尔值用于判断是否存储成功; 14 | * 2、key的命名建议以SK或者SP_KEY作为前缀; 15 | * 3、表的命名建议以sp_file作为前缀。 16 | */ 17 | 18 | /**默认存储的文件名**/ 19 | private var defFileName = "sp_util" 20 | 21 | private fun getShare(fileName: String = defFileName) = AndUtil.appContext.getSharedPreferences(fileName, MODE_PRIVATE) 22 | 23 | internal fun setSpDefaultFile(fileName: String) { 24 | defFileName = fileName 25 | } 26 | 27 | @JvmOverloads 28 | fun putSpString(key: String, value: String, fileName: String = defFileName): Boolean = 29 | getShare(fileName).edit().putString(key, value).commit() 30 | 31 | @JvmOverloads 32 | fun getSpString(key: String, defValue: String = "", fileName: String = defFileName): String = 33 | getShare(fileName).getString(key, defValue) ?: "" 34 | 35 | @JvmOverloads 36 | fun putSpBoolean(key: String, value: Boolean, fileName: String = defFileName): Boolean = 37 | getShare(fileName).edit().putBoolean(key, value).commit() 38 | 39 | @JvmOverloads 40 | fun getSpBoolean(key: String, defValue: Boolean = false, fileName: String = defFileName): Boolean = 41 | getShare(fileName).getBoolean(key, defValue) 42 | 43 | @JvmOverloads 44 | fun putSpStrSet(key: String, value: Set, fileName: String = defFileName): Boolean = 45 | getShare(fileName).edit().putStringSet(key, value).commit() 46 | 47 | @JvmOverloads 48 | fun getSpStrSet(key: String, defValue: Set, fileName: String = defFileName): Set = 49 | getShare(fileName).getStringSet(key, defValue) ?: setOf() 50 | 51 | @JvmOverloads 52 | fun putSpInt(key: String, value: Int, fileName: String = defFileName): Boolean = 53 | getShare(fileName).edit().putInt(key, value).commit() 54 | 55 | @JvmOverloads 56 | fun getSpInt(key: String, defValue: Int = 0, fileName: String = defFileName): Int = 57 | getShare(fileName).getInt(key, defValue) 58 | 59 | @JvmOverloads 60 | fun putSpLong(key: String, value: Long, fileName: String = defFileName): Boolean = 61 | getShare(fileName).edit().putLong(key, value).commit() 62 | 63 | @JvmOverloads 64 | fun getSpLong(key: String, defValue: Long = 0L, fileName: String = defFileName): Long = 65 | getShare(fileName).getLong(key, defValue) 66 | 67 | @JvmOverloads 68 | fun putSpFloat(key: String, value: Float, fileName: String = defFileName): Boolean = 69 | getShare(fileName).edit().putFloat(key, value).commit() 70 | 71 | @JvmOverloads 72 | fun getSpFloat(key: String, defValue: Float = 0F, fileName: String = defFileName): Float = 73 | getShare(fileName).getFloat(key, defValue) 74 | 75 | 76 | /** 77 | * 保存数据,数据类型由传入的值确定 78 | * @throws IllegalArgumentException:数据类型不属于SharedPreferences能保存的类型 79 | */ 80 | @JvmOverloads 81 | @SuppressLint("ApplySharedPref") 82 | fun putSp(key: String, value: T, fileName: String = defFileName): Boolean = 83 | with(getShare(fileName).edit()) { 84 | when (value) { 85 | is Int -> putInt(key, value) 86 | is Float -> putFloat(key, value) 87 | is Long -> putLong(key, value) 88 | is Double -> putFloat(key, value.toFloat()) 89 | is Boolean -> putBoolean(key, value) 90 | is String -> putString(key, value) 91 | else -> throw IllegalArgumentException("This type can not be saved into SharedPreferences!") 92 | }.commit() 93 | } 94 | 95 | /** 96 | * 取出数据,数据类型由传入的默认值确定 97 | * @throws IllegalArgumentException:数据类型不属于SharedPreferences能保存的类型 98 | */ 99 | @Suppress("UNCHECKED_CAST", "IMPLICIT_CAST_TO_ANY") 100 | fun getSp(key: String, defValue: T, fileName: String = defFileName): T = with(getShare(fileName)) { 101 | when (defValue) { 102 | is Int -> getInt(key, defValue) 103 | is Float -> getFloat(key, defValue) 104 | is Long -> getLong(key, defValue) 105 | is String -> getString(key, defValue) 106 | is Boolean -> getBoolean(key, defValue) 107 | is Double -> getFloat(key, defValue.toFloat()) 108 | else -> throw IllegalArgumentException("This type can not be found in SharedPreferences!") 109 | } as T 110 | } 111 | 112 | /** 113 | * 删除某条数据 114 | */ 115 | @JvmOverloads 116 | fun deleteSpKey(key: String, fileName: String = defFileName): Boolean = 117 | getShare(fileName).edit().remove(key).commit() 118 | 119 | /** 120 | * 清除SharedPreferences中的数据 121 | * @param fileName :默认清除defFileName的数据,也可以输入其他的表名 122 | */ 123 | @JvmOverloads 124 | fun clearSp(fileName: String = defFileName): Boolean = 125 | getShare(fileName).edit().clear().commit() 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/ToastUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("ToastUtil") 2 | package com.lindroid.androidutilskt.extension 3 | 4 | import android.os.Handler 5 | import android.os.Looper 6 | import android.support.annotation.StringRes 7 | import android.widget.TextView 8 | import android.widget.Toast 9 | import com.lindroid.androidutilskt.app.AndUtil 10 | 11 | /** 12 | * @author Lin 13 | * @date 2018/10/29 14 | * @function Toast工具类 15 | * @Description 16 | */ 17 | private var toast: Toast? = null 18 | private var firstShowTime = 0L 19 | private var nextShowTime = 0L 20 | private var toastTextSize = 14 21 | 22 | private fun showToast(message: CharSequence, duration: Int,textSize:Int = toastTextSize): Toast { 23 | fun durationTime() = if (duration == Toast.LENGTH_SHORT) 2000L else 3500L 24 | return when (toast == null) { 25 | true -> { 26 | firstShowTime = System.currentTimeMillis() 27 | toast = Toast.makeText(AndUtil.appContext, "", duration) 28 | toast!!.apply { 29 | //这里调用setText 30 | setText(message) 31 | view.findViewById(android.R.id.message).textSize = textSize.toFloat() 32 | } 33 | } 34 | false -> toast!!.apply { 35 | nextShowTime = System.currentTimeMillis() 36 | setText(message) 37 | setDuration(duration) 38 | } 39 | }.apply { 40 | if (nextShowTime == 0L || nextShowTime - firstShowTime > durationTime()) { 41 | show() 42 | Handler(Looper.getMainLooper()).postDelayed({ 43 | cancelToast() 44 | }, durationTime()) 45 | } 46 | } 47 | } 48 | 49 | private fun showToast(@StringRes messageId: Int, duration: Int): Toast { 50 | return showToast(AndUtil.getString(messageId), duration) 51 | } 52 | 53 | /** 54 | * 取消Toast,要将toast、firstShowTime和nextShowTime都初始化 55 | */ 56 | private fun cancelToast() { 57 | toast?.cancel() 58 | toast = null 59 | firstShowTime = 0L 60 | nextShowTime = 0L 61 | } 62 | 63 | fun shortToast(message: CharSequence) = showToast(message, Toast.LENGTH_SHORT) 64 | 65 | fun shortToast(@StringRes messageId: Int) = showToast(messageId, Toast.LENGTH_SHORT) 66 | 67 | fun longToast(message: CharSequence) = showToast(message, Toast.LENGTH_LONG) 68 | 69 | fun longToast(@StringRes messageId: Int) = showToast(messageId, Toast.LENGTH_LONG) 70 | 71 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/ViewUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("ViewUtil") 2 | 3 | package com.lindroid.androidutilskt.extension 4 | 5 | import android.graphics.Bitmap 6 | import android.support.annotation.LayoutRes 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.widget.TextView 10 | import com.lindroid.androidutilskt.app.AndUtil 11 | 12 | /** 13 | * @author Lin 14 | * @date 2019/3/8 15 | * @function View工具类 16 | * @Description 17 | */ 18 | 19 | /** 20 | * 根据布局id填充一个布局 21 | */ 22 | @JvmOverloads 23 | fun inflate(@LayoutRes layoutId: Int, root: ViewGroup? = null) = View.inflate(AndUtil.appContext, layoutId, root) 24 | 25 | /** 26 | * 当前View是否可见 27 | */ 28 | val View.isVisible 29 | get() = visibility == View.VISIBLE 30 | 31 | /** 32 | * 当前View是否不可见 33 | */ 34 | val View.isInvisible 35 | get() = visibility == View.INVISIBLE 36 | 37 | /** 38 | * 当前View是否隐藏 39 | */ 40 | val View.isGone 41 | get() = visibility == View.GONE 42 | 43 | /** 44 | * 将View设置为隐藏 45 | */ 46 | fun View.setGone() { 47 | if (visibility != View.GONE) { 48 | visibility = View.GONE 49 | } 50 | } 51 | 52 | /** 53 | * 将View设置为可见 54 | */ 55 | fun View.setVisible() { 56 | if (visibility != View.VISIBLE) { 57 | visibility = View.VISIBLE 58 | } 59 | } 60 | 61 | /** 62 | * 将View设置为不可见 63 | */ 64 | fun View.setInvisible() { 65 | if (visibility != View.INVISIBLE) { 66 | visibility = View.INVISIBLE 67 | } 68 | } 69 | 70 | /** 71 | * 设置View的宽度 72 | * @param width: 宽度值,单位为px 73 | */ 74 | fun View.setWidth(width: Int) { 75 | layoutParams = layoutParams.apply { 76 | this.width = width 77 | } 78 | } 79 | 80 | /** 81 | * 设置View的高度 82 | * @param height: 高度值,单位为px 83 | */ 84 | fun View.setHeight(height: Int) { 85 | layoutParams = layoutParams.apply { 86 | this.height = height 87 | } 88 | } 89 | 90 | /** 91 | * 设置View的宽度和高度 92 | * @param width: 宽度值,单位为px 93 | * @param height: 高度值,单位为px 94 | */ 95 | fun View.setWidthAndHeight(width: Int, height: Int) { 96 | layoutParams = layoutParams.apply { 97 | this.width = width 98 | this.height = height 99 | } 100 | } 101 | 102 | /** 103 | * 将View转换为Bitmap 104 | * @param scale: 生成的Bitmap相对于原View的大小比例,范围为0~1.0 105 | */ 106 | fun View.toBitmap(scale: Float = 1.0F): Bitmap? = viewToBitmap(this, scale) 107 | 108 | 109 | /** 110 | * 设置View的padding 111 | */ 112 | fun View.setNewPadding( 113 | left: Int = paddingLeft, 114 | top: Int = paddingTop, 115 | right: Int = paddingRight, 116 | bottom: Int = paddingBottom 117 | ) { 118 | setPadding(left, top, right, bottom) 119 | } 120 | 121 | /** 122 | * 测量View 123 | */ 124 | private fun View.measureView() { 125 | var params = layoutParams 126 | if (params == null) { 127 | params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) 128 | } 129 | val widthSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width) 130 | val heightSpec = if (params.height > 0) { 131 | View.MeasureSpec.makeMeasureSpec(params.height, View.MeasureSpec.EXACTLY) 132 | } else { 133 | View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) 134 | } 135 | measure(widthSpec, heightSpec) 136 | } 137 | 138 | /** 139 | * 获取View的高度 140 | * 如果是“math_parent”属性则无法获取,值为0。 141 | */ 142 | val View.viewHeight: Int 143 | get() { 144 | measureView() 145 | return measuredHeight 146 | } 147 | 148 | /** 149 | * 获取View的宽度 150 | * 如果是“math_parent”属性则无法获取,值为0。 151 | */ 152 | val View.viewWidth: Int 153 | get() { 154 | measureView() 155 | return measuredWidth 156 | } 157 | 158 | /** 159 | * 获取TextView的String内容 160 | */ 161 | val TextView.textString: String 162 | get() = text.toString() 163 | 164 | /** 165 | * 获取TextView的String内容长度 166 | */ 167 | val TextView.textLength: Int 168 | get() = text.length 169 | 170 | /** 171 | * 判断TextView的内容是否为空 172 | */ 173 | val TextView.isTextEmpty: Boolean 174 | get() = text.isEmpty() 175 | 176 | /** 177 | * 判断TextView的内容是否为null或空 178 | */ 179 | val TextView.isTextNullOrEmpty: Boolean 180 | get() = text.isNullOrEmpty() 181 | 182 | /** 183 | * 判断TextView的内容是否为非空 184 | */ 185 | val TextView.isTextNotEmpty: Boolean 186 | get() = !isTextEmpty 187 | 188 | /** 189 | * 判断TextView的内容是否为空白 190 | */ 191 | val TextView.isTextBlank: Boolean 192 | get() = text.isBlank() 193 | 194 | /** 195 | * 判断TextView的内容是否为null或空白 196 | */ 197 | val TextView.isTextNullOrBlank: Boolean 198 | get() = text.isNullOrBlank() 199 | 200 | /** 201 | * 判断TextView的内容是否为非空白 202 | */ 203 | val TextView.isTextNotBlank: Boolean 204 | get() = text.isNotBlank() -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/DiskConfig.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat 2 | 3 | import android.os.Environment 4 | import android.os.HandlerThread 5 | import com.lindroid.androidutilskt.extension.logcat.formatstrategy.CsvFormatStrategy 6 | import com.lindroid.androidutilskt.extension.logcat.logadapter.DiskLogAdapter 7 | import com.lindroid.androidutilskt.extension.logcat.logstrategy.DiskLogStrategy 8 | import com.lindroid.androidutilskt.extension.logcat.logstrategy.LogStrategy 9 | import java.io.File 10 | import java.text.SimpleDateFormat 11 | import java.util.* 12 | 13 | /** 14 | * @author Lin 15 | * @date 2019/9/3 16 | * @function 输入日志到磁盘的配置 17 | * @Description 18 | */ 19 | const val MAX_BYTES = 500 * 1024 //每个文件的容量, 20 | 21 | class DiskConfig constructor() { 22 | internal var folderName = "AndLog" //存储日志的目录名称 23 | internal var tag = "LogUtil" 24 | internal var date = Date() 25 | internal var dateFormat = SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS", Locale.CHINA) 26 | internal var logStrategy: LogStrategy? = null 27 | private var init: (DiskConfig.() -> Unit)? = null 28 | 29 | /** 30 | * 设置保存日志文件的目录名称 31 | */ 32 | fun setFolderName(folderName: String) = this.also { it.folderName = folderName } 33 | 34 | /** 35 | * 保存的Tag 36 | */ 37 | fun setTag(tag: String) = this.also { it.tag = tag } 38 | 39 | /** 40 | * 设置时间,默认为日志打印到控制台的时间 41 | */ 42 | fun setDate(date: Date) = this.also { it.date = date } 43 | /** 44 | * 设置时间格式 45 | */ 46 | fun setDateFormat(format: SimpleDateFormat) = this.apply { dateFormat = format } 47 | 48 | constructor(init: (DiskConfig.() -> Unit)? = null) : this() { 49 | init?.run { 50 | this() 51 | this@DiskConfig.init = init 52 | addDiskConfig() 53 | } 54 | } 55 | 56 | /** 57 | * 如果是以Lambda的形式设置,则可以不必调用build()方法 58 | */ 59 | fun build() { 60 | if (init == null) { 61 | addDiskConfig() 62 | } 63 | } 64 | 65 | private fun addDiskConfig() { 66 | addLogAdapter(object : DiskLogAdapter(createFormatStrategy()) { 67 | 68 | }) 69 | } 70 | 71 | internal fun createFormatStrategy(): CsvFormatStrategy { 72 | if (logStrategy == null) { 73 | //存储在根目录下 74 | val diskPath = Environment.getExternalStorageDirectory().absolutePath 75 | val folder = "$diskPath${File.separatorChar}$folderName" 76 | val ht = HandlerThread("AndroidFileLogger.$folder") 77 | ht.start() 78 | val handler = DiskLogStrategy.WriteHandler(ht.looper, folder, MAX_BYTES) 79 | logStrategy = DiskLogStrategy(handler) 80 | } 81 | return CsvFormatStrategy(this) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/LogConfig.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.formatstrategy.AndroidFormatStrategy 4 | import com.lindroid.androidutilskt.extension.logcat.logadapter.AndroidLogAdapter 5 | import com.lindroid.androidutilskt.extension.logcat.logstrategy.LogcatLogStrategy 6 | 7 | /** 8 | * @author Lin 9 | * @date 2019/3/22 10 | * @function 日志工具配置类 11 | * @Description 12 | */ 13 | class LogConfig constructor() { 14 | 15 | internal var isLoggable = true 16 | internal var methodCount = 1 17 | internal var methodOffset = 0 18 | internal var isShowThread = true 19 | internal var isShowGlobalTag = true 20 | internal var isShowBorder = true 21 | internal var logStrategy: LogcatLogStrategy = LogcatLogStrategy() 22 | internal var tag: String? = "LogUtil" 23 | private var init: (LogConfig.() -> Unit)? = null 24 | /** 25 | * 是否是临时性的设置 26 | */ 27 | private var isTempConfig = false 28 | 29 | constructor(isTempConfig: Boolean, init: (LogConfig.() -> Unit)? = null) : this() { 30 | init?.run { 31 | this() 32 | this@LogConfig.init = init 33 | this@LogConfig.isTempConfig = isTempConfig 34 | addLogConfig() 35 | } 36 | } 37 | 38 | /** 39 | * 如果是以Lambda的形式设置,则可以不必调用build()方法 40 | */ 41 | fun build() { 42 | if (init == null) { 43 | addLogConfig() 44 | } 45 | } 46 | 47 | private fun addLogConfig() { 48 | addLogAdapter(object : AndroidLogAdapter(createFormatStrategy()) { 49 | override fun isLoggable(level: Int, tag: String?) = isLoggable 50 | override fun isTempAdapter() = isTempConfig 51 | }) 52 | } 53 | 54 | internal fun createFormatStrategy() = AndroidFormatStrategy(this) 55 | 56 | /** 57 | * 设置是否显示日志 58 | */ 59 | fun setLogEnable(isLoggable: Boolean) = this.apply { this.isLoggable = isLoggable } 60 | 61 | /** 62 | * 设置显示的方法数,默认为1 63 | */ 64 | fun setMethodCount(count: Int) = this.apply { methodCount = count } 65 | 66 | /** 67 | * 设置栈偏移量,默认为0 68 | */ 69 | fun setMethodOffset(offset: Int) = this.apply { methodOffset = offset } 70 | 71 | /** 72 | * 设置是否显示线程 73 | */ 74 | fun setShowThread(isShow: Boolean) = this.apply { isShowThread = isShow } 75 | 76 | /** 77 | * 设置是否在临时Tag前面显示全局Tag 78 | */ 79 | fun setShowGlobalTag(isShow: Boolean) = this.apply { isShowGlobalTag = isShow } 80 | 81 | /** 82 | * 自定义日志打印策略 83 | */ 84 | fun setLogStrategy(logStrategy: LogcatLogStrategy) = this.apply { this.logStrategy = logStrategy } 85 | 86 | /** 87 | * 是否显示边框,默认显示,为了美观,建议显示 88 | */ 89 | fun setShowBorder(isShowBorder: Boolean) = this.apply { this.isShowBorder = isShowBorder } 90 | 91 | /** 92 | * 设置默认的全局Tag,默认为LogUtil 93 | */ 94 | fun setTag(tag: String?) = this.apply { this.tag = tag } 95 | 96 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/LogLevel.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat 2 | 3 | import android.support.annotation.IntDef 4 | import android.util.Log 5 | 6 | /** 7 | * @author Lin 8 | * @date 2019/3/19 9 | * @function 日志等级 10 | * @Description 11 | */ 12 | 13 | const val VERBOSE = Log.VERBOSE 14 | const val DEBUG = Log.DEBUG 15 | const val INFO = Log.INFO 16 | const val WARN = Log.WARN 17 | const val ERROR = Log.ERROR 18 | const val ASSERT = Log.ASSERT 19 | 20 | @IntDef(VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT) 21 | @Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE) 22 | @Retention(AnnotationRetention.SOURCE) 23 | annotation class LogLevel 24 | 25 | fun logLevel(@LogLevel level: Int) = when(level){ 26 | VERBOSE->"VERBOSE" 27 | DEBUG->"DEBUG" 28 | INFO->"INFO" 29 | WARN->"WARN" 30 | ERROR->"ERROR" 31 | ASSERT->"ASSERT" 32 | else->"UNKNOWN" 33 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/LogUtil.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("LogUtil") 2 | 3 | //此处的文件名修改后需要到com.lindroid.androidutilskt.extension.logcat.AndroidFormatStrategy.getStackOffset方法中同步修改 4 | 5 | package com.lindroid.androidutilskt.extension.logcat 6 | 7 | import com.lindroid.androidutilskt.extension.logcat.logadapter.LogAdapter 8 | import com.lindroid.androidutilskt.extension.logcat.printer.LogPrinter 9 | 10 | /** 11 | * @author Lin 12 | * @date 2019/3/19 13 | * @function 日志工具类 14 | * @Description 15 | */ 16 | 17 | private val printer: LogPrinter by lazy { 18 | LogPrinter() 19 | } 20 | 21 | /** 22 | * 初始化LogUtil 23 | */ 24 | internal fun addLogAdapter(adapter: LogAdapter) { 25 | printer.addAdapter(adapter) 26 | } 27 | 28 | /** 29 | * 清除所有的配置 30 | */ 31 | fun clearLogConfigs() { 32 | printer.clearLogAdapters() 33 | } 34 | 35 | /** 36 | * 重置LogUtil配置 37 | */ 38 | fun resetLogConfig() { 39 | printer.resetLogAdapter() 40 | } 41 | 42 | /** 43 | * 打印Debug日志,仅支持String? 44 | * @receiver : 仅支持可空String,为null时打印“null” 45 | */ 46 | fun String?.d(vararg args: Any?) { 47 | printer.d(null, this, *args) 48 | } 49 | 50 | /** 51 | * 打印临时tag的Debug日志 52 | * @receiver : 仅支持可空String,为null时打印“null” 53 | */ 54 | fun String?.dt(tag: String, vararg args: Any?) { 55 | printer.d(tag, this, *args) 56 | } 57 | 58 | /** 59 | * 打印Debug日志 60 | * @receiver : 支持如下类型:List、Array、Set和Map 61 | */ 62 | fun Any?.d() { 63 | printer.d(null, content = this) 64 | } 65 | 66 | /** 67 | * 打印临时性Tag的Debug日志 68 | * @receiver : 支持如下类型:List、Array、Set和Map 69 | */ 70 | fun Any?.dt(tag: String) { 71 | printer.d(tag, content = this) 72 | } 73 | 74 | /** 75 | * 打印Verbose日志 76 | * @receiver : 仅支持可空String,为null时打印“null” 77 | */ 78 | fun String?.v(vararg args: Any?) { 79 | printer.v(null, this, * args) 80 | } 81 | 82 | /** 83 | * 打印带临时性tag的Verbose日志 84 | * @receiver : 仅支持可空String,为null时打印“null” 85 | */ 86 | fun String?.vt(tag: String, vararg args: Any?) { 87 | printer.v(tag, this, args) 88 | } 89 | 90 | /** 91 | * 打印Info日志 92 | * @receiver : 仅支持可空String,为null时打印“null” 93 | */ 94 | fun String?.i(vararg args: Any?) { 95 | printer.i(null, this, *args) 96 | } 97 | 98 | /** 99 | * 打印带tag的Info日志 100 | * @receiver : 仅支持可空String,为null时打印“null” 101 | */ 102 | fun String?.it(tag: String, vararg args: Any?) { 103 | printer.i(tag, this, *args) 104 | } 105 | 106 | /** 107 | * 打印Warn日志 108 | * @receiver : 仅支持可空String,为null时打印“null” 109 | */ 110 | fun String?.w(vararg args: Any?) { 111 | printer.w(null, this, *args) 112 | } 113 | 114 | /** 115 | * 打印带tag的Warn日志 116 | * @receiver : 仅支持可空String,为null时打印“null” 117 | */ 118 | fun String?.wt(tag: String, vararg args: Any?) { 119 | printer.w(tag, this, *args) 120 | } 121 | 122 | /** 123 | * 打印Error日志 124 | * @receiver : 仅支持可空String,为null时打印“null” 125 | */ 126 | fun String?.e(vararg args: Any?) { 127 | printer.e(null, null, this, *args) 128 | } 129 | 130 | /** 131 | * 打印带tag的Error日志 132 | * @param throwable: 抛出的异常 133 | */ 134 | fun String?.e(throwable: Throwable?, vararg args: Any?) { 135 | printer.e(null, throwable, this, *args) 136 | } 137 | 138 | /** 139 | * 打印带临时性tag的Error日志 140 | */ 141 | fun String?.et(tag: String, vararg args: Any?) { 142 | printer.e(tag, null, this, *args) 143 | } 144 | 145 | /** 146 | * 打印带tag的Error日志 147 | * @param throwable: 抛出的异常 148 | */ 149 | fun String?.et(tag: String, throwable: Throwable?, vararg args: Any?) { 150 | printer.e(tag, throwable, this, *args) 151 | } 152 | 153 | /** 154 | * 打印wtf日志 155 | * @receiver : 仅支持可空String,为null时打印“null” 156 | */ 157 | fun String?.wtf(vararg args: Any?) { 158 | printer.wtf(null, this, *args) 159 | } 160 | 161 | /** 162 | * 打印带tag的wtf日志 163 | * @receiver : 仅支持可空String,为null时打印“null” 164 | */ 165 | fun String?.wtft(tag: String, vararg args: Any?) { 166 | printer.wtf(tag, this, *args) 167 | } 168 | 169 | /** 170 | * 打印格式化的json 171 | */ 172 | fun String?.json(tag: String? = null) { 173 | printer.json(tag, this) 174 | } 175 | 176 | /** 177 | * 打印格式化的xml 178 | */ 179 | fun String?.xml(tag: String? = null) { 180 | printer.xml(tag, this) 181 | } 182 | 183 | /** 184 | * 设置LogUtil配置,会优先于AndUtil.setLogGlobalConfig()的全局设置,但不会覆盖它 185 | */ 186 | @JvmOverloads 187 | fun buildLogConfig(init: (LogConfig.() -> Unit)? = null) = LogConfig(false, init) 188 | 189 | /** 190 | * 设置临时性的LogUtil配置,打印一次之后就会失效 191 | */ 192 | @JvmOverloads 193 | fun buildLogTempConfig(init: (LogConfig.() -> Unit)? = null) = LogConfig(true, init) 194 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/formatstrategy/CsvFormatStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.formatstrategy 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.DiskConfig 4 | import com.lindroid.androidutilskt.extension.logcat.logLevel 5 | 6 | /** 7 | * @author Lin 8 | * @date 2019/9/3 9 | * @function 格式化成CSV文件 10 | * @Description 11 | */ 12 | private val NEW_LINE = System.getProperty("line.separator") 13 | private val NEW_LINE_REPLACEMENT = "
" 14 | private val SEPARATOR = "," 15 | 16 | class CsvFormatStrategy(private val builder: DiskConfig) : FormatStrategy { 17 | 18 | private val tag = builder.tag 19 | private val date = builder.date 20 | private val dateFormat = builder.dateFormat 21 | private val logStrategy = builder.logStrategy 22 | 23 | override fun log(level: Int, tag: String?, message: String) { 24 | val logTag = if (!tag.isNullOrEmpty() && this.tag != tag) "${this.tag}-$tag" else this.tag 25 | date.time = System.currentTimeMillis() 26 | val sb = with(StringBuilder()) { 27 | //供机器读取的时间 28 | append(date.time) 29 | //供人读取的时间 30 | append(SEPARATOR) 31 | append(dateFormat.format(date)) 32 | //日志等级 33 | append(SEPARATOR) 34 | append(logLevel(level)) 35 | //tag 36 | append(SEPARATOR) 37 | append(logTag) 38 | val msg = if (message.contains(NEW_LINE)) { 39 | //换行符会破坏CSV格式,需要替换掉 40 | message.replace(NEW_LINE, NEW_LINE_REPLACEMENT) 41 | } else message 42 | append(SEPARATOR) 43 | append(msg) 44 | append(NEW_LINE) 45 | this 46 | } 47 | logStrategy?.log(level, logTag, sb.toString()) 48 | } 49 | 50 | companion object { 51 | fun newBuilder() = DiskConfig() 52 | } 53 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/formatstrategy/FormatStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.formatstrategy 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.LogLevel 4 | 5 | /** 6 | * @author Lin 7 | * @date 2019/3/19 8 | * @function 设置日志打印格式接口 9 | * @Description 10 | */ 11 | 12 | interface FormatStrategy { 13 | fun log(@LogLevel level: Int, tag: String?, message: String) 14 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/logadapter/AndroidLogAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.logadapter 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.LogLevel 4 | import com.lindroid.androidutilskt.extension.logcat.formatstrategy.AndroidFormatStrategy 5 | import com.lindroid.androidutilskt.extension.logcat.formatstrategy.FormatStrategy 6 | 7 | /** 8 | * @author Lin 9 | * @date 2019/3/20 10 | * @function 11 | * @Description 12 | */ 13 | open class AndroidLogAdapter : LogAdapter { 14 | 15 | constructor() 16 | 17 | constructor(formatStrategy: FormatStrategy) { 18 | this.formatStrategy = formatStrategy 19 | } 20 | 21 | private var formatStrategy: FormatStrategy = AndroidFormatStrategy.newBuilder().createFormatStrategy() 22 | 23 | /** 24 | * 设置是否打印日志 25 | */ 26 | override fun isLoggable(@LogLevel level: Int, tag: String?) = true 27 | 28 | /** 29 | * 是否是临时的设置 30 | */ 31 | override fun isTempAdapter(): Boolean = false 32 | 33 | override fun log(@LogLevel level: Int, tag: String?, message: String) { 34 | formatStrategy.log(level, tag, message) 35 | } 36 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/logadapter/DiskLogAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.logadapter 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.formatstrategy.CsvFormatStrategy 4 | import com.lindroid.androidutilskt.extension.logcat.formatstrategy.FormatStrategy 5 | 6 | /** 7 | * @author Lin 8 | * @date 2019/9/3 9 | * @function 保存日志到磁盘 10 | * @Description 11 | */ 12 | open class DiskLogAdapter : LogAdapter { 13 | 14 | private var formatStrategy: FormatStrategy = CsvFormatStrategy.newBuilder().createFormatStrategy() 15 | 16 | constructor(formatStrategy: CsvFormatStrategy) { 17 | this.formatStrategy = formatStrategy 18 | } 19 | 20 | /** 21 | * 设置是否打印日志 22 | */ 23 | override fun isLoggable(level: Int, tag: String?) = true 24 | 25 | /** 26 | * 所有日志的打印通道 27 | */ 28 | override fun log(level: Int, tag: String?, message: String) { 29 | formatStrategy.log(level, tag, message) 30 | } 31 | 32 | /** 33 | * 是否是临时的设置 34 | */ 35 | override fun isTempAdapter() = false 36 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/logadapter/LogAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.logadapter 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.LogLevel 4 | 5 | /** 6 | * @author Lin 7 | * @date 2019/3/19 8 | * @function 9 | * @Description 10 | */ 11 | interface LogAdapter { 12 | 13 | /** 14 | * 设置是否打印日志 15 | */ 16 | fun isLoggable(@LogLevel level: Int, tag: String?): Boolean 17 | 18 | /** 19 | * 所有日志的打印通道 20 | */ 21 | fun log(@LogLevel level: Int, tag: String?, message: String) 22 | 23 | /** 24 | * 是否是临时的设置 25 | */ 26 | fun isTempAdapter(): Boolean 27 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/logstrategy/DiskLogStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.logstrategy 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import android.os.Message 6 | import java.io.File 7 | import java.io.FileWriter 8 | import java.io.IOException 9 | 10 | /** 11 | * @author Lin 12 | * @date 2019/9/4 13 | * @function 将日志输出成CSV格式 14 | * @Description 15 | */ 16 | class DiskLogStrategy(private val handler:Handler) : LogStrategy { 17 | 18 | override fun log(level: Int, tag: String?, message: String) { 19 | handler.sendMessage(handler.obtainMessage(level,message)) 20 | } 21 | 22 | class WriteHandler(looper: Looper, private var folder: String, private var maxFileSize: Int) : Handler(looper) { 23 | override fun handleMessage(msg: Message?) { 24 | super.handleMessage(msg) 25 | val content = when (msg) { 26 | null -> "" 27 | else -> msg.obj as String 28 | } 29 | var fileWriter: FileWriter? = null 30 | val logFile = getLogFile(folder,"Log") 31 | try { 32 | fileWriter = FileWriter(logFile, true) 33 | fileWriter.append(content) 34 | 35 | fileWriter.flush() 36 | fileWriter.close() 37 | } catch (e: IOException) { 38 | if (fileWriter != null) { 39 | try { 40 | fileWriter.flush() 41 | fileWriter.close() 42 | } catch (e1: IOException) { /* fail silently */ 43 | } 44 | } 45 | } 46 | 47 | } 48 | 49 | private fun getLogFile(folderName: String, fileName: String): File { 50 | val folder = File(folderName) 51 | if (!folder.exists()){ 52 | folder.mkdirs() 53 | } 54 | var newFileCount = 0 55 | var newFile = File(folder,String.format("%s_%s.csv", fileName, newFileCount)) 56 | var existingFile:File? = null 57 | while (newFile.exists()){ 58 | existingFile = newFile 59 | newFileCount++ 60 | newFile = File(folder,String.format("%s_%s.csv", fileName, newFileCount)) 61 | } 62 | if(existingFile != null){ 63 | if (existingFile.length() >= maxFileSize){ 64 | return newFile 65 | } 66 | return existingFile 67 | } 68 | return newFile 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/logstrategy/LogStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.logstrategy 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.LogLevel 4 | 5 | 6 | /** 7 | * @author Lin 8 | * @date 2019/3/19 9 | * @function Logcat日志打印策略 10 | * @Description 11 | */ 12 | 13 | interface LogStrategy { 14 | fun log(@LogLevel level: Int, tag: String?, message: String) 15 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/logstrategy/LogcatLogStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.logstrategy 2 | 3 | import android.util.Log 4 | import com.lindroid.androidutilskt.extension.logcat.LogLevel 5 | 6 | /** 7 | * @author Lin 8 | * @date 2019/3/21 9 | * @function 日志策略 10 | * @Description 11 | */ 12 | private const val DEFAULT_TAG = "DEFAULT_TAG" 13 | 14 | class LogcatLogStrategy : LogStrategy { 15 | 16 | override fun log(@LogLevel level: Int, tag: String?, message: String) { 17 | Log.println(level, tag ?: DEFAULT_TAG, message) 18 | } 19 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/logcat/printer/Printer.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.logcat.printer 2 | 3 | import com.lindroid.androidutilskt.extension.logcat.LogLevel 4 | import com.lindroid.androidutilskt.extension.logcat.logadapter.LogAdapter 5 | 6 | /** 7 | * @author Lin 8 | * @date 2019/3/19 9 | * @function 10 | * @Description 11 | */ 12 | interface Printer { 13 | 14 | fun v(tag: String?, message: String?, vararg args: Any?) 15 | 16 | fun i(tag: String?, message: String?, vararg args: Any?) 17 | 18 | fun d(tag: String?, message: String?, vararg args: Any?) 19 | 20 | fun d(tag: String?, content: Any?) 21 | 22 | fun w(tag: String?, message: String?, vararg args: Any?) 23 | 24 | fun e(tag: String?, throwable: Throwable? = null, message: String?, vararg args: Any?) 25 | 26 | fun wtf(tag: String?, message: String?, vararg args: Any?) 27 | 28 | fun json(tag: String?, json: String?) 29 | 30 | fun xml(tag: String?, xml: String?) 31 | 32 | fun log(@LogLevel level: Int, tag: String?, message: String?, throwable: Throwable?) 33 | 34 | fun addAdapter(adapter: LogAdapter) 35 | 36 | fun clearLogAdapters() 37 | 38 | /** 39 | * 重置成全局设置 40 | */ 41 | fun resetLogAdapter() 42 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/extension/statusbar/DeviceUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.extension.statusbar 2 | 3 | import android.Manifest 4 | import android.annotation.SuppressLint 5 | import android.content.Context 6 | import android.net.wifi.WifiManager 7 | import android.os.Build 8 | import android.support.annotation.RequiresPermission 9 | import android.text.TextUtils 10 | import android.util.Log 11 | import java.util.* 12 | 13 | /** 14 | * @author Lin 15 | * @date 2018/10/22 16 | * @function 手机设备工具类 17 | * @Description 18 | */ 19 | private const val STATUSBAR_KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name" 20 | private const val STATUSBAR_KEY_FLYME_VERSION_NAME = "ro.build.display.id" 21 | private const val FLYME = "flyme" 22 | 23 | /** 24 | * MIUI系统版本号,返回-1表示不是MIUI系统 25 | */ 26 | private val miuiVersionCode: Int 27 | get() { 28 | return try { 29 | val clz = Class.forName("android.os.SystemProperties") 30 | val mtd = clz.getMethod("get", String::class.java) 31 | var versionName = mtd.invoke(null, "ro.miui.ui.version.name") as String 32 | versionName = versionName.replace("[vV]".toRegex(), "") 33 | versionName.toInt() 34 | } catch (e: Exception) { 35 | -1 36 | } 37 | } 38 | 39 | /** 40 | * 是否是MIUI9及以上版本 41 | */ 42 | val isMIUI9ABOVE = miuiVersionCode >= 9 43 | /** 44 | * 是否是MIUI9以下版本 45 | */ 46 | val isMIUI9BELOW = miuiVersionCode < 9 47 | /** 48 | * 是否是MIUI6及以上版本 49 | */ 50 | val isMIUI6ABOVE = miuiVersionCode >= 6 51 | /** 52 | * 是否是MIUI6以下版本 53 | */ 54 | val isMIUI6BELOW = miuiVersionCode < 6 55 | 56 | /** 57 | * 是否是MIUI系统 58 | */ 59 | val isMIUI = miuiVersionCode > 0 60 | /** 61 | * 是否是Flyme系统 62 | */ 63 | val isFlyme: Boolean 64 | get() { 65 | return try { 66 | val versionName = getOsVersionName(STATUSBAR_KEY_FLYME_VERSION_NAME) 67 | versionName.isNotEmpty() && versionName.contains(FLYME) 68 | } catch (e: Exception) { 69 | false 70 | } 71 | } 72 | 73 | /** 74 | * 判断Flyme是否是6.2.0.0A及以上版本 75 | */ 76 | val isFlyme6Above: Boolean 77 | get() { 78 | return try { 79 | val name = getOsVersionName(STATUSBAR_KEY_FLYME_VERSION_NAME).replace(" ", "").substringAfter(FLYME) 80 | name.contains("6.2.0.0A") || name[0].toInt() > 6 81 | } catch (e: Exception) { 82 | Log.e("DeviceUtil", "判断flyme6系统失败") 83 | false 84 | } 85 | } 86 | 87 | /** 88 | * 获取Mac地址 89 | */ 90 | @RequiresPermission(Manifest.permission.ACCESS_WIFI_STATE) 91 | @SuppressLint("HardwareIds") 92 | fun Context.getMac(): String { 93 | val wifiManager: WifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager 94 | val mac = wifiManager.connectionInfo.macAddress 95 | return if (TextUtils.isEmpty(mac)) "" else mac 96 | } 97 | 98 | 99 | /** 100 | * 获取手机操作系统名称 101 | */ 102 | fun getOsVersionName(key: String): String { 103 | val properties = Properties() 104 | val clzSystemProperties: Class<*>? = Class.forName("android.os.SystemProperties") 105 | val method = clzSystemProperties?.getDeclaredMethod("get", String::class.java) 106 | var name = properties.getProperty(key) 107 | if (name == null) { 108 | name = try { 109 | method?.invoke(null, key) as String 110 | } catch (e: Exception) { 111 | null 112 | } 113 | } 114 | // name = name?.toLowerCase() ?: "" 115 | name = name ?: "" 116 | return name 117 | } 118 | 119 | 120 | /** 121 | * 获取deviceId 122 | */ 123 | val deviceId: String 124 | get() { 125 | val szDevIDShort = with(StringBuilder("35")) { 126 | append(Build.BOARD.length % 10) 127 | append(Build.BRAND.length % 10) 128 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 129 | append(Build.SUPPORTED_ABIS[0].length % 10) 130 | } else { 131 | append(Build.CPU_ABI.length % 10) 132 | } 133 | append(Build.DEVICE.length % 10) 134 | append(Build.DISPLAY.length % 10) 135 | append(Build.HOST.length % 10) 136 | append(Build.ID.length % 10) 137 | append(Build.MANUFACTURER.length % 10) 138 | append(Build.MODEL.length % 10) 139 | append(Build.PRODUCT.length % 10) 140 | append(Build.TAGS.length % 10) 141 | append(Build.TYPE.length % 10) 142 | append(Build.USER.length % 10) 143 | }.toString() 144 | val serial = try { 145 | Build::class.java.getField("SERIAL").get(null).toString() 146 | } catch (e: Exception) { 147 | "serial" // 随便一个初始化 148 | } 149 | return UUID(szDevIDShort.hashCode().toLong(), serial.hashCode().toLong()).toString() 150 | 151 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/statics/AppManager.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.statics 2 | 3 | import android.app.Activity 4 | import android.app.ActivityManager 5 | import android.content.Context 6 | import android.util.ArrayMap 7 | import kotlin.system.exitProcess 8 | 9 | /** 10 | * @author Lin 11 | * @date 2018/10/23 12 | * @function App管理器 13 | * @Description 14 | */ 15 | 16 | object AppManager { 17 | 18 | // private val activityStack: Stack = Stack() 19 | 20 | val activitySet: ArrayMap = ArrayMap() 21 | 22 | /** 23 | * 当前Activity标记 24 | */ 25 | private var curTag = "" 26 | 27 | /** 28 | * Activity入栈 29 | */ 30 | @JvmStatic 31 | fun addActivity(activity: Activity) { 32 | // activityStack.add(activity) 33 | curTag = getObjectTag(activity) 34 | activitySet[curTag] = activity 35 | 36 | } 37 | 38 | /** 39 | * Activity出栈 40 | */ 41 | @JvmStatic 42 | fun removeActivity(activity: Activity) = activitySet.remove(getObjectTag(activity)) 43 | 44 | /** 45 | * Activity出栈 46 | */ 47 | fun removeActivity(vararg clazz:Class<*>){ 48 | clazz.forEach {clz-> 49 | activitySet.forEach{ 50 | if (it.value.javaClass == clz){ 51 | removeActivity(it.value) 52 | } 53 | } 54 | } 55 | } 56 | 57 | /** 58 | * 销毁一个Activity并出栈 59 | */ 60 | 61 | @JvmStatic 62 | fun finishActivity(activity: Activity): Activity? { 63 | if (!activity.isDestroyed) { 64 | activity.finish() 65 | } 66 | // activityStack.remove(activity) 67 | return removeActivity(activity) 68 | } 69 | 70 | /** 71 | * 销毁Activity并出栈 72 | */ 73 | @JvmStatic 74 | fun finishActivity(vararg clazz:Class<*>){ 75 | val keys = activitySet.keys 76 | clazz.forEach {clz-> 77 | keys.forEach{ 78 | val activity = activitySet[it] 79 | if (activity!=null && activity.javaClass == clz){ 80 | finishActivity(activity) 81 | } 82 | } 83 | } 84 | 85 | } 86 | 87 | /** 88 | * 销毁除了给定的Activity外的所有Activity 89 | * @param clazz:Activity白名单 90 | */ 91 | @JvmStatic 92 | fun finishExceptActivity(vararg clazz:Class<*>){ 93 | val keys = activitySet.keys 94 | clazz.forEach { clz-> 95 | keys.forEach { 96 | val activity = activitySet[it] 97 | if (activity!= null && activity.javaClass != clz){ 98 | finishActivity(activity) 99 | } 100 | } 101 | } 102 | } 103 | 104 | /** 105 | * 获取当前栈顶Activity 106 | * @return 如果栈内元素为空,则返回null 107 | */ 108 | @JvmStatic 109 | fun currentActivity(): Activity? = 110 | if (activitySet.isNotEmpty()) activitySet[curTag] else null 111 | // if (activityStack.isNotEmpty()) activityStack.lastElement() else null 112 | 113 | /** 114 | * 清理栈中所有的Activity 115 | */ 116 | @JvmStatic 117 | fun finishAllActivity() { 118 | /* activityStack.forEach { 119 | it.finish() 120 | } 121 | activityStack.clear()*/ 122 | activitySet.forEach{ 123 | if (!it.value.isDestroyed){ 124 | it.value.finish() 125 | } 126 | } 127 | activitySet.clear() 128 | } 129 | 130 | /** 131 | * 退出应用程序 132 | */ 133 | @JvmStatic 134 | fun exitApp(context: Context) { 135 | finishAllActivity() 136 | val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager 137 | activityManager.killBackgroundProcesses(context.packageName) 138 | exitProcess(0) 139 | } 140 | 141 | /** 142 | * 设置栈中Activity的key 143 | */ 144 | private fun getObjectTag(activity: Activity) = 145 | activity.javaClass.name + Integer.toHexString(activity.hashCode()) 146 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/statics/IntentUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.statics 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.net.Uri 7 | import android.provider.MediaStore 8 | import android.provider.Settings 9 | import android.support.annotation.RequiresPermission 10 | import com.lindroid.androidutilskt.R 11 | import com.lindroid.androidutilskt.app.AndUtil 12 | 13 | /** 14 | * @author Lin 15 | * @date 2019/2/28 16 | * @function 17 | * @Description 18 | */ 19 | object IntentUtil { 20 | /** 21 | * 打开系统设置界面 22 | */ 23 | @JvmStatic 24 | fun launchSystemSetting(context: Context) { 25 | context.startActivity(Intent(Settings.ACTION_SETTINGS)) 26 | } 27 | 28 | /** 29 | * 打开wifi设置界面 30 | */ 31 | @JvmStatic 32 | fun launchWifiSetting(context: Context) { 33 | context.startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) 34 | } 35 | 36 | /** 37 | * 打开拨号面板 38 | */ 39 | @JvmStatic 40 | fun launchDialPage(context: Context) { 41 | context.startActivity(Intent(Intent.ACTION_DIAL)) 42 | } 43 | 44 | /** 45 | * 直接拨打电话 46 | */ 47 | @JvmStatic 48 | @RequiresPermission(android.Manifest.permission.CALL_PHONE) 49 | fun callPhone(context: Context, phoneNumber: String) { 50 | context.startActivity(Intent(Intent.ACTION_CALL, Uri.parse("tel:$phoneNumber"))) 51 | } 52 | 53 | /** 54 | * 调用浏览器并打开一个网页 55 | * 为了避免手机上面没有安装浏览器引发崩溃,应弹出选择面板 56 | * @param url : 网页地址 57 | * @param browserListener : 是否成功打开浏览器选择面板的监听 58 | */ 59 | @JvmStatic 60 | @JvmOverloads 61 | fun launchBrowse( 62 | context: Context, 63 | url: String, 64 | title: String = AndUtil.getString(R.string.util_intent_choose_browser), 65 | browserListener: ((isSuccess: Boolean) -> Unit)? = null 66 | ) { 67 | val intentWeb = with(Intent(Intent.ACTION_VIEW)) { 68 | addCategory(Intent.CATEGORY_BROWSABLE) 69 | data = Uri.parse(url) 70 | this 71 | } 72 | if (intentWeb.resolveActivity(context.packageManager) != null) { 73 | browserListener?.invoke(true) 74 | context.startActivity(Intent.createChooser(intentWeb, title)) 75 | } else { 76 | //手机上没有安装浏览器 77 | browserListener?.invoke(false) 78 | } 79 | } 80 | 81 | 82 | /** 83 | * 启动系统相机 84 | */ 85 | @JvmStatic 86 | fun launchCamera(activity: Activity, requestCode: Int) { 87 | activity.startActivityForResult(Intent(MediaStore.ACTION_IMAGE_CAPTURE), requestCode) 88 | } 89 | 90 | /** 91 | * 发送短信 92 | * @param phoneNumber 手机号码 93 | * @param message 短信内容 94 | */ 95 | @JvmStatic 96 | fun sendSMS(context: Context, phoneNumber: String = "", message: String = "") { 97 | val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:$phoneNumber")) 98 | intent.putExtra("sms_body", message) 99 | context.startActivity(intent) 100 | } 101 | 102 | } 103 | 104 | -------------------------------------------------------------------------------- /androidutilskt/src/main/java/com/lindroid/androidutilskt/statics/VibratorUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilskt.statics 2 | 3 | import android.Manifest.permission.VIBRATE 4 | import android.content.Context 5 | import android.os.Vibrator 6 | import android.support.annotation.RequiresPermission 7 | import com.lindroid.androidutilskt.app.AndUtil 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/3/11 12 | * @function 手机振动工具类 13 | * @Description 待支持Android8.0的API 14 | * 15 | */ 16 | object VibratorUtil { 17 | 18 | /** 19 | * 获取Vibrator实例 20 | */ 21 | @JvmStatic 22 | val vibrator: Vibrator by lazy { 23 | AndUtil.appContext.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator 24 | } 25 | 26 | /** 27 | * 检测设备是否具有振动器 28 | */ 29 | @JvmStatic 30 | val hasVibrator 31 | get() = vibrator.hasVibrator() 32 | 33 | /** 34 | * 开启振动 35 | * @param pattern: 设置振动的间歇和持续时间;每一对中的第一个值表示等待的毫秒数,第二个值表示在持续振动的毫秒数。 36 | * @param repeat : 重复的次数,默认为-1不重复 37 | */ 38 | @JvmStatic 39 | @JvmOverloads 40 | @RequiresPermission(VIBRATE) 41 | fun vibrate(vararg pattern: Long, repeat: Int = -1) { 42 | if (hasVibrator) { 43 | vibrator.vibrate(pattern, repeat) 44 | } 45 | } 46 | 47 | /** 48 | * 取消振动 49 | */ 50 | @JvmStatic 51 | @RequiresPermission(VIBRATE) 52 | fun cancel() { 53 | if (hasVibrator) { 54 | vibrator.cancel() 55 | } 56 | } 57 | 58 | 59 | } -------------------------------------------------------------------------------- /androidutilskt/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AndroidUtilsKt 3 | 请选择浏览器 4 | 5 | 昨天 6 | 前天 7 | 1分钟前 8 | 分钟前 9 | %d小时前 10 | 11 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion 28 9 | defaultConfig { 10 | applicationId "com.lindroid.androidutilsktdemo" 11 | minSdkVersion 19 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0.0" 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(include: ['*.jar'], dir: 'libs') 27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 28 | implementation 'com.android.support:appcompat-v7:28.0.0' 29 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 30 | implementation 'com.android.support:design:28.0.0' 31 | testImplementation 'junit:junit:4.12' 32 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 34 | implementation project(':androidutilskt') 35 | implementation 'com.youngfeng.android:snake:0.3.2' 36 | //动态权限 37 | implementation 'com.github.tbruyelle:rxpermissions:0.10.2' 38 | //内存泄漏 39 | debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3' 40 | releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3' 41 | implementation 'com.android.support:recyclerview-v7:28.0.0' 42 | implementation 'cn.bingoogolapple:bga-baseadapter:1.2.9@aar' 43 | } 44 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lindroid/androidutilsktdemo/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.lindroid.androidutilsktdemo", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/ic_launch-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lindroy/AndroidUtilsKt/5d6832813a4a0dba7290ad5ef92959f638ea51ab/app/src/main/ic_launch-web.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lindroy/AndroidUtilsKt/5d6832813a4a0dba7290ad5ef92959f638ea51ab/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/JavaActivity.java: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo; 2 | 3 | import android.graphics.Color; 4 | import android.widget.TextView; 5 | import com.lindroid.androidutilsktdemo.base.BaseActivity; 6 | 7 | /** 8 | * @author Lin 9 | * @date 2019/2/28 10 | * @function 仅用于测试 11 | * @Description 12 | */ 13 | public class JavaActivity extends BaseActivity { 14 | private TextView textView; 15 | 16 | @Override 17 | public int getContentViewId() { 18 | return R.layout.activity_java; 19 | } 20 | 21 | @Override 22 | public void initView() { 23 | super.initView(); 24 | textView = findViewById(R.id.textView); 25 | textView.setTextColor(Color.BLACK); 26 | /* AndUtil.init(this.getApplication()) 27 | .setLogGlobalConfig(new Function1() { 28 | @Override 29 | public Unit invoke(LogConfig logConfig) { 30 | logConfig.setLogEnable() 31 | return null; 32 | } 33 | });*/ 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/AppInfoActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.view.View 4 | import com.lindroid.androidutilskt.extension.* 5 | import com.lindroid.androidutilskt.extension.logcat.d 6 | import com.lindroid.androidutilsktdemo.R 7 | import com.lindroid.androidutilsktdemo.base.BaseActivity 8 | import com.youngfeng.snake.annotations.EnableDragToClose 9 | import kotlinx.android.synthetic.main.activity_app_info.* 10 | 11 | /** 12 | * @author Lin 13 | * @date 2018/10/26 14 | * @function 应用信息 15 | * @Description 16 | */ 17 | @EnableDragToClose 18 | class AppInfoActivity(override val contentViewId: Int = R.layout.activity_app_info) : BaseActivity() { 19 | 20 | 21 | override fun initView() { 22 | super.initView() 23 | initToolBar(R.string.util_app_info) 24 | tvVersionName.text = "版本名:${getAppVersionName()}" 25 | tvVersionCode.text = "版本号:${getAppVersionCode()}" 26 | tvAppSize.text = "应用大小:${getAppSize()}" 27 | ivIcon.setImageDrawable(getAppIcon()) 28 | val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 shl 30) - 1, View.MeasureSpec.AT_MOST) 29 | val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 shl 30) - 1, View.MeasureSpec.AT_MOST) 30 | ivIcon.measure(widthMeasureSpec, heightMeasureSpec) 31 | "ivIcon.viewHeight=${px2dp(ivIcon.measuredHeight)},ivIcon.viewWidth=${px2dp(ivIcon.measuredWidth)}".d() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/BrightnessActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.os.Build 7 | import android.provider.Settings 8 | import android.widget.SeekBar 9 | import com.lindroid.androidutilskt.extension.isAutoBrightness 10 | import com.lindroid.androidutilskt.extension.shortToast 11 | import com.lindroid.androidutilskt.extension.systemBrightness 12 | import com.lindroid.androidutilskt.extension.windowBrightness 13 | import com.lindroid.androidutilsktdemo.R 14 | import com.lindroid.androidutilsktdemo.base.BaseActivity 15 | import com.youngfeng.snake.annotations.EnableDragToClose 16 | import kotlinx.android.synthetic.main.activity_brightness.* 17 | 18 | /** 19 | * @author Lin 20 | * @date 2019/3/9 21 | * @function 亮度工具类 22 | * @Description 23 | */ 24 | private const val RQ_WRITE_SETTINGS = 100 25 | 26 | @EnableDragToClose 27 | class BrightnessActivity(override val contentViewId: Int = R.layout.activity_brightness) : BaseActivity() { 28 | 29 | @SuppressLint("SetTextI18n") 30 | override fun initView() { 31 | super.initView() 32 | initToolBar(R.string.util_brightness) 33 | tvAutoBright.text = "是否是自动亮度:${if (isAutoBrightness) "是" else "否"}" 34 | tvWindowBright.text = "当前窗口亮度=$windowBrightness" 35 | sbWindowBright.progress = if (windowBrightness > 0) (windowBrightness * 100).toInt() else 0 36 | sbWindowBright.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { 37 | override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { 38 | windowBrightness = progress.toFloat() / 100F 39 | tvWindowBright.text = "当前窗口亮度=$windowBrightness" 40 | } 41 | 42 | override fun onStartTrackingTouch(seekBar: SeekBar?) { 43 | } 44 | 45 | override fun onStopTrackingTouch(seekBar: SeekBar?) { 46 | } 47 | 48 | }) 49 | 50 | tvSystemBright.text = "系统亮度=$systemBrightness" 51 | sbSystemBright.progress = ((systemBrightness.toFloat() / 255) * 100).toInt() 52 | 53 | //修改系统屏幕亮度需要修改系统设置的权限 54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 55 | //如果当前平台版本大于23平台 56 | if (!Settings.System.canWrite(mContext)) { 57 | val intent = with(Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)) { 58 | data = Uri.parse("package:$packageName") 59 | // addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 60 | this 61 | } 62 | startActivityForResult(intent, RQ_WRITE_SETTINGS) 63 | } else { 64 | changeSystemBrightness() 65 | } 66 | } else { 67 | //Android6.0以下的系统则直接修改亮度 68 | changeSystemBrightness() 69 | } 70 | } 71 | 72 | private fun changeSystemBrightness() { 73 | sbSystemBright.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { 74 | override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { 75 | systemBrightness = progress * 255 / 100 76 | tvSystemBright.text = "系统亮度=$systemBrightness" 77 | } 78 | 79 | 80 | override fun onStartTrackingTouch(seekBar: SeekBar?) { 81 | } 82 | 83 | 84 | override fun onStopTrackingTouch(seekBar: SeekBar?) { 85 | } 86 | 87 | }) 88 | } 89 | 90 | 91 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 92 | super.onActivityResult(requestCode, resultCode, data) 93 | when (requestCode) { 94 | RQ_WRITE_SETTINGS -> { 95 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 96 | if (Settings.System.canWrite(mContext)) { 97 | shortToast("已获取权限") 98 | changeSystemBrightness() 99 | } else { 100 | shortToast("你拒绝了权限") 101 | } 102 | } 103 | } 104 | } 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/CatalogActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.content.Intent 4 | import android.widget.ArrayAdapter 5 | import com.lindroid.androidutilsktdemo.R 6 | import com.lindroid.androidutilsktdemo.activity.statusbar.StatusBarActivity 7 | import com.lindroid.androidutilsktdemo.base.BaseActivity 8 | import kotlinx.android.synthetic.main.activity_catalog.* 9 | 10 | /** 11 | * @author Lin 12 | * @date 2019/2/27 13 | * @function 目录页 14 | * @Description 15 | */ 16 | class CatalogActivity(override val contentViewId: Int = R.layout.activity_catalog) : BaseActivity() { 17 | private lateinit var map: LinkedHashMap> 18 | private val names: MutableList = ArrayList() 19 | 20 | override fun initBefore() { 21 | super.initBefore() 22 | map = linkedMapOf( 23 | R.string.util_app_info to AppInfoActivity::class.java, 24 | R.string.util_brightness to BrightnessActivity::class.java, 25 | R.string.util_intent to IntentActivity::class.java, 26 | R.string.util_keyboard to KeyboardActivity::class.java, 27 | R.string.util_log to LogActivity::class.java, 28 | R.string.util_navigation to NavigationBarActivity::class.java, 29 | R.string.util_regex to RegexActivity::class.java, 30 | R.string.util_sdcard to SDCardActivity::class.java, 31 | R.string.util_screen to ScreenActivity::class.java, 32 | R.string.util_Spannable to SpannableActivity::class.java, 33 | R.string.util_status_bar to StatusBarActivity::class.java, 34 | R.string.util_time to TimeActivity::class.java, 35 | R.string.util_toast to ToastActivity::class.java, 36 | R.string.util_vibrator to VibratorActivity::class.java, 37 | R.string.util_view to ViewActivity::class.java 38 | ) 39 | names.addAll(map.map { 40 | getString(it.key) 41 | }) 42 | } 43 | 44 | override fun initView() { 45 | super.initView() 46 | initToolBar(title = "目录", isShowArrow = false) 47 | fun startActivity(cls: Class<*>?) { 48 | startActivity(Intent(mContext, cls)) 49 | } 50 | list.adapter = ArrayAdapter(mContext, android.R.layout.simple_list_item_1, android.R.id.text1, names) 51 | list.setOnItemClickListener { parent, view, position, id -> 52 | val rightMap = map.filterKeys { 53 | getString(it) == names[position] 54 | }.values.toList() 55 | startActivity(rightMap[0]) 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/IntentActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import com.lindroid.androidutilskt.extension.extraParam 4 | import com.lindroid.androidutilskt.extension.shortToast 5 | import com.lindroid.androidutilskt.statics.IntentUtil 6 | import com.lindroid.androidutilsktdemo.R 7 | import com.lindroid.androidutilsktdemo.base.BaseActivity 8 | import com.lindroid.androidutilsktdemo.util.permCallPhone 9 | import com.lindroid.androidutilsktdemo.util.permCamera 10 | import com.lindroid.androidutilsktdemo.util.permSendSMS 11 | import com.youngfeng.snake.annotations.EnableDragToClose 12 | import kotlinx.android.synthetic.main.activity_intent.* 13 | 14 | /** 15 | * @author Lin 16 | * @date 2018/11/5 17 | * @function 意图工具类 18 | * @Description 19 | */ 20 | @EnableDragToClose 21 | class IntentActivity(override val contentViewId: Int = R.layout.activity_intent) : BaseActivity() { 22 | 23 | override fun initView() { 24 | super.initView() 25 | initToolBar(R.string.util_intent) 26 | } 27 | 28 | override fun initOnClick() { 29 | super.initOnClick() 30 | //打开系统设置 31 | btnSystemSetting.setOnClickListener { 32 | IntentUtil.launchSystemSetting(mContext) 33 | } 34 | //打开wifi设置 35 | btnWiFiSetting.setOnClickListener { 36 | IntentUtil.launchWifiSetting(mContext) 37 | } 38 | //打开拨号面板 39 | btnDialPage.setOnClickListener { 40 | IntentUtil.launchDialPage(mContext) 41 | } 42 | //直接拨打电话 43 | btnCallPhone.setOnClickListener { 44 | permCallPhone { 45 | if (it) { 46 | IntentUtil.callPhone(mContext, "1008611") 47 | } 48 | } 49 | } 50 | //打开浏览器 51 | btnBrowser.setOnClickListener { 52 | IntentUtil.launchBrowse(mContext, "http://www.baidu.com/") { 53 | if (it) { 54 | shortToast("成功打开浏览器选择面板") 55 | } else { 56 | shortToast("打开浏览器选择面板失败") 57 | } 58 | } 59 | } 60 | //启动相机 61 | btnCamera.setOnClickListener { 62 | permCamera { 63 | IntentUtil.launchCamera(this, 100) 64 | } 65 | } 66 | //发送短信 67 | btnSendSMS.setOnClickListener { 68 | permSendSMS { 69 | IntentUtil.sendSMS(mContext, "10086", "这是一条短信") 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/KeyboardActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import com.lindroid.androidutilskt.extension.* 4 | import com.lindroid.androidutilsktdemo.R 5 | import com.lindroid.androidutilsktdemo.base.BaseActivity 6 | import com.youngfeng.snake.annotations.EnableDragToClose 7 | import kotlinx.android.synthetic.main.activity_keyboard.* 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/2/28 12 | * @function 13 | * @Description 14 | */ 15 | @EnableDragToClose 16 | class KeyboardActivity(override val contentViewId: Int = R.layout.activity_keyboard) : BaseActivity() { 17 | 18 | override fun initView() { 19 | super.initView() 20 | initToolBar(R.string.util_keyboard) 21 | } 22 | 23 | override fun initOnClick() { 24 | super.initOnClick() 25 | btnShow.setOnClickListener { editText.showKeyboard() } 26 | btnHide.setOnClickListener { editText.hideKeyboard() } 27 | btnToggle.setOnClickListener { editText.toggleKeyboard() } 28 | 29 | /*llRoot.addOnKeyboardStatusWatcher { hasShow, keyboardHeight -> 30 | "软键盘状态:${hasShow},键盘高度:$keyboardHeight".d() 31 | "软键盘是否打开:${llRoot.isKeyboardShowed}".d() 32 | }*/ 33 | 34 | 35 | val keyboardStatus = KeyboardStatusWatcher(llRoot) 36 | //监听软键盘状态 37 | keyboardStatus.addKeyboardStatusWatcher { isShowed, keyboardHeight -> 38 | val status = if (isShowed) "软键盘显示,高度为${keyboardStatus.keyboardHeight}px" else "软键盘收起" 39 | shortToast(status) 40 | flKeyboard.setHeight(keyboardHeight) 41 | } 42 | //软键盘高度 43 | keyboardStatus.keyboardHeight 44 | //软键盘是否显示 45 | keyboardStatus.isKeyboardShowed 46 | //软键盘是否隐藏 47 | keyboardStatus.isKeyboardHidden 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/NavigationBarActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import com.lindroid.androidutilskt.extension.* 4 | import com.lindroid.androidutilsktdemo.R 5 | import com.lindroid.androidutilsktdemo.base.BaseActivity 6 | import com.youngfeng.snake.annotations.EnableDragToClose 7 | import kotlinx.android.synthetic.main.activity_navigation_bar.* 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/6/11 12 | * @function 虚拟状态栏 13 | * @Description 14 | */ 15 | @EnableDragToClose 16 | class NavigationBarActivity(override val contentViewId: Int = R.layout.activity_navigation_bar) : BaseActivity() { 17 | 18 | override fun initView() { 19 | super.initView() 20 | initToolBar(R.string.util_navigation) 21 | tvHasNav.text = "是否有虚拟导航栏:$hasNavBar" 22 | tvNavHeight.text = "虚拟导航栏高度:${navBarHeight}px" 23 | } 24 | 25 | override fun initOnListener() { 26 | super.initOnListener() 27 | NavBarStatusWatcher(tvNavShow).addNavBarStatusWatcher { 28 | val status = if (it) "导航栏显示,高度为${navBarHeight}px" else "导航栏收起" 29 | shortToast(status) 30 | } 31 | } 32 | 33 | override fun onWindowFocusChanged(hasFocus: Boolean) { 34 | super.onWindowFocusChanged(hasFocus) 35 | tvNavShow.text = "虚拟导航栏是否显示:$isNavBarShowed" 36 | setNavBarColorRes(android.R.color.holo_red_light) 37 | swNav.setOnCheckedChangeListener { buttonView, isChecked -> 38 | // window.setShowNavBar(isChecked) 39 | /* if (isChecked){ 40 | llRoot.setNewPadding(top = 0) 41 | }else{ 42 | llRoot.setNewPadding(top = statusBarHeight) 43 | 44 | }*/ 45 | } 46 | 47 | 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/RegexActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.view.View 4 | import android.widget.AdapterView 5 | import android.widget.ArrayAdapter 6 | import com.lindroid.androidutilskt.extension.* 7 | import com.lindroid.androidutilsktdemo.R 8 | import com.lindroid.androidutilsktdemo.base.BaseActivity 9 | import com.youngfeng.snake.annotations.EnableDragToClose 10 | import kotlinx.android.synthetic.main.activity_regex.* 11 | import kotlin.properties.Delegates 12 | import kotlin.reflect.KProperty 13 | 14 | /** 15 | * @author Lin 16 | * @date 2019/3/15 17 | * @function 正则表达式 18 | * @Description 19 | */ 20 | @EnableDragToClose 21 | class RegexActivity(override val contentViewId: Int = R.layout.activity_regex) : BaseActivity() { 22 | 23 | private lateinit var map: LinkedHashMap 24 | 25 | private var content: String by Delegates.observable("") { property: KProperty<*>, oldValue: String, newValue: String -> 26 | } 27 | 28 | override fun initView() { 29 | super.initView() 30 | initToolBar(R.string.util_regex) 31 | initSpinner() 32 | } 33 | 34 | 35 | override fun initOnClick() { 36 | super.initOnClick() 37 | 38 | spRegex.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { 39 | override fun onNothingSelected(parent: AdapterView<*>?) { 40 | } 41 | 42 | override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { 43 | val key = map.keys.toList()[position] 44 | content = map[key] ?: "" 45 | etRegex.setText(content) 46 | } 47 | } 48 | 49 | btnMobile.setOnClickListener { shortToast("${getString(R.string.regex_mobile)}:${content.isMobile}") } 50 | btnEmail.setOnClickListener { shortToast("${getString(R.string.regex_email)}:${content.isEmail}") } 51 | btnUrl.setOnClickListener { shortToast("${getString(R.string.regex_url)}:${content.isWebUrl}") } 52 | btnNumber.setOnClickListener { shortToast("${getString(R.string.regex_number)}:${content.isNumber}") } 53 | btnPosInt.setOnClickListener { shortToast("${getString(R.string.regex_pos_int)}:${content.isPositiveInt}") } 54 | btnNegInt.setOnClickListener { shortToast("${getString(R.string.regex_neg_int)}:${content.isNegativeInt}") } 55 | btnLetter.setOnClickListener { shortToast("${getString(R.string.regex_letter)}:${content.isLetter}") } 56 | btnUpperCase.setOnClickListener { shortToast("${getString(R.string.regex_upper_case)}:${content.isUpperCaseLetter}") } 57 | btnLowerCase.setOnClickListener { shortToast("${getString(R.string.regex_lower_case)}:${content.isLowerCaseLetter}") } 58 | btnChinese.setOnClickListener { shortToast("${getString(R.string.regex_chinese)}:${content.isChinese}") } 59 | btnQQ.setOnClickListener { shortToast("${getString(R.string.regex_chinese)}:${content.isQQ}") } 60 | btnMacaoMobile.setOnClickListener { shortToast("${getString(R.string.regex_chinese)}:${content.isMacaoMobile}") } 61 | } 62 | 63 | private fun initSpinner() { 64 | map = linkedMapOf( 65 | getString(R.string.regex_mobile) to "13800138000", 66 | getString(R.string.regex_email) to "iamcoder@163.com", 67 | getString(R.string.regex_url) to "https://www.baidu.com/", 68 | getString(R.string.regex_number) to "012345", 69 | getString(R.string.regex_pos_int) to "1024", 70 | getString(R.string.regex_neg_int) to "-1024", 71 | getString(R.string.regex_letter) to "aBcD", 72 | getString(R.string.regex_upper_case) to "ABCDEFG", 73 | getString(R.string.regex_lower_case) to "abcdefg", 74 | getString(R.string.regex_chinese) to "https://www.baidu.com/", 75 | getString(R.string.regex_qq) to "1001", 76 | getString(R.string.regex_macao_mobile) to "65535" 77 | ) 78 | val adapter = ArrayAdapter(mContext, android.R.layout.simple_spinner_item, map.keys.toList()) 79 | adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice) 80 | spRegex.adapter = adapter 81 | content = map.keys.toList()[0] 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/SDCardActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import com.lindroid.androidutilskt.extension.isSDCardMounted 4 | import com.lindroid.androidutilskt.extension.sdCardAvailableSize 5 | import com.lindroid.androidutilskt.extension.sdCardPath 6 | import com.lindroid.androidutilskt.extension.sdCardTotalSize 7 | import com.lindroid.androidutilsktdemo.R 8 | import com.lindroid.androidutilsktdemo.base.BaseActivity 9 | import com.youngfeng.snake.annotations.EnableDragToClose 10 | import kotlinx.android.synthetic.main.activity_sdcard.* 11 | 12 | /** 13 | * @author Lin 14 | * @date 2019/3/19 15 | * @function SD卡工具类 16 | * @Description 17 | */ 18 | @EnableDragToClose 19 | class SDCardActivity(override val contentViewId: Int = R.layout.activity_sdcard) : BaseActivity() { 20 | 21 | override fun initView() { 22 | super.initView() 23 | initToolBar(R.string.util_sdcard) 24 | tvMounted.text = "SD卡是否可用:$isSDCardMounted" 25 | tvPath.text = "SD卡路径:${sdCardPath}" 26 | tvTotalSize.text = "SD卡的总大小:${sdCardTotalSize / (1024 * 1024 * 1024)}G" 27 | tvAvailableSize.text = "SD卡可用空间大小:${sdCardAvailableSize / (1024 * 1024 * 1024)}G" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/SpannableActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.graphics.Color 4 | import com.lindroid.androidutilskt.extension.* 5 | import com.lindroid.androidutilsktdemo.R 6 | import com.lindroid.androidutilsktdemo.base.BaseActivity 7 | import com.youngfeng.snake.annotations.EnableDragToClose 8 | import kotlinx.android.synthetic.main.activity_spannable.* 9 | 10 | /** 11 | * @author Lin 12 | * @date 2019/3/11 13 | * @function Spannable工具类 14 | * @Description 15 | */ 16 | @EnableDragToClose 17 | class SpannableActivity(override val contentViewId: Int = R.layout.activity_spannable) : BaseActivity() { 18 | 19 | override fun initView() { 20 | super.initView() 21 | initToolBar(R.string.util_Spannable) 22 | tvFgColor.setFgColorSpan("设置文本前景色", Color.BLUE, 4, 7) 23 | tvBgColor.setBgColorSpan("设置文本背景色", Color.YELLOW, 4, 7) 24 | tvStrike.setStrikethroughSpan("设置文本删除线", 4, 7) 25 | tvUnderline.setUnderlineSpan("设置文本下划线", 4, 7) 26 | tvBold.setBoldSpan("设置粗体字", 2, 5) 27 | tvItalic.setItalicSpan("设置斜体字", 2, 5) 28 | tvBoldItalic.setBoldItalicSpan("同时设置粗体斜体", 4, 8) 29 | tvClickable.setClickableSpan("设置可点击文本", 2, 5, textColor = Color.RED) { clickString, widget -> 30 | shortToast(clickString) 31 | } 32 | tvUrl.setUrlSpan("设置超链接", "https://www.baidu.com/", 2, 5, true, textColor = Color.BLUE) 33 | tvRelativeSize.setRelativeSizeSpan("设置文字相对大小", 6, 7, 1.2F) 34 | tvSuperScript.buildSpan("设置文字上标:210=1024") { 35 | setStartEnd(8, 10) 36 | setRelativeSize(0.6F) 37 | setSuperScript() 38 | }.create() 39 | 40 | tvSuperScript.buildSpan("设置文字上标:210=1024") 41 | .setStartEnd(8, 10) 42 | .setRelativeSize(0.6F) 43 | .setSuperScript() 44 | .create() 45 | 46 | tvSubscript.buildSpan("设置文字下标:H20") { 47 | setStartEnd(8, 9) 48 | setRelativeSize(0.6F) 49 | setSubscript() 50 | create() 51 | } 52 | 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/TimeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.annotation.SuppressLint 4 | import com.lindroid.androidutilskt.extension.* 5 | import com.lindroid.androidutilsktdemo.R 6 | import com.lindroid.androidutilsktdemo.base.BaseActivity 7 | import com.youngfeng.snake.annotations.EnableDragToClose 8 | import kotlinx.android.synthetic.main.activity_time.* 9 | 10 | /** 11 | * @author Lin 12 | * @date 2019/3/1 13 | * @function 时间工具类 14 | * @Description 15 | */ 16 | 17 | @EnableDragToClose 18 | class TimeActivity(override val contentViewId: Int = R.layout.activity_time) : BaseActivity() { 19 | 20 | private val serverTime = "2019-03-04T14:42:30.100" 21 | 22 | @SuppressLint("SetTextI18n") 23 | override fun initView() { 24 | super.initView() 25 | initToolBar(R.string.util_time) 26 | tvOriginalTime.text = "服务器时间示例:$serverTime" 27 | initCurTimeInfo() 28 | initServerTimeInfo() 29 | } 30 | 31 | @SuppressLint("SetTextI18n") 32 | override fun initOnClick() { 33 | super.initOnClick() 34 | btnRefresh.setOnClickListener { initCurTimeInfo() } 35 | 36 | } 37 | 38 | 39 | @SuppressLint("SetTextI18n") 40 | private fun initServerTimeInfo() { 41 | tvServerY.text = "服务器时间转换为年:${serverTime.formatTimeY()}" 42 | tvServerM.text = "服务器时间转换为月:${serverTime.formatTimeM()}" 43 | tvServerD.text = "服务器时间转换为日:${serverTime.formatTimeDD()}" 44 | tvServerYM.text = "服务器时间转换为年月:${serverTime.formatTimeYM()}" 45 | tvServerYMD.text = "服务器时间转换为年月日:${serverTime.formatTimeYMD()}" 46 | tvServerYMDChinese.text = "服务器时间转换为年月日(汉字):${serverTime.formatTimeYMDChinese()}" 47 | tvServerTime.text = "服务器时间转换为时间:${serverTime.formatTimeHM()}" 48 | tvServerYMDHM.text = "服务器时间转换为年月日时分:${serverTime.formatTimeYMDHM()}" 49 | tvServerYMDHMS.text = "服务器时间转换为年月日时分秒:${serverTime.formatTimeYMDHMS()}" 50 | } 51 | 52 | @SuppressLint("SetTextI18n") 53 | private fun initCurTimeInfo() { 54 | tvCurYear.text = "当前年份:$currentYear" 55 | tvCurMon.text = "当前月份:$currentMonth" 56 | tvCurDay.text = "当前日:$currentDay" 57 | tvCurMilli.text = "当前时间戳:$currentTimeMillis" 58 | tvCurDate.text = "当前日期:${formatCurrentDate()}" 59 | tvCurDateTime.text = "当前日期时间:${formatCurrentDateTime()}" 60 | tvCurTime.text = "当前时间:${formatCurrentTime()}" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/ToastActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import com.lindroid.androidutilskt.extension.longToast 4 | import com.lindroid.androidutilskt.extension.shortToast 5 | import com.lindroid.androidutilsktdemo.R 6 | import com.lindroid.androidutilsktdemo.base.BaseActivity 7 | import com.youngfeng.snake.annotations.EnableDragToClose 8 | import kotlinx.android.synthetic.main.activity_toast.* 9 | 10 | /** 11 | * @author Lin 12 | * @date 2019/2/27 13 | * @function Toast工具类 14 | * @Description 15 | */ 16 | @EnableDragToClose 17 | class ToastActivity(override val contentViewId: Int = R.layout.activity_toast) : BaseActivity() { 18 | 19 | override fun initView() { 20 | super.initView() 21 | initToolBar(R.string.util_toast) 22 | } 23 | 24 | override fun initOnClick() { 25 | super.initOnClick() 26 | btnShortToast.setOnClickListener { shortToast("短Toast") } 27 | btnLongToast.setOnClickListener { longToast("长Toast") } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/VibratorActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.content.Context 4 | import android.os.Vibrator 5 | import android.util.Log 6 | import com.lindroid.androidutilskt.statics.VibratorUtil 7 | import com.lindroid.androidutilsktdemo.R 8 | import com.lindroid.androidutilsktdemo.base.BaseActivity 9 | import com.youngfeng.snake.annotations.EnableDragToClose 10 | import kotlinx.android.synthetic.main.activity_vibrator.* 11 | 12 | 13 | /** 14 | * @author Lin 15 | * @date 2019/3/10 16 | * @function 手机振动工具类 17 | * @Description 18 | * https://developer.android.google.cn/reference/android/os/VibrationEffect.html 19 | * https://www.jianshu.com/p/38fde766cc03 20 | * https://www.jianshu.com/p/921d24ba1974 21 | * https://github.com/Blankj/AndroidUtilCode/blob/master/utilcode/lib/src/main/java/com/blankj/utilcode/util/VibrateUtils.java 22 | */ 23 | 24 | @EnableDragToClose 25 | class VibratorActivity(override val contentViewId: Int = com.lindroid.androidutilsktdemo.R.layout.activity_vibrator) : 26 | BaseActivity() { 27 | private lateinit var vibrator: Vibrator 28 | 29 | override fun initView() { 30 | super.initView() 31 | initToolBar(R.string.util_vibrator) 32 | vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator 33 | Log.e("VibratorActivity", "是否有振动器:${vibrator.hasVibrator()}") 34 | } 35 | 36 | override fun initOnClick() { 37 | super.initOnClick() 38 | btnStart.setOnClickListener { 39 | VibratorUtil.vibrate(1000, 2000, 3000, 5000) 40 | /* if (Build.VERSION.SDK_INT >= 26){ 41 | val ve = VibrationEffect.createOneShot(2000,VibrationEffect.DEFAULT_AMPLITUDE) 42 | vibrator.vibrate(ve) 43 | }else{ 44 | 45 | vibrator.vibrate(longArrayOf(1000,2000,3000,5000),-1) 46 | }*/ 47 | 48 | } 49 | btnCancel.setOnClickListener { 50 | VibratorUtil.cancel() 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/ViewActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity 2 | 3 | import android.annotation.SuppressLint 4 | import android.widget.SeekBar 5 | import com.lindroid.androidutilskt.extension.* 6 | import com.lindroid.androidutilskt.extension.logcat.d 7 | import com.lindroid.androidutilsktdemo.R 8 | import com.lindroid.androidutilsktdemo.base.BaseActivity 9 | import com.youngfeng.snake.annotations.EnableDragToClose 10 | import kotlinx.android.synthetic.main.activity_view.* 11 | 12 | 13 | /** 14 | * @author Lin 15 | * @date 2019/3/9 16 | * @function View相关工具类 17 | * @Description 18 | */ 19 | 20 | @EnableDragToClose 21 | class ViewActivity(override val contentViewId: Int = R.layout.activity_view) : BaseActivity() { 22 | 23 | @SuppressLint("SetTextI18n") 24 | override fun initView() { 25 | super.initView() 26 | initToolBar(R.string.util_view) 27 | tvWidth.text = "设置View的宽度:${screenWidth}px" 28 | tvHeight.text = "设置View的高度:${(dp2px(150))}px" 29 | // "llRoot.viewHeight=${px2dp(llRoot.viewHeight)},llRoot.viewWidth=${px2dp(llRoot.viewWidth)}".d() 30 | "frameLayout.viewHeight=${px2dp(frameLayout.viewHeight)},frameLayout.viewWidth=${px2dp(frameLayout.viewWidth)}".d() 31 | } 32 | 33 | override fun initOnClick() { 34 | super.initOnClick() 35 | btnVisible.setOnClickListener { frameLayout.setVisible() } 36 | btnInvisible.setOnClickListener { frameLayout.setInvisible() } 37 | btnGone.setOnClickListener { frameLayout.setGone() } 38 | btnToBitmap.setOnClickListener { 39 | ivBitmap.setImageBitmap(frameLayout.toBitmap()) 40 | } 41 | } 42 | 43 | override fun initOnListener() { 44 | super.initOnListener() 45 | //动态设置宽度 46 | sbWidth.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { 47 | override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { 48 | tvWidth.text = "设置View的宽度:${(screenWidth * progress) / 100}px" 49 | frameLayout.setWidth((screenWidth * progress) / 100) 50 | } 51 | 52 | override fun onStartTrackingTouch(seekBar: SeekBar?) { 53 | } 54 | 55 | override fun onStopTrackingTouch(seekBar: SeekBar?) { 56 | } 57 | 58 | }) 59 | //动态设置高度 60 | sbHeight.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { 61 | override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { 62 | tvHeight.text = "设置View的高度:${(dp2px(150) * progress) / 100}px" 63 | frameLayout.setHeight((dp2px(150) * progress) / 100) 64 | } 65 | 66 | override fun onStartTrackingTouch(seekBar: SeekBar?) { 67 | } 68 | 69 | override fun onStopTrackingTouch(seekBar: SeekBar?) { 70 | } 71 | 72 | }) 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/statusbar/StatusBarActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity.statusbar 2 | 3 | import com.lindroid.androidutilskt.extension.launchActivity 4 | import com.lindroid.androidutilskt.extension.px2dp 5 | import com.lindroid.androidutilskt.extension.shortToast 6 | import com.lindroid.androidutilskt.extension.statusbar.statusBarHeight 7 | import com.lindroid.androidutilsktdemo.R 8 | import com.lindroid.androidutilsktdemo.base.BaseActivity 9 | import com.youngfeng.snake.annotations.EnableDragToClose 10 | import kotlinx.android.synthetic.main.activity_status_bar.* 11 | 12 | 13 | /** 14 | * @author Lin 15 | * @date 2019/3/1 16 | * @function 状态栏工具类 17 | * @Description 18 | */ 19 | @EnableDragToClose 20 | class StatusBarActivity(override val contentViewId: Int = R.layout.activity_status_bar) : BaseActivity() { 21 | override fun initView() { 22 | super.initView() 23 | initToolBar(R.string.util_status_bar) 24 | } 25 | 26 | override fun initOnClick() { 27 | super.initOnClick() 28 | btnHeight.setOnClickListener { 29 | shortToast("状态栏高度:${px2dp(statusBarHeight)}dp") 30 | } 31 | btnChangeColor.setOnClickListener { 32 | launchActivity() 33 | } 34 | btnImage.setOnClickListener { 35 | launchActivity() 36 | } 37 | btnSlide.setOnClickListener { 38 | launchActivity() 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/statusbar/StatusBarChangeColorActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity.statusbar 2 | 3 | import com.lindroid.androidutilskt.extension.statusbar.* 4 | import com.lindroid.androidutilsktdemo.R 5 | import com.lindroid.androidutilsktdemo.base.BaseActivity 6 | import com.youngfeng.snake.annotations.EnableDragToClose 7 | import kotlinx.android.synthetic.main.activity_status_bar_change_color.* 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/3/1 12 | * @function 改变状态栏颜色 13 | * @Description 14 | */ 15 | @EnableDragToClose 16 | class StatusBarChangeColorActivity(override val contentViewId: Int = R.layout.activity_status_bar_change_color) : 17 | BaseActivity() { 18 | 19 | override fun initView() { 20 | super.initView() 21 | // initToolBar("改变状态栏颜色", toolBarColor = android.R.color.transparent) 22 | // toolBar.setPadding(0, getStatusBarHeight(), 0, 0) 23 | setTransParentStatusBar() 24 | } 25 | 26 | override fun initOnClick() { 27 | super.initOnClick() 28 | btnTransparent.setOnClickListener { 29 | setStatusBarColorRes(android.R.color.transparent) 30 | } 31 | btnWhite.setOnClickListener { 32 | setStatusBarColorRes(android.R.color.white) 33 | } 34 | btnBlack.setOnClickListener { 35 | setStatusBarColorRes(android.R.color.black) 36 | } 37 | btnGradient.setOnClickListener { 38 | setGradientStatusBar(R.drawable.shape_gradient_bar) 39 | } 40 | btnLight.setOnClickListener { 41 | setStatusBarLightMode() 42 | } 43 | btnDark.setOnClickListener { 44 | setStatusBarDarkMode() 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/statusbar/StatusBarImageActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity.statusbar 2 | 3 | import com.lindroid.androidutilskt.extension.statusbar.setTransParentStatusBar 4 | import com.lindroid.androidutilskt.extension.statusbar.statusBarHeight 5 | import com.lindroid.androidutilskt.statics.AppManager 6 | import com.lindroid.androidutilsktdemo.R 7 | import com.lindroid.androidutilsktdemo.base.BaseActivity 8 | import com.youngfeng.snake.annotations.EnableDragToClose 9 | import kotlinx.android.synthetic.main.activity_status_bar_image.* 10 | import kotlinx.android.synthetic.main.toolbar.* 11 | 12 | /** 13 | * @author Lin 14 | * @date 2019/3/4 15 | * @function 顶部为图片的沉浸式状态栏 16 | * @Description 17 | */ 18 | 19 | @EnableDragToClose 20 | class StatusBarImageActivity(override val contentViewId: Int = R.layout.activity_status_bar_image) : BaseActivity() { 21 | 22 | override fun initView() { 23 | super.initView() 24 | initToolBar("顶部为图片的沉浸式状态栏", toolBarColor = android.R.color.transparent) 25 | setTransParentStatusBar() 26 | 27 | /* val lp = FrameLayout.LayoutParams(toolBar.layoutParams) 28 | lp.setMargins(0,getStatusBarHeight(),0,0) 29 | toolBar.layoutParams = lp*/ 30 | 31 | toolBar.setPadding(0, statusBarHeight, 0, 0) 32 | tvDesc.text = """ 33 | 顶部为图片的沉浸式状态栏的设置步骤: 34 | 1、设置透明状态栏; 35 | 2、标题栏的高度设为“wrap_content”,固定高度可通过“minHeight”设置; 36 | 3、在代码中将标题栏的paddingTop或者marginTop设为状态栏高度。 37 | """.trimIndent() 38 | 39 | imageView.setOnClickListener { 40 | AppManager.finishActivity(StatusBarActivity::class.java) 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/activity/statusbar/StatusBarSlideActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.activity.statusbar 2 | 3 | import com.lindroid.androidutilskt.extension.statusbar.setTransParentStatusBar 4 | import com.lindroid.androidutilsktdemo.R 5 | import com.lindroid.androidutilsktdemo.base.BaseActivity 6 | import com.youngfeng.snake.annotations.EnableDragToClose 7 | import kotlinx.android.synthetic.main.activity_status_bar_slide.* 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/3/1 12 | * @function 配合侧滑返回上一页面(Snake库)使用 13 | * @Description 14 | */ 15 | 16 | @EnableDragToClose 17 | class StatusBarSlideActivity(override val contentViewId: Int = R.layout.activity_status_bar_slide) : BaseActivity() { 18 | 19 | override fun initView() { 20 | super.initView() 21 | initToolBar("配合侧滑使用", toolBarColor = android.R.color.holo_red_light) 22 | setTransParentStatusBar() 23 | 24 | tvDesc.text = """ 25 | 侧滑返回上一页时状态栏无法跟随移动,所以如果前后页面状态栏颜色不一致,可以做如下操作: 26 | 1、根布局添加如下属性:android:fitsSystemWindows="true"; 27 | 2、将根布局背景色设为标题栏颜色或者原本要设置的状态栏颜色; 28 | 3、设置透明状态栏。 29 | """ 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/app/App.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.app 2 | 3 | import android.app.Application 4 | import com.lindroid.androidutilskt.app.AndUtil 5 | import com.squareup.leakcanary.LeakCanary 6 | import com.youngfeng.snake.Snake 7 | 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/2/27 12 | * @function 13 | * @Description 14 | */ 15 | class App : Application() { 16 | companion object { 17 | lateinit var instance: App 18 | } 19 | 20 | init { 21 | instance = this 22 | } 23 | 24 | override fun onCreate() { 25 | super.onCreate() 26 | // 对Snake进行初始化 27 | Snake.init(this) 28 | AndUtil.init(this) 29 | .setLogGlobalConfig { 30 | setLogEnable(true) 31 | setMethodCount(2) 32 | } 33 | .setLogDiskConfig { } 34 | 35 | // .setDefaultSpFile() //设置SharePreferences的默认表名,默认为“sp_util” 36 | // .setServerTimeFormat() //设置时间格式化中服务器时间格式,默认为“yyyy-MM-dd'T'HH:mm:ss.SSS” 37 | if (LeakCanary.isInAnalyzerProcess(this)) { 38 | // This process is dedicated to LeakCanary for heap analysis. 39 | // You should not init your app in this process. 40 | return 41 | } 42 | LeakCanary.install(this) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/base/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.base 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.support.annotation.ColorRes 6 | import android.support.annotation.StringRes 7 | import android.support.v4.content.ContextCompat 8 | import android.support.v7.app.AppCompatActivity 9 | import android.view.MenuItem 10 | import com.lindroid.androidutilskt.extension.logcat.buildLogConfig 11 | import com.lindroid.androidutilskt.statics.AppManager 12 | import com.lindroid.androidutilsktdemo.R 13 | import kotlinx.android.synthetic.main.toolbar.view.* 14 | 15 | /** 16 | * @author Lin 17 | * @date 2019/2/27 18 | * @function 基类Activity 19 | * @Description 20 | */ 21 | abstract class BaseActivity : AppCompatActivity() { 22 | protected lateinit var mContext: Context 23 | 24 | //默认值为0 25 | abstract val contentViewId: Int 26 | 27 | override fun onCreate(savedInstanceState: Bundle?) { 28 | super.onCreate(savedInstanceState) 29 | mContext = this 30 | AppManager.addActivity(this) 31 | initBefore() 32 | setContentView(contentViewId) 33 | initView() 34 | initOnListener() 35 | buildLogConfig { 36 | 37 | } 38 | } 39 | 40 | open fun initOnListener() { 41 | initOnClick() 42 | } 43 | 44 | 45 | open fun initOnClick() { 46 | 47 | } 48 | 49 | open fun initBefore() { 50 | 51 | } 52 | 53 | open fun initView() { 54 | 55 | } 56 | 57 | 58 | fun initToolBar( 59 | title: String = getString(R.string.app_name), 60 | isShowArrow: Boolean = true, @ColorRes toolBarColor: Int = R.color.colorPrimary 61 | ) { 62 | val toolView = window.decorView 63 | toolView.toolBar.title = title 64 | toolView.toolBar.setBackgroundColor(ContextCompat.getColor(mContext, toolBarColor)) 65 | //ToolBar的属性设置要在setSupportActionBar方法之前调用 66 | setSupportActionBar(toolView.toolBar) 67 | supportActionBar?.setDisplayHomeAsUpEnabled(isShowArrow) 68 | } 69 | 70 | fun initToolBar(@StringRes stringId: Int, isShowArrow: Boolean = true) { 71 | initToolBar(mContext.getString(stringId), isShowArrow) 72 | } 73 | 74 | override fun onOptionsItemSelected(item: MenuItem?): Boolean { 75 | when (item!!.itemId) { 76 | android.R.id.home -> finish() 77 | } 78 | return true 79 | } 80 | 81 | override fun onDestroy() { 82 | super.onDestroy() 83 | AppManager.removeActivity(this) 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/receiver/ScreenActionReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.receiver 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.IntentFilter 7 | import android.util.Log 8 | import com.lindroid.androidutilskt.extension.isScreenLocked 9 | import com.lindroid.androidutilskt.extension.isScreenOff 10 | import com.lindroid.androidutilskt.extension.isScreenOn 11 | import com.lindroid.androidutilskt.extension.isScreenUnlocked 12 | 13 | const val SCREEN_TAG = "ScreenTag" 14 | 15 | class ScreenActionReceiver(private val mContext: Context) : BroadcastReceiver() { 16 | private var isRegistered = false 17 | 18 | private var screenActionListener: ScreenActionListener? = null 19 | 20 | override fun onReceive(context: Context, intent: Intent) { 21 | 22 | when (intent.action) { 23 | Intent.ACTION_SCREEN_ON -> { 24 | //亮屏 25 | screenActionListener?.onScreenOn() 26 | } 27 | Intent.ACTION_SCREEN_OFF -> { 28 | //暗屏 29 | screenActionListener?.onScreenOff() 30 | 31 | } 32 | Intent.ACTION_USER_PRESENT -> { 33 | //解锁 34 | screenActionListener?.onScreenUnLocked() 35 | } 36 | } 37 | Log.d(SCREEN_TAG, "isScreenLocked:$isScreenLocked") 38 | Log.d(SCREEN_TAG, "isScreenUnlocked:$isScreenUnlocked") 39 | Log.d(SCREEN_TAG, "isScreenOn:$isScreenOn") 40 | Log.d(SCREEN_TAG, "isScreenOff:$isScreenOff") 41 | } 42 | 43 | fun registerScreenActionReceiver() { 44 | if (!isRegistered) { 45 | Log.d(SCREEN_TAG, "注册锁屏监听广播") 46 | isRegistered = true 47 | mContext.registerReceiver(this, with(IntentFilter()) { 48 | addAction(Intent.ACTION_SCREEN_ON) 49 | addAction(Intent.ACTION_SCREEN_OFF) 50 | addAction(Intent.ACTION_USER_PRESENT) 51 | this 52 | }) 53 | } 54 | } 55 | 56 | fun unRegisterScreenActionReceiver() { 57 | Log.d(SCREEN_TAG, "解绑锁屏监听广播") 58 | if (isRegistered) { 59 | isRegistered = false 60 | screenActionListener = null 61 | mContext.unregisterReceiver(this) 62 | } 63 | } 64 | 65 | fun setScreenActionListener(listener: ScreenActionListener) { 66 | screenActionListener = listener 67 | } 68 | 69 | interface ScreenActionListener { 70 | fun onScreenOn() 71 | fun onScreenOff() 72 | fun onScreenUnLocked() 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/lindroid/androidutilsktdemo/util/PermissionUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lindroid.androidutilsktdemo.util 2 | 3 | import android.Manifest 4 | import android.annotation.SuppressLint 5 | import android.support.v4.app.Fragment 6 | import android.support.v4.app.FragmentActivity 7 | import com.tbruyelle.rxpermissions2.RxPermissions 8 | 9 | /** 10 | * @author Lin 11 | * @date 2019/2/21 12 | * @function 动态权限申请工具类 13 | * @Description 14 | */ 15 | 16 | @SuppressLint("CheckResult") 17 | private fun RxPermissions.checkPermission(listener: (granted: Boolean) -> Unit, vararg permissions: String) { 18 | this.request(*permissions) 19 | .subscribe { 20 | listener.invoke(it) 21 | } 22 | this.requestEach() 23 | .subscribe { 24 | 25 | } 26 | } 27 | 28 | /** 29 | * 获取拨打电话权限 30 | */ 31 | fun FragmentActivity.permCallPhone(listener: (granted: Boolean) -> Unit) { 32 | RxPermissions(this).checkPermission(listener, Manifest.permission.CALL_PHONE) 33 | } 34 | 35 | /** 36 | * 获取拨打电话权限 37 | */ 38 | fun Fragment.permCallPhone(listener: (granted: Boolean) -> Unit) { 39 | RxPermissions(this).checkPermission(listener, Manifest.permission.CALL_PHONE) 40 | } 41 | 42 | /** 43 | * 获取读取存储权限 44 | */ 45 | fun FragmentActivity.permStorage(listener: (granted: Boolean) -> Unit) { 46 | RxPermissions(this).checkPermission( 47 | listener, 48 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 49 | Manifest.permission.READ_EXTERNAL_STORAGE 50 | ) 51 | } 52 | 53 | /** 54 | * 获取读取存储权限 55 | */ 56 | fun Fragment.permStorage(listener: (granted: Boolean) -> Unit) { 57 | RxPermissions(this).checkPermission( 58 | listener, 59 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 60 | Manifest.permission.READ_EXTERNAL_STORAGE 61 | ) 62 | } 63 | 64 | /** 65 | * 获取拍照权限 66 | */ 67 | fun FragmentActivity.permCamera(listener: (granted: Boolean) -> Unit) { 68 | RxPermissions(this).checkPermission( 69 | listener, 70 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 71 | Manifest.permission.CAMERA 72 | ) 73 | } 74 | 75 | /** 76 | * 获取拍照权限 77 | */ 78 | fun Fragment.permCamera(listener: (granted: Boolean) -> Unit) { 79 | RxPermissions(this).checkPermission( 80 | listener, 81 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 82 | Manifest.permission.CAMERA 83 | ) 84 | } 85 | 86 | /** 87 | * 获取读取通讯录权限 88 | */ 89 | fun FragmentActivity.permReadContacts(listener: (granted: Boolean) -> Unit) { 90 | RxPermissions(this).checkPermission( 91 | listener, 92 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 93 | Manifest.permission.READ_CONTACTS 94 | ) 95 | } 96 | 97 | /** 98 | * 获取读取通讯录权限 99 | */ 100 | fun Fragment.permReadContacts(listener: (granted: Boolean) -> Unit) { 101 | RxPermissions(this).checkPermission( 102 | listener, 103 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 104 | Manifest.permission.READ_CONTACTS 105 | ) 106 | } 107 | 108 | /** 109 | * 获取发送短信权限 110 | */ 111 | fun FragmentActivity.permSendSMS(listener: (granted: Boolean) -> Unit) { 112 | RxPermissions(this).checkPermission(listener, Manifest.permission.SEND_SMS, Manifest.permission.READ_CONTACTS) 113 | } 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_build.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_android.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lindroy/AndroidUtilsKt/5d6832813a4a0dba7290ad5ef92959f638ea51ab/app/src/main/res/drawable/img_android.jpeg -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_gradient_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_app_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 17 | 18 | 23 | 24 | 29 | 30 | 34 | 35 | 39 | 40 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_brightness.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | 24 | 25 | 26 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_catalog.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_intent.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 |