|
|
作者: 杨江
E CLA p p lic ati o n 客户端主程序说明
在 ECLApp lic at i on 的 mai n( ) 方法中,如果没有任 何参数传进来,那么就是说程序是在 手机启动的时候被初始化调用的,启动 Pu sh e d D at aLis t en e r 线程在后台 运行,监听 pu sh 来的数据。
class ECLApplication extends UiApplication {
private MenuItem _copyItem ;
/******************************************************************************************
* main() - controls the startup of the application...thread will start i n the background
* and the GUI starts when user clicks from main menu
******************************************************************************************/
public static void main(String[] args) {
if ( args != null && args. length > 0) { //entry point 是有参数 的,那么 打开 GUI 窗口
ECLApplication theApp = new ECLApplication();
theApp.enterEventDispatcher();
}
else { //entry point 是没有参 数的, 那么启 动 Pu sh ed Da ta Li st en er 线程在后 台运 行,监听 push 来的数 据
PushedDataListener.waitForSingleton ().start();
}
}
在 ECLApp lic at i on 的 ma in ( ) 方法中,如果发现有参数传进来,那么说是有用户点击
了应用图标,想打开 GU I 界面查看数据。
class ECLApplication extends UiApplication {
public static void main(String[] args) {
if ( args != null && args. length > 0) { //entry point 是有参数 的,那么 打开 GUI 窗口
ECLApplication theApp = new ECLApplication();
theApp.enterEventDispatcher();
}
else { //entry point 是没有参 数的, 那么启 动 Pu sh ed Da ta Li st en er 线程在后 台运 行,监听 push 来的数 据
PushedDataListener.waitForSingleton ().start();
}
}
在 ECLApplication 构造方法中,首先把应用的图标从未读状态,修改为已读状
态;然后调用 DataStore 类读取 PersistentStore 里面的数据,最后弹出
EclScreen 窗口以树状组件显示数据。
DataStore 和 EclScreen 代码因为和 Push 操作无关,这里就不再做代码分析 了。
public ECLApplication () {
…
Bitmap icon=Bitmap.getBitmapResource("icon/read.gif");
net.rim.blackberry.api.homescreen.HomeScreen.updateIcon(icon);
//call the datastore class
DataStore dataStore = new DataStore();
//opens the persistent store and loads in the group list dataStore.loadGroupListFromStore();
EclScreen screen = new EclScreen(dataStore);
pushScreen(screen);
}
Pu s h e d Da t aLis t e ne r 代码说明
Pu sh 监听代码是客户端 最核心的代码。 Pu sh .ja va 首先是使用 w ait Fo rSin glet o n ( ) 方 法达到手机上只有一个 Pu sh e dD a t aList en er 对象在运行的目的,然后构建并启动 List en er Th r ead 类开始 监听。
w ait Fo rSin gle t o n ( ) 方法把唯一的 Pu sh e dD a t aLis t en er 对象实例保存到 Runt im eSt or e 对象中,从而实现 sin glet on 模式。 Ru nt i meS t o re 在黑莓手机中是程序间共享的存 储空间,或者说所有程序都可以访问其他程序保存在 Runt ime St or e 里面的数据。 在手机重新启动后, Runt imeS t ore 被清空。
class PushedDataListener extends UiApplication {
ime
public static final long RTSID_MY_APP = 0x56b19e51d45ff827L;
private static final String LISTEN_URL = "http://:911" ; //the listen port
private ListenerThread myThread ;
public PushedDataListener() {
myThread = new ListenerThread();
}
public static PushedDataListener waitForSingleton (){
P u sh. jav a P u shedD ataL is te n er 的监听 代码放 在 L is te n erThread 类 中。 L is te n erT h read 类扩展 |
RuntimeStore store = RuntimeStore.getRuntimeStore ();
Object o = store.get( RTSID_MY_APP );
if (o == null ){
store.put( RTSID_MY_APP , new PushedDataListener());
return (PushedDataListener)store.get( RTSID_MY_APP );
} else {
return (PushedDataListener)o;
}
}
Th read 线程类,调用 ( S t reamConne c t i on N ot i f ier ) Conn ect or.o p e n ( LISTE N _UR L) 方法和
st ream = n ot i f y. acc ept An d Open () ; 代码开始监听 91 1 端口上 p u sh 过来 的数据。
收到数据后调用 D at aS t ore 方法保存数据到持久存储中,工 ECL GU I 进程显示数 据;然后调用 H omeS c reen .u pd a t eIc on ( ic on , 1) 代码更新 ECL 图标为未读提示 。
class ListenerThread extends Thread {
public void run() {
System. out .println( "eclBackGroundThread -- running" ); StreamConnectionNotifier notify = null ;
StreamConnection stream = null ; InputStream input = null ;
try {
sleep (1000);
}
catch (Exception e){}
try {
notify = (StreamConnectionNotifier)Connector. open ( LISTEN_URL );
for (;;) {
//NOTE: the following will block until data is received
stream = notify.acceptAndOpen();
input = stream.openInputStream();
后记: |
StringBuffer sb = new StringBuffer();
int datum = -1;
while ( -1 != (datum = input.read()) )
{
sb.append(( char )datum);
}
stream.close();
stream = null ;
String contactData = sb.toString(); DataStore dataStore = new DataStore(); dataStore.saveData(contactData);
Bitmap icon=Bitmap.getBitmapResource ( "icon/unread.gif" );
net.rim.blackberry.api.homescreen.HomeScreen. updateIcon (icon,1);
bytes) /n" );
System. err .println( "Push message received...(" +contactData.length()+ "
System. err .println(contactData);
常 见运 行错误 处理
1 . 模拟器无法收到 Pu sh 数据
解决办法:使用最新的 B lack b err y P lu gin f o r eclip se 1.1 版本,运行 项目的时
候选择启动 MD S 模拟 器。启动模拟器后,确认模拟器的网络连接是好的, 方法是打开浏
览器访问任意外网网站。
2 . 服务器端和客户端程序各自的端口不匹配
解决办法:在 ECL 例子程序中两个端口都是 911 ,注意查看。如果你 参考
ECL 代码编写自己的 Pu sh 程序,那么建议你把服务器和客户端的端口都修 改为非 91 1 的端口,以 避免在手机上参数监听端口冲突。
3 . 客户端程序没有 aut o st art ,因而没能启动监听 程序
解决办法:在 ECL 例子程序中,编辑 B lack B err y_App _ D escrip t or.x ml , 选择
Aut o - ru n o n s t art u p ,并 在代码的 main ( ) 方法中相应处理,启动 list en e r th rea d 在后台开始监听 。
4 . 客户端收到的文字中文乱码 解决办法:首先,服务器端代码在提出 Pu sh 请求时候要通过
HttpURLConnection.setRequestProperty ( ("Conten t -Type",… ) 方法告诉 B ES /MD S 服务器,它将发送什么样的内容。如果是 Con t en t - Type 是 t ext / p lai n ,那么 服务器将以 gb 23 12 编 码发送数据;为代码清晰起见,建议设置 Con t en t-
Type 为 t ext /p lai n ; c h ars et =u tf-8 。
public void sendToHandheld(String recipientEmail) … {
HttpURLConnection conn = null;
…
establishRequestHeaders(conn);
…
}
protected void establishRequestHeaders(HttpURLConnection conn) {
conn.setRequestProperty("Content-Type", "text/plain ; charset=utf-8 ");
}
其次,客户端接收数据的时候,建议读取 b yte [] ,然后按照服务器 Co nt e n t-
Type 相同的编码进行转码获得字符 串 St ring 。
stream = notify.acceptAndOpen();
input = stream.openInputStream();
//Extract the data from the input stream byte[] bytes = loadBytesFromStream(input); stream.close();
stream = null;
String contactData = new String(bytes , “UTF-8” );
英文缩 写说明
BES – Bla ckBe rr y Enterpr is e Ser v er , 是 Bla ck Berry 解 决方案的 核心服 务器之一 ,架设在 企业 内网。
MD S – Bla c kBerr y Mo b il e D ata Sy s te m ,是 BES 服务 器的一个 重要组 件。在 Pu sh 技术中,
MD S 接 受 P u sh 请 求,然 后通过 BES 其他组 件把数 据推送出 去。
参考资 料
1 . BES 服务器推 送机制 分析
ht t p : / / ww w . s earchc i o. c o m.cn /whitepa p er _ 1 1 61. h tm
2 . What Is - Sa m p le app li cati on s dem o n stra tin g BlackB er ry pu sh te chn o l o g y : E m erg ency
Co n tac t L is t h tt p : / / ww w.bl ackberry. com / go / ecl
附录:
一.如何更换不同版本的 Bl a c k B e r r y S DK ?
由于不同 Bla ckB erry 手机 使用不同 版本的 OS, 所以 在应用编 译的时 候,需要 使用不同 的
Bla ckBe rr y S D K 。
首先可以 在 Eclip se 中获 取所有版 本的 Bla c kBerr y SDK , 目前有的 包括 4 .5, 4 .6 和 5 . 0 版本 : Eclip se à H elp à In s tall N ew S o ftw are à 输入 URL :
ht t p : / / ww w . b la c kberry.c o m/ g o /eclip s eU pdat e /3 . 5/j a va
然后进 行 更新即 可。
二. 如何选择 不同版本的 Bl a c k B e r r y S DK ?
或者 : 在 J RE Syste m L ib rar y 右击 鼠标, 属性中 选择 不同的 S D K 即可 。
三 . ECL sa m p le Br o ws er p u sh 中文问题 的解决
现象: x y z li st.xls 数 据源里 面有中文 ,通过 M D S 服 务器 pu sh 到手机 里面的 网页,中 文是乱 码,显示 不正常 。
ste p 1 . 编辑 ECL _Ja v a / src / Serve r / Br o ws erChann elP u s h er.java
把
c o n .se tRe qu es tP r o p er ty ('C o n te n t -T y p e', 't ex t / h t m l' );
修改为
c o n .se tRe qu es tP r o p er ty ('C o n te n t -T y p e', 't ex t / h t m l; cha rset =gb 2 3 1 2 ' );
ste p 2 . 重新 编译生 成 ECL _ J ava/ b in / S erv er/ ecl.jar
执行 ECL _Ja v a / src / Ser v er / bu ild .b at
ste p 3 . 重新 运行 pu sh ser v er/ cli ent 测试 即可
BlackBerry SDK下载
BES 推送应用实例演示与分析(一)
BES 推送应用实例演示与分析(二)
BES 推送应用实例演示与分析(三)