Skip to content

Instantly share code, notes, and snippets.

@rock3r
Created October 5, 2017 16:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rock3r/f62c5330de539c9bd36558106fd62200 to your computer and use it in GitHub Desktop.
Save rock3r/f62c5330de539c9bd36558106fd62200 to your computer and use it in GitHub Desktop.
Testable Kotlin Android OS version checker, with tests

How to use the checker

Java

import static me.seebrock3r.utils.VersionChecker.android;

if (android().isLollipopOrLater()) {
  // ...
}

// OR

switch (android().sdkVersion()) {
  case Build.SDK_INT.O:
    //...
    break;
  case Build.SDK_INT.LOLLIPOP:
    //...
    break;
  default:
    //...
    break;
}

Kotlin

import me.seebrock3r.utils.android 

if (android.isLollipopOrLater()) {
  // ...
}

// OR

when (android.sdkVersion) {
  Build.SDK_INT.O -> //...
  Build.SDK_INT.LOLLIPOP -> //...
  else -> //...
}
package me.seebrock3r.utils
import android.os.Build.VERSION_CODES.JELLY_BEAN_MR1
import android.os.Build.VERSION_CODES.JELLY_BEAN_MR2
import android.os.Build.VERSION_CODES.KITKAT
import android.os.Build.VERSION_CODES.LOLLIPOP
import android.os.Build.VERSION_CODES.LOLLIPOP_MR1
import android.os.Build.VERSION_CODES.M
import android.os.Build.VERSION_CODES.N
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
// Notes: these are JVM Junit 4.12 tests. The assertions require AssertJ, or Truth. Pick your poison, just tweak the imports.
@RunWith(Parameterized::class)
class AndroidOSVersionCheckerTest(private val checker: OSVersionChecker, private val currentSdkVersion: Int) {
companion object {
@Parameterized.Parameters(name = "{index}: SDK_INT {1}")
@JvmStatic
fun data(): Collection<Array<Any>> {
return listOf(
arrayOf(AndroidOSVersionChecker(JELLY_BEAN_MR1), JELLY_BEAN_MR1),
arrayOf(AndroidOSVersionChecker(JELLY_BEAN_MR2), JELLY_BEAN_MR2),
arrayOf(AndroidOSVersionChecker(KITKAT), KITKAT),
arrayOf(AndroidOSVersionChecker(LOLLIPOP), LOLLIPOP),
arrayOf(AndroidOSVersionChecker(LOLLIPOP_MR1), LOLLIPOP_MR1),
arrayOf(AndroidOSVersionChecker(M), M),
arrayOf(AndroidOSVersionChecker(N), N),
arrayOf(AndroidOSVersionChecker(N_MR1), N_MR1),
arrayOf(AndroidOSVersionChecker(O), O)
)
}
}
@Test
fun `should report correct SDK version`() {
assertThat(checker.sdkVersion).isEqualTo(currentSdkVersion)
}
@Test
fun `should detect correctly if Oreo or later`() {
assertThat(checker.isAtLeastOreo).isEqualTo(currentSdkVersion >= O)
}
@Test
fun `should detect correctly if NougatMR1 or later`() {
assertThat(checker.isAtLeastNougatMR1).isEqualTo(currentSdkVersion >= N_MR1)
}
@Test
fun `should detect correctly if Nougat or later`() {
assertThat(checker.isAtLeastNougat).isEqualTo(currentSdkVersion >= N)
}
@Test
fun `should detect correctly if Marshmallow or later`() {
assertThat(checker.isAtLeastMarshmallow).isEqualTo(currentSdkVersion >= M)
}
@Test
fun `should detect correctly if LollipopMR1 or later`() {
assertThat(checker.isAtLeastLollipopMR1).isEqualTo(currentSdkVersion >= LOLLIPOP_MR1)
}
@Test
fun `should detect correctly if Lollipop or later`() {
assertThat(checker.isAtLeastLollipop).isEqualTo(currentSdkVersion >= LOLLIPOP)
}
@Test
fun `should detect correctly if KitKat or later`() {
assertThat(checker.isAtLeastKitKat).isEqualTo(currentSdkVersion >= KITKAT)
}
@Test
fun `should detect correctly if JellyBeanMR2 or later`() {
assertThat(checker.isAtLeastJellyBeanMR2).isEqualTo(currentSdkVersion >= JELLY_BEAN_MR2)
}
@Test
fun `should detect correctly if JellyBeanMR1 or later`() {
assertThat(checker.isAtLeastJellyBeanMR1).isEqualTo(currentSdkVersion >= JELLY_BEAN_MR1)
}
}
@file:JvmName("VersionChecker")
package me.seebrock3r.utils
import android.annotation.SuppressLint
import android.os.Build
import android.support.annotation.VisibleForTesting
val android: OSVersionChecker
@SuppressLint("VisibleForTests") // Accessing it as private would be correct here, probably a Lint bug with Kotlin visibilities
@JvmName("android")
get() = AndroidOSVersionChecker()
interface OSVersionChecker {
val sdkVersion: Int
val isAtLeastOreo: Boolean
val isAtLeastNougatMR1: Boolean
val isAtLeastNougat: Boolean
val isAtLeastMarshmallow: Boolean
val isAtLeastLollipop: Boolean
val isAtLeastLollipopMR1: Boolean
val isAtLeastKitKat: Boolean
val isAtLeastJellyBeanMR2: Boolean
val isAtLeastJellyBeanMR1: Boolean
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal class AndroidOSVersionChecker(sdkVersionInt: Int = Build.VERSION.SDK_INT) : OSVersionChecker {
override val sdkVersion = sdkVersionInt
override val isAtLeastOreo = sdkVersionInt >= Build.VERSION_CODES.O
override val isAtLeastNougatMR1 = sdkVersionInt >= Build.VERSION_CODES.N_MR1
override val isAtLeastNougat = sdkVersionInt >= Build.VERSION_CODES.N
override val isAtLeastMarshmallow = sdkVersionInt >= Build.VERSION_CODES.M
override val isAtLeastLollipopMR1 = sdkVersionInt >= Build.VERSION_CODES.LOLLIPOP_MR1
override val isAtLeastLollipop = sdkVersionInt >= Build.VERSION_CODES.LOLLIPOP
override val isAtLeastKitKat = sdkVersionInt >= Build.VERSION_CODES.KITKAT
override val isAtLeastJellyBeanMR2 = sdkVersionInt >= Build.VERSION_CODES.JELLY_BEAN_MR2
override val isAtLeastJellyBeanMR1 = sdkVersionInt >= Build.VERSION_CODES.JELLY_BEAN_MR1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment