您的位置:首页 > 其它

如何将MIDlet应用移植到BlackBerry(四)

2010-09-13 23:47 204 查看
作者:
邓明轩、王恒进、王志刚

使


P

ersist
ent


S

t

or
e


进行存储



Bla
ck
Be
rr
y


台上
还可
以通


P
er
s
ist
en
tS
t
o
r
e

存储
数据,
这种
方法
可以
将对
象直接


存在设
备内
存中


要使
用的时
候可
以通


AP
I


设备内
存中
直接
读取
出来

读取
出来
看获

得的是一


o
bjec
t


象,
需要开
发人
员对
该对
象进
行强制
转换


相比

RunT
im
eSt
o
r
e


P
er
s
ist
en
tS
t
o
r
e

的好处
是可
以持
久保存
数据
,即
使设
备掉
电数据


不会丢
失。
不过
,使用

P
e
r
s
ist
en
t
S
t
o
r
e

要求被
保存的
数据必
须实现

P
er
s
ist
ab
le

接口。
如下


代码所
示,
如果
希望


My
Da
t
a

实例
保存


P
er
s
ist
en
tS
t
o
r
e

中,

M
yDa
t
a


需要实


P
er
s
ist
ab
le
接口:

public

class


MyData

implements


Persistable
{

//
其中为
MyData

方法和
属性定义


}




P
er
s
ist
en
tS
t
o
r
e

中保
存的
对象以
一个
长整型


ID


为标记

保存
或者
是获
取该
对象都

以这个
长整
型的

I
D


为参
数。为
了保
证所
保存
的对
象和其
它应
用保
存的
对象
不冲突
,可


通过

ha
s
h


法通
过包
名生
成一个
长整


ID


Bla
ck
Ber
ry

E
cl
ips
e

P
lu
g-i
n

环境
也提
供了一
个方

法将字
符串
转换
成长
整型
,选中
某一
行字
符串
,点
击右键
,选
择“

Co
n
v
er
t
St
r
in
g
t
o
lo
ng
”,

可以将
选中
的字
符串
转换
成长整
数。

无论用
什么
方式
生成
长整
数,对


ID

的定
义语
句都
类似于
以下
代码


public

static
long


PersistentID

=
0x815402392d453a9d
L;

定义


P
er
s
ist
en
t
ID

后,可
以通


P
er
s
ist
en
tS
t
o
r
e

的静
态方


g
et
P
er
s
ist
en
t
Ob
ject

获得所

保存的
持久
化对
象,
g
et
P
e
r
s
ist
en
t
Ob
ject

方法只有一
个参数
,为
保存
对象


ID

,本例
使用


面定义


P
er
s
ist
en
t
ID



获得持
外化
对象
以后
,可
以通过
该实例


g
et
Co
n
t
en
t
s

方法获
得真
正保
存在设
备内存


对象,
可以通


s
et
Co
n
t
en
t
s

将内存中
的对
象保
存到
持久化
对象
中。
在获
得对
象的过
程中


得要将
返回


Ob
j
ect

实例
强制转
换为
你使
用的类

在保存
对象
时记
得要调


P
ers
ist
en
tSot
r
e



c
omm
it

方法
完成
保存动
作。

P
ers
ist
en
tS
t
o
r
e

使用
的代码
片段如
下:

PersistentObject

persistentStore

;

persistentStore

=
PersistentStore.
getPersistentObject

(

PersistentID

);

synchronized


(
persistentStore

)
{

if


(
persistentStore

.getContents()
==

null

)
{

myData

=

new


MyData();
persistentStore

.setContents(
myData

);
persistentStore

.commit();

}

else


{

myData

=
(
MyData)

persistentStore

.getContents();

}

}

}

使


SQLit
e









Bla
ck
Be
rry

5
.
0


上的
平台上
提供了


S
ql
it
e


支持,
使开
发人
员可以


Bla
ck
Be
rry
手机上
使用
关系
型数
据库
。对于


MI
Dl
et

移植


Bl
ac
kBe
rry

上的
开发
人员

言,这
无疑


一个好
消息
,使
用关
系型
数据库
保存
数据
可以
让程
序更加
简单
有效


当然,
决定
是否
将数
据存
储方式
由之
前的

RMS

转变
为关系
型数
据库
,具
体要
看应用


规模和
数据
类型


般而
言,

果应
用规
模不
大,
数据类
型更
接近
树状
的文
档结构


不建

议使用
关系
型数
据库


之,
如果
应用
规模较大

而且需
要存
储的
数据
是大
批量的
规整
的数

据,则
使用
关系
型数
据库
比较有
利。

从具体
实现
上讲
,在

Bla
ck
Berr
y


台上


Da
t
ab
a
s
eF
a
ct
o
ry

可以用
于创
建或
者是
连接数

据库,
所创
建的
数据
库以一
个文件
的形
式保
存在
设备
中,

以是
设备
内存,
也可
以是媒
体卡
































Da
t
ab
a
s
e















Da
t
ab
a
s
e

实例


cre
a
t
eSt
a
t
emen
t


法创建
一句

S
QL

语句
,通


S
t
a
t
emen
t

实例


pr
ep
ar
e

方法
准备执
行,


后通过该实例


e
x
ecut
e

方法执行。如
果是查询语句,可以


p
r
epa
r
e

方法执行后,通


g
et
Cu
r
so
r


得查
询结
果的
光标,
再通
过光
标操
作获
得所查
询的
内容


下面是
创建
或者
是连
接数
据库的
语句


String
dbLocation
=

"/SDCard/databases/SQLite
Demo
/"

; URI
uri
=
URI.create

(dbLocation
+

"mydb
"
);

Database

db
=
DatabaseFactory.
openOrCreate

(uri,

new


DatabaseSecurityOptions(

false

))
;

下面是
执行
查询
语句
的代
码片段


Statement
statement
=

_db
.createStatement(

"SELECT
*
FROM
Category"

);

statement.prepare();

Cursor
cursor
=
statement.getCursor();

下面是
查询
后遍
历结
果的
代码片
段:

Row
row;

int


id; String
nam
e;

while

(c
ur
s
or
.n
ex
t(
))

{

ro
w
=
c
ur
so
r.
ge
tR
ow
()
;

id
=
r
o
w.
ge
tI
nt
eg
er(0);

na
me
=

ro
w.
ge
tS
tr
in
g(
1)
;

}

使用完
之后
记得要


S
t
a
t
emen
t

实例


Cu
r
so
r

实例关
闭,如


statement.
close();

cursor.clo
se();

对于

S
QLi
t
e

的使用

关键
点是

S
QLi
t
e

是一
个轻
量级


S
QL


据库

不能
支持
所有


S
QL
功能。

方面
是在
数据格
式上只
支持
简单
的类


In
t
eg
er


T
e
xt


样的
类型,

一方面
是所


持的

S
QL

语句
也有
限,不
支持复
杂的
查询
操作


有关

S
QLi
t
e

的更
多信
息可
以在下
面的
网站
中找
到:

h
t
t
p://www
.s
ql
it
e.o
r
g
/

使用全局事件
来进行应用交


对于应
用通讯

只能
共享
数据是
不足
够的


共享
数据之
后需
要通
知相
应的
应用




标应用
可以
对数
据变
化进
行响应


Bla
ck
Be
rry

平台
提供
了事
件模型
,用
来在
不同
的应
用之间
通信

Bla
c
kBe
rry

上的任
何应

用程序
都可
以发
布或
者监
听全局
事件
,发
布全
局事
件的时
候需
要指
定一
个事


ID


,一


应用所
发布
的事
件会
被所
有监听
全局
事件
的应
用获
取,不
同的
应用
需要
通过

I
D

号判
断是


对该事
件进
行处
理。
另外


发送
全局
事件的
过程
中可以
同时
发送
一些
简单
的数据

使用


来会更
简单
一些


是对
于大量
的数
据,
一般
采用
的方式
是先
将数
据保
存到
特定的
共享
空间

中,然
后通
过事
件通
知目
标应用


首先需
要定
义一
个全
局事
件,对
于全
局事
件的
定义

Bla
ck
Ber
ry

有自
己的
定义
规范:

l

定义一


ID

变量

l



ID


量定
义为
静态
的,
从而使
得其
他的
类也
可以
引用到

l

通对包名


HA
S
H




ID

,使

ID

变得
独一
无二

示例代
码如


public

static

long


GLOBAL_ID
=
0xba4b84944bb7429eL;

定义了
全局
事件
后可
以将
该事件
发布

,

过把
事件

ID

传递


po
s
t
G
lo
ba
lE
v
en
t
(
)

方法中



我们可
以发
布一
个全
局事


Bla
ck
Be
rr
y


供了
有四
种不
同的方
法来
发布
一个
事件

简单的
方法
是只
传入事


I
D

不带

数据,
相对
复杂
的方
法在
发布事
件时
可以
传入
两个
整数作
为随
事件
发布
的内
容,

复杂
的可

以在发
布事
件时
传入
对象
作为发
布的
内容

开发
人员
可以根
据自
己程
序的
复杂
程序决
定使


什么方
法发
布一
个事
件。

