preface

I first encountered Kotlin in 2017, before it was fully fledged and not an official Android development language. As for how I got into Amway, if I remember correctly, it was Kotlin’s tutorial in open Source Lab. At that time, few people around me were learning Kotlin, and there was very little information on the Internet. I also translated some of the official website documents and wrote a GitBook. Of course, now there is a better Kotlin Language Chinese site, for those who are not very good at English foundation, this is a good entry material.

Two and a half years later, Kotlin has become the official Android development language. Although it may have been to avoid a lawsuit with Oracle, I’m sure it wasn’t the main reason. Kotlin, defined as Better Java, did Better and became more widely used.

New LeakCanary 2! Completely Based on Kotlin Refactoring upgrade!

Retrofit server! Faster coroutine experience!

A growing number of well-known tripartite libraries are already offering support for Kotlin. Kotlin will also be a priority in Android’s official new features. In addition to Android, Spring 5 officially announced Kotlin as one of its key new features. As far as you can see, Kotlin has a future in the JVM language.

My previous article really smells good! Kotlin+MVVM+LiveData+ Coroutine build Wanandroid! The Kotlin MVVM version of the Wanandroid app has been opened source in China, with a total of 138 stars and 20 forks. Data isn’t stellar, but it’s a big step in my open source career. I am also updating this project all the time. Welcome to continue to pay attention to it.

In my current job, I’ve made Kotlin my first choice, barring some irresistible factors. After working on multiple projects, I found myself copying code from project to project, base classes, extension functions, utility classes, etc. Sometimes it even goes back to old Java code, or Blankj’s AndroidUtilCode, and uses it directly. But a lot of the time, it’s not very elegant and doesn’t make good use of the Kotlin language. I desperately need a generic Kotlin utility class library.

From this, AndroidUtilCodeKTX was born. If you’ve ever used Blankj’s AndroidUtilCode, it’s the same, but it’s not a simple Kotlin translation, it’s more of a Kotlin hybrid, everything from “simple” to less code. Talk is easy, show me the code! Without further ado, the following code shows the use of some utility classes in AndroidUtilCodeKTX.

AndroidUtilCodeKTX

Permission to request

request(Manifest.permission.READ_CALENDAR, Manifest.permission.RECORD_AUDIO) {
    onGranted { toast("onGranted") }
    onDenied { toast("onDenied") }
    onShowRationale { showRationale(it) }
    onNeverAskAgain { goToAppInfoPage() }
}
Copy the code

With extension functions and DSLS, it’s easy to gracefully request permissions and handle callbacks in an Activity. This is not an entirely new wheel, the main code comes from PermissionsKt. But it has a fatal flaw, need a developer manual override a onRequestPermissionsResult () to process the authorization request as a result, it is not so simple and elegant. I’ve borrowed the RxPermissions approach here by attaching the Activity to a Fragment for permission requests and callback processing, which is insensitive to the user and avoids extra code. A separate article will be written to examine the Kotlin DSL in action.

SharedPreferences

putSpValue("int".1)
putSpValue("float".1f)
putSpValue("boolean".true)
putSpValue("string"."ktx")
putSpValue("serialize", Person("Man".3))

getSpValue("int".0)
getSpValue("float".0f)
getSpValue(key = "boolean".default = false)
getSpValue("string"."null")
getSpValue("serialize", Person("default".0))
Copy the code

Basic store and read operations can be done by a single function, relying on generics without actively declaring the type of the value. The default storage file name is called the package name. If you want to customize the file name, declare the name parameter:

putSpValue("another"."from another sp file",name = "another")
getSpValue("another"."null",name = "another")
Copy the code

The Activity related to the

The main thing is to optimize the use of startActivity so that you can start the Activity with a single line of code in any case.

Normal jump:

startKtxActivity<AnotherActivity>()
Copy the code

Jump with flag:

startKtxActivity<AnotherActivity>(Intent.FLAG_ACTIVITY_NEW_TASK)
Copy the code

StartActivityForResult:

startKtxActivityForResult<AnotherActivity>(requestCode = 1024)
Copy the code

Valued jump:

startKtxActivity<AnotherActivity>(value = "string" to "single value")
Copy the code

Jump with multiple values:

startKtxActivity<AnotherActivity>(
                values = arrayListOf(
                    "int" to 1."boolean" to true."string" to "multi value"))Copy the code

Jump with Bundle:

startKtxActivity<AnotherActivity>(
                extra = Bundle().apply {
                    putInt("int".2)
                    putBoolean("boolean".true)
                    putString("string"."from bundle")})Copy the code

Basically covers all Activity jumps.

Aes encryption correlation

ByteArray.aesEncrypt(key: ByteArray, iv: ByteArray, cipherAlgotirhm: String = AES_CFB_NOPADDING): ByteArray
ByteArray.aesDecrypt(key: ByteArray, iv: ByteArray, cipherAlgotirhm: String = AES_CFB_NOPADDING): ByteArray 
File.aesEncrypt(key: ByteArray, iv: ByteArray, destFilePath: String): File?
File.aesDecrypt(key: ByteArray, iv: ByteArray, destFilePath: String): File?
Copy the code

Encapsulates Aes encryption operation, provides fast data and file encryption and decryption method, without paying attention to internal details. AES/CFB/NoPadding is used by default. You can modify the mode with the cipherAlgotirhm parameter.

plainText.toByteArray().aesEncrypt(key, iv, "AES/CBC/PKCS5Padding"
plainText.toByteArray().aesEncrypt(key, iv, "AES/ECB/PKCS5Padding"
plainText.toByteArray().aesEncrypt(key, iv, "AES/CTR/PKCS5Padding"
Copy the code

Hash related

String and ByteArray extension methods for fast hashing.

ByteArray.hash(algorithm: Hash): String
String.hash(algorithm: Hash, charset: Charset = Charset.forName("utf-8")): String
ByteArray.md5Bytes(): ByteArray
ByteArray.md5(): String
String.md5(charset: Charset = Charset.forName("utf-8")): String
ByteArray.sha1Bytes(): ByteArray
ByteArray.sha1(): String
String.sha1(charset: Charset = Charset.forName("utf-8")): String
ByteArray.sha224Bytes(): ByteArray
ByteArray.sha224(): String
String.sha224(charset: Charset = Charset.forName("utf-8")): String
ByteArray.sha256Bytes(): ByteArray
ByteArray.sha256(): String
String.sha256(charset: Charset = Charset.forName("utf-8")): String
ByteArray.sha384Bytes(): ByteArray
ByteArray.sha384(): String
String.sha384(charset: Charset = Charset.forName("utf-8")): String
ByteArray.sha512Bytes(): ByteArray
ByteArray.sha512(): String
String.sha512(charset: Charset = Charset.forName("utf-8")): String
File.hash(algorithm: Hash = Hash.SHA1): String
Copy the code

Supports MD5, SHA1, SHA224, SHA256, SHA384, and SHA512. MD5 is no longer secure and cryptographically no longer recommended.

val origin = "hello"
val md5 = origin.hash(Hash.MD5)
val sha1 = origin.hash(Hash.SHA1)
Copy the code

In addition to string hash, file hash operations are also provided.

val file = File("xxx")
val md5 = file.hash(Hash.MD5)
val sha1 = file.hash(Hash.SHA1)
Copy the code

Intent related

Switch to the application information page:

Context.goToAppInfoPage(packageName: String = this.packageName)
Copy the code

Jump to the Date and Time page:

Context.goToDateAndTimePage()
Copy the code

Jump to the language setting page:

Context.goToLanguagePage()
Copy the code

Jump to the barrier-free service setting page:

Context.goToAccessibilitySetting()
Copy the code

Browser to open the specified page:

Context.openBrowser(url: String)
Copy the code

Install the apk:

// need android.permission.REQUEST_INSTALL_PACKAGES after N
Context.installApk(apkFile: File)
Copy the code

Opening an app in the App Store:

Context.openInAppStore(packageName: String = this.packageName)
Copy the code

Start the App:

Context.openApp(packageName: String)
Copy the code

Uninstall the App :(doesn’t seem to work)

Context.uninstallApp(packageName: String)
Copy the code

The Log related

fun String.logv(tag: String = TAG) = log(LEVEL.V, tag, this)
fun String.logd(tag: String = TAG) = log(LEVEL.D, tag, this)
fun String.logi(tag: String = TAG) = log(LEVEL.I, tag, this)
fun String.logw(tag: String = TAG) = log(LEVEL.W, tag, this)
fun String.loge(tag: String = TAG) = log(LEVEL.E, tag, this)

private fun log(level: LEVEL, tag: String, message: String) {
    when (level) {
        LEVEL.V -> Log.v(tag, message)
        LEVEL.D -> Log.d(tag, message)
        LEVEL.I -> Log.i(tag, message)
        LEVEL.W -> Log.w(tag, message)
        LEVEL.E -> Log.e(tag, message)
    }
}
Copy the code

Tag is KTX by default, or you can specify it yourself.

"abc".logv()
"def".loge(tag = "xxx")
Copy the code

SystemService related

This is how we get system services:

val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
Copy the code

It’s actually pretty neat, but we forgot context.window_service. You can make it more elegant by extending the properties.

val Context.powerManager get() = getSystemService<PowerManager>()

inline fun <reified T> Context.getSystemService(a): T? =
    ContextCompat.getSystemService(this, T::class.java)
Copy the code

For the user, you can just use powerManager without any extra work.

The system services that have been extended as attributes are as follows:

val Context.windowManager
val Context.clipboardManager
val Context.layoutInflater
val Context.activityManager
val Context.powerManager
val Context.alarmManager
val Context.notificationManager
val Context.keyguardManager
val Context.locationManager
val Context.searchManager
val Context.storageManager
val Context.vibrator
val Context.connectivityManager
val Context.wifiManager
val Context.audioManager
val Context.mediaRouter
val Context.telephonyManager
val Context.sensorManager
val Context.subscriptionManager
val Context.carrierConfigManager
val Context.inputMethodManager
val Context.uiModeManager
val Context.downloadManager
val Context.batteryManager
val Context.jobScheduler
Copy the code

App related

Context.versionName: String
Context.versionCode: Long
Context.getAppInfo(apkPath: String): AppInfo
Context.getAppInfos(apkFolderPath: String): List<AppInfo>
Context.getAppSignature(packageName: String = this.packageName): ByteArray?
Copy the code

This section is still relatively small for the time being, but mainly summarizes some common requirements that I have encountered in projects. Get the version number, version name, get the application information from the APK file, get the application signature, etc. In fact, there will be many tool classes related to App, which will be added gradually in the future.

View related

View.visible()
View.invisible()
View.gone()
var View.isVisible: Boolean
var View.isInvisible: Boolean
var View.isGone: Boolean
View.setPadding(@Px size: Int)
View.postDelayed(delayInMillis: Long.crossinline action: () -> Unit): Runnable
View.toBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap
Copy the code

These are some of the more common functions.

Common

Context.dp2px(dp: Float) :Int
Context.px2dp(px: Float) :Int
View.dp2px(dp: Float) :Int
View.px2dp(px: Float) :Int
Context.screenWidth
Context.screenHeight
Context.copyToClipboard(label: String, text: String)
Copy the code

other

RecyclerView.itemPadding(top: Int, bottom: Int, left: Int = 0, right: Int = 0)
ByteArray.toHexString(): String
...... 
Copy the code

use

implementation 'luyao. Util. KTX: AndroidUtilKTX: 0.0.5'
Copy the code

conclusion

That’s what I distilled from the project, and AndroidUtilCodeKTX is just a kid, and it can’t be that perfect. I will continue to update and improve this library. I also hope that you can make more issues and PR and provide your valuable opinions!

I would also like to thank Jie Smart for his email feedback yesterday, which provided me with some suggestions for revision and made me more motivated to continue maintenance. In addition, I will be using the latest version of AndroidUtilCodeKTX on my open source project WanAndroid for the first time. Welcome star, fork!

Article first published wechat public account: Bingxin said, focus on Java, Android original knowledge sharing, LeetCode problem solving.

More relevant knowledge, scan code to pay attention to me!