首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >静态测试技术之 Lint 冗余资源清理

静态测试技术之 Lint 冗余资源清理

原创
作者头像
腾讯移动品质中心TMQ
修改于 2017-06-30 08:59:47
修改于 2017-06-30 08:59:47
2.2K00
代码可运行
举报
运行总次数:0
代码可运行

引言

谈到冗余资源清理,我们不妨先来看看Android的资源组织方式和访问方式。

一、Android资源组织方式及访问方式

新建一个android工程后,默认资源路径res下生成对应的layout、drawable、values等子目录,分别对应以下几类常见的非代码资源:

layout,menu,anim等,代表res资源的顶层使用者,通过xml的方式组合控件,渐变动画等资源,给Activity等组件提供视图,通过这些xml脚本取代代码实现的布局&动效,解耦视图和界面逻辑,提升开发效率;

values,color,xml等,这一类代表res中的文本资源,都是xml格式资源,values主要存放arrays,attrs,colors,dimens,ids,string,integers,theme等基础资源,支持比较丰富的语言扩展;color主要存放返回color资源的selector资源;没有明确归属目录的xml资源,都可以放到xml目录下;

drawable,drawabld-xxx,raw等,这一类代表res中的多媒体资源,有比较丰富分辨率扩展,其中drawable目录主要存放返回drawable格式的selector,带nodpi标签主要存放一些与分辨率无关的9.png资源,其他带xxdpi等目录对应相应的分辨率机型,没有明确归属的非xml资源都可以放到raw目录下。

在资源目录中分类组织资源后,我们就可以通过引用资源 ID 来引用资源,所有资源的ID 都在项目中aapt工具自动生成的./gen/R类中定义,该文件不能被手动修改,当资源发生变动时,它会相应更新。

访问资源的方法主要有两种:

  • 在代码中:R.resource_type.resource_name (引用自定义资源) 或者android.R.resource_type.resource_name(引用系统标准资源),比如R.string.hello,string 是资源类型,hello 是资源名称,API可以通过这种语法来访问定义的资源,如:getResources().getString(R.string.hello);
  • 在 XML 中:使用对应的XML 语法,@[package:]type/name,例如@string/hello,string 是资源类型,hello 是资源名称,可以在 XML 资源通过该语法来访问定义的资源,如:android:text="@string/hello"

二、冗余资源的清理

随着长时间的版本迭代,工程中会冗余许多资源文件,手动查找删除效率太低难免有漏网之鱼,代码扫描工具可以方便的查找出未被引用的图片、ID等资源,本文主要应用Android lint的unUsedResources规则进行冗余资源查找清理。

Android Lint是针对Android的静态代码分析工具,能够对Android项目中潜在的bug、可优化的代码、安全性、性能、可用性、可访问性、国际化等进行检查。

在Android SDKTools 16及更高的版本中,Lint工具会自动安装。通过对Android工程源代码等进行扫描检查,可发现潜在的问题,更好的提升代码质量。

通过lint进行冗余资源清理主要有以下几种方式:

1、我们可以通过lint –check unUsedResources查找冗余资源列表然后手工或者通过其他删除工具加以清理。

2、如果工程使用的是gradle打包,可以在build.gradle中打开shrinkResources开关,这样打包的时候不会把冗余资源打包进来:shrinkResources true //移除无用的resource文件

3、也可以在Android Studio中使用Analyze-unUsedResources项查找出所有未被引用的资源列表:

在结果上右键选择ApplyFix’Android Lint Quick Fixes’,可以直接删除所有无用的资源:

可能存在的误删除与白名单配置 lint扫描工具无法判断出通过反射方式(android.content.res.Resources#getIdentifier)来获取的资源,可能会产生误删除,如:

此时资源被清理后界面上会找不到图片,如果工程中有该用法可以通过以下几种方式对资源添加白名单配置:

1、局部配置:在XML文件中通过tools:ignore="UnusedResources"属性配置忽略:

在xml文件开头声明命名空间tools,并为对应的element加上tools:ignore="UnusedResources "tools:ignore属性对其xml节点的所有子节点都生效:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<string name="string"tools:ignore="UnusedResources">我知道了</string>

2、 全局配置:在Android工程的根目录下创建一个名叫lint.xml的文件,如非xml资源可以通过这种方式添加白名单,IDE会读取根目录下的配置,命令行下可以通过—config指定具体配置,需要注意的是,如果工程根目录下存在lint.xml时,--config命令指定的参数无效:

配置文件中支持几个维度的自定义配置:

(1)规则id级别调整,置为ignore则该规则不生效,如:

(2)路径忽略,如:

(3)正则表达式忽略,如:

三、冗余资源清理原理解析

Lint扫描工具是如何扫描出冗余资源的呢,我们先来认识下LintUnusedResources扫描规则,从源码中规则的定义可以看到,UnusedResourceDetector继承自ResourceXmlDetector和Detector.JavaScanner ,查找范围包括Manifest,资源文件,java源文件及测试代码:

1、根据R.java获取资源列表:

Detetor类中JavaScanner接口定义的getApplicableNodeTypes()需要与createJavaVisitor()配合使用,getApplicableNodeTypes()返回我们感兴趣的Node列表,然后在createJavaVisitor()返回的AstVisitor中去处理这些Node。

定义一个AstVisitor的子类,并在createJavaVisitor()中返回它的一个实例,那么当扫描到符合定义语句对应的node就会触发UnusedResourceVisitor()中对应的回调函数:

2、查找代码中的引用:

Detetor类中JavaScanner接口定义的appliesToResourceRefsh()需要与visitResourceReference()函数配合使用,appliesToResourceRefsh()返回true,那么代码中的资源引用会触发visitResourceReference()处理函数:

3、同样的,查找xml文件中的引用:

4、从收集到的资源声明列表中删除被引用的资源列表并去除xml中声明不做处理(如tools:ignore="UnusedResources")或配置了白名单的资源,剩余的资源列表可认为是冗余资源:

5、report最终未被引用的资源列表:

四、手管的冗余资源清理应用

清楚了lint冗余资源的清理规则,我们可以放(小)心(心)地开始删删删了,谨慎起见,提供本地工具由开发童鞋本地清理确认,同时在持续集成平台自动监控冗余资源清理情况,形成一键清理+自动监控的灵活处理模式:

1、一键清理:在lint扫描结果的基础上提供命令行清理/还原工具,支持本地一键清理:

  • 清理: 调用lint unUsedResources扫描规则生成冗余资源的xml文件,解析该结果xml文件区分文件格式和xml属性格式的资源(资源格式见本文第一节),批量删除两种不同格式的资源,并在执行路径下生成备份路径按res原路径结构备份删除的内容,支持多次循环调用直至冗余资源结果为0。
  • 还原:将备份路径下的文件或xml属性资源还原到原路径,并自动添加到lint白名单。

2、自动监控:在持续集成平台上集成清理工具,输出冗余资源清理前后两个安装包及清理资源集,及时监控项目中的冗余资源情况,也可以直观看到清理带来的优化效果,推动项目组在发布前清理冗余资源。

也附上在手管6.8.1版本代码的清理结果:删除文件资源950+个,其他各类型属性2500+个,包大小缩小2.11M,预计在7.0页面改版可以达到更好的应用效果。

冗余资源清理是借助静态代码分析工具的一个小应用,大家在项目过程中是否有其他静态分析工具应用的场景呢? 欢迎大家一起探讨。

参考资源:

[1] https://developer.android.com/guide/topics/resources/index.html;

[2] Android资源管理-drawable篇;

[3] http://tools.android.com/tips/lint/writing-a-lint-check;

[4] https://android.googlesource.com/platform/tools/base/+/master/lint;

[5] 微桌面Android资源清理工具。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
内网转发及隐蔽隧道 | 使用SSH做端口转发以及反向隧道
SSH开启端口转发需要修改 /etc/ssh/sshd_config配置文件,将 GatewayPorts修改为yes
谢公子
2022/01/19
2.2K0
内网转发及隐蔽隧道 | 使用SSH做端口转发以及反向隧道
ssh代理
ssh隧道技术 1. 用ssh做正向连接 啥叫正向连接?就是client连上server,然后把server能访问的机器地址和端口(当然也包括server自己)镜像到client的端口上。 ssh -L [客户端IP或省略]:[客户端端口]:[服务器侧能访问的IP]:[服务器侧能访问的IP的端口] [登陆服务器的用户名@服务器IP] -p [服务器ssh服务端口(默认22)] 其中,客户端IP可以省略,省略的话就是127.0.0.1了,也就是说只能在客户端本地访问。服务器IP都可以用域名来代替。 举例说明:
小小科
2018/05/02
2.8K0
利用反向ssh从外网访问内网主机
最近遇到一个问题,就是过几天我需要离开学校,而且到时候仍然想登陆校园网里的一台服务器进行工作;但是我又没有校园网网关的操作权限,不能做端口映射,也不能搞到校园网内部主机的外网ip,而且学校自己提供的v**又根本没法用。研究了半天,总算找到了一个比较不错的利用反向ssh(reverse ssh tunnel)进行内网登陆的解决方案。
mythsman
2022/11/14
3.1K0
内网主机从外面连接不了?SSH反向隧道来帮你!
现在我们有一台内网主机 A,在局域网内是可以访问的,但是如果我们现在不处在局域网内,可以选择 V** 连接,但这样其实并不太方便,所以本节我们来说明一下利用 SSH 反向隧道来实现访问内网主机的方法。 准备 首先我们需要有一台公网主机作为跳板,这台主机是可以公网访问的,我们将其命名为 B,它的 IP 假设为 10.10.10.10。 所以两台机器网络配置如下: A 内网机器 IP:192.168.1.2 SSH端口: 22 用户名:usera 密码:passworda 内网配置
崔庆才
2018/06/25
2K0
内网转发及隐蔽隧道 | 端口转发和端口映射
端口映射:端口映射就是将内网中的主机的一个端口映射到外网主机的一个端口,提供相应的服务。当用户访问外网IP的这个端口时,服务器自动将请求映射到对应局域网内部的机器上。比如,我们在内网中有一台Web服务器,但是外网中的用户是没有办法直接访问该服务器的。于是我们可以在路由器上设置一个端口映射,只要外网用户访问路由器ip的80端口,那么路由器会把自动把流量转到内网Web服务器的80端口上。并且,在路由器上还存在一个Session,当内网服务器返回数据给路由器时,路由器能准确的将消息发送给外网请求用户的主机。在这过程中,路由器充当了一个反向代理的作用,他保护了内网中主机的安全
谢公子
2022/01/19
4K1
内网转发及隐蔽隧道 | 端口转发和端口映射
windows端口转发工具_android 端口转发
比如我们在 host2 机器上面部署了很多服务,但是由于某种原因导致我们无法直接 ssh 访问该服务器已经其上服务的对应端口,但是 host3 服务器,既能够访问 host2 服务器,又可以访问我们的 host1 服务器。这时,我们就可以通过设置 ssh 来进行服务的访问。但是还有两个问题:你需要保持终端开启防止 SSH 进程被关闭;由于网络故障/波动导致 SSH 终断时无法自动重连。
全栈程序员站长
2022/11/15
6.4K0
【实战技巧】利用ssh将内网端口反向连接穿透到外网vps
将内网机器的127.0.0.1的8882端口,通过主动连接外网的122.114.250.153的ssh,映射到外网vps的122.114.250.153的7280端口,实现网络穿透.这样访问122.114.250.153的7280就可以相当于直接访问内网的8882端口了.
用户1631416
2020/02/26
5.7K0
用autossh工具进行端口转发
比如我们在host2机器上面部署了很多服务,但是由于某种原因导致我们无法直接ssh访问该服务器已经其上服务的对应端口,但是host3服务器,既能够访问host2服务器,又可以访问我们的 host1 服务器。这时,我们可以通过设置ssh来进行服务的访问。但是还有两个问题:你需要保持终端开启防止SSH进程被关闭;由于网络故障/波动导致SSH终断时无法自动重连。
子润先生
2021/06/17
5.7K0
流量转发映射
客户端无法直接请求服务器,只能将请求发往转发代理服务器(简称代理服务器),代理服务器将请求转发给服务器,接收到服务器响应后再将响应转发回客户端。适用于客户端从内部网络访问外部网络时,可能由于防火墙的存在无法直接访问外网,这时需要借助转发代理服务器访问外部网络
宸寰客
2020/10/10
2.7K0
流量转发映射
【内网渗透】关于内网代理转发技术
有如下图所示测试环境,外网服务器拥有双网卡,既可与公网进行通信,也可以与内网服务器进行通信。
一名白帽的成长史
2020/07/20
2.9K0
【内网渗透】关于内网代理转发技术
内网渗透之各种正反向内网穿透、端口转发(http,socks5)- 渗透红队笔记
在我们拿下一个Webshell的时候,我们没办法把一些工具上传到目标服务器上去使用,那样可能会有风险,而且有的时候还没有特定的环境来使用工具。这个时候我们就可以使用内网穿透来吧服务器的流量代理到本地,就相当于我们是在内网环境,我们就可以使用自己PC上的工具对内网进行扫描,内网渗透,域渗透等等。
渗透攻击红队
2020/11/25
5.4K0
内网渗透之各种正反向内网穿透、端口转发(http,socks5)- 渗透红队笔记
内网渗透 | 内网转发工具的使用
在渗透测试中,当我们获得了外网服务器(如web服务器,ftp服务器,mali服务器等等)的一定权限后发现这台服务器可以直接或者间接的访问内网。此时渗透测试进入后渗透阶段,一般情况下,内网中的其他机器是不允许外网机器访问的。这时候,我们可以通过 端口转发(隧道) 或将这台外网服务器设置成为 代理,使得我们自己的攻击机可以直接访问与操作内网中的其他机器。实现这一过程的手段就叫做内网转发。
谢公子
2022/01/19
2.8K0
内网渗透 | 内网转发工具的使用
SSH加密隧道之端口转发
SSH会自动加密和解密所有SSH客户端与服务端之间的网络数据,还能够将其他TCP端口的网络数据通过SSH连接进行转发,并且自动提供了相应的加密及解密服务,这一过程被叫做“SSH隧道” (tunneling)。
糖果
2020/02/17
4K0
SSH加密隧道之端口转发
[树莓派公网远程监控]autossh反向代理
https://www.cnblogs.com/xiaobaiskill/p/9803867.html
SAnBlog
2020/07/29
1.2K0
内网全局代理工具及特征分析
端口转发是点对点的方式,代理是点对面的方式,如果我们只需要访问主机的特定的端口,使用端口转发就够了,但通常在渗透进内网之后,我们还需要对整个内网进行横向渗透,这时代理必然是一个高校的方法。代理分为正向代理和反向代理,正向代理常适用于外网可以直接访问到web服务器的情况下,反向代理适用于服务器可以出网,但是外部无法直接访问服务器的情况,针对大型企业,现在几乎都是CDN,负载均衡等设备,所以个人认为现在反向代理更常见于渗透攻击中。
FB客服
2019/07/29
1.8K0
可以实现内网穿透的几款工具
最近没什么事情,看了一些关于内网穿透的文章,因我本身已是做微信开发相关的工作,对这部分关注的比较多,现分享给大家。
java思维导图
2018/12/21
8.6K1
可以实现内网穿透的几款工具
内网渗透常用端口转发与代理工具枚举
lcx.exe是一个端口转发工具,有Windows版和Linux版两个版本,Windows版是lcx.exe,Linux版为portmap,
字节脉搏实验室
2020/04/24
3.2K0
内网渗透测试:隐藏通讯隧道技术
上一节中,我们讲解了网络层的隧道技术(IPv6 隧道、ICMP 隧道)和传输层的隧道技术(TCP 隧道、UDP 隧道、常规端口转发)。现如今,TCP、UDP 通信大量被防御系统拦截,传统的Socket隧道也已经濒临淘汰,DNS、ICMP、HTTP/HTTPS 等难以被禁用的协议已经成为了攻击者控制隧道的主要渠道。在这一节中,我们将对应用层的隧道 SOCKS 代理技术进行实验性的讲解,由于小编能力太菜,很多东东也是现学现卖,应用层的DNS隧道我会在未来专门写一个专题进行讲解。
FB客服
2020/07/13
2.5K0
【计网】深入理解NAT机制,内网穿透与内网打洞,代理服务
NAT机制我们在解决IP地址不足的问题中提到过。为了解决IP地址不足的问题,采取了私有IP与公网IP的策略:
叫我龙翔
2024/10/30
6250
【计网】深入理解NAT机制,内网穿透与内网打洞,代理服务
使用frps和frpc实现内网穿透
内网穿透的作用包括跨网段访问一个局域网中的一台主机。 如上图,假设我们想要通过主机 A 访问主机 C,但是主机 A 和主机 C 绑定的都是私有 ip 地址,所以它们之间是无法直接进行通信的。要想使得 A 和 C 能够进行通信,就需要用到内网穿透的技术。 我们可以借助 frps(服务端)和 frpc(客户端)来实现主机 A 对主机 C 的访问。 需要做的是: 在绑定了公网 ip 的主机 B 中配置 frps(服务端) 在主机 C 中配置 frpc(客户端) frps/frpc 的工具包的 github 地
入门笔记
2022/06/03
5.3K0
使用frps和frpc实现内网穿透
推荐阅读
相关推荐
内网转发及隐蔽隧道 | 使用SSH做端口转发以及反向隧道
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档