最简单
的发
布事
件的
示例
代码如
下:

ApplicationManager.getApplicationManager()

.postGlobalEvent(GLOBAL_ID);

对于事
件接
受者
来说
,需
要考虑
和实
现的
关键
点如


·

全局监
听应
用程
序必
须要
是一个
自动
启动
应用
程序

·

监听程
序需
要有
类实
现一


G
lo
ba
l
E
v
en
t
List
ene
r

接口

·

监听程
序需
要添


G
lo
ba
lE
v
en
t
List
ener

实例

实现
Globa
lEven
t
L
ist
e
n
e
r

和添加
ClobalEve
nt
L
i
stene
r

的示例代码如下


class


GlobalEventListenerApp

extends


UiApplication

i

mp
le
me
nt
s


GlobalEventListener
{

public


GlobalEventListenerApp()
{

addGlobalEventListener
(
this


);

}

}

对于实


G
lo
ba
lE
v
en
t
List
ener

接口
的类


然实


ev
e
n
t
O
cc
ure
d

方法
以响
应全局
事件的

发生。
需要
注意
的一
点是
不管事
件由
谁发
布,
也不
管事件
是系
统事
件还
是程
序发布
的事件


只要有
事件
发生
,一
个注
册过


G
lo
ba
lEn
v
en
t
List
ene
r



ev
en
t
O
cc
ur
e
d

都会被
调用,
这意


着开发
人员
需要
自己
通过
事件

ID

进行
判断


果事


ID


于需
要处
理的
范围
才对事
件进


响应。
示例
代码
如下


public

void


eventOccured(

long


guid,

int


data0,

int


dat1,

Object
object0,
Object
object1
)
{

//
注意这里需要检
查事


ID
是不是
需要响
应的事件


if


(guid
==
Gl
ob
al
E
v
e
n
t
F
i
r
i
n
g
A
p
p

.GLOBAL_ID)
{

//
在这里完成事件响


}

}

接收推送数据

数据推送


Bla
ck
Be
rry


台的一
大优
势,
当服
务器
端有数
据更
新时


用服
务器可
以将

数据推
送到
手机上


需要
手机上
的应
用通
过轮
询的
方式检
查服
务器
上是
否有
需要更
新的


据。

关数
据推
送的
基本
架构与
服务
器的
推送
代码

请参


Bla
c
kB
er
r
y

推送
的相关
文档



小节只
描述
如何


MI
Dl
et

应用中
加上
手机
上侦
听推
送数据
的方
法。

应用自启动

如果希
望在
手机
端侦
听从
服务器
上推
送的
数据


般而言
需要
自动
启动
该侦
听应用



则有可
能该
侦听
应用
没有
启动,
导致
推送
数据
没有
被客户
端程
序接
收。



Bla
ck
B
er
ry

平台上要自动启动
一个应用程序比较简单,
可以直接通过设置完成,


Bla
ck
Be
rr
y


目中
双击
打开

Bla
ck
B
er
ry_
App
_De
s
cri
pt
o
r
.xm
l

,在
左边


G
en
er
al
In
f
o
rm
a
t
io
n



栏下方
选中

Aut
o
-run
o
n s
t
art
up
”就
可以
让该
项目中
的应用
在手
机启
动过
程中
自动启
动。



需要注
意的
是选
项“

Aut
o
-r
un
o
n

s
t
art
up

”只
有在
应用
类型为

Bla
c
kBe
rry
App
li
c
a
t
io
n



时可用
,也
就是
说如
果你
选择应
用类
型为

MI
Dl
et

”的话
就不
能使
用“

Aut
o
-r
un o
n st
art
up


选项。

所以需
要创
建一


Bla
c
kBe
rry

应用
进行
侦听
,而
不是
使用标准


MI
Dl
et



有关

Bla
ck
B
er
r
y


用项目
的创建
在这
里不
做详
细描
述,

要了
解具
体的
步骤
请参考
相关

文档。
创建


Bla
c
kBe
rry

项目后
首先
要考
虑应
用的
启动代
码,

Bla
ck
B
er
ry

应用
与普通


ja
v
a
应用一样


m
ai
n


法作为
入口。

为了更
好地
对应
用实
例进
行控制

这里
采用
单例模
式,
为类

P
us
he
dD
a
t
aLi
s
t
ener

创建


个静态
的单
例获
取方
法,


m
ai
n


数中
进行
调用


public

static
void


main(String[]
args)
{ PushedDataListener.
waitForSingleton

().start();

}




取单



态方法








通的单



方法

该方

的返




P
us
he
dD
a
t
aLi
s
t
ener



。在





使



R
un
t
im
eSt
o
r
e




保存
起来





Run
t
im
eS
t
o
r
e


已经
有实
例的话
则从

Run
t
im
eSt
o
r
e

中获取
,没
有则
创建
一个
新的实
例并


回。

public

static


PushedDataListener
waitForSingleton()
{

//
make
sure
this
is
a
singleton
instance

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;

}

}

推送侦听

从上一
节的
启动
代码
可以
看到,
在应
用实
例得
到后调
用了

s
t
art

方法。

P
us
h
e
dD
a
t
aLi
s
t
ener















线













s
t
art









































List
ener
Th
re
a
d


实例
,并
启动该
线程


List
ener
Th
re
a
d


例的
实现
主要是
创建
侦听
连接
,并
通过一
个不
结束
的循
环不
断从该


接中获
取服
务器
上推
送下
来的数
据。

首先需
要定


St
r
e
am
Co
nn
ect
io
nNot
ifi
e
r


例,

S
t
re
a
m
Co
nn
ect
io
nNot
ifi
e
r

用于
创建连
接。

其次需
要定


St
r
e
am
Co
nn
ect
io
n



In
putSt
re
am

,从
连接中
获取
到输
入流
,用
于侦听
数据


听。

StreamConnectionNotifier
notify
=

null


; StreamConnection
stream
=

null

; InputStream
input

=

null

;

定义

St
r
e
am
Co
nn
ect
io
nN
ot
ifi
er

实例
后通


Co
nn
ect
o
r



o
pen

方法
打开
连接。

Co
nn
ect
o
r

是一个
标准
的类

用于连
接不同
连接



h
t
t
p

so
ck
et




接不
同网
络的时
候都是
使用


o
pen

方法
,在
参数
中传入

U
RL

打开
指定
的地
址。网
络的不
同类
型通


U
RL


数的不
同进


区分,


h
t
t
p



U
RL



h
t
t
p://



头,


so
ck
et



U
RL

是以

so
ck
et
:
//


头。

送数


不属于
其它
标准
的协议

所以它


U
R
L


式比
较特
殊,
格式
为:

h
t
t
p://
:
<po
rt
>



虽然
推送



U
RL



h
t
t
p://


开头

但是
它不
是一


h
t
t
p


求,

中的


<po
rt
>


为端
口号,
需要


服务器
推送
端约
定使
用同
一个端
口号

下面
是打开
边接的
代码
片段

其中


LIS
TEN
_U
R
L

”为

定义的
字符
串变
量,
值为

h
t
t
p://
:
9
1
1



其中

9
1
1

为约定
的端
口。

notify
=
(StreamConnectionNotifier)
Connecto
r.open
(

LISTEN_URL

);































St
re
am
Co
nn
ect
io
nNot
if
ier







St
re
am
Co
nn
ect
io
nN
ot
ifi
er

后就通
过一
个循
环不
断侦
听获取
推送
数据


循环的
第一
句为

not
ify
.a
cc
ept
And
Op
en


注意
这一句
语句执
行后
该线
程会
开始
等待,


再执行
,直
到有
推送
数据
到达。















ac
c
ept
And
Op
en













St
re
am
Co
nn
ect
io
n











St
re
am
Co
nn
ect
io
n

实例的

o
penI
np
ut
St
re
am

方法
可以
获得输
入流
,然
后通
过输
入流获
得推


数据。

注意操
作完
成后
需要
将输
入流


St
re
am
Co
nn
ect
io
n

关闭,
关闭
后重
新开
始侦
听,

待下

一个推
送数
据。

侦听的
代码
片段
如下


for


(;;)
{

stream
=
notify.acceptAndOpen();

input
=
stream.openInputStream();

//
在这里通
过对
input

的操
作获得推
送数据

input.close(); stream.close(); stream
=

null

;

}

另外需
要注
意的
是异
常处
理,
因为
连接
的建
立和
输入
流的处
理可
能会
因为
一些
原因抛


异常

一种方法是在循环内处

异常,处理完了继续循


但是这无



C
o
nn
ect
o
r
.o
pen
方法进
行处
理。
所以
需要
在循环
外对
异常
进行
处理



Co
nn
ect
o
r
.o
pen

包含
进来,
本文
的例

子就是
使用
这种
方法


是,
实际
而言
这种处
理方
式也有
问题

当输入
流处
理有问
题的时


会跳出
循环
,不
再侦
听推
送数据


最终建
议的
方法
是建
立两
重循环


两重
循环
都加
上异常
捕获


层循
环中
的异常
处理

负责处


Co
nn
ect
o
r
.o
pen

的异常
,出
现异
常的
话处
理后重
新通


Co
nn
ect
o
r
.o
pen


开连
接。

内层循
环对
输入
流异
常进
行处理


理后
继续
侦听
数据,
而不
需要
重新
通过

Co
nn
ect
o
r
.o
pen
打开连接


体代
码请
参考
开发环
境附
带的
样例

本文
为简化
代码
没有
采用
双重
循环的方式


侦听程序与主
程序的交


获取侦
听数
据后
需要
做的
工作是
通知
主程
序有
新数
据到达
,由
主程
序对
数据
进行处理


因为侦
听程
序为
后台
程序

不负
责界
面更
新等
操作

界面
更新
的操
作由

MI
Dl
e
t

主程序
完成


可以看
到关
键是
作为
侦听
程序


Bla
ck
Be
rr
y


用与
作为主
程序


MI
Dl
et

如何
交互,
这可


使用上
一章
节介
绍的
方法
,通


G
lo
ba
lE
v
en
t


知主
程序,
然后
将数
据写
入共
享数据
中。


程序在
接收
到事
件通
知后
共享数
据中
获得
推送
数据
再进行
数据
处理
和界
面更
新处理

具体


法不再
详细
描述


推送侦听的完
整代


下面是
推送
数据
侦听
的完
整代码
,不
包括
应用
交互
部分:

package


cn.searb;

import


java.io.IOException;

import


java.io.InputStream;

import


javax.microedition.io.Connector;

import


javax.microedition.io
.StreamConnection;

import


javax.microedition.io.StreamConnectionNotifier;

import


net.rim.device.api.system.RuntimeStore;

import


net.rim.device.api.ui.UiApplication;

public

class


PushedDataListener

extends


UiApplication
{

public

static
final
long


RTSID_MY_APP

=
0x68b31bd292413108L;

private


static


final


String

LISTEN_URL

=

"
ht
tp
:/
/:
91
1"

;

//

th
e

li
st
en port

private


ListenerThread

myThread
;

public

static
void


main(String[]
args)
{ PushedDataListener.
waitForSingleton

().start();

}

public


PushedDataLi
stener()
{

myThread

=

new


ListenerThread();

}

public


static


PushedDataListener

waitForSingleton()
{

//
make
sure
this
is
a
singleton
instance

RuntimeStore
store
=
RuntimeStore.
getRuntimeStore
(); Object
o
=
store.get(

RTSID_MY_APP

);

if


(o

==

nu
ll

)

{

store.put(

RTSID_MY_APP

,

new


PushedDataListener());

return


(PushedDataListener)
store.get(

RTSID_MY_APP

);

}

else


{

return


(PushedDataListener)
o;

}

}

public


void


start()

{

invokeLater(

new


Runnable()
{

public

void


run()
{

myThre
ad
.start();

}

});

this

.enterEventDispatcher();

}

class


ListenerThread

extends


Thread

{

public

void


run()
{

System.

out

.println(
"DemoOA
BackGroundThread
--
running"

); StreamConnectionNotifier
notify
=

null

;

StreamConnection
stream
=

null


; InputStream
input

=

null

;

try


{

sleep

(1000);

}

catch


(Exception
e)
{

}

try


{

notify
=
(StreamConnectionNotifier) Connector.open
(

LISTEN_URL

);

for


(;;)
{

stream
=
notify.acceptAndOpen();

input
=
stream.openInput
Stream();

//

stream.close();

stream
=

null

;

}

}

catch


(IOException
e)
{ System.

err

.println(e.toString());

}

finally


{

try


{

if


(stream
!=

null

)
{

stream.close();

}

}

catch


(Exception
ex)
{

}

try


{

if


(notify
!=

null

)
{

notify.close();

}

}

catch


(Exception
ex)
{

}

}

}

}

}

小结

通过本
文的
介绍
读者
可以
发现,


MI
Dl
et

程序
移植


Bla
ck
Be
rr
y


并不
困难
,同时


发人员
也可
以根
据项
目的
时间要
求和
应用
的特
点决
定移植
的程
度。

不过,
无论
如何
,移植


MI
Dl
et

程序
都不
能够
充分
地发


Bla
ck
Be
rr
y


台的
优势,


果希望
最大
地发


Bla
c
kBe
rry

平台
的优
势,

是需要
根据

Bla
ck
B
er
r
y


台的特
点重新
对应


进行实
现。

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

相关链接:

如何将MIDlet

应用移植到BlackBerry

(一)

如何将MIDlet

应用移植到BlackBerry

(二)

如何将MIDlet

应用移植到BlackBerry

(三)

如何将MIDlet

应用移植到BlackBerry

(四)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: