PC远程调用Android上的程序(RPC)

来源:互联网 发布:java自定义随机数算法 编辑:程序博客网 时间:2024/06/08 00:03

Author 正正 Date  2010.12.31 23:15:00   转载请注明出处 http://www.2009fly.com

最近做一个项目,需要用PC去调用Android上的程序实现某些操作。原来是利用PC来模拟Android上的工作过程,由于时间紧张,一直没有时间移植过去,当时也不知道Android上到底该怎么操作,接口是什么。到了产品的第二阶段,需要考虑移植的问题,但是这时候已经有很多的类全是按照在PC上写的,幸亏当时只是提供的接口。好了,废话少说,现在看看具体实现吧。

Android做Server,一开始我考虑的是将WebService移植到Android上,至于Web容器,已有人将Jetty移植了过去,也就是i-jetty。但是这个太重量级了,而且要修改的东西会太多。比如PC上要实现WebService上的客户端操作,这个未免小题大做,况且只有很少的几个接口调用,于是我考虑自己写一个简单的RPC操作,下面是我的构思:

PC(RPC Client)端发送一个RPCRequest,然后用socket通信方式发送到Android(RPC Server)上,Android解析RPCRequest,用反射机制完成相应类的调用,如果是第一次调用,并且传递的方法名和类的名称一样,则会初始化该类【构造函数调用】,并将类的实例在Server端注册,以便下次可以直接调用;如果是其他方法,则可以直接调用。将调用的结果构造成RPCResponse对象返回给PC(RPC  Client),这样就完成一次完整的RPC操作。需要注明的一点,就是socket传递的对象必须是可以序列化的,否则会出错的。(当然,这是很基础的事情,我只是提醒一下,因为很多时候你会忘记这么做!)

现在的关键是RPCRequest和RPCResponse具体内容是什么?

RPCRequest里面主要包括|RequestHead和RequestBody两个部分。其中,Head部分主要含有协议的版本信息,还有用于处理除实例方法调用外的其他事情,比如系统初始化、通知server释放注册的实例等等。Body部分包括类实例的唯一标识id、类的完全限定名、要调用的方法名、方法的参数类型表、参数的具体值。其中,id主要用来唯一的标识一个类的实例,我用的算法是类的完全限定名称和当前时间(1970年1月1日0:00至今的毫秒时间)的字符串组合,当然,你可以再进行一次摘要算法来保证准确性。类的完全限定名是指远程调用的类的名称,存在于RPCServer端,也就是这里的Android上。参数的类型和参数值,可以参考反射的知识,因为在RPCServer端要根据反射来调用相应的类。

RPCResponse里面也包括两个部分,ResponseHead和ResponseBody。其中Head也包括协议的版本信息,初次之外就是功能部分,其主要是在RPCServer端调用实例方法出现异常错误的时候传递的execepiton信息。Body部分和RequestHead部分一样,只不过最后多了个返回的结果信息。

除了上面两个类之外,你还要准备一个Handle接口,主要用来处理对上面RPCRequest、RPCResponse的具体解析,为了使RPC可以“跨平台”——指的是不只是针对pc和android,也可以是pc对pc,android对android。需要对打印信息进行封转,不过要记住,你先要判断你所在的平台,可以用System的getProperties方法,这个简单,就不用多讲了。

下面是我给的RPCRequest,RPCResponse的定义,仅供参考:

RPCRequest类的member及其类型:

private  Map<?,?> header;

private  String id;//实例的唯一标识,如果是静态的,可以不用加毫秒时间

private  String className;

private  String methodName;//用于Class的getMethod

private  Class<?>  parameterTypes;//用于Class的getMethod

private  Object[]   parameter;//用于Method的invoke

RPCResponse类的member及其类型:

private  Map<?,?> header;

private  String id;//实例的唯一标识,如果是静态的,可以不用加毫秒时间

private  String className;

private  String methodName;//用于Class的getMethod

private  Class<?>  parameterTypes;//用于Class的getMethod

private  Object[]   parameter;//用于Method的invoke

private  Object    result;//Method的invoke返回的参数(你要保证它可以被序列化)

上面我之所以一直强调要保持socket传递的对象必须可以序列化是因为我用的ObjectInputStream和ObjectOutputStream来传递对象的,当然,你可以有自己的序列化规则。好了,今天就到这里了,如果你还有什么疑问,可以email给我:zzcwfp@gmail.com。或者在我的博客留言!

补充:我只是在模拟器上实现了上述操作,真机没有试验过。注意adb forward命令使用啊,这里就不详细说了,你可以google一下。

请关注正正博客:http://www.2009fly.com 。在主站(http://www.2009fly.com )的博客会更新快于其它站(http://www.cnblogs.com/zzc1986 , http://blog.csdn.net/zzc1986 )的博客

原创粉丝点击