While working on an Android app, I found an interesting annotation called @ChecksSdkIntAtLeast
. I had no idea this annotation existed under the androidx.annotation
package. I got curious and started looking into how it works.
Simple way
It looks like the most simplest way of using this annotation is to use api
parameters like so (source):
@ChecksSdkIntAtLeast(api = Build. VERSION_CODES. O)
public static boolean isAtLeastO() {
return Build. VERSION. SDK_INT >= 26;
}
But I thought maybe we can reuse this into class and able to inject places where we need to.
Classy way
To make this logic somewhat reusable, I created an interface and its concrete implementation:
interface DeviceVersion {
@ChecksSdkIntAtLeast(parameter = 0)
fun isAtLeast(osLevel: Int): Boolean
}
class RealDeviceVersion : DeviceVersion {
override fun isAtLeast(osLevel: Int): Boolean {
return Build.VERSION.SDK_INT >= osLevel
}
}
Here, the DeviceVersion interface provides a method isAtLeast(osLevel: Int)
has the @ChecksSdkIntAtLeast
while RealDeviceVersion
has the OS level checking logic. When injected linter will understand that DeviceVersion#isAtLeast
has done the appropriate OS level checking logic. (Probably a good idea to add some unit tests around here! 👀)
Practical (sort of...) Example
Imagine you have a class that includes methods restricted to certain API levels, like this (Apology for the class/method names):
class SomeAPIRestrictedMethodClass {
@RequiresApi(34)
fun fooFor34() {
// Some operation requires SDK 30
}
fun fooForAll() {
// Some operation for all SDK
}
}
When calling fooFor34
method which can only be used for API 34 or above, you would typically do a check like this:
if (Build.VERSION.SDK_INT > 34) {
someAPIRestrictedMethodClass.fooFor34()
}
With the DeviceVersion interface, you can achieve the same result more cleanly:
if (deviceVersion.isAtLeast(34)) {
someAPIRestrictClass.fooFor34()
}
This approach could help with the unit testing if you somehow can't run AndroidTestRunner or RobolectricTestRunner for some classes/methods. Plus, the linter doesn't seem to complain about this usage!
I just found this super interesting annotation since I have not seen it before. I hope you enjoyed learning about this as much as I did. If you have encountered unique annotations feel free to share them on the comment section and have a great day!
🧀
Top comments (0)