Android 库的 Android API 级别注解

15

我正在编写一个Android库。大部分接口都支持Android API级别10或更高版本。但是,一些功能需要更高的API级别。例如,库的一部分需要API 18来支持低功耗蓝牙。

为了具体说明,假设该库产生三个类ClassAClassBClassC。其中ClassA使用API 10中可用的功能,ClassB使用API 14中可用的功能,而ClassC则使用API 18中可用的功能。

我想能够在某人在其项目中使用不具备所需API级别的库类时触发一个lint问题(警告/错误) (除非他们使用适当的注释抑制警告),类似于lint使用的内置NewApi问题。

经过搜索,我找到了以下可能的解决方案:

1) 这个解决方案与lint不符:将库分成三个.jar文件,例如包含使用API 10可用功能的所有类(示例中的ClassA)的lib_10.jar,包含使用API 14可用功能的所有类(示例中的ClassB)的lib_14.jar,以及包含使用API 18可用功能的所有类(示例中的ClassC)的lib_18.jar。这个解决方案允许移植性,但会使代码库的后期维护变得复杂,并且可能需要一些代码复制。

2) 创建自己的注释(例如,@RequireAndroidApi(API_LEVEL),表示所需的最低API级别)并使用lint-api.jarhttp://tools.android.com/tips/lint-custom-rules)创建自定义lint规则,检查任何带有低于所需API的注释类/方法等的使用情况。最终将类似于以下内容:

@RequireAndroidApi(10)
Class ClassA {
}

@RequireAndroidApi(14)
Class ClassB {
}

@RequireAndroidApi(18)
Class ClassC {
}
问题在于我找不到Lint API的好文档,而且这似乎是在为一个Lint已经支持的功能(Lint已经检查“NewApi”问题)重新发明轮子。
3)最后,我成功地编辑了<SDK>/platform-tools/api/api-versions.xml,以以下方式指示每个类所需的API级别:
<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>

这导致lint以与Android API相同的方式触发NewApi问题。我喜欢这种解决方案,因为它不会重复造轮子,并且如果出现任何错误,都可以利用Eclipse或Android Studio中编程的建议解决方案来处理问题(例如Eclipse中的“快速修复”)。这种解决方案的问题在于,它需要编辑随Android SDK一起提供的api-versions.xml文件,这使得将该库发布给多个用户时不太容易实现,原因包括:a) api-versions.xml文件不是项目本地文件,而且更改它会影响所有Android项目的lint行为,包括那些不使用该库的项目;b)每次从Android SDK管理器更新SDK时,api-versions.xml都会被覆盖,这将覆盖所有已做出的更改。

我想知道是否有更简单的解决方案来实现“最小API错误/警告”,或者是否有一种类似于lint.xml的单独文件可以放置在项目目录中,每当针对该项目运行lint时,它就会被读取(类似于lint.xml)。

感谢您在解释问题时耐心阅读,预先感谢任何帮助。


你最终为此做了什么? - Adam Johns
2个回答

22

不需要创建自己的注释,Android Support库中的@RequiresApi注释是您要寻找的。例如:

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

这个注解告诉Lint在可能具有更低API级别的上下文中使用someMethod()时发出警告。

请注意,@TargetApi不同:它用于确保linter只调用目标API时才会调用带注释的方法,在否则会警告您不要使用该方法的情况下。因此,@TargetApi可用于消除由@RequiresApi触发的lint警告。


感谢您的回复,我刚刚注意到它。RequiresApi是在support-annotations v24.0.0中引入的,比原始问题提出大约一年。晚来总比不来好,我猜 :) - madmare

1

最近我在自定义视图类上完成了这个任务,需要为某些API级别提供特殊的构造函数。

我使用了@TargetApi注释来完成它。

如果一个方法仅在API级别16及以上可用:

@TargetApi(16)
public void someMethod () {}

这应该能解决问题,包括Lint错误。


4
@TargetApi注解似乎并没有警告调用者所需的API级别要求... - Adam Johns
确实,TargetApi注释并不能解决这个问题。为了解决这种情况以及类似的情况,Android在很久之后添加了RequiresApi注释,正如@yuval所回答的那样。 - madmare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接