Push注册机制介绍
MIDP2.0引入了Push注册机制,作为一种允许应用被自动启动的方法,由预先设置的警告或者经inbound连接收到的消息。
通过这种方法,MIDlets可以用来设置处理规则事件,如定时从
服务器上同步数据,或者非规则事件如一个突来的消息。
Push注册机制由javax.microedtion.io.PushRegistry类管理,它还是应用
程序管理系统——它处理所有事件——的一部分。
警告事件通过指定MIDlet名称和启动时间进行注册。对于任何MIDlet只能注册一个警告事件,因此注册一个新的警告会重写注册机制中以前的任何警告。这种情况可以被检测到,因为若原来存在警告,注册方法会返回被重写的警告的时间。
无线消息API(Wireless Messaging API)可以和Push注册机制联合使用,通过消息监听器来处理到来的消息,消息监听器实现在AMS启动MIDlet后处理消息有效载荷的逻辑。在这种情况下,MIDlet会注册一个特定的端口号和消息类型作为启动MIDlet的触发器,AMS监视端口的行为,以寻找在该端口上的正确
网络请求。另外,注册的连接可能被过滤,允许MIDlet指定只有来自特定服务器的连接作为启动MIDlet的触发器。
使用Push注册机制的效果 如果警告到来时,注册了这个警告的MIDlet正在运行中,那么这个MIDlet会继续运行,而警告会被忽略。如果MIDlet没有运行,它就会被启动。
类似地,如果inbound连接出现时,而注册了这个连接的MIDlet也已经在运行中,MIDlet会处理那个连接(若代码指定了,就包括任何消息的有效载荷),就不再提交给用户。
如果没有MIDlet在运行中,用户会收到消息的通知,并且会被给予是否运行MIDlet的选择。
如果另外一个MIDlet在运行中,用户会被给予是否运行与这个消息相关的MIDlet的选择:若选择运行,就会终止当前运行的MIDlet。
如果收到多个消息,AMS会排队等候到5,并且传递要读取的选择,依顺序按消息进行操作,包括联合push动作。
如果没有应用程序被注册为push,到来的push消息会被忽略。
方法 PushRegistry类包含了以下的方法:
·getFilter(),为连接返回一个<AllowedSender>值(可能是一个服务器IP地址、一个以逗号分割的IP地址列表,或者一个“*”表示允许任何连接)。
·getMidlet(),返回为特定的连接注册的MIDlet名称。
·listConnections(),返回为特定的MIDlet套件push连接列表。
·registerAlarm(),注册一个基于定时器的触发器来启动MIDlet,或者若变量被设置为0,则取消对MIDlet已经存在的警告 l registerConnection(),为MIDlet注册一个连接
·unregisterConnection(),同样取消一个连接的注册
异常 应该捕获异常有:
ClassNotFoundException、ConnectionNotFoundException、IllegalArgumetException、IOException和SecurityException。
ConnectionNotFoundException和IOException可能遇到,因为请求端口或者连接类型可能不会连续可用,因此应该为这种情况编写处理代码。
网络连接和push注册机制是特别的操作,MIDlet在使用它们之前必须有正确的许可,因此需要捕获SecurityException。
连接(Connection) 连接包括三种类型:TCP Socket,UDP数据包或者SMS。
当前在所有的Motorola手机范围内,只有SMS是适合于inbound连接的可用类型。UDP数据包只能用于最新的手机(2005年后半年发行的,例如,V3X、E1070,等等)。从这点出发,这篇文章将不会讲解TCP Socket,而对UDP数据包也只是有少许讲解。
使用SMS连接 注意到以下的这点是很有用的,如果需要进一步的数据交换,在被到来的消息唤醒后,MIDlet可以初始化一个Socket或者HTTP连接。
指定的端口可以是从1到65535的范围中的任何一个,然而下面的端口是被保留的,必须不能使用:
2805 WAP WTA
安全非连接会话服务
2923 WAP WTA 安全会话服务
2948 WAP Push无连接会话服务(客户端)
2949 WAP Push安全无连接会话服务(客户端)
5502 Service Card Reader
5503 因特网访问配置阅读器
5508 动态菜单控制协议(Dynamic Menu Control Protocol)
5511 消息访问协议(Message Access Protocol)
5512 简单邮件通知(Simple e-mail 通知)
9200 WAP无连接会话服务
9201 WAP会话服务
9202 WAP安全无连接会话服务
9203 WAP安全会话服务
9207 WAP vCal安全 49996 SyncML OTA 配置
49999 WAP OTA配置
注意:上面的端口号不能注册为任何其它类型的动作,否则注册请求会失败。参考JSR 120无线消息API(Wireless Messaging API),A.6.0部分给出了一个保留端口的权威列表。
使用数据包连接 开发者必须清楚,网络上的限制条件可能会阻碍传递给一个正在监听的设备的UDP/IP数据包通信量。
大部分的操作者使用DHCP(Dynamic Host Configuration Protocol, 动态主机配置协议)只为活动的用户分配IP地址。一个活动的用户可以是一个启动网络应用程序的用户,或者是使手机建立PDP上下文的浏览器,如果没有建立的PDP上下文,你也不可能拥有任何IP地址。
另外,你的移动设备被(操作者)分配的实际的IP地址很可能是10.x.x.x或者192.168.x.x等保留范围中一个,针对这些保留IP范围的规范就是任何外部的
路由器遇到这个IP地址时会丢弃数据包不再发送。
当然,也有一些情况会按照预期工作,但是最可靠的选择是使用SMS作为MIDlet触发器,那么MIDlet应该建立一个支持的连接以得到预期的数据。
使用警告 警告由完整的MIDlet名称和一个与Date.getTime()方法得到整数同样格式的长整数(自从1970年1月1号到现在的毫秒数)指定。
注册 Push注册机制可以处理请求来注册连接通过两种方式:运行时的动态注册和JAD文件中条目静态注册。
动态注册 动态注册是一个MIDlet在运行时通知AMS,它希望被到来的网络连接激活或者警告事件,MIDlet应该先于事件发生退出。
注册连接,要使用registerConnection方法:
registerConnection(String connection, String midlet, String filter)
并且可以使用this.getClass().getName()指定当前的MIDlet.
注册警告,要使用registerAlarm方法:
registerAlarm(String midlet, long time)
并且now.getTime() + (1000 * 60 * 60)可以被用来指定警告时间,从现在开始一个小时(以毫秒形式)。 动态注册例子:
registerConnection(“sms://:” + portNumber); registerConnection(“datagram://:” + protNumber); |
静态注册 如果一个连接发送者和连接类型在MIDlet安装时可以知道,注册请求在安装时完成,因此被认为静态的。静态请求在JAD文件中使用Midlet-Push-<n>属性定义:
MIDlet-Push-<n>: <ConnectionURL>, <MIDletClassName>, <AllowedSender>
n是一个顺序数,允许声明多于一个连接,ConnectionURL是用来监视到来的连接的URL,MIDletClassName是要启动的MIDlet,AllowedSender是过滤器:IP地址列表或者“*”(任意地址)。SMS连接的例子:
MIDlet-Push-1: sms://:10000, TestMIDlet, *
数据包例子:
MIDlet-Push-2: datagram://:50000, TestMIDlet, *
“*”在IP地址中也可以用作通配符,所以像142.100.200.*或者142.*也可以用来指定地址组。
警告必须要动态注册,那么就没有静态注册的等价物。
取消注册 动态注册可以通过使用unregisterConnection移除,只需要指定连接:
unregisterConnection(“sms://:10000”);
静态注册只有在安装时可被改变,因此顺序是卸载MIDlet,改变JAD属性然后重新安装MIDlet。卸载MIDlet总是会移除所有静态注册。
例子
为了确定MIDlet是否被到来的
信息调用:
在startApp():
String connectsFound[]; connectsFound = PushRegistry.listConnections(true); |
上面的代码返回注册的连接列表。
if (connectsFound == null || connectsFound.length == 0) { ~由用户启动、编码来推出或者忽略push相关动作~ } else { ~由inbound连接启动,因此编码为Push注册机制初始化~ } |
为了定时一个警告动作 在这个线程入口点的run()方法中:
private void scheduleMIDlet(long targettime) throws ClassNotFoundException, ConnectionNotFoundException, SecurityException { String md = this.getClass().getName(); Date alarm = new Date(); long tm = PushRegistry.registerAlarm(md, alarm.getTime() + targettime); |
在清除和释放资源后destroyApp():
scheduleMIDlet(defaultDeltaTime); |
查看本文来源