[置顶] Android学习之开源项目分析--screencast

Update: 最近观看了ELC2011的关于android的一个视频, 里面提到了Android System Test Environment Runtime这么一个可以在PC端控制并执行一些定制的script测试脚本的测试框架, 其中PC与Device之间的UI同步用的就是screencast类似的机制--不停的传递screenshot, 而不是hack fbdev driver来传递实时的framebuffer中的内容。我另外会总结一篇对于ASTER的文章,希望和大家一起学习下.


Screencast是一个C/S的实用小程序, 用来通过desktop pc控制android device. 实现的相当精巧.


项目的地址: http://code.google.com/p/androidscreencast/


关键技术:

Java web start

适合dalvik的可执行jar包的生成

利用ADB实现PC与device的通信

通过app_process直接启动一个可执行的android jar包,而不需要安装它

我们先来看看它的client的实现:

1. 把AndroidScreencastClient导入eclipse, 查看对应.classpath, 修改对应的3个jar包指向你的环境中的对应位置

2. 使用提供的MyInjectEventApp.jardesc,生成Server端需要使用的MyInjectEventApp.jar

3. 按照MyInjectEventApp的描述, 生成包含classes.dex的jar包,这个包之后才能在android device被执行!!

!!这一步很重要,像我们展示了,如何使用普通的java工程, 生成普通的jar包(但是,这个包里包含有android的相关类), 再利用android提供的dx, aapt生成能在android device上执行的可执行jar包!!

以上编译准备工作做好,就可以看它的实现了

Main.java -- 很简单的一个入口点, 从PC测接收一个端口号, 以此新建一个socket通信, 并新起一个线程来使用该socket.

ClientHandler.java -- 关键做事的类, 利用常用的hook android framework的方法, 使用ServiceManage获得"window" service的Binder, 然后调用它所对应的WindowManager的内部接口来进行,point/key/trackball事件的触发

IBinder wmbinder = ServiceManager.getService( "window" );
final IWindowManager wm = IWindowManager.Stub.asInterface( wmbinder );

injectPointerEvent/injectKeyEvent/injectTrackballEvent就是WindowsManager中的内部接口, 对应的代码在frameworks/base/services/java/com/android/server/wm/WindowManagerService.java

如何读取设备上的framebuffer

Process p = Runtime.getRuntime().exec("/system/bin/cat /dev/graphics/fb0");
InputStream is = p.getInputStream();
System.out.println("Starting sending framebuffer");
OutputStream os = s.getOutputStream();

再来看看Server(即desktop PC)的实现:

使用swt构建了PC侧的UI.

使用了非公开的DDMS提供的ADB接口完成通信

AndroidDebugBridge bridge = AndroidDebugBridge.createBridge();
		waitDeviceList(bridge);
IDevice devices[] = bridge.getDevices();

使用了ADB daemon提供的接口来获得各种adb service提供的功能, 比如获得framebuffer的内容,从而显示到PC端. (adb daemon提供的service文档, 参见system/core/adb/SERVICES.TXT):具体的通信还是由传统的socket通信来完成, 没要求一次screenshot, 就会发一次获得当前framebuffer的请求.

RawImage rawImage = null;
synchronized (device) {
	rawImage = device.getScreenshot();
}

通过反射,使用ddms提供的syncmanager的接口, 从而提供了DDMS提供的pull/push文件的功能

Method m = device.getSyncService().getClass().getDeclaredMethod(
					"doPullFile", String.class, String.class,
					ISyncProgressMonitor.class);

!!通过使用app_process来执行一个android的可执行jar包!!

String fullCmd = "export CLASSPATH=" + REMOTE_AGENT_JAR_LOCATION;
fullCmd += "; exec app_process /system/bin " + AGENT_MAIN_CLASS + " "
	+ cmdList;
System.out.println(fullCmd);
device.executeShellCommand(fullCmd,
		new OutputStreamShellOutputReceiver(System.out));



你可能感兴趣的:(eclipse,android,socket,server,jar,service)