1 WMA编程
1.1 WMA概述:(wireless Messageing API无线消息接口)规范设计的目标是那些能够发送和接书消息的移动设备。低层的传输机制可以是 GSM SMS(Short Message Service短消息服务),GSM CBS(Cell Broadcast service小区广播服务),CDMA SMS或MMS(Multimedia Message Service多媒体信息服务)
与WMA相关的主要类和接口都包含在java.wrieless.messaging中主要接口如下:
1)Message:基本的消息接口,它又派生出了BinaryMessage、TextMessage、MultipartMessage。方法有
getAddress():获取消息地址
getTimestamp():获取时间戳
setAddress:设置消息目标地址
2)BinaryMessage:代表一个二进制消息,并提供了方法来获取或设置传输的二进制数据
getPayloadData():得到二进制消息
setPayloadData():设置二进制消息负载的数据
3)TextMessage:代表一个文本消息,并提供了方法来获取或设置传输的二进制数据
getPayloadData():得到文本消息
setPayloadData():设置文本消息负载的数据
4)MessageConnection:通用连接框架连接的子接口,提供了一个消息对象的连接工厂以及发送的接收消息的方法
newMessage():创建一个文本消息对象
receive():接收消息对象
send(Message msg):发送消息对象
5)MessageListener:定义一个侦听接口来实现异步消息对象的通知
setMessageListener():设置消息监听
numberOfSegments():方法来计算消息被分成几段来传输
notifyIncomingMessage()
6)MessagePart:定义一个可以添加到MultipartMessage的消息部件
getContent(),getContentAsStream(),getContentID(),getContentLocation(),getEncoding(),getLength()
getMIMEType()
7)MultipartMessage:Message接口的子接口,代表一个mlti-part消息,并提供方法来获取或设置多个传输数据
addAddress(),addMessagePart(),getAddress(),getAddresses(),getHeader(),getMessagePart()
getMessageParts(),getStartContentId(),getSubject(),removeAddress(),removeAddresses()
removeMessagePart(),removeMessagePartId(),removeMessagePartLocation(),setAddress()
setHeader(),setStartContentId(),setSubject()
1.2 WMA消息类型:BinaryMessage代表SMS上的二进制短消息,TextMessage代表在SMS上的文本短消息,MultipartMessage代表
MMS上的传输的多媒体消息
[Message]
____________|____ __________
| | |
[BinaryMessage] [TextMessage] [MultipartMessage]
1.3 WMA连接
WMA中的连接都是基于MessageConnection接口的,定义了一个工厂方法来创建各种类型的消息。在newMessage(String type)
TEXT_MESSAGE:代表文本类型,BINARY_MESSAGE:代表二进制消息,MULTIPART_MESSAGE:代表多媒体消息
如果一个消息太长可以通过numberOfSegments(Message message)方法来计算消息被分成几段来传输
可以以两种方式创建MessageConnection连接:客户模式和服务器模式。如果是客户模式只能够发送消息;如果是服务器模式可以
创建发送消息,也可以接收消息
连接URL格式:scheme://:address-part [params]。
scheme:是传输协议名称,WMA规范支持三种传输协议
1)SMS:短消息系统上的一种协议,SMS是一种双向的传输协议,既可以在SMS上创建和发送短消息,也可以接收短消息,因此基于SMS既可以创建客户模式和服务器模式两种连接。
2)MMS:多媒体信息系统上的一种协议,和SMS一样,它既可以创建客户模式和服务器模式连接
3)CBS:基于手机广播上的一种协议,CBS消息可以通过一个基站进行广播并只能被接收。
address-part:为特定于协议的连接地址,用来指定移动设备和应用程序。同时指明了连接模式。客户模式的URL指定了一个完整的目的地址,包括一个主机号和一个端口号(或应用ID)。而服务器模式的URL只包含了本地地址,只指定了一个端口
Connector.open("sms://:+121234567:5000")客户模式连接
Connector.open("mms://:+121234567:com.* *.MmsApp")
Connector.open("sms://:5000") 服务器模式
Connector.open("mms://:com.* *.MmsApp")
Connector.open("cbs://:6000") cbs不支持客户模式
params为独立于协议的连接参数,用来传输一些特定的信息如连接的用户名,密码等。
1.4 发送和接收文本消息
1)发送
String address="sms://目标号码:Port";
MessageConnection smscon=(MessageConnection)Connector.open(address); 得到一个连接
TextMessage txtmsg=(TextMessage)smscon.newMessage(MessageConnection.TEXT_MESSAGE); 根据连接创建一个消息对象
txtmsg.setAddress(address); 组装消息对象的目标地址
txtmsg.setPayloadText("发送的消息内容"); 组装消息对象的发送内容
smscon.send(txtmsg); 用连接发送消息对象
2)接收
在startApp中注册监听
String address="sms://:端口号";
MessageConnection smscon=(MessageConnection)Connector.open(address);
smscon.setMessageListener(this);
在notifyIncomingMessage()方法中来启动一个接收线程
在线程中接收
Message msg=smscon.receive() 得到一个消息对象
String sendAddress=msg.getAddress();得到消息的地址
System.out.println("消息来自:"+sendAddress+"消息内容:"+((TextMessage)msg).getPayloadText());
1.5 发送和接收多媒体消息
多媒体消息又称彩信。是通过MultipartMessage消息来实现的。遵循的标准是E-Mail格式,包含一个基于RFC822格式的Message头
部和多个Multipurpose Internet MailExtensions(MIME)格式的Message Part对象。每个Message Part对象都包含一个Message Parg Header 对象和多个Message Part Content对象(可以是文本数据或二进制数据)
1.6 接收手机广播消息
GSM小区广播服务允许将消息发送到当前位于某个特定小区的每个移动信息设备。在WMA中只允许建立服务器模式的CBS连接。而且
只支持文本和二进制类型的消息。建立CBS连接及接收消息的方法和SMS基本一致
在startApp()中
String cbsC;
MessageConnection cbscon=(MessageConnection)Connector.open(cbsConnection);
cbscon.setMessageListener(this);
在notifyIncomingMessage()中启动接收线程
Message msg=cbscon.receive();
if(msg instanceof TextMessage)
System.out.println("接收的消息是:"+((TextMessage)msg).getPayloadText());
else
{
StringBuffer buf=new StringBuffer();
byte[] data=((BinaryMessage)msg).getPayloadData());
for(int i=0;i<data.length;i++)
{
buf.append(Integer.toHexString((int)data[i]));
buf.append('');
}
Form.setString(buf.toString());
}
2 访问移动设备上的文件
2.1 FileConnection
可用于访问移动信息设备上的文件系统。FileConnection分别提供了两个可选包,分别提供了对个人信息管理数据和本地文件系统的访问。
在J2ME设备中,可以利用通用连接架构通过各种连接类型特有的Connection接口来处理I/O操作。但GCF不是J2ME或MIDP的必选荐。所以规范
中提出了FileConnection API。仅包含一个类,两个接口和两个异常类。现在创建FileConnection 的实现使用方法Connector.open,其中URL格式为[url=file:///C:/Nokia/Image/image1.jpg]file:///C:/Nokia/Image/image1.jpg[/url]
2.2 设备文件的特性
FileConnectioni API版本:System.getProperty("microedition.io.file.FileConnection.version");
文件分隔符:System.getProperty("file.separator");
列出移动设备文件系统的所有根目录
Enumeration drives=FileSystemRegistry.listRoots();
while(drives.hasMoreElements())
{
String root=(String)drives.nextElement();
System.out.println("\t"+root);
}
文件操作
FileConnection fc=(FileConnection)Connector.open("[url=file:///]file:///[/url]路径");
fc.mkdir() 创建目录
fc.create() 创建文件
fc.delete() 删除文件或目录(非空的)
fc.exists() 文件是否存在
fc.canRead() 文件属性是否可读
fc.canWrite()文件属性是否可写
fc.isHidden()文件属性是否隐藏
fc.isDirectory() 判断文件是目录还是文件
Enumerati.listRoots(); 列出移动设备文件系统的所有根目录
Enumeration e=fc.list("*",true); 显示open打开路径的所有文件或目录
读文件内容
InputStream is=fc.openInputStream(); 得到输入流
byte b[]=new byte[1024];
int length=is.read(b,0,1024); 从输入流中,0的位置,大小为1024字节,得到数据放在b中,返回的是实际文件大小
is.close();
fc.close();
写文件
fc.create();
OutputStream os=fc.openOutputStream();
byte data=new byte[11];
os.write(data);
os.close();
fc.close();
2.3 移动存储卡的操作
文件存储卡都映射到文件系统中的一个根目录。FileSystemListener接口,专门用来监视存储卡的插入、拔出操作。必须重载
rootChanged(int state,java.lang.String rootName)方法。
FileSystemRegistry.addFileSystemListener(this) 添加监听
public void rootChanged(int state,String rootName)
{
if(state==FileSystemListener.ROOT_ADDED) 卡在手机中插着
{
...
}
if(state==FileSystemListener.ROOT_REMOVE) 卡不在手机中插着
{
...
}
}
3 管理移动设备上的个人信息
3.1 PIM API:提供了一个标准的接口来访问移动设备上的本地数据库。目前支持三种类型的本地数据库:电话本,日程表,任务表。
PIM API提供了一个接口PIMList代表本地数据库,它的三个子接口ContactList(电话本),EventList(日程表),ToDoList(任务表)
PIMItem代表本地数据库中的记录对象。在ContactList中对应的记录对象为Contact;在EventList中对应的记录对象是Event, 在ToDoList对应的记录对象为ToDo。
不同的数据库间通过唯一的名字来区分,可以用listPIMLists来获取某一类型数据库的列表。
PIMList对象支持对其包含的PIMItem对象的创建、修改、删除。但对于创建和修改操作要commit才能成功。删除会马上生效。
对于PIMList对象中的每个PIMItem对象。PIMList都提供一系列的字段来描述其信息。isSupportedField来判断一个字段是否被 支持,getSupportedField来获取所有支持的字段。
对于一个PIMItem对象,字段可能包含一个或多个入口。例如:联系人的信息中可能有多个手机号码。PIMItem对象的coutValue 方法可用计算字段下有几个入口。 对于每个入口,它可能包含几个特殊的属性来说明入口的性质。例如:电话号码字段可以包含属性以说明它是家庭还是办公。
可以用PIMList的isSupportedAttribute(int field int attribute)来判断特定的字段是否支持某个属性,getSupportedAttributes(int field) 来获取某个字段所支持的所有属性。
PIM API还支持组的概念。而且还支持序列化和反序列化。可以将这样电话本对象序列化成vCard格式的电子名片,日程表和任务表序列化成vCalandar格式的信息。就可以通过Midlet与外部应用程序进行信息交换
3.2 电话本管理(Contact)
PIM pim=PIM.getInstance() 得到一个PIM对象
String[] list=pim.listPIMLists(PIM.CONTACT_LIST); 根据类型得到所有PIM列表,类型有EVENT_LIST,CONTACT_LIST,TODO_LIST
3.3 日程表管理(Event)
3.4 任务表管理(ToDo)
4 移动多媒体
在J2ME中提供了一规范的操作音频或视频数据的应用接口,MMAPI。
4.1 MMAPI体系架构
通常将媒体处理过程分解为两个过程:通过各种传输协议获取媒体数据的过程和处理媒体数据内容的过程。获取数据的过程是指从数据源上读取数据内容后,将其传送到媒体数据内容处理器的过程。处理过程是指处理器对媒体数据进行解释和解码,然后发送到应用硬件设备的数据缓冲区中。
基于媒体处理过程,整个MMAPI的体系架构邮一个管理器(Manager)、一个数据源(DataSource)、一个播放器(Player)和若干控件 器(Control)组成。
1)数据源:可以被保存在不同的位置,它可以位于远程服务器,资源文件或是RMS数据库。可以从原始位置通过HTTP,RTP等流式传输协议或其他传输到播放器。由javax.microedition.media.protocol.DataSource来实现
2)播放器:用来处理媒体数据内容。
3)控制器:控制器由javax.microedition.media.Control接口来实现。12种控制器
MetaDataControl:用来从媒体数据中获取元数据信息
MIDIControl:提供对播放器显示和传输设备的访问
GUIControl:代表一个具有用户界面组件的控制操作
PitchControl:升高或降低重放的位置而不改变重放的速度
RateControl:控制重放的速率
TempoControl:控制MIDI歌曲的节奏
VolumeControl:控制音量
VideoControl::控制可视内容的显示
FramePositioningControl:可以对一个视频帧精确定位
RecordControl:记录当前被播放器播放的是什么内容
StopTimeControl:使应用程序可以为一个播放器预先指定一个停止时间
ToneControl:是一个可以播放用户自定音调序列的接口
4)管理器:管理器可以从数据源中创建播放器,也可以从本地或InputStream中创建播放器
4.2 Player状态模型
MMAPI使用Manager的createPlayer来创建Player对象
Player.start():重放媒体流
Player.stop():停止媒体流
Player.setMidiaTime(long now):设置媒体时间
Player.close():关闭媒体流并释放媒资源
Player.getState:获取Player的当前状态
4.3 设备多媒体支持特性
可以用System.getProperty(String key)得到设备所支持的特性
microedition.media.version:代表MMAPI实现版本的字符串
supports.mixing:支持混频(true)
supports.audio.capture:支持音频记录
supports.video.capture:支持视频记录
supports.recording:支持录制
audio.encodings:返回所支持的音频格式的字符串
video.encodings:返回所支持的视频格式的字符串
video.snapshot.encodings:返回所支持的图像格式的字符串
streamable.contents:支持的流媒体内容类型的字符串
4.4 播放单音和序列音乐
利用Manager.playTone()来播放单音,如果要播放序列音,刚必须用ToneControl对象。
Player play=Manager.createPlayer(Manager.TONT_DEVICE_LOCATOR);
play.realize();
ToneControl tc=(ToneControl)(play.getControl("ToneControl"));
tc.setSequence(new byte[]{ToneControl.C4,8 ToneControl.C4+2,8});
play.start();
4.5 播放声音媒体文件
如果播放HTTP上的
Player play=Manager.createPlayer(" http://something.com/somefile.wav ");
player.start();
如果播放一段已经在JAR文件中的声音文件,要先了解MIME类型(如"audio/x-wav")
Wave audio files: audio/x-wav
AU audio files: audio/basic
MP3 audio files: audio/mpeg
MIDI files: audio/midi
Tone sequences: audio/x-tone-seq
InputStream is=getClass().getResourceAsStream("/somefile.wav");
Player play=Manager.createPlayer(is,"audio/x-wav");
play.start();
播放位于RMS中的声音文件
RecordStore rs=RecordStroe.open("name");
byte[] data=rs.getRecord(id);
ByteArrayInputStream bis=new ByteArrayInputStream(data);
Player play=Manager.createPlayer(bis,"audio/x-wav");
play.strat();
4.6 播放视频
从视频播放器得到一个视频控件,然后在一个Form或Canvas显示出来
Form:
InputStream is=getClass().getResourceAsStream("/somefile.3pg"); //根据位置从jar文件文件中得到数据源,并转换成输入流
Player play=Manager.createPlayer(is,"video/3gpp"); //得到Player对象,根据输流和类型
play.realize();
VideoControl vc=(VideoControl)play.getControl("VideoControl"); //得到一个视频控制对象
if(vc!=null)
{
Item it=(Item)vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE,null); //初始化视频对象
Form.append(it);
play.start();
}
Canvas:
InputStream is=getClass().getResourceAsStream("/somefile.3pg");
Player play=Manager.createPlayer(is,"video/3gpp");
play.realize();
VideoControl vc=(VideoControl)play.getControl("VideoControl");
if(vc!=null)
{
vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE,Canvas);
vc.setVisible(true);
play.start();
}