【Android自动触发】
2014-04-22 20:05
501 查看
参考资料:http://www.cnblogs.com/vowei/archive/2012/07/30/2614353.html
连接view server
(1)Forword端口。
采用adb devices命令会展示当前主机运行的Android设备
(2)打开ViewServer服务。
首先,需要判断ViewServer是否打开:
adb -s emulator-5556 shell service call window 3
如果返回值是"Result: Parcel(00000000 00000000 '........')",说明ViewServer没有打开,那么需要用下面的命令打开ViewServer:
adb -s emulator-5556 shell service call window 1 i32 4939
反之,关闭ViewServer的命令是:
(3)连接ViewServer。
既然ViewServer已经打开,那么下一步我们就需要连接它了。
由于我们已经把设备emulator-5556的4939端口映射为PC的4939端口上,所以我们需要连接的是127.0.0.1:4939。这需要写一些java代码:
out和in用于发送命令和接受返回数据,需要注意的是,HierarchyViewer和ViewServer的通信采用短连接,所以每发送一次命令,需要重新建立一次连接,所以以上代码需要反复调用。
如何获取活动的Activity?
我们获取的是这样的列表:
注意,每行前面的16进制数字,那是一个hashcode,我们在进一步请求该Activity对应的控件树时要用到该hashcode。
如何获取Activity的控件树
获取控件树信息的命令是DUMP,后面要接对应的Activity的hash code,如果使用ffffffff作为参数,那么就是取最前端的Activity。
我们以com.android.launcher2.Launcher为例,它的hash code是4507aa28,看代码:
其实也可以用“dump -1”来获取
返回的控件树被保存文本context1中,一般文本的内容都非常大,这里我不把它全部打印出来,我们只取其中一行来看:
android.widget.FrameLayout@44edba90 mForeground=52,android.graphics.drawable.NinePatchDrawable@44edc1e0 mForegroundInPadding=5,false mForegroundPaddingBottom=1,0 mForegroundPaddingLeft=1,0 mForegroundPaddingRight=1,0 mForegroundPaddingTop=1,0 mMeasureAllChildren=5,false mForegroundGravity=2,55 getDescendantFocusability()=24,FOCUS_BEFORE_DESCENDANTS getPersistentDrawingCache()=9,SCROLLING isAlwaysDrawnWithCacheEnabled()=4,true isAnimationCacheEnabled()=4,true isChildrenDrawingOrderEnabled()=5,false isChildrenDrawnWithCacheEnabled()=5,false mMinWidth=1,0 mPaddingBottom=1,0 mPaddingLeft=1,0 mPaddingRight=1,0 mPaddingTop=2,38 mMinHeight=1,0 mMeasuredWidth=3,480 mMeasuredHeight=3,800 mLeft=1,0 mPrivateFlags_DRAWING_CACHE_INVALID=3,0x0 mPrivateFlags_DRAWN=4,0x20 mPrivateFlags=8,16911408 mID=10,id/content mRight=3,480 mScrollX=1,0 mScrollY=1,0 mTop=1,0 mBottom=3,800 mUserPaddingBottom=1,0 mUserPaddingRight=1,0 mViewFlags=9,402653186 getBaseline()=2,-1 getHeight()=3,800 layout_bottomMargin=1,0 layout_leftMargin=1,0 layout_rightMargin=1,0 layout_topMargin=1,0 layout_height=12,MATCH_PARENT layout_width=12,MATCH_PARENT getTag()=4,null getVisibility()=7,VISIBLE getWidth()=3,480 hasFocus()=5,false isClickable()=5,false isDrawingCacheEnabled()=5,false isEnabled()=4,true isFocusable()=5,false isFocusableInTouchMode()=5,false isFocused()=5,false isHapticFeedbackEnabled()=4,true isInTouchMode()=4,true isOpaque()=5,false isSelected()=5,false isSoundEffectsEnabled()=4,true willNotCacheDrawing()=5,false willNotDraw()=5,false
返回的文本中的每一行是Activity中的一个控件,里面包含了该控件的所有信息,HierarchyViewer正是通过解析这些信息并把它们显示在属性列表中的。
需要注意每行的开始处都包含一个“控件类型@hash code”的字段,如android.widget.FrameLayout@44edba90 ,这个字段在获取该控件的屏幕截图时将被用到。
HierarchyViewer是怎么把这个文本解析成层次图的呢? 原来,每行前面都有若干空格的缩进,比如缩进5个空格表示该控件在第六层,那么往上找,最近的缩进4个空格的控件就是它的父控件。
附:小可代码:
连接view server
(1)Forword端口。
采用adb devices命令会展示当前主机运行的Android设备
adb devices
List of devices attached emulator-5554 device emulator-5556 device以emulator-5554为例,我们将它的4939端口映射到PC机上的4939端口
adb -s emulator-5556 forward tcp:4939 tcp:4939如果连接了多台Android设备,HierarchyViewer将把下一台Android设备的4939端口映射到PC的4940端口,以此类推。
(2)打开ViewServer服务。
首先,需要判断ViewServer是否打开:
adb -s emulator-5556 shell service call window 3
如果返回值是"Result: Parcel(00000000 00000000 '........')",说明ViewServer没有打开,那么需要用下面的命令打开ViewServer:
adb -s emulator-5556 shell service call window 1 i32 4939
反之,关闭ViewServer的命令是:
adb -s emulator-5556 shell service call window 2 i32 4939
(3)连接ViewServer。
既然ViewServer已经打开,那么下一步我们就需要连接它了。
由于我们已经把设备emulator-5556的4939端口映射为PC的4939端口上,所以我们需要连接的是127.0.0.1:4939。这需要写一些java代码:
import java.net.*; try{ Socket socket = new Socket(); socket.connect(new InetSocketAddress("127.0.0.1", 4939),40000); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8")); } } catch ( Exception e ) { e.printStackTrace(); }
out和in用于发送命令和接受返回数据,需要注意的是,HierarchyViewer和ViewServer的通信采用短连接,所以每发送一次命令,需要重新建立一次连接,所以以上代码需要反复调用。
如何获取活动的Activity?
//send ‘LIST’ command out.write("LIST"); out.newLine(); out.flush(); //receive response from viewserver String context=""; String line; while ((line = in.readLine()) != null) { if ("DONE.".equalsIgnoreCase(line)) { //$NON-NLS-1$ break; } context+=line+"\r\n"; }
我们获取的是这样的列表:
44fd1b78 com.android.internal.service.wallpaper.ImageWallpaper 4507aa28 com.android.launcher/com.android.launcher2.Launcher 45047328 com.tencent.mobileqq/com.tencent.mobileqq.activity.HomeActivity 450b8d18 com.tencent.mobileqq/com.tencent.mobileqq.activity.NotificationActivity 451049c0 com.tencent.mobileqq/com.tencent.mobileqq.activity.NotificationActivity 451167a8 com.tencent.mobileqq/com.tencent.mobileqq.activity.UpgradeActivity 450efef0 com.tencent.mobileqq/com.tencent.mobileqq.activity.UpgradeActivity 4502f2e0 TrackingView 4503f560 StatusBarExpanded 44fe0bb0 StatusBar 44f09250 Keyguard
注意,每行前面的16进制数字,那是一个hashcode,我们在进一步请求该Activity对应的控件树时要用到该hashcode。
如何获取Activity的控件树
获取控件树信息的命令是DUMP,后面要接对应的Activity的hash code,如果使用ffffffff作为参数,那么就是取最前端的Activity。
我们以com.android.launcher2.Launcher为例,它的hash code是4507aa28,看代码:
其实也可以用“dump -1”来获取
//out.write("DUMP ffffffff"); out.write("DUMP 4507aa28"); out.newLine(); out.flush(); String context1=""; line=""; while ((line = in.readLine()) != null) { if ("DONE.".equalsIgnoreCase(line)) { //$NON-NLS-1$ break; } context1+=line+"\r\n"; }
返回的控件树被保存文本context1中,一般文本的内容都非常大,这里我不把它全部打印出来,我们只取其中一行来看:
android.widget.FrameLayout@44edba90 mForeground=52,android.graphics.drawable.NinePatchDrawable@44edc1e0 mForegroundInPadding=5,false mForegroundPaddingBottom=1,0 mForegroundPaddingLeft=1,0 mForegroundPaddingRight=1,0 mForegroundPaddingTop=1,0 mMeasureAllChildren=5,false mForegroundGravity=2,55 getDescendantFocusability()=24,FOCUS_BEFORE_DESCENDANTS getPersistentDrawingCache()=9,SCROLLING isAlwaysDrawnWithCacheEnabled()=4,true isAnimationCacheEnabled()=4,true isChildrenDrawingOrderEnabled()=5,false isChildrenDrawnWithCacheEnabled()=5,false mMinWidth=1,0 mPaddingBottom=1,0 mPaddingLeft=1,0 mPaddingRight=1,0 mPaddingTop=2,38 mMinHeight=1,0 mMeasuredWidth=3,480 mMeasuredHeight=3,800 mLeft=1,0 mPrivateFlags_DRAWING_CACHE_INVALID=3,0x0 mPrivateFlags_DRAWN=4,0x20 mPrivateFlags=8,16911408 mID=10,id/content mRight=3,480 mScrollX=1,0 mScrollY=1,0 mTop=1,0 mBottom=3,800 mUserPaddingBottom=1,0 mUserPaddingRight=1,0 mViewFlags=9,402653186 getBaseline()=2,-1 getHeight()=3,800 layout_bottomMargin=1,0 layout_leftMargin=1,0 layout_rightMargin=1,0 layout_topMargin=1,0 layout_height=12,MATCH_PARENT layout_width=12,MATCH_PARENT getTag()=4,null getVisibility()=7,VISIBLE getWidth()=3,480 hasFocus()=5,false isClickable()=5,false isDrawingCacheEnabled()=5,false isEnabled()=4,true isFocusable()=5,false isFocusableInTouchMode()=5,false isFocused()=5,false isHapticFeedbackEnabled()=4,true isInTouchMode()=4,true isOpaque()=5,false isSelected()=5,false isSoundEffectsEnabled()=4,true willNotCacheDrawing()=5,false willNotDraw()=5,false
返回的文本中的每一行是Activity中的一个控件,里面包含了该控件的所有信息,HierarchyViewer正是通过解析这些信息并把它们显示在属性列表中的。
需要注意每行的开始处都包含一个“控件类型@hash code”的字段,如android.widget.FrameLayout@44edba90 ,这个字段在获取该控件的屏幕截图时将被用到。
HierarchyViewer是怎么把这个文本解析成层次图的呢? 原来,每行前面都有若干空格的缩进,比如缩进5个空格表示该控件在第六层,那么往上找,最近的缩进4个空格的控件就是它的父控件。
附:小可代码:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetSocketAddress; import java.net.Socket; import com.android.ddmlib.AndroidDebugBridge; import com.android.ddmlib.IDevice; //import com.android.hierarchyviewerlib.device.DeviceBridge; import com.android.hierarchyviewerlib.device.DeviceBridge; public class hierarchy{ // get Element list public static void listActivity(){ Socket socket; BufferedReader in; BufferedWriter out; socket = null; in = null; out = null; try{ socket= new Socket(); socket.connect(new InetSocketAddress("127.0.0.1", 4939),40000); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8")); //send ‘LIST’ command out.write("LIST"); out.newLine(); out.flush(); //receive response from viewserver //-----get the activity----- String context=""; String line; while ((line = in.readLine()) != null) { if ("DONE.".equalsIgnoreCase(line)) { //$NON-NLS-1$ break; } context+=line+"\r\n"; System.out.println(context); } // DUMP socket= new Socket(); socket.connect(new InetSocketAddress("127.0.0.1", 4939),40000); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8")); out.write("DUMP -1"); out.newLine(); out.flush(); String context1=""; String line1=""; // System.out.println("HI"+in.readLine()); while ((line1 = in.readLine()) != null) { if ("DONE.".equalsIgnoreCase(line1)) { //$NON-NLS-1$ break; } context1+=line1+"\r\n"; System.out.println(context1); } } catch ( Exception e ) { e.printStackTrace(); } } public static void main(String[] args){ listActivity(); } }
相关文章推荐
- Android变量交换
- Android旅程开启
- Android SurfaceView讲解
- Android编译系统详解(一)
- Android基本数据类型测试
- 从零开始开发Android版2048 (一)初始化界面
- android开发人员您还在为模拟器犯愁吗?神级android模拟器---Genymotion一个更快局机关
- Android 之 远程图片获取和本地缓存
- Android系统权限和root权限
- android 连续两次点击返回键 退出程序
- Android Debug 命令实践
- android 进程监控 top
- 7种形式的Android Dialog使用举例
- Android开发基础——真机测试错误,ADB启动不了,程序安装不了,the connection to adb is down,INSTALL_CANCELED_BY_USER...
- android恢复出厂设置以及系统升级流程
- android recovery模式流程
- android 不同版本
- Android恢复出厂设置流程分析【Android源码解析十】
- Android关机流程解析
- Android:制作Update.zip升级包