Home Better Android Backward Compatibility Checks πŸ‘
Post
Cancel

Better Android Backward Compatibility Checks πŸ‘

As an android developer, did you ever grew so frustrated with checking the device’s Android OS version when using some Android SDK feature that has different implementations between Android versions? πŸ€”

How many times you had to write this nifty check?

1
2
3
4
5
6
7
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    // do something πŸ™‹β€β™‚οΈ
 } else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // yet do another thing 🫣
 } else {
    // Euhh! do this at last 😩
 }

Should we all agree that this is very ugly, repetitve, error prone and mostly not testeable? Well! luckily our job is to make our job easier πŸ€“

♻️ Let’s transform this garbage into something useful!

Utilities to help you out βš™οΈ

We’ll define for each android SDK level (that we’re using) a utility function that should return a boolean to pass the check of the SDK level

1
2
3
4
5
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.N)
fun isNougatOrAbove(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N

@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.LOLLIPOP)
fun isLollipopOrAbove(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP

Now we can rewrite the previous code as the following:

1
2
3
4
5
when {
    isNougatOrAbove() -> { // do something πŸ™‹β€β™‚οΈ}
    isLollipopOrAbove() -> { // yet do another thing 🫣 }
    else -> { // Euhh! do this at last 😩 }
}

βœ… Done! no need to worry again about the previous ugly syntax, just use the new functions to do the check for you.

Write it, mock it, test it –> PASS βœ…

The rule of πŸ‘ in software engineering is DO NOT EVER TRUST YOUR CODE!

If you ask yourself how can I test this code?

1
2
3
4
5
6
7
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    // do something πŸ™‹β€β™‚οΈ
 } else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // yet do another thing 🫣
 } else {
    // Euhh! do this at last 😩
 }

you will quickly notice that you unfourtunately can’t, well at least not without resorting to Reflection which will definitely make your test FLACKY and in most cases will fail. Simply because mocking final properties in not possible with most of mocking frameworks (i.g: mockito or mockk).

However, mocking the return of a function is πŸ’― possible and also recommended πŸ˜‰. With that in mind testing your code using mockk becomes as easy as the following:

1
2
3
4
5
6
// prepare the toplevel function for static mocking
mockkStatic(::isNougatOrAbove)
// mock the response
every { isNougatOrAbove() } returns true

// assert the code block is called or some expected results are observed

And there you go! I believe now life is much better 😌 And as always happy coding and may the Source be with you!

This post is licensed under CC BY 4.0 by the author.