使用Android lint发现并解决高版本API问题

标签: android lint 发现 | 发表时间:2015-07-25 16:51 | 作者:
出处:http://droidyue.com/

在编写代码时,为了实现一些功能,我们需要使用高版本的API,比如SharedPreference的Editor中的apply方法为API 9开始引入,在API 9 以上的机器使用没有问题,但是在API 8上,如果运行时执行了这段代码,就会崩溃,问题相当严重。尤其是该问题出现在正式版中,后果不堪设想。本文将介绍如何使用lint发现并解决这些问题。

lint是什么

lint是Android提供的一个静态代码分析的工具,使用这个工具可以帮助我们找出Android项目中潜在的bug,安全,性能,可用性,辅助性和国际化等问题,同时还可以查找出错误拼写,提示开发者更正。

lint的工作流程

上图为lint的工作流程图,下面为一些元素的简短说明。

程序源文件

程序源文件就是Android工程的组成部分,包括Java和xml文件,图标以及混淆配置文件

lint.xml文件

lint配置文件,用来排除某些检查或者自定义检测问题的严重程度。

lint工具

一个静态代码扫描工具,对Android工程进行扫描分析,可以从终端执行命令,也可以从Android Studio等IDE中使用。lint工具可以帮助我们找到Android应用性能和代码质量问题。在正式发布应用之前,强烈建议使用lint检查并修复发现的问题。

lint检查结果

lint的检查结果可以从终端,Android Studio等IDE工具,或者生成结果文件查看。每一个问题都会标明在文件中的位置行数,以及关于该问题的说明等信息。

查找问题

知道了lint如何工作,就只需执行lint查找问题,有了明确的问题,才能有的放矢地解决。

Android Sutdio

选择菜单Analyze—>Configure Current File Analysis—>Configure Inspections 清空所有的检查项,然后如下图勾选 Calling new methods on older versionsUsing inlined constants on older versions

然后执行Analyze—> Inspect Code,然后查看底部的Inspection即可

command line

lineos:false
1
2
      cd project_root_dir
lint --check NewApi,InlinedApi --html /tmp/api_check.html ./

无需多时,结果就会以html形式写入/tmp/api_check.html文件

Gradle Command Line

配置build.gradle

lineos:false
1
2
3
4
5
6
7
8
      android{
    //some other config
    lintOptions {
        abortOnError false
        xmlReport false
        check 'NewApi', 'InlinedApi'
    }
}

然后执行下面的命令

lineos:false
1
2
      cd project_root_dir
./gradlew lint

结果会输出到工程目录build/outputs/lint-results.html。

如何解决

结合上面的输出结果,我们接下来要做的就是如何解决,如下为一些解决思路。

必然执行高版本API

  • 如果是NewApi警告,考虑其他方法代替。比如String.isEmpty自API 9才引入,但是使用TextUtils.isEmpty替换。
  • 如果是InlinedApi警告,可以自定义与常量同值的另一个常量。
  • 使用反射,对于不太重要的方法,我们可以使用反射来解决问题。

或然执行高版本API

如果该段代码进行了API Level限制,确保高版本API不会在低版本设置执行,只需对这个警告设置为忽略即可。

实战解决

以下代码所属工程最低支持2.2系统,即API 8。

NewApi有警报代码

lineos:false
1
2
3
      private void testNewApi() {
    PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit().putBoolean("first_use", false).apply();
}

上面代码中的apply方法为Android API 9引入,使用lint检查会提示警告。

方案一

按照API Level不同,选择不同的方法,对于API 9以下使用commit,API 9及其以上使用apply

lineos:false
1
2
3
4
5
6
7
8
9
      private void testNewApi() {
    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
    editor.putBoolean("first_launch", false);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
      editor.apply();
    } else {
      editor.commit();
    }
}

方案二

对于确定不会在低版本运行的情况,我们可以增加@TargetApi加上对应的API引入的版本即可。

lineos:false
1
2
3
4
5
      @TargetApi(Build.VERSION_CODES.GINGERBREAD)
private void testNewApi() {
    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
    editor.putBoolean("first_launch", false).apply();
}

方案三

同样确保新API不会在低版本运行,也可以忽略警报。

lineos:false
1
2
3
4
5
      @SuppressLint("NewApi")
private void testNewApi() {
    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
    editor.putBoolean("first_launch", false).apply();
}

但是这种方案不推荐,是直接对方法的警告忽略,如果继续在方法中增加代码,则不利于发现问题,比如

lineos:false
1
2
3
4
5
6
      @SuppressLint("NewApi")
private void testNewApi() {
    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
    editor.putBoolean("first_launch", false).apply();
    "".isEmpty(); //新增加代码,不容易发现问题
}

含有InlinedApi警告的代码

下面代码过于简单,只是为了打印一个API 19引入的int常量值。

lineos:false
1
2
3
      private void testInlinedApi() {
    Log.i("MainActivity", "inlinedValue=" + View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE);
}

