您的位置:首页 > 其它

BES 推送应用实例演示与分析(二)

2010-09-15 14:43 357 查看
作者:
杨江

第三
部分

手机端

码导


E
clip
se

1
.

打开

Eclip
se
,



2
.

Fi
le


I
m
p
o
r
t
,




Gene
ral

à
Existin
g
P
r
o
jec
ts
t
o
Wo
r
kspace











第四
部分

核心代码
分析

Bl
ac
kB
e
rr
y


Pu
s
h


架构

在分析样例代码之前,首先让我们从整体上了解

B
lack
B
err
y

Pu
sh

架构


更加详细的

B
lack
B
err
y

推送机制的分析和介绍,请参考黑莓官方网站,以及参考资

料“
B
ES

服务器推送机制分析”。



从示意图中,我们可以看到,在

B
lack
B
err
y


用平台上的数据推送从整体上可以分

为六步,按时间顺序分别为:

1


应用服务器向

MD
S/
B
E
S

服务器发送推送请求,该请求为

H
TTP
POST

请求。

2/3


M
D
S/
B
ES

服务器
做必要的权限和数据监测,告知应用服务器推送请求是否被

接受并将被执行。

4

MD
S
/
B
ES

服务器通过

B
lack
B
err
y Inf
rast
ru
ct
u
re

和无线网络把数据
推送到手持设

备端。

5


手持设备收到数据
后,向

MD
S/
B
ES

服务
器反馈。

6

MD
S
/
B
ES

服务器告知应用服务器其推送数据是否送达手持
设备。

ECL



统架




B
lack
B
err
y Pu
sh

系统架构上看,从服务器端

Pu
sh

数据到手机端
,要经过多个服

务器和网络甚至无线基站,整个流程相当复杂。幸运的是,从应用开发的角度,程

序员可以不考虑

Pu
sh

的复杂底层实现,而只需简单地发送

Pu
sh


求并监听

Pu
sh
请求的处理状态,客户端监听并接受推送数据即可:

1


服务器程序向

MD
S/
B
E
S

服务器发送推送请求,所发送的请求为

H
TTP

POST

请求。

2


手持设备上的

Java

客户端程序接收

pu
sh


来的数据,做出灯光闪烁

/
振铃

等提示,甚至修改桌面图标提示用户,用
户打开程序界面查看数据。

3


服务器程序从

MD
S/
B
E
S

服务器获得推送请求是否完成的状态信息。

Ja
v
a





E

CL


服务器代码
分析

核心代码说
明,

Ja
v
a


类列表

Java

版本

ECL

服务器程序是一个命令行程序,根据命令行参数把指定

exc
el

表格中

的联系人列表

c
ont
act
li
st

数据推送给指定的手机上。

1
.

主程序:是
ec
lTim
e
dU
pda
te.ja
va

,这是一个包


main()

方法的控制程
序,根

据不同参数调用两个
P
usher

类做
Brow
se
r Push


Custom
i
z
e P
ush



2
.

核心

P
ush

代码
:由

B
row
s
e
rCha
nne
lP
usher
.j
a
va/Custom
AppPushe
r.ja
va/P
usher
.java

三个类构
成。

3
.

服务器配置信息:

MdsP
rope
rties.ja
va

等四个类
用于读取配置文本文件,让

EC
L

服务器主程序获


MDS/B
ES

服务器

I
P

地址端口号等信息。

4
.

数据访问:
Da
taRea
d
e
r.
java

通过

J
DB
C
-
OD
B
C

接口读取

Ex
ce
l

表单数据。

EC
L

服务器程序各个
J
a
va

类的功能说明列表如
下:

Java Class


De
scr
ip
tion


eclTi
m
edUpdate.
j
ava

包含
main()

方法的控制
程序,根据不同参数调

用两个
P
usher

类做
B
ro
wse
r Push


Custom
iz
e

P
ush

Bro
w
s
erChannel
P
usher.
j
ava

Custom
AppPushe
r.ja
va

Pushe
r
.java

核心的服务器

P
ush

代码,包括

B
row
s
e
r pushe
r



c
ustom

应用

pushe
r



B
row
s
e
r pushe
r


c
usto
m

应用
pushe
r

的共同父

类是
P
usher
.java

MdsP
rope
rties.ja
va Ca
tche
rPrope
rties.java Cha
nne
lP
rope
rties.ja
va S
trong
l
y
T
y
pe
dP
ropertiesSet.java

MdsP
rope
rties.ja
va

读取

MDS

服务器参数,比如

B
ES

服务器主机名
/
I
P

地址
/

端口号。

Ca
tche
rPrope
rties.ja
va

读取手机端监听端口。

Cha
nne
lP
rope
rties.ja
va

读取浏览器
P
ush

相关参

数。

配置文件
样本:

#
The
name
of
the
machine
that
hosts
the

MDS

push
server

BesHostName
=
localhost

#
The
port
on
which
the
MDS
Push
service is
listening.

#
(Set
equal
to
the

"WebServer.listen.port"

property
for
the

MDS.)

BesPushPort

=
8080

#
The
port
that
the
device
-side
catcher app
is
listening
on.

DeviceListenPort
=
911

Da
taRea
d
e
r.ja
v
a

S
prea
dshee
tP
rop
e
rties.ja
va

Da
taRea
d
e
r

通过
J
DB
C
-
OD
B
C

接口读取

Ex
ce
l



单数据


紧急情况联系人列表。

e

c

lTime
d
U
pd
a
te
.j
a
v
a


代码分析


据参
数构造

P

us
her



(BrowserC
ha
nn
elP
us
her


或者

C

ust
omAp
pPusher
)

作为整个服务器端推送数据程序的入口,

eclTimed
Up
d
at
e.java

是一个
标准的

J2
SE
程序。



main
(
)
方法中首先分析第一个参数。如果参数值是

c
h
ann
el

,则构


pu
sh
er



B
ro
w
serCh
ann
el
Pu
sh
er

类;如果参数值是

c
at
c
h
er

,则构造

p
u
sh
er



Cust
omAp
p
P
u
sh
er

类。

public static void main(String[] args)



// Process command-line arguments

if


(args.
length
>= 1) {

if


(args[0].equalsIgnoreCase(
"channel"
)) {

// Construct a pusher that sends to a browser channel.

pusher =
new


BrowserChannelPusher
();
//Browser push
也是一个很有
趣的话


}
else


if


(args[0].equalsIgnoreCase(
"catcher"
)) {

// Construct a pusher that sends to a custom catcher.

pusher =
new


CustomAppPusher
();

}

}


据参
数从文
本文
件中读


Bl
a
ckBe
rry





P

IN



列表

例如从

simu
lat
o
remail.tx
t

文件中读取到的

PIN

码为黑莓模拟器的

PIN



21
00
00
0a



提示:
B
lack
B
err
y MD
S/B
ES

服务器支持以手机

PIN

码和

email

地址识
别要推送的目

标手机。在

ECL

样例程序中是使用手机

PIN

码。

if (args.length >= 2) {

emailListFile = args[1];

}





// Get the list of emails to push to.

List recipientEmails = getRecipients(emailListFile);


据参
数从

ex
cel


表格

件中
读取

ECL


联系人
列表

在这里调用
D
at
aRea
d
er
类访问
Exc
el
表,读取每个组和每个人的联系方式,并通过

pu
sh
e
r.add
Co
nt
ac
t
(
d
at
a
Field
s)
;

方法把数据传递

pu
sh
e
r

,最后调用

pu
sh
e
r.f
in
is
h
ed
Co
n
st
r
u
c
t
ion
()
;

方法告诉

pu
sh
er

数据全部读取完毕。
P
u
sh
er

会把所有

联系人方式构造成一个

x
ml
字符串保存起来以备下一步调用

pu
sh
e
r.sen
d
ToH
an
dh
el
d(c
u
rRec
ip
ient
)
;

进行发送


// Fetch the group names from the spreadsheet.

Vector groupDescription = dataReader.getGroupList();

// Assemble the data of all contacts (from all groups) that we

// will push to handhelds.

for


(
int


i = 0;
i < groupDescription.size();
i++) {

// Define the current group.

pusher.beginGroup((String)groupDescription.elementAt(i));

// Add all its members.

Vector groupContactList = dataReader.getContactList(

(String)groupDescription.elementAt(i));

for


(
int


j = 0;
j < groupContactList.size();
j++) {

String[] dataFields = dataReader.getContactData(

(String)groupContactList.elementAt(j));

pusher.addContact(dataFields);

}

}

// Indicate that we're done building the contacts list.
After,

// the pusher is ready to send the message multiple times.

pusher.finishedConstruction();




p

us
her.sen
dT
oH
a
n
dh
eld
()

推送
数据
到每
一部
黑莓手
机上


做一个

Fo
r

循环,多次调用

pu
sh
e
r.sen
d
ToH
an
dh
el
d
(c
u
rRec
ip
ie
nt
)




B
ES/MD
S



务器把数据发送到各个手机上面。

// Push the message we just built to all recipients.

for


(
int


i = 0;
i < recipientEmails.size();
i++) {

String curRecipient = (String)recipientEmails.get(i);

try


{

System.
out

.print(
"Contacting BES for "
+ curRecipient);

pusher.sendToHandheld(curRecipient);
System.
out

.println(
" - successful push."
);

}
catch


(Pusher.MDSConnectionException ex) {

// Unable to connect to MDS.
The condition is unlikely

// to be temporary so abort.

System.
out

.println(
" - "
+ ex.getMessage());

Pu
s
he
r.j
av
a


代码分析

break

;

}
catch


(Pusher.MDSResponseException ex) {

// Connected OK but MDS responded with error.
Log it and

// try the next email.

System.
out

.println(
" - MDS responded with "

+ ex.getMessage());

}
catch


(Exception ex) {

// Unexpected error.
Log a full stack trace and try the

// next email.

System.
out

.println(
" - unexpected error:"
);

ex.printStackTrace();

}

}

Pu
sh
e
r.java

代码实际上包括两部分内容,一部分是准备要推送的数据,一部分是真

正的推送操作。

B
egin
Group
(
)

ad
d
Cont
a
c
t
(
)

f
in
ish
e
d
Con
s
t
ru
ct
ion
(
)

三个方法是用来准备要推送的数

据。主逻辑程序多次调用这三个方法
告诉

Pusher

有哪些联系人数据要推送。

Pusher

会把这些数据拼装成一个

html

或者是一个大文本,并最终推送给手机浏

览器或者手机客户端程序。

writeTo(OutputStream)
方法用来把前面三个方法

构造出来的数据写到输出流中。

注意:以上

4

个方法和

push

无关,更好的做法应该是把他们分离出去做一个独

立的数据构造类。

Pusher.java
代码的核心方法是

sendToHandheld(String recipientEmail)
。该方法构造标准的

http POST
请求给
MDS/BES
服务器,通

过参数
DESTINATION

指定要把数据
push
给哪些人(参数值可以是
email

地址或

者是手机
PIN
码),参数

PORT
告知要把数据推送到手机上面哪个端口(例子代码

中是端口
911
)。

/**

* Pushes the already
-
constructed message to the indicated recipient.
May

* be used many times, but only in the "sending" state.

*/

public


void


sendToHandheld(String recipientEmail)

throws


IOException, MDSConnectionException, MDSResponseException

{

HttpURLConnection conn =
null

;

OutputStream out =
null

;

try


{

// Build the URL to define our connection to the BES.

URL url =
new


URL(
"http"
,
_props
.getBesHostName(),

_props
.getBesPushPort(),

"/push?DESTINATION="
+ recipientEmail

+
"&PORT="
+ getDevicePort()

+
"&REQUESTURI=/"
);

conn = (HttpURLConnection)url.openConnection();

conn.setDoOutput(true

);

//to post data

conn.setRequestMethod("POST"
);

establishRequestHeaders(conn);

//write the data to the http connection

out = conn.getOutputStream();

writeTo(out);

// Check the MDS's response so that we report an error if the push

// was unsuccessful.

int


responseCode = conn.getResponseCode();

if


(responseCode != HttpURLConnection.

HTTP_OK

) {

String serverMessage = conn.getResponseMessage();

throw


new


MDSResponseException(

"HTTP-"
+ responseCode +
": "
+ serverMessage);

}

核心代码说
明,

Ja
v
a


类列表

客户端代码由三个

Java

类,两个图标文件,
B
lack
B
err
y

应用描述文件
构成。



EC
L

客户端程序三个
J
a
va

类的功能说明列表如
下:

Java Class


Pushe
d
D
a
t
a
Lis
t
ener

在指定端口
911

上监听
push

过来的数据。收到

后调用
Da
taSt
or
e

,修
改手机上应用的图标以提

示用户有更新过的联系人列表。

EC
LApplic
a
t
i
on

客户端主程序,通过配置,最终会在客户端启

动两个
J
a
va

进程:后台运行的

P
ushed
Da
ta
L
ist
e
ne
r


来监听

push

过来的数据;

前台

GU
I

界面

EC
L
App
li
ca
ti
on

和内部类

Ec
lS
c
re
e
n

用于展现收
到的

push

数据


联系人列

表。

Da
taSt
or
e

使用

net.rim.device.api.system.PersistentStore

保存最新

ECL

联系
人员列
表数据。

E

C

L


客户端程序的
两个入口


(A
lt
e
r
nat
e


E

n

t

ry

P
o
i
nt
s
)



EC
L

客户端程序是如何
自动启动监听程序的?又是如何区分点击

icon

启动

GU
I



面程序的呢?答案在应用描述文件
B
lac
k
B
e
rr
y
_App_De
sc
riptor.x
ml

和主程序的
main()

方法上。

打开
B
lac
k
B
e
rr
y
_App_
De
sc
riptor.x
ml

,在
Applica
ti
on

标签栏目里面,你会看到

Auto-
run o
n sta
rtup

被选
中。这样,

EC
L
S
a
mpl
e

程序会在手机启动过程中自动地启

动,产生一个后台
J
a
va

进程监听
P
ush

数据。


Alter
na
te En
tr
y
P
oint
s

栏目中,设置了一个参数
Applica
ti
on a
r
g
ume
nt



g
ui

,并

单独设置了程序
Titl
e



I
c
on

,因此程序安装
后在“下载”目录里面出现一个应用

图标。点击图标将产生一个前台
GU
I

进程来读
取并显示
P
ush

过来的数据。



BlackBerry SDK下载

BlackBerry Java Plug-in for Eclipse v1.1

Java Plug-in for Eclipse Update Site

BlackBerry Web Plug-in v2.0

BlackBerry Widget SDK v1.0

BlackBerry Theme Studio v5.0

Plazmic Content Developer’s Kit v4.7

BlackBerry smartphone simulators

BES 推送应用实例演示与分析(一)

BES 推送应用实例演示与分析(二)

BES 推送应用实例演示与分析(三)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: