Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android API level annotation for Android libraries

I am writing an Android library. The vast majority of the interface in the lbirary supports Android API level 10 or above. Some functionality, though, requires a higher API level. For instance, part of the library requires API 18 for Bluetooth Low Energy.

For the sake of concreteness, let's say that the library produces three classes ClassA, ClassB and ClassC. ClassA uses functionality available in API 10, ClassB uses functionality available in API 14 and ClassC uses functionality available in API 18.

I want to be able to trigger a lint issue (warning/error) whenever someone uses a class from my library without having the required API level in their project (unless they suppress the warning with the appropriate annotation), similar to the already built-in NewApi issue used by lint.

After searching, I have found the following possible solutions:

1) This solution isn't along the lines of lint: Split the library into three .jar files, say lib_10.jar that includes all classes using functionality available in API 10 (ClassA in the example), lib_14.jar that includes all the classes using functionality available in API 14 (ClassB in the example) and lib_18.jar that includes all classes using functionality available in API 18 (ClassC in the example). This solution allows portability but would complicate the later maintainability of the codebase and would potentially require some code duplication as well.

2) Create my own annotation (say, @RequireAndroidApi(API_LEVEL) indicating the minimum API level required by the annotated class/method/etc...) and use the lint-api.jar (http://tools.android.com/tips/lint-custom-rules) to create a custom lint rules that check the usage of any annotated classes/methods/etc... with a lower API than required. Something that would later look like this:

@RequireAndroidApi(10)
Class ClassA {
}

@RequireAndroidApi(14)
Class ClassB {
}

@RequireAndroidApi(18)
Class ClassC {
}

The problem is that I couldn't find good documentation for the lint API and it seems that this is reinventing the wheel for a functionality that lint already supports (lint already checks for the "NewApi" issue).

3) Finally, I succeeded to edit <SDK>/platform-tools/api/api-versions.xml in order to indicate the API level required by each class as follows:

<api version="1">
    ...
    <class name="package/path/ClassA" since="10">
        <extends name="java/lang/Object" />
        <method name="&lt;init>()V" />
    </class>
    <class name="package/path/ClassB" since="14">
        <extends name="java/lang/Object" />
        <method name="&lt;init>()V" />
    </class>
    <class name="package/path/ClassC" since="18">
        <extends name="java/lang/Object" />
        <method name="&lt;init>()V" />
    </class>
</api>

Which caused lint to trigger the NewApi issue in the same manner as it would with the Android APIs. I like this type of solution because it doesn't reinvent the wheel and further any errors thrown this way would utilize the suggested solutions programmed in Eclipse or Android Studio to deal with the problem (i.e. "quick fixes" in Eclipse). The problem with this solution is that it requires editing api-versions.xml that ships with the Android SDK, which makes this solution not very portable for releasing the library for several reasons including: a) the api-versions.xml file is not local to a project and changes the behavior of lint for all android projects, including the ones that do not use the library; and b) api-versions.xml will be overwritten every time the SDK is updated from the Android SDK manager which would overwrite any changes made.

I was wondering if there is a simpler solution to achieve this "minimum API errors/warnings" or if there is a way to write a separate file similar to api-versions.xml that can be placed in the project directory which can be read by lint whenever lint is ran on the project in question (something similar to lint.xml).

Thanks for bearing with me during this long description of the problem and I appreciate any help in advance.

like image 868
madmare Avatar asked Mar 26 '15 07:03

madmare


People also ask

What API level should I use Android?

Starting November 1, 2022 if your app doesn't target API level 30 or above, new users with newer Android OS versions won't be able to discover or install your app on Google Play. You can request an extension if you need more time to update your app.

What is minSdkVersion and targetSdkVersion?

android:minSdkVersion — Specifies the minimum API Level on which the application is able to run. The default value is "1". android:targetSdkVersion — Specifies the API Level on which the application is designed to run.


1 Answers

There is no need to create your own annotation, the android support library's @RequiresApi annotation is what you are looking for. For example:

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public void someMethod() {}

This annotation tells lint to warn if someMethod() is used in a context that may have a lower API level.

Note that @TargetApi is different: It's used to assure the linter that the annotated method will only be called with the targeted API, in a situation where it would otherwise warn you not to use that method. So @TargetApi can be used to silence the lint warning triggered by @RequiresApi.

like image 85
yuval Avatar answered Oct 16 '22 12:10

yuval