对于这个问题的方案很简答,就是自己定义一个常量,其值与高版本的API常量相同,然后使用这个自定义常量即可。如下代码

lineos:false
1
2
3
4
      private void testInlinedApi() {
    final int VIEW_ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2;
    Log.i("MainActivity", "inlinedValue=" + VIEW_ACCESSIBILITY_LIVE_REGION_ASSERTIVE);
}

小问题

  • 如果没有lint命令,需要将Android中的sdk/tools/目录加入PATH即可。

相关 [android lint 发现] 推荐:

使用Android lint发现并解决高版本API问题

- - 技术小黑屋
在编写代码时,为了实现一些功能,我们需要使用高版本的API,比如SharedPreference的Editor中的apply方法为API 9开始引入,在API 9 以上的机器使用没有问题,但是在API 8上,如果运行时执行了这段代码,就会崩溃,问题相当严重. 尤其是该问题出现在正式版中,后果不堪设想.

Android自定义Lint实践

- - 美团点评技术团队
Android Lint是Google提供给Android开发者的静态代码检查工具. 使用Lint对Android工程代码进行扫描和检查,可以发现代码潜在的问题,提醒程序员及早修正. 为保证代码质量,美团在开发流程中加入了代码检查,如果代码检测到问题,则无法合并到正式分支中,这些检查中就包括Lint.

Android-Lint:查错与代码优化利器

- - 移动开发 - ITeye博客
转自: http://blog.csdn.net/thl789/article/details/8037473. Android-Lint是SDK Tools 16 (ADT 16)之后才引入的工具,通过代码检查,可发现潜在的问题,并能对Android程序进行优化处理. Android-Lint提供了命令行方式执行,还可与IDE(如Eclipse)集成,并提供了html形式的输出报告.

CSS代码检查工具推荐:CSS Lint

- - 标点符
CSS Lint是一个开源的校验CSS文件质量的工具,最初是由 Nicholas C. Zakas和 Nicole Sullivan编写的,最初版本在Velocity会议上于2011年6月发布. CSS Lint的检测规则包括错误的和警告,当选择器或属性书写不正确、漏掉了大括号、多写了分号等时,会提示解析错误,解析错误优先提示.

使用husky + lint-staged助力团队编码规范

- - 掘金前端
husky 是一个为 git 客户端增加 hook 的工具. 安装后,它会自动在仓库中的 .git/ 目录下增加相应的钩子;比如 pre-commit 钩子就会在你执行 git commit 的触发. 那么我们可以在 pre-commit 中实现一些比如 lint 检查、单元测试、代码美化等操作.

谷安: Android Market 网上商店发现后门,赤裸裸的安全漏洞

- Levi - 谷奥聚合——谷奥主站+谷安 aggregator
大家都知道作为 Android 设备用户 Android Market 是必不可少的,它是一个应用下载和购买平台,不过你有没有想过如果有人通过 Android Market 窃取的你的密码信息会怎么样. 黑客现在可以利用一个漏洞绕过简单的密码保护,我们必须要尽可能的小心. 如果黑客窃取了你的 Google 账户密码,他们就可以从世界上的任何地方下载应用到你的设备上,因为现在 Google 可以从云端直接下载应用到你的设备,所以如果有人可以访问你的 Google 账户这意味着它可以随意下载应用到你的设备上.

另一家中国公司被发现在Android固件中植入后门

- - Solidot
在上海广升之后,安全研究人员通过监视手机的流量,发现另一家叫锐嘉科集团有限公司的上海公司也在Android固件中植入后门,受影响的智能手机多达数百万部. 在广升后门曝光之后,Anubis Networks的研究人员购买了一部BLU Studio G廉价手机进行测试,通过捕捉网络流量,他们发现了锐嘉科的后门.

研究发现众多Android VPN应用含有恶意间谍软件

- - Solidot
越来越多的国家开始屏蔽盗版网站,也促使越来越多的人寻找VPN之类的工具绕过屏蔽. 然而对Android用户而言,使用VPN应用需要谨慎,来自澳大利亚和美国的研究人员发现有大量的Android VPN应用含有间谍软件、病毒和其它恶意的广告软件. 在他们分析的283款VPN应用中有38%含有恶意代码,这些应用的下载量有的多达上百万.

Android 遥控车

- CasparZ - LinuxTOY
您确定您真的会用 Android 手机玩赛车. 16 岁的法国学生 Jonathan Rico 使用 Android 手机通过蓝牙实现了对改装玩具汽车的遥控. 操控的方式和那些标榜的智能手机游戏一样,使用重力感应,差别是这次控制的是现实世界中的遥控汽车. 收藏到 del.icio.us |.

Android免费?毛

- Ruby - FeedzShare
来自: 36氪 - FeedzShare  . 发布时间:2011年08月17日,  已有 2 人推荐. 微软CEO Steve Ballmer在预测竞争对手产品时通常口无遮拦. 比如他去年抨击Google的Android战略时,很多人都不屑一顾. 接着Android蚕食了微软的地盘,后来又开始侵犯苹果的地盘.