一、前言
在优化移动端稳定性评测过程中,设定控制特定几个Activity运行monkey是一种提高发现问题效率的方式。那么问题来了,我们如何获取APP完整的Activity List呢?对此,本文简单介绍小编调研和实现的历程,最后使用python脚本实现相关功能。
二、通过什么方式获取Activity
1. adb
adb是我们日常工作每天都会接触的,也是最简单有效。通过adb命令我们可以查看当前手机内应用的包名和Activity信息。常用的命令例如:
adb shell pm list package -f //查看包名
adb shell dumpsys dumpsys activity //查询AMS服务相关信息
adb shell logcat | grep android.intent.category.LAUNCHER //logcat日志抓取LAUNCHE
但是基于我们的需求,在配置参数时,不太可能要先连接手机通过adb查找相关信息。
2. appium
在appium的设置页,设置apk包路径就可以解析获取相关的包名和activity信息,如果之前手动需要临时查看部分信息,这是一种非常不错的方式。
3. 查看源码
查看源码是最直接的方式,有源码,就没有什么看不了的秘密了。
但是并不是所有人都有源码权限。同时,有时候我们需要测试SDK接入第三方应用后的稳定性,也不可能和第三方应用说,请把你的源码给我看看吧。
4.Android APK逆向解析
通过工具对应用市场的APP进行反编译或者逆向工程,可以从APK中获取相关信息(比如清单文件AndroidManifest.xml里面的package、versionName和versionCode等等)。这里大家都了解,在apk中的AndroidManifest.xml是经过编译的,即是二进制格式,如果直接用编辑器打开,显示会是乱码。只有通过APP反编译获取原始的清单文件AndroidManifest.xml,才能对其进行解析就能方便的获取包名,所有activity等信息。
三、确定获取Activity的思路和技术方案
通过对目标和方法的分析,我们确定的大致思路:实现通过任意市场APP的APK文件,都要能获取应用相关的基本信息。那么,通过脚本封装工具反编译获得原始的清单文件AndroidManifest.xml就能解决这件事情了。
问题又来了:业界有哪些反编译和逆向分析工具呢?
1. apktool
apktool是Android领域反编译最常用的开源工具,可以对AndroidAPK直接进行反编译(也可以在反编译得到的目录基础上进行回编,生成apk)
2.jadx
可以将dex文件和apk文件反编译成可阅读的格式,主要涉及java代码和AndroidManifest.xml查看。同时提供了Python binding-PyJadx,方便当时编写python脚本对目标APK进行反编译。
3.ClassyShark
ClassyShark是google官方为Android开发者推出的独立的二进制文件检查工具,因此其权威性和强大毋庸赘言,且得到较好的维护和更新。其github地址为:[https://github.com/google/android-classyshark],其支持多种文件格式的解析,包括:库文件 (.dex, .aar, .so), 可执行文件 (.apk, .jar, .class) 和所有的Android二进制XML格式文件如AndroidManifest, resources, layouts等等。
4. aapt
Android SDK中自带的aapt工具,可以用于解析APK,包括清单文件AndroidManifest.xml中的信息。aapt工具的功能很强大,子命令和参数非常丰富。同时其功能实现不依赖于GUI,可以将其封装进脚本,用于编写自动化工具去解析和执行,这对于构建自动化测试或者自动打包流程等非常有用。
5. AXMLParser
AXMLParser仅仅是用于解析APK里面的二进制AndroidManifest.xml,从而得到与原始工程里的AndroidManifest.xml内容一致的可读xml。较轻量级,适用于只想查看和AndroidManifest.xml里面包含的信息,比如包名package,versionCode和versionName,启动Activity等。
四、代码如何实现Activity的获取
上述的方法均可以满足我们的需求,由于本次需求只是需要获取AndroidManifest.xml进行信息查看和处理就可以,所以这里使用轻量级的AXMLParser完成AndroidManifest.xml的反编译,进而通过对AndroidManifest.xml的解析获取应用所有的Activity。
1.AXMLPrint的python实现 class AXMLPrinter(object):
def __init__(self, raw_buff):
self.axml = AXMLParser(raw_buff)
self.xmlns = False
self.buff = u''
while True andself.axml.is_valid():
_type = self.axml.next()
if _type ==START_DOCUMENT:
self.buff +=u'<?xml version="1.0" encoding="utf-8"?>\n'
elif _type == START_TAG:
self.buff += u'<'+ self.getPrefix(self.axml.getPrefix()) + self.axml.getName() + u'\n'
self.buff += self.axml.getXMLNS()
for i in range(0,self.axml.getAttributeCount()):
self.buff +="%s%s=\"%s\"\n" % (self.getPrefix(
self.axml.getAttributePrefix(i)), self.axml.getAttributeName(i),
self._escape(self.getAttributeValue(i)))
self.buff +=u'>\n'
elif _type == END_TAG:
self.buff +="</%s%s>\n" % (self.getPrefix(self.axml.getPrefix()),self.axml.getName())
elif _type == TEXT:
self.buff +="%s\n" % self.axml.getText()
elif _type ==END_DOCUMENT:
break
解析后的AndroidManifest.xml如下所示 2.应用activity获取的python实现 def get_activities(self):
l = []
for i in self.xml:
for item in self.xml[i].getElementsByTagName("activity"):
value = item.getAttributeNS(NS_ANDROID_URI,"name")
value =self.format_value(value)
l.append(str(value))
return l
Activity 获取结果如下所示:
五、结束语
这里简单介绍使用AXMLParser实现方法,使用其他的方法也可以实现相关需求,大家可以尝试实现。
搜狗测试微信号
搜狗测试QQ粉丝群
本文分享自微信公众号 - 搜狗测试(SogouQA)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。