SDK(Software Development Kit)软件开发工具包。被软件开发工程师用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合。Android是Google公司推出的手机开发平台。Android-sdk就是指Android专属的软件开发工具包。Android-sdk中我们最常用的就是tools和Platform-tools文件夹中的工具。tools包含调试和测试的工具如常用的自动化工具MonkeyRunner,抓log的工具ddms,查看包名和坐标的工具hierarchyviewer.bat。platform-tools包含一些开发工具和一些应用程序的调试工具如adb.exe和fastboot.exe
2. DDMS
DDMS全称:Dalvik Debug Monitor Service, 它可以提供诸如:为测试设备截屏、针对特定的进程查看正在运行的线程和堆的信息,logcat,广播状态信息,模拟来电呼叫和短信,虚拟地理坐标等等。注:更多详情可参考http://developer.android.com/tools/debugging/ddms.html。
1) DDMS怎样工作
每一个Android应用都运行在一个Dalvik虚拟机实例里,而每一个虚拟机实例都是一个独立的进程空间。虚拟机的线程机制,内存分配和管理,Mutex等等都是依赖底层操作系统而实现的。所有Android应用的线程都对应一个Linux线程,虚拟机因而可以更多的 依赖操作系统的线程调度和管理机制。 DDMS在IDE与设备或模拟器之间的起着中间人的角色。
DDMS启动时会与ADB之间建立一个device monitoring service用于监控设备。当设备断开或链接时,这个service就会通知DDMS。当一个设备链接上时,DDSM和ADB之间又会建立VM monitoring service用于监控设备上的虚拟机。 通过ADB Deamon与设备上的虚拟机的debugger建立链接,这样DDMS就开始与虚拟机对话了。
对于设备上每个虚拟机的debugger, DDMS都会开启一个监听端口。端口从8600开始。
2) 如何启动 DDMS
DDMS 工具存放在SDK – tools/路径下,采用下面两种方式启动DDMS均可:
1. 直接双击ddms.bat运行:
2. 在Eclipes调试程序的过程中启动DDMS,如下图所示。启动后,右侧窗口显示DDMS:
DDMS对Emulator和外接测试机有同等效用。如果系统检测到它们(VM)同时运行,那么DDMS将会默认指向 Emulator。
3) DDMS的一些功能
Devices:在GUI的左上角可以看到标签为”Devices”的面板,这里可以查看到所有与DDMS连接的终端的详细信息,以及每个终端正在运行的APP进程,每个进程最右边相对应的是与调试器链接的端口。因为Android是基于Linux内核开发的操 作平台,同时也保留了Linux中特有的进程ID,它介于进程名和端口号之间。在面板的右上角有一排很重要的按键他们分别是Debug the selected process、Update Threads、Update Heap、Stop Process和ScreenShot。
Emulator Control:通过这个面板的一些功能可以非常容易的使测试终端模拟真实手机所具备的一些交互功能,比如:接听电话,根据选项模拟各种不同网络情况,模拟接受SMS消息和发送虚拟地址坐标用于测试GPS功能等。
Telephony Status: 通过选项模拟语音质量以及信号连接模式。
Telephony Actions: 模拟电话接听和发送SMS到测试终端。
Location Control: 模拟地理坐标或者模拟动态的路线坐标变化并显示预设的地理标识,可以通过以下3种方式:
Manual: 手动为终端发送二维经纬坐标。
GPX: 通过GPX文件导入序列动态变化地理坐标,从而模拟行进中GPS变化的数值。
KML: 通过KML文件导入独特的地理标识,并以动态形式根据变化的地理坐标显示在测试终端。Threads、Heap、File Exporler这几项,我们在其他开发工具中也经常使用,就在不此详细说明了。通过File Exporler可以查看Android模拟器中的文件,可以很方便的导入/出文件。
Locate:显示输出的调试信息,详见Android下如何调试程序;
Console:是Android模拟器输出的信息,加载程序等信息;单击新短信,详细查看短信内容:中文显示为乱码,在未来的开发中,我们必须要注意中文字符的问题。
3. 在DDMS里检查heap的使用情况
1) 在左边的面板选择进程com.example.android.hcgallery,然后在 工具条上边点击Show heap updates按钮。这个时候切换到DDMS的VM Heap分页。它会显示每次gc后heap内存的一些基本数据。要看第一次gc后的数据内容,点击Cause GC按钮,请求一次之后就不用再次点击该按钮了,因为Heap会刷新页面,来显示当前的内存的变化。
2) 分析数据:
DDMS 中使用Heap视图来分析的话,基本上就查看1个数据
在Data object 中有叫Total Size的数据。具体的含义就是当前进程中Java的对象所占用的内存总量。
3) 判断依据:
一般情况下我的分析是这样的:
i. 不断在手机上操作一个功能,如果该数据在不断地增加,则判定该功能模块存在内存泄露问题。
ii. 如果反复操作该功能之后,有一定范围的起伏,但是又被稳定在某一个有限的范围内,则说明代码良好。
iii. 如果有效内存手机,可能会出现程序被kill,但是程序被kill并不能代表程序一定有内存泄露。
4. 实验一 —— 半自动检测出的内存泄漏
注:打开DDMS的时候,不能同时打开eclipse中的logcat查看真机,否则DDMS无法连接真机
在本实验中,反复切换如下两个页面(公司内部APP,就不公开啦~~~,特点是:有上传头像哦~~~)。通过DDMS观察到Total Size不断增加,怀疑有内存泄漏。使用Monkeyrunner + Python执行上述动作。
步骤一:手动生成执行测试次数文本文件。如,在脚本程序所在目录下新建num.txt,写入执行次数(如,100)。
步骤二:编写如下代码。
#Import package
import sys
from com.android.monkeyrunner import MonkeyRunner as mr
from com.android.monkeyrunner import MonkeyDevice as md
from com.android.monkeyrunner import MonkeyImage as mi
#Define the numbers of execution
def exec_num(num):
while( num > 0 ):
num = num - 1
device.touch(360,1029,'DOWN_AND_UP')
mr.sleep(7.0)
device.touch(45,96,'DOWN_AND_UP')
mr.sleep(5.0)
if __name__ == '__main__':
# Connect device
device = mr.waitForConnection()
print 'device is connected.'
if not device:
print >> sys.stderr,"fail"
sys.exit(1)
# Read the file which includes numbers of execution
try:
fp = open('num.txt','r')
num = int(fp.read())
print "num is:",num
finally:
if fp:
fp.close()
# Begin to run exec_num function
print "exec_num is beginning..."
exec_num(num)
print 'finish'
执行结果:(未来得及保存DDMS上的截图,执行约200次页面切换动作后,Total Size增至40MB,APP crash)
改进点:
1. 由于不清楚是否Monkeyrunner不支持交互,因此不能通过CMD输入执行测试次数的方式进行,只能通过文件读取。
2. 执行次数文件的生成可以改为自动生成。但文件中的内容输入可能同样涉及问题1
3. 由于不清楚动作执行后页面反应时间,因此代码中只是凭经验预估的时间
4. 若遇到程序意外终止,没有增加异常捕获代码和执行次数的打印