Android快速入门教程(图解)——Monkey工具.doc_第1页
Android快速入门教程(图解)——Monkey工具.doc_第2页
Android快速入门教程(图解)——Monkey工具.doc_第3页
Android快速入门教程(图解)——Monkey工具.doc_第4页
Android快速入门教程(图解)——Monkey工具.doc_第5页
免费预览已结束,剩余11页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android快速入门教程(图解)Monkey工具文章目录:一、Monkey简介二、Monkey的基本用法三、Monkey测试示例图解四、Monkey命令参数介绍五、Monkey log分析一、Monkey简介Monkey:Android中的一命令行工具,压力测试软件稳定性和健壮性特点: 1.测试对象为程序包,有一定局限性 2.伪随机事件,不能自定义 3.可对事件数量、类型、频率设置以下内容来自:猴子的来源:至于Monkey的名字是有何而来的呢?这个没有去怎么考究,Monkey这个工具就是一个调皮的猴子,在App中乱按、乱摸、乱滚、乱跳。Monkey测试是Android平台下自动化测试的一种快速有效的手段,通过Monkey工具可以模拟用户触摸屏幕、滑动轨迹球、按键等操作来对模拟器或者手机设备上的软件进行压力测试,检测该软件的稳定性、健壮性。它的原理是向系统发送伪随机的用户事件流(如按键输入、触摸输入、手势输入等),实现对正在开发的应用程序进行压力测试。 注:MonkeyRunner官方文档的网址/guide/developing/tools/monkeyrunner_concepts.html二、Monkey的基本用法 基本语法如下: $ adb shell monkey options 如果不指定options,Monkey将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部包。下面是一个更为典型的命令行示例,它启动指定的应用程序,并向其发送1000个伪随机事件: $ adb shell monkey -p -v number $ monkey -p(package的意思) 指定文件名-v(测试的次数和频率)number(次数)三、Monkey测试示例图解通过简单的测试示例,初步了解并掌握Monkey测试的步骤。注意,这里主要是使用adb命令进行安装和相关操作。测试的具体参考步骤如下: (1)首先,先准备了一个测试用的应用程序(apk文件)。为了测试,这里选择了一个格瓦拉手机购票App进行测试。下载地址为:/mobile/mobileMovie.xhtml。 下载好后,得到下图所示的apk文件。 (2)将apk文件复制到android sdk对应platform-tools的目录下。例如,笔者的sdk路径为D:androidandroid-sdk-windowsplatform-tools。如图所示 (3)进行apk文件的安装(安装的前提是,已经启动并可以检测模拟器):有安装91助手或者豌豆的用户可以直接双击apk文件进行安装;也可以使用android下的adb命令进行安装(如下图所示,Success表示安装成功)。adb命令下安装apk文件的命令为:adb install文件名.apk。(4)安装好后,会在模拟器上看到应用程序的启动图标 (5)安装好apk文件后,需要知道应用程序主Activity(第一个启动的Activity)所在的包名。方法(获取顶级包名的方法):在C盘根目录新建log.txt,接着输入cmd启动控制台,在控制台中输入:adb logcatC:/log.txt,然后点击模拟器已经安装好的APK图标一下,然后打开控制台,点击ctrl+C;接着找到log.txt文件,打开文件,按下快捷键CTRL+F在文件中查找“I/Activity”关键字,找到有“Displayed ”关键字的后面就是包名。(知道了apk的包名,我们也可以利用adb命令进行应用程序的卸载;卸载apk文件的命令为:adb uninstall包名)(6)这里是最关键的一步,使用moneky命令进行自动化压力测试。adb shell monkey options 命令为:#monkey -p com.gewara -v 1000(参数说明:-p后跟着软件所在包名,-v后跟测试的次数)。这里对该软件进行1000次的自动化测试,几分钟内即可以完成测试。如图所示 (7)测试完毕,发现程序出错了。程序出错,表明该软件的稳定性和健壮性还有待提高。 这时,可以打开Lotcat查看出错信息。如图所示四、Monkey命令参数介绍要获取Monkey命令自带的简单帮助,在CMD中执行命令:adb shell monkey help1)参数:-p参数-p用于约束限制,用此参数指定一个或多个包(Package,即App)。指定包之后,Monkey将只允许系统启动指定的APP。如果不指定包,Monkey将允许系统启动设备中的所有APP。*指定一个包:adb shell monkey -p com.htc.Weather100说明:com.htc.Weather为包名,100是事件计数(即让Monkey程序模拟100次随机用户事件)。*指定多个包:adb shell monkey -p com.htc.Weather p com.htc.pdfreader-p com.htc.photo.widgets 100*不指定包:adb shell monkey 100说明:Monkey随机启动APP并发送100个随机事件。*要查看设备中所有的包,在CMD窗口中执行以下命令:adb shell#cd data/data#ls2)参数:-v用于指定反馈信息级别(信息级别就是日志的详细程度),总共分3个级别,分别对应的参数如下表所示:日志级别Level 0示例adb shell monkey -p com.htc.Weather v 100说明缺省值,仅提供启动提示、测试完成和最终结果等少量信息日志级别Level 1示例adb shell monkey -p com.htc.Weather v -v 100说明提供较为详细的日志,包括每个发送到Activity的事件信息日志级别Level 2示例adb shell monkey -p com.htc.Weather v -v v 100说明最详细的日志,包括了测试中选中/未选中的Activity信息3)参数:-s用于指定伪随机数生成器的seed值,如果seed相同,则两次Monkey测试所产生的事件序列也相同的。*示例:Monkey测试1:adb shell monkey -p com.htc.Weather s 10 100Monkey测试2:adb shell monkey -p com.htc.Weather s 10 100两次测试的效果是相同的,因为模拟的用户操作序列(每次操作按照一定的先后顺序所组成的一系列操作,即一个序列)是一样的。操作序列虽然是随机生成的,但是只要我们指定了相同的Seed值,就可以保证两次测试产生的随机操作序列是完全相同的,所以这个操作序列伪随机的;4)参数:-throttle 用于指定用户操作(即事件)间的时延,单位是毫秒;*示例:adb shell monkey -p com.htc.Weather throttle 3000 1005)参数:-ignore-crashes用于指定当应用程序崩溃时(Force & Close错误),Monkey是否停止运行。如果使用此参数,即使应用程序崩溃,Monkey依然会发送事件,直到事件计数完成。*示例1:adb shell monkey -p com.htc.Weather -ignore-crashes 1000测试过程中即使Weather程序崩溃,Monkey依然会继续发送事件直到事件数目达到1000为止;*示例2:adb shell monkey -p com.htc.Weather 1000测试过程中,如果Weather程序崩溃,Monkey将会停止运行。6)参数:-ignore-timeouts用于指定当应用程序发生ANR(Application No Responding)错误时,Monkey是否停止运行。如果使用此参数,即使应用程序发生ANR错误,Monkey依然会发送事件,直到事件计数完成。7)参数:-ignore-security-exceptions用于指定当应用程序发生许可错误时(如证书许可,网络许可等),Monkey是否停止运行。如果使用此参数,即使应用程序发生许可错误,Monkey依然会发送事件,直到事件计数完成。8)参数:-kill-process-after-error用于指定当应用程序发生错误时,是否停止其运行。如果指定此参数,当应用程序发生错误时,应用程序停止运行并保持在当前状态(注意:应用程序仅是静止在发生错误时的状态,系统并不会结束该应用程序的进程)。9)参数:-monitor-native-crashes用于指定是否监视并报告应用程序发生崩溃的本地代码。10)参数:-pct-+事件类别+事件类别百分比用于指定每种类别事件的数目百分比(在Monkey事件序列中,该类事件数目占总事件数目的百分比)参数:使用说明:示例:-pct-touch+百分比调整触摸事件的百分比(触摸事件是一个down-up事件,它发生在屏幕上的某单一位置)adb shell monkey -p com.htc.Weather -pct-touch 10 1000-pct-motion+百分比调整动作事件的百分比(动作事件由屏幕上某处的一个down事件、一系列的伪随机事件和一个up事件组成)adb shell monkey -pcom.htc.Weather -pct-motion 20 1000-pct-trackball+百分比调整轨迹事件的百分比(轨迹事件由一个或几个随机的移动组成,有时还伴随有点击)adb shell monkey -p com.htc.Weather -pct-trackball 30 1000-pct-nav+百分比调整“基本”导航事件的百分比(导航事件由来自方向输入设备的up/down/left/right组成)adb shell monkey -p com.htc.Weather -pct-nav 40 1000-pct-majornav+百分比调整“主要”导航事件的百分比(这些导航事件通常引发图形界面中的动作,如:5-way键盘的中间按键、回退按键、菜单按键)adb shell monkey -p com.htc.Weather -pct-majornav 50 1000-pct-syskeys+百分比调整“系统”按键事件的百分比(这些按键通常被保留,由系统使用,如Home、Back、Start Call、End Call及音量控制键)adb shell monkey -p com.htc.Weather -pct-syskeys 60 1000-pct-appswitch+百分比调整启动Activity的百分比。在随机间隔里,Monkey将执行一个startActivity()调用,作为最大程度覆盖包中全部Activity的一种方法adb shell monkey -p com.htc.Weather -pct-appswitch 70 1000-pct-anyevent+百分比调整其它类型事件的百分比。它包罗了所有其它类型的事件,如:按键、其它不常用的设备按钮、等等adb shell monkey -p com.htc.Weather-pct -anyevent 100 1000*指定多个类型事件的百分比:adb shell monkey -p com.htc.Weather -pct-anyevent 50 -pct-appswitch 50 1000注意:各事件类型的百分比总数不能超过100%;测试语句如:adb -s emulator-5556 shell monkey -p 包名-v 10000adb -s emulator-5556 shell monkey -p com.soft0754.android -vvv 10000 C:/log.txt-v 为 verbose的缩写,就是详细输出事件等级,这个3个v就是输出等级1至3的所有事件,然后再使用管道命令将输出结果放到一个文本里面方便查看.接下来就是看你的程序能不能在这样的折腾下坚持下去了.五、Monkey log分析(内容来自)Log 在android中的地位非常重要,要是作为一个android程序员不能过分析log这关,算是android没有入门吧。下面我们就来说说如何处理log文件 。(1)什么时候会有Log文件的产生 ?Log的产生大家都知道 , 大家也都知道通过DDMS来看log , 但什么时候会产生log文件呢 ?一般在如下几种情况会产生log文件 。1. 程序异常退出 , uncaused exception2. 程序强制关闭 ,Force Closed (简称FC)3. 程序无响应 , Application No Response (简称ANR) , 顺便,一般主线程超过5秒么有处理就会ANR4. 手动生成 。拿到一个日志文件,要分成多段来看 。 log文件很长,其中包含十几个小单元信息,但不要被吓到 ,事实上他主要由三大块儿组成 。1,系统基本信息 ,包括 内存,CPU ,进程队列 ,虚拟内存 , 垃圾回收等信息 。- MEMORY INFO (/proc/meminfo) - CPU INFO (top -n 1 -d 1 -m 30 -t) - PROCRANK (procrank) - VIRTUAL MEMORY STATS (/proc/vmstat) - VMALLOC INFO (/proc/vmallocinfo) -格式如下:- MEMORY INFO (/proc/meminfo) -MemTotal: 347076 kBMemFree: 56408 kBBuffers: 7192 kBCached: 104064 kBSwapCached: 0 kBActive: 192592 kBInactive: 40548 kBActive(anon): 129040 kBInactive(anon): 1104 kBActive(file): 63552 kBInactive(file): 39444 kBUnevictable: 7112 kBMlocked: 0 kBSwapTotal: 0 kBSwapFree: 0 kBDirty: 44 kBWriteback: 0 kBAnonPages: 129028 kBMapped: 73728 kBShmem: 1148 kBSlab: 13072 kBSReclaimable: 4564 kBSUnreclaim: 8508 kBKernelStack: 3472 kBPageTables: 12172 kBNFS_Unstable: 0 kBBounce: 0 kBWritebackTmp: 0 kBCommitLimit: 173536 kBCommitted_AS: 7394524 kBVmallocTotal: 319488 kBVmallocUsed: 90752 kBVmallocChunk: 181252 kB2,时间信息 , 也是我们主要分析的信息 。- VMALLOC INFO (/proc/vmallocinfo) - EVENT INFO (/proc/vmallocinfo) -格式如下:- SYSTEM LOG (logcat -b system -v time -d *:v) -01-15 16:41:43.671 W/PackageManager( 2466): Unknown permission com.wsomacp.permission.PROVIDER in package com.android.mms01-15 16:41:43.671 I/ActivityManager( 2466): Force stopping package com.android.mms uid=1009201-15 16:41:43.675 I/UsageStats( 2466): Something wrong here, didnt expect com.sec.android.app.twlauncher to be paused01-15 16:41:44.108 I/ActivityManager( 2466): Start proc alarm for service alarm/.engine.DataService: pid=20634 uid=10005 gids=3003, 1015, 300201-15 16:41:44.175 W/ActivityManager( 2466): Activity pause timeout for HistoryRecord48589868 com.sec.android.app.twlauncher/.Launcher01-15 16:41:50.864 I/KeyInputQueue( 2466): Input event01-15 16:41:50.866 D/KeyInputQueue( 2466): screenCaptureKeyFlag setting 001-15 16:41:50.882 I/PowerManagerService( 2466): Ulight 0-7|001-15 16:41:50.882 I/PowerManagerService( 2466): Setting target 2: cur=0.0 target=70 delta=4.6666665 nominalCurrentValue=001-15 16:41:50.882 I/PowerManagerService( 2466): Scheduling light animator!01-15 16:41:51.706 D/PowerManagerService( 2466): enableLightSensor true01-15 16:41:51.929 I/KeyInputQueue( 2466): Input event01-15 16:41:51.933 W/WindowManager( 2466): No focus window, dropping: KeyEventaction=0 code=26 repeat=0 meta=0 scancode=26 mFlags=93,虚拟机信息 , 包括进程的,线程的跟踪信息,这是用来跟踪进程和线程具体点的好地方 。- VM TRACES JUST NOW (/data/anr/traces.txt.bugreport: 2011-01-15 16:49:02) - VM TRACES AT LAST ANR (/data/anr/traces.txt: 2011-01-15 16:49:02) -格式如下 :- pid 21161 at 2011-01-15 16:49:01 -Cmd line: com.android.mmsDALVIK THREADS:main prio=5 tid=1 NATIVE | group=main sCount=1 dsCount=0 s=N obj=0x4001d8d0 self=0xccc8 | sysTid=21161 nice=0 sched=0/0 cgrp=default handle=-1345017808 | schedstat=( 4151552996 5342265329 10995 ) at android.media.MediaPlayer._reset(Native Method) at android.media.MediaPlayer.reset(MediaPlayer.java:1218) at android.widget.VideoView.release(VideoView.java:499) at android.widget.VideoView.access$2100(VideoView.java:50) at android.widget.VideoView$6.surfaceDestroyed(VideoView.java:489) at android.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:572) at android.view.SurfaceView.updateWindow(SurfaceView.java:476) at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:206) at android.view.View.dispatchDetachedFromWindow(View.java:6082) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1156) at android.view.ViewGroup.removeAllViewsInLayout(ViewGroup.java:2296) at android.view.ViewGroup.removeAllViews(ViewGroup.java:2254) at com.android.mms.ui.SlideView.reset(SlideView.java:687) at com.android.mms.ui.SlideshowPresenter.presentSlide(SlideshowPresenter.java:189) at com.android.mms.ui.SlideshowPresenter$3.run(SlideshowPresenter.java:531) at android.os.Handler.handleCallback(Handler.java:587) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4627) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at ernal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) at ernal.os.ZygoteInit.main(ZygoteInit.java:616) at dalvik.system.NativeStart.main(Native Method)-闲话少说,我总结了观察log文件的基本步骤 。1,如果是ANR问题 , 则搜索“ANR”关键词 。 快速定位到关键事件信息 。2,如果是ForceClosed 和其它异常退出信息,则搜索Fatal 关键词, 快速定位到关键事件信息 。3,定位到关键事件信息后 , 如果信息不够明确的,再去搜索应用程序包的虚拟机信息 ,查看具体的进程和线程跟踪的日志,来定位到代码 。用这种方法,出现问题,根本不需要断点调试 , 直接定位到问题,屡试不爽 。下面,我们就开始来分析这个例子的log 。打开log文件 , 由于是ANR错误,因此搜索ANR , 为何要加空格呢,你加上和去掉比较一下就知道了 。 可以屏蔽掉不少保存到anr.log文件的无效信息 。定位到关键的事件信息如下:01-15 16:49:02.433 E/ActivityManager( 2466): ANR in com.android.mms (com.android.mms/.ui.SlideshowActivity)01-15 16:49:02.433 E/ActivityManager( 2466): Reason: keyDispatchingTimedOut01-15 16:49:02.433 E/ActivityManager( 2466): Load: 0.6 / 0.61 / 0.4201-15 16:49:02.433 E/ActivityManager( 2466): CPU usage from 1337225ms to 57ms ago:01-15 16:49:02.433 E/ActivityManager( 2466): sensorserver_ya: 8% = 0% user + 8% kernel / faults: 40 minor.01-15 16:49:02.433 E/ActivityManager( 2466): -com.android.mms: 0% = 0% user + 0% kernel01-15 16:49:02.433 E/ActivityManager( 2466): -flush-179:8: 0% = 0% user + 0% kernel01-15 16:49:02.433 E/ActivityManager( 2466): TOTAL: 25% = 10% user + 14% kernel + 0% iowait + 0% irq + 0% softirq01-15 16:49:02.436 I/ ( 2466): dumpmesg /data/log/dumpstate_app_anr.log我们用自然语言来描述一下日志,这也算是一种能力吧 。01-15 16:49:02.433 E/ActivityManager( 2466): ANR in com.android.mms (com.android.mms/.ui.SlideshowActivity)翻译:在16:49分2秒433毫秒的时候 ActivityManager (进程号为2466) 发生了如下错误:com.android.mms包下面的.ui.SlideshowActivity 无响应 。01-15 16:49:02.433 E/ActivityManager( 2466): Reason: keyDispatchingTimedOut翻译:原因 , keyDispatchingTimeOut - 按键分配超时01-15 16:49:02.433 E/ActivityManager( 2466): Load: 0.6 / 0.61 / 0.42翻译:5分钟,10分钟,15分钟内的平均负载分别为:0.6 , 0.61 , 0.42在这里我们大概知道问题是什么了,结合我们之前的操作流程,我们知道问题是在点击按钮某时候可能处理不过来按钮事件,导致超时无响应 。那么现在似乎已经可以进行工作了 。 我们知道Activity中是通过重载dispatchTouchEvent(MotionEvent ev)来处理点击屏幕事件 。 然后我们可以顺藤摸瓜,一点点分析去查找原因 。 但这样够了么 ?其实不够 , 至少我们不能准确的知道到底问题在哪儿 , 只是猜测 ,比如这个应用程序中,我就在顺藤摸瓜的时候发现了多个IO操作的地方都在主线程中,可能引起问题,但不好判断到底是哪个 ,所以我们目前掌握的信息还不够 。于是我们再分析虚拟机信息 , 搜索“Dalvik Thread”关键词,快速定位到本应用程序的虚拟机信息日志,如下:- pid 2922 at 2011-01-13 13:51:07 -Cmd line: com.android.mmsDALVIK THREADS:main prio=5 tid=1 NATIVE | group=main sCount=1 dsCount=0 s=N obj=0x4001d8d0 self=0xccc8 | sysTid=2922 nice=0 sched=0/0 cgrp=default handle=-1345017808 | schedstat=( 349749230610358 ) at android.media.MediaPlayer._release(Native Method) at android.media.MediaPlayer.release(MediaPlayer.java:1206) at android.widget.VideoView.stopPlayback(VideoView.java:196) at com.android.mms.ui.SlideView.stopVideo(SlideView.java:640) at com.android.mms.ui.SlideshowPresenter.presentVideo(SlideshowPresenter.java:443) at com.android.mms.ui.SlideshowPresenter.presentRegionMedia(SlideshowPresenter.java:219) at com.android.mms.ui.SlideshowPresenter$4.run(SlideshowPresenter.java:516) at android.os.Handler.handleCallback(Handler.java:587) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4627) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at ernal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) at ernal.os.ZygoteInit.main(ZygoteInit.java:616) at dalvik.system.NativeStart.main(Native Method)Binder Thread #3 prio=5 tid=11 NATIVE | group=main sCount=1 dsCount=0 s=N obj=0x4837f808 self=0x242280 | sysTid=3239 nice=0 sched=0/0 cgrp=default handle=2341032 | schedstat=( 32410506 932842514 164 ) at dalvik.system.NativeStart.run(Native Method)AsyncQueryWorker prio=5 tid=9 WAIT | group=main sCount=1 dsCount=0 s=N obj=0x482f4b80 self=0x253e10 | sysTid=3236 nice=0 sched=0/0 cgrp=default handle=2432120 | schedstat=( 3225061 26561350 27 ) at java.lang.Object.wait(Native Method) - waiting on (a android.os.MessageQueue) at java.lang.Object.wait(Object.java:288) at android.os.MessageQueue.next(MessageQueue.java:146) at android.os.Looper.loop(Looper.java:110) at android.os.HandlerThread.run(HandlerThread.java:60)Thread-9 prio=5 tid=8 WAIT | group=main sCount=1 dsCount=0 s=N obj=0x4836e2b0 self=0x25af70 | sysTid=2929 nice=0 sched=0/0 cgrp=default handle=2370896 | schedstat=( 130248 4389035 2 ) at java.lang.Object.wait(Native Method) - waiting on (a java.util.ArrayList) at java.lang.Object.wait(Object.java:288) at com.android.mms.data.Contact$ContactsCache$TaskStack$1.run(Contact.java:488) at java.lang.Thread.run(Thread.java:1096)Binder Thread #2 prio=5 tid=7 NATIVE | group=main sCount=1 dsCount=0 s=N obj=0x482f8ca0 self=0x130fd0 | sysTid=2928 nice=0 sched=0/0 cgrp=default handle=1215968 | schedstat=( 40610049 1837703846 195 ) at dalvik.system.NativeStart.run(Native Method)Binder Thread #1 prio=5 tid=6 NATIVE | group=main sCount=1 dsCount=0 s=N obj=0x482f4a78 self=0x128a50 | sysTid=2927 nice=0 sched=0/0 cgrp=default handle=1201352 | schedstat=( 40928066 928867585 190 ) at dalvik.system.NativeStart.run(Native Method)Compiler daemon prio=5 tid=5 VMWAIT | group=system sCount=1 dsCount=0 s=N obj=0x482f1348 self=0x118960 | sysTid=2926 nice=0 sched=0/0 cgrp=default handle=1149216 | schedstat=( 753021350 3774113668 6686 ) at dalvik.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论