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)