【问题标题】:Android API level annotation for Android librariesAndroid 库的 Android API 级别注释
【发布时间】:2015-05-30 03:25:25
【问题描述】:

我正在编写一个 Android 库。图书馆中的绝大多数接口都支持Android API level 10或以上。但是,某些功能需要更高的 API 级别。例如,部分库需要用于蓝牙低功耗的 API 18。

为了具体起见,假设该库生成三个类ClassA、ClassB 和ClassC。 ClassA 使用 API 10 中可用的功能,ClassB 使用 API 14 中可用的功能,ClassC 使用 API 18 中可用的功能。

每当有人使用我的库中的类而他们的项目中没有所需的 API 级别(除非他们使用适当的注释抑制警告)时,我希望能够触发 lint 问题(警告/错误),类似于lint 使用的已内置 NewApi 问题。

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

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

2) 创建我自己的注解(例如,@RequireAndroidApi(API_LEVEL) 指示注解的类/方法/等...所需的最低 API 级别)并使用 lint-api.jar (http://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 错误/警告”,或者是否有办法编写一个类似于 api-versions.xml 的单独文件,可以放在项目目录中,可以读取每当在相关项目上运行 lint 时通过 lint(类似于 lint.xml)。

感谢您在对问题的详细描述过程中对我的包容,并提前感谢任何帮助。

【问题讨论】:

  • 你最终为此做了什么?

标签: android android-sdk-tools android-lint


【解决方案1】:

无需创建自己的注解,android 支持库的@RequiresApi 注解就是你要找的。例如:

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

如果在可能具有较低 API 级别的上下文中使用 someMethod(),此注释告诉 lint 发出警告。

请注意,@TargetApi 不同:它用于确保 linter 仅使用目标 API 调用带注释的方法,否则它会警告您不要使用该方法。所以@TargetApi 可以用来消除@RequiresApi 触发的lint 警告。

【讨论】:

  • 谢谢...刚刚注意到这个回复。 RequiresApi 是在 support-annotations v24.0.0 中引入的;在提出原始问题大约一年后。迟到总比没有好,我猜 :)
【解决方案2】:

我最近在一个自定义视图类上做了这个,它需要一些 api 级别的特殊构造函数。

我已经用@TargetApi 注释做到了。

如果方法仅在 api 级别 16 之后可用:

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

这应该可以解决问题,包括 lint 错误。

【讨论】:

  • @TargetApi 注释似乎并未警告调用者 API 级别要求...
  • 没错,TargetApi 注释没有这样做。为了解决这种情况和类似情况,Android 很晚才添加了一个 RequiresApi 注释,正如@yuval 所回答的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 2013-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多