版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1.Activity21. Activity的生命周期【简介】22Activity 的创建23Actvity 堆栈3Intent对象调用Activity实例42. Context menus for expandablelists63. Android自动化测试初探81:捕获Activity上的Element82: Hierarchyviewer 捕获Element的123: 架构实现144:模拟键盘鼠标事件(Socket+Instrumentation实现)155:再述模拟键盘鼠标事件(adb shell 实现)184. 背景图片迎合不同手机分辨率的问题285. 应用程序图标296. 动态s
2、tart页面297. 运用java mail包实现发Gmail邮件33第一个类:MailSenderInfo.java33第二个类:SimpleMailSender.java35第三个类:MyAuthenticator.java38主函数代码38注意:398. Android键盘响应函数399. Vector用法4110. 线程的处理4411. Message Hander 监听消息4612. 显示简单的提示信息471. 简单的对话框:472. tost提示信息:473. 包含两个按钮的对话框484. 三个按钮的提示框495. 包含输入的dlg(xml不完整)506. 圆形进度框511. Ac
3、tivity1. Activity的生命周期【简介】和其他手机平台的应用程序一样,Android的应用程序的生命周期是被统一掌控的,也 就是说我们写的应用程序命运掌握在别人(系统)的手里,我们不能改变它,只能学习并 适应它。 简单地说一下为什么是这样:我们手机在运行一个应用程序的时候,有可能打进来电话 发进来短信,或者没有电了,这时候程序都会被中断,优先去服务电话的基本功能,另 外系统也不允许你占用太多资源,至少要保证电话功能吧,所以资源不足的时候也就有可 能被干掉。OPhone Activity生命周期解析要为你的OPhone应用程序创建用户界面屏幕,就需要继承Activity类,并且使用V
4、iews为你的应用程序提供用户交互。每个Activity表示用户界面中的一个屏幕。你的应用程序越复杂,需要的屏就越多,每一屏都是一个新的Activity。典型的一个应用程序一般至少包括一个屏用来处理用户界面的主要功能,也常常还有其他的屏用来输入用户信息,或者展现不同的数据并支持更多的功能。大多数Activity都是全屏的,但是你也可以创建半透明或者浮动的Activity.理解Activity的生命周期对应用程序开发来说是至关重要的,这样才能确保您的应用提供了一个很好的用户体验和妥善管理其资源。由于OPhone应用程序不控制自己的进程寿命,由OPhone Runtime管理每个应用程序进程,但是
5、每个Activity的状态反过来会影响到OPhone Runtime是否将终止当前Activity和还是让它继续运行2Activity 的创建通过继承Activity类,我们可以创建一个新的Activity。基本的示例代码如下所示:import android.app.Activity; import android.os.Bundle; public class MyActivity extends Activity /* Called when the activity is first created. */ Override public void onCreate(Bundle ic
6、icle) super.onCreate(icicle); Activity基类仅仅是一个封装了一些与窗口显示相关功能的空空的屏幕,本身并不具备太具体用处,因此创建Activity以后,第一件事情就是在这个空空的屏幕上摆上你所需要的物件,各种Views。你可以在xml文件中的定义你所需要的Views, 也可以在代码中定义。通过在Acitvity onCreate方法中调用setContentView,便可将Activity与你的Views绑定在一起来实现用户交互的功能。在代码中定义你的Views Override public void onCreate(Bundle icicle) supe
7、r.onCreate(icicle); MyView myView = new MyView(this); setContentView(myView); 在layout文件中定义你的Views Override public void onCreate(Bundle icicle) super.onCreate(icicle); setContentView(R.layout.main); 为了在你的应用程序中使用Acitvity,你还需要将你写的Acitvity类注册到Manifest当中,参见以下XML片段:3Actvity 堆栈每个Actvity的状态由它所在Activity栈中的位置
8、所决定,所有当前正在运行的Actvity将遵循照后进先出的原则。当一个新的Activity启动,当前的Activity将移至堆栈的顶部,如果用户使用Back按钮,或在前台Activity被关闭,下一个Activity将被激活并且移至到堆栈的顶部。这个过程如下图所示 Intent对象调用Activity实例Android中一个Activity调用另一个Activity Intent对象的使用第一步:建Android 工程:IntentDemo。第二步:编写Activity 的子类别:IntentDemo,其程序代码如下:package ent;import android
9、.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;public class IntentDemo extends Activity /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceSt
10、ate); setContentView(R.layout.main); Button btn1 = (Button) findViewById(R.id.btn1); btn1.setOnClickListener(new Button.OnClickListener() Override public void onClick(View v) / TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(IntentDemo.this, Intent2.class); /* 调用一个新的Act
11、ivity */ startActivity(intent); /* 关闭原本的Activity */ IntentDemo.this.finish(); ); 第三步:新建一个Activity 的子类别:Intent2,其程序代码如下:package ent;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;public class Intent2
12、 extends Activity /* Called when the activity is first created. */ Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.mylayout); Button btn2 = (Button) findViewById(R.id.btn2); btn2.setOnClickListener(new Button.OnClickListener() Over
13、ride public void onClick(View v) / TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(Intent2.this, IntentDemo.class); startActivity(intent); Intent2.this.finish(); ); 第四步:修改res/layout/main.xml,其代码如下:第五步:修改res/layout/ mylayout.xml,其代码如下:第六步: AndroidManifest.xml中声明activity
14、OK了!2. Context menus for expandablelistsBy steveoliverc An expandable list supports context menus in pretty much the same way that a standard list does: add a listener for the context menu (when the user has long-pressed on a list item). Unlike a standard list view, however, you probably want to kno
15、w whether the user has selected a group (expandable item) or a child (sub-item) list item.Furthermore, you might not want to do anything if the user tries to bring up a context menu on a group item. There might be cases where you would want to do something to all of the children under a group, but i
16、n my Librarium application, I wanted to ignore group items and present the context menu only for children.First, you need to know when the context menu is going to be created so that you can identify whether the user pressed on a group or a child. If they pressed on a group, then cancel the context
17、menu. This also gives us a chance to get the text of the child item, so that we can put it into the header of the context menu.public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) super.onCreateContextMenu(menu, v, menuInfo);ExpandableListView.ExpandableListContextMenuI
18、nfo info =(ExpandableListView.ExpandableListContextMenuInfo) menuInfo;int type =ExpandableListView.getPackedPositionType(info.packedPosition);int group =ExpandableListView.getPackedPositionGroup(info.packedPosition);int child =ExpandableListView.getPackedPositionChild(info.packedPosition);/Only crea
19、te a context menu for child itemsif (type = 1) /Array created earlier when we built the expandable listString page =mListStringArraygroupchild;menu.setHeaderTitle(page);menu.add(0, MENU_READ, 0, “Read page”);menu.add(0, MENU_EDIT, 0, “Edit page”);menu.add(0, MENU_FAVORITE, 0, “Add page to favorites”
20、);menu.add(0, MENU_EXPORT, 0, “Export page to file”);menu.add(0, MENU_DELETE, 1, “Delete page”);Second, create the context menu:public boolean onContextItemSelected(MenuItem menuItem) ExpandableListContextMenuInfo info =(ExpandableListContextMenuInfo) menuItem.getMenuInfo();int groupPos = 0, childPo
21、s = 0;int type = ExpandableListView.getPackedPositionType(info.packedPosition);if (type = ExpandableListView.PACKED_POSITION_TYPE_CHILD) groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);/Pull values fr
22、om the array we built when we created the listString author = mListStringArraygroupPos0;String page = mListStringArraygroupPoschildPos * 3 + 1;rowId = Integer.parseInt(mListStringArraygroupPoschildPos * 3 + 3);switch (menuItem.getItemId() case MENU_READ:readNote(rowId);return true;case MENU_EDIT:edi
23、tNote(rowId);return true;/etc.default:return super.onContextItemSelected(menuItem);Thats it. Now users can long-press on an item in an expandable list, and get the context menu if its a child item.3. Android自动化测试初探1:捕获Activity上的Element第一部分:前言Android系统下应用程序的测试现在应该还算是个新的领域,网上关于这方面的资料很多都是基于白盒测试的,一般都是基于
24、JUnit框架和Android SDK中android.test等命名空间下的内容进行,但是有一个前提,那就是必须要有应用程序的源代码以提供测试接入点,但是这在很多软件公司中是不现实的。很多测试工程师做的工作是完全黑盒,基本接触不到源代码,白盒测试大部分也是由开发自己完成。 回顾一下Windows下的黑盒测试自动化,先前使用的是微软提供的基于.net framework的UI Automation自动化测试框架(要求版本在.net framework 3.0以上,即VS.NET 2008 开发环境),对与擅长C#语言的人来说,使用起来确认比较好用。本人也写了基于UI Automation的轻量
25、级的自动化框架,将在以后的博文中引出。 那在Android操作系统中能不能做类似于UI Automation的事情呢?不幸的是,Android的权限控制分的非常清楚,不同程序之间的数据访问只能通过Intent,content provider类似的功能实现。也就是说你开发的运行在Android中的自动化程序想要捕获当前运行的AUT (Application under Test) 界面上的控件等Element(该术语引自UI Automation,觉得翻译成元素有点生硬,故不作翻译)基本不可能,你也拿不到当前active activity的引用(截止本文发帖为止,个人暂时没有找到办法获得此引用
26、)。 无路可走了?模拟器里面不能走,外面能不能走?或许可以。第二部分:捕获Activity上的Element 在Android的SDK中自带了一个对自动化测试比较有用的工具:hierarchyviewer(位于SDK的tools目录下)。在模拟器运行的情况下,使用该工具可以将当前的Activity上的Element以对象树的形式展现出来,每个Element所含的属性也能一一尽显。这有点像Windows上运行的UI SPY,唯一遗憾的是不支持事件的触发。不过没有关系,可以想办法绕,当务之急是能在自行编写的自动化测试代码里找到Activity上的Element。 第一个想到的办法就是看hierar
27、chyviewer源码,不巧,网上搜了一下,没有资源。或许Google的官网上有,但是上不去。看来只能反编译了,找来XJad,暴力之。虽然反编译出来的代码很多地方提示缺少import,但代码基本上是正确的。看了一下,确实也知道了许多。后来在编写代码的过程中,确实也证明了如果想引用hierarchyviewer.jar这个包并调试,还是需要知道里面的一些设置的。 创建基于hierarchyviewer.jar这个包的调用,需要将它和另外两个包,ddmlib.jar(在hierarchyviewer.jar同级目录中有)和org-netbeans-api-visual.jar(需要下载并安装net
28、beans,在其安装目录中有)一并导入到工程项目中,因为hierarchyviewer的实现依附于这两个包。 想在代码中获取Activity上的Element需要进行如下几个步骤(如果使用过hierarchyviewer这个工具后会发现,自动化代码所要写的就是该工具上的使用步骤):1. Ensure adb running2. Set adb location(因为hierarchyviewer和模拟器的沟通完全是依靠adb做的,所以设定正确的adb程序的位置至关重要,本人就曾在这个问题上栽了半天多)3. Get Active Device (这个等同动作发生在启动hierarchyviewe
29、r工具时)4. Start View Server (等同于工具上Start Server 菜单触发事件)5. Load Scene (等同于工具上Load View Hierarchy菜单触发事件)6. Get Root View Node (获得对象树的根节点,这个动作在工具上点击Load View Hierarchy菜单后会自动加载)7. Get Sub View Node (获得想要查找的View Node,这个动作在工具上点击Load View Hierarchy菜单后会自动加载)说明:上述步骤中一些名称实际上就是hierarchyviewer中所提供的可访问方法名称,如startV
30、iewServer、loadScene、rootNode等。另外View Node实际上hierarchyviewer中的一个类,表示的对象树上的一个Element。现将部分核心代码粘贴如下:1. Set adb location System.setProperty(hierarchyviewer.adb,E: Androidandroid-sdk-windowstools);其中”hierarchyviewer.adb” 这个key是hierarchyviewer.jar中指定的,后面的value是存放Android SDK的路径。这个目录必须是当前运行的模拟器所对应的adb的目录,不能自
31、行使用其他目录下adb,否则会发生adb进程异常退出的错误。2. Get Active DeviceIDevice devices = null;DeviceBridge.terminate();while(null=devices | 0=devices.length)DeviceBridge.initDebugBridge() ;/it must wait for some time, otherwise will throw exceptiontry Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(
32、);devices = DeviceBridge.getDevices() ;return devices;以上方法返回的是所有当前运行的Device列表3. Start View Server DeviceBridge.startViewServer(device);4. Load SceneViewHierarchyLoader.loadScene(device,Window.FOCUSED_WINDOW) ;5.Get Root View Nodevhs.getRoot() ;其中vhs是ViewHierarchyScene的实例对象6.Get Sub View Nodepublic V
33、iewNode findFirstChildrenElement(IDevice device, ViewNode entryViewNode, String elementID) ViewNode node=null; if(0!=entryViewNode.children.size() for(int i=0;i DUMP);out.write(new StringBuilder().append(DUMP -1).toString();out.newLine(); out.flush(); do String line;if (line = in.readLine() = null |
34、 DONE.equalsIgnoreCase(line) break; line = line.trim(); System.out.println(line); while (true); catch (IOException e) e.printStackTrace(); 运行后的结果摘录其中一部分(button5),列举如下。注:当前device中运行的是2.1SDK中自带的Calculator程序:com.android.calculator2.ColorButton43b8bee8 mText=1,5 getEllipsize()=4,null mMinWidth=1,0 mMinH
35、eight=1,0 mMeasuredWidth=2,79 mPaddingBottom=1,0 mPaddingLeft=1,0 mPaddingRight=1,0 mPaddingTop=1,0 mMeasuredHeight=2,78 mLeft=2,81 mPrivateFlags_DRAWING_CACHE_INVALID=3,0x0 mPrivateFlags_DRAWN=4,0x20 mPrivateFlags=8, mID=9,id/digit5 mRight=3,160 mScrollX=1,0 mScrollY=1,0 mTop=1,0 mBottom=2,78 mUser
36、PaddingBottom=1,0 mUserPaddingRight=1,0 mViewFlags=9, getBaseline()=2,54 getHeight()=2,78 layout_gravity=4,NONE layout_weight=3,1.0 layout_bottomMargin=1,0 layout_leftMargin=1,1 layout_rightMargin=1,0 layout_topMargin=1,0 layout_height=11,FILL_PARENT layout_width=11,FILL_PARENT getTag()=4,null getVi
37、sibility()=7,VISIBLE getWidth()=2,79 hasFocus()=5,false isClickable()=4,true isDrawingCacheEnabled()=5,false isEnabled()=4,true isFocusable()=4,true isFocusableInTouchMode()=5,false isFocused()=5,false isHapticFeedbackEnabled()=4,true isInTouchMode()=4,true isOpaque()=5,false isSelected()=5,false is
38、SoundEffectsEnabled()=4,true willNotCacheDrawing()=5,false willNotDraw()=5,false另外还支持如下命令:- LIST will show the list of windows:LIST com.android.launcher/com.android.launcher.Launcher4359e4d0 TrackingView435b00a0 StatusBarExpanded StatusBar43484c58 KeyguardDONE.3: 架构实现前两节讲了用Android SDK自带的tool-hierarc
39、hyviewer来捕获Activity上Element,并分析了其中的原理。对于要实现GUI自动化,还有哪些工作没有完成呢?n Invoke界面上的Element,如点击按钮,在文本框中输入内容等n Press手机自身所有的按键,如HOME键,Menu键,左右上下方向键,通话键,挂机键等n 判断测试结果前面说过,直接从Emulator内部获取当前Activity上的Element这条路已经断了,同理,探索像UI Automation上一样Invoke Element的操作估计是行不通了,因为你拿不到Element的对象实例,所以实例所支持的方法当然也没有办法拿到。怎么办?实在不行,基于坐标来对
40、Element进行触发总可以吧。在Windows中发送基于坐标发送键盘和鼠标事件一般是在无法识别Element的情况下,想的最后一招,这使我想起起了Android中的monkey测试,对着屏幕就是一通乱点,压根就不管点的是什么。所幸的是,当前Android系统中我们得到了Element的属性信息,其中就包括坐标信息,而且这种信息是具有弹性的,也就是说即使Element的坐标随着开发的改变而有所变化,也不用担心,因为当前的坐标是实时获得的。那么怎样才能给Element发送模拟按键等操作呢?总不能用Windows当前的键盘和鼠标事件吧,那样一旦模拟器的位置改变或失去焦点,啥都白搭,风险太大了。看来
41、给Emulator内部发送模拟按键等操作比较靠谱。查了一下SDK,其中确实有这样的方法存在,但是我们当前的测试基础架构程序位于Emulator外部,怎么办?突然想起了hierarchyviewer的实现机制,通过Socket来发送信息。Hierarchyviewer有系统自带的进程给予答复响应(具体是哪个进程进行的响应不清楚,没有研究过)。那么我们也来模拟做一个Listener总可以吧。其实对于模拟按键发送,网上的帖子很多,但大部分是基于一种方式实现的,IWindowManager接口。不巧的是,SDK并没有将该接口提供为public,所以需要用android源码替代android.jar包进
42、行编译的方式进行绕行,感觉方法有点复杂。在后面另一篇系列文章中我会列出我在网上看到的另一种基于Instrumentation和MessageQueue的机制实现方法。最后就剩下判断测试结果了。判断测试结果一般分为如下两种:外部条件是否满足,如文件是否产生,数据是否生成等;内部条件是否满足,如对应的Element是否出现或消失,Element上内容如字符串是否有变化。对于前一种本文不予讨论,后一种情况下,Element出现或消失可以通过hierarchyviewer来获取。仔细研究过hierarchyviewer会发现,它并没有提供Element界面上内容(Text)的属性。这可有点晕了,好像又
43、要回到实现捕获Activity实例的老路上来了。考虑图像识别?这好像不靠谱。突然想到,4939端口上发送DUMP命令后的返回结果中会不会有此类hierarchyviewer没有显示出来的信息呢,万幸,还真有。在我上一篇博文(Hierarchyviewer 捕获Element的实现原理)中查询mText字段,会发现mText=1,5这样的信息,其实就是代表了计算器Button5上显示的内容5,逗号前的1表示后跟一位信息。至此,问题似乎都解决掉了。画个基础架构图做个总结:4:模拟键盘鼠标事件(Socket+Instrumentation实现)通过Socket + Instrumentation实现
44、模拟键盘鼠标事件主要通过以下三个部分组成:l Socket编程:实现PC和Emulator通讯,并进行循环监听l Service服务:将Socket的监听程序放在Service中,从而达到后台运行的目的。这里要说明的是启动服务有两种方式,bindService和startService,两者的区别是,前者会使启动的Service随着启动Service的Activity的消亡而消亡,而startService则不会这样,除非显式调用stopService,否则一直会在后台运行因为Service需要通过一个Activity来进行启动,所以采用startService更适合当前的情形l Instru
45、mentation发送键盘鼠标事件:Instrumentation提供了丰富的以send开头的函数接口来实现模拟键盘鼠标,如下所述:sendCharacterSync(int keyCode) /用于发送指定KeyCode的按键sendKeyDownUpSync(int key) /用于发送指定KeyCode的按键sendPointerSync(MotionEvent event) /用于模拟TouchsendStringSync(String text) /用于发送字符串注意:以上函数必须通过Message的形式抛到Message队列中。如果直接进行调用加会导致程序崩溃。对于Socket编程
46、和Service网上有很多成功的范例,此文不再累述,下面着重介绍一下发送键盘鼠标模拟事件的代码:1. 发送键盘KeyCode:步骤1. 声明类handler变量private static Handler handler;步骤2. 循环处理Message/在Activity的onCreate方法中对下列函数进行调用private void createMessageHandleThread() /need start a thread to raise looper, otherwise it will be blocked Thread t = new Thread() public void run() Log.i( TAG,Creating handler . ); Looper.prepare(); handler = new Handler() public void handleMessage(Message msg) /process incoming messages here ; Looper.loop(); Log.i(
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 木材干馏工活动策划能力考核试卷含答案
- 普通镗工诚信品质能力考核试卷含答案
- 玻璃钢制品喷射工岗前实操熟练考核试卷含答案
- 生物材料在骨科领域的应用
- 新教科版四年级上册科学第一单元《空气》单元检测题及参考答案
- 《安徽中医药高》课件
- 医院感染暴发调查与处理
- 疼痛的观察与护理
- 2026年秋招:PACK结构工程师笔试题及答案
- 2026年普利司通(中国)招聘面试题及答案
- 雅马哈电钢琴P-115B中文说明书
- 中药饮片鉴别知识培训课件
- 2025-2030动力电池快充技术安全边界探索
- 充电桩运维安全培训课件
- 专利知识培训班课件
- 《健康养老职业素养与安全》养老服务与管理专业全套教学课件
- 航海模型培训课件
- T-CSTM 00901-2023 手持式X射线荧光光谱仪校准规范
- 医院培训课件:《恶性黑色素瘤》
- 冀教版四年级上册除法竖式计算题200道及答案
- 混凝土及原材台账表格
评论
0/150
提交评论