`
android_mylove
  • 浏览: 380319 次
社区版块
存档分类
最新评论

通过SMS-Push技术激活J2ME程序

 
阅读更多

Push技术是一种通过异步方式将信息传送给设备并自动启动MIDlet程序的机制。通常进行网络连接时,客户端主动去连接服务器,服务器处理请求并返回给客户端响应,这是同步处理机制。而Push技术不同,它不需要应用程序通过“拉”的方式从网络中取得数据,应用程序需要的数据会被主动“推”向设备。当设备接收到信息时,相关的MIDlet会被激活并开始运行,处理发送过来的数据。注意:Push技术是MIDP2.0的一个可选项。

Push机制可以通过如下两种方式激活MIDlet:

1.通过inbound网络连接,就是基于接入的连接的通知。

2.通过基于计时器的时钟,又称基于警告的通知。

Push注册机制的行为可以被描述为如下三个步骤:

1.MIDlet在移动设备中注册一个连同协议名称的端口,如果任何信息到达指定的端口,并且使用相同的协议,那么AMS就将它转交给MIDlet。注册使用Java ME应用程序描述符(JAD)文件静态的完成。程序也能使用应用程序内置的API执行动态注册。

2. 从服务器,信息被发送到特定的移动设备,使用MIDlet应用程序注册监听的协议和端口。

3. 在信息被传递到移动设备后,AMS调用注册了监听此端口和协议的MIDlet应用程序。一旦信息被转交到MIDlet,那么处理信息就是此应用程序的责任了。典型的,根据信息的信息的内容,一个应用程序会选择打开一个屏幕,并允许用户与服务器进行一些事务。

在jad文件中,每一个push注册条目都包含如下信息:

MIDlet-Push-<n>: <ConnectionURL>, <MIDletClassName>, <AllowedSender>。

MIDlet-Push-<n>:push注册属性名称。MIDlet套件中可以包含多条push注册。<n>的数值从1开始,并且对于附加的条目必须使用连续的序数。第一个发现的缺失条目将中止列表。任何剩余的条目都会被忽略。


ConnectionURL:被Connector.open()使用的连接字符串。

MIDletClassName:负责连接的MIDlet。指定的MIDlet必须使用MIDlet-<n>记录在描述文件或jar文件的manifest中登记过。

AllowedSender:一个指定的过滤器,它将限制哪些发送者能够能正当启动请求的MIDlet。

通过上面的简单介绍,下面进入正题。如果对上面的介绍需要更详细的了解,请自己google或百度一下。在进入开发之前,需要注意的要点是一条简单的SMS消息将不会激活MIDlet。我们必须发送SMS消息到MIDlet注册监听的特定的端口。因此被用来发送SMS消息的软件(或SMS服务提供商)必须能够将它发送到设备指定的端口。接下来开发一个实例程序,我们能够从一个Java服务器端应用程序发送一条SMS消息到一个移动电话的指定端口,并自动启动移动设备中的一个MIDlet。在这里我利用两个支持java的手机来作为测试。一个手机作为服务器端,另一个手机作为接收该SMS消息的客户端。

1.首先开发客户端程序:

为方便起见,这里直接使用J2ME Wireless Toolkit工具创建该程序。

(1).点击新建工程图标。会打开一个弹出窗口;在那里你可以指定工程名称和MIDlet类名。在工程名称中输入 MySamplePushRegistryProject,在MIDlet类名中输入com.sample.MySamplePushRegistry。

(2).继上个步骤完成之后,会自动出现另一个弹出窗口,它将允许你设定项目的其他设置。确保你在API 选择标签中。在此标签中,从目标平台下拉菜单中选择JTWI(如果还没有选择)。同样确保CLDC 1.0单选按钮被选中。不要钩选Mobile Media API多选框(因为不会使用任何跟多媒体有关的API)。

(3).进入push注册标签。点击添加按钮。将会出现一个弹出窗口。在连接URL域中输入sms://:50001,在类域中输入com.sample.MySamplePushRegistry,在允许发送者域中输入*。在完成该步骤后,一个条目将会被加入到父窗口中。

(4).进入许可标签。单击添加按钮。从许可树中选择javax/microedtion/io/Connector/sms并单击OK。重复相同的步骤来添加许可javax/wireless/messaging/sms/receive 和 javax/microedtion/io/PushRegistry。在完成该步骤后,三项许可将被添加到应用程序中。

(5).进入用户定义标签。这里,我们添加用户定义的变量,这将包含SMS端口。从我们的程序,我们查阅此用户定义变量来读取SMS端口。在此标签中,单击添加按 钮。打开一个弹出窗口。输入SMS-Port作为属性名称。选择OK。出现了最初的弹出的窗口。输入50001作为SMS-Port的值。

(6),一切设置完成之后,在设置窗口中单击OK。

通过以上设置,就生成了一个jad文件。该文件路径就要看你的WTK的工程目录所在路径了。在该jad文件中,你会找到在前面步骤中设定的完整配置。所有条目中最重要的一个如下:

MIDlet-Push-1: sms://:50001,com.smaple.MySamplePushRegistry, *.

此条目确保你的应用程序监听50001端口上的SMS消息。

配置完成之后,这里我们做一个接收消息的类,该消息是服务器端通过SMS发送过来的。

import javax.microedition.midlet.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.wireless.messaging.*;

import java.io.*;


public class MySamplePushRegistry extends MIDlet
implements CommandListener, Runnable, MessageListener {

/** user interface command for indicating Exit request. */
Command exitCommand = new Command("Exit", Command.EXIT, 1);
/** user interface text box for the contents of the fetched URL. */
Alert content;
/** current display. */
Display display;
/** instance of a thread for asynchronous networking and user interface. */
Thread thread;
/** The port on which we listen for SMS messages */
String smsPort;
/** SMS message connection for inbound text messages. */
MessageConnection smsconn;
/** Current message read from the network. */
Message msg;
/** The screen to display when we return from being paused */
Displayable resumeScreen;

public MySamplePushRegistry() {

display = Display.getDisplay(this);

content = new Alert("SMS Receive");
content.setTimeout(Alert.FOREVER);
content.addCommand(exitCommand);
content.setCommandListener(this);
content.setString("Receiving...");

resumeScreen = content;
}

public void startApp() {
smsPort = getAppProperty("SMS-Port");
String smsConnection = "sms://:" + smsPort;
//System.out.println(smsConnection);
if (smsconn == null) {
try {
smsconn = (MessageConnection)
Connector.open(smsConnection);
smsconn.setMessageListener(this);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
display.setCurrent(resumeScreen);
}
public void notifyIncomingMessage(MessageConnection conn) {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
try {
msg = smsconn.receive();
if (msg != null) {
if (msg instanceof TextMessage) {
content.setString(((TextMessage)msg).getPayloadText());
}
display.setCurrent(content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//other methods to follow
public void destroyApp(boolean unconditional) {
thread = null;
if (smsconn != null) {
try {
smsconn.close();
} catch (IOException e) {
// Ignore any errors on shutdown
}
}
}
public void pauseApp() {
thread = null;
resumeScreen = display.getCurrent();
}

/**
* Respond to commands, including exit
* @param c user interface command requested
* @param s screen object initiating the request
*/
public void commandAction(Command c, Displayable s) {
try {
if (c == exitCommand || c == Alert.DISMISS_COMMAND) {
destroyApp(false);
notifyDestroyed();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

客户端开发完成之后,接下来开发服务器端:

服务器端,我们通过调用J2ME中的jsr75包里的SMS相关类来发送指定端口的消息,代码如下:

import javax.microedition.io.Connector;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.TextMessage;


public class smsDemo extends Form implements CommandListener{

private final smsMIDlet sms;
private TextField textMesg;
private String strMesg;
private String port="";
private TextField dest;
private String strDest;
private Command send1Command;
public smsDemo(smsMIDlet MIDlet) {
// TODO Auto-generated constructor stub
super("短消息");
this.sms = MIDlet;
//发送目的地
dest = new TextField("电话号码", "",20, TextField.PHONENUMBER);
//消息内容
textMesg = new TextField("发送内容", "",100, TextField.ANY);

append( dest );
append( textMesg );

send1Command = new Command("发送",Command.SCREEN, 2);

addCommand(send1Command);
setCommandListener(this);//注册监听事件

}
public void commandAction(Command arg0, Displayable arg1) {
// TODO Auto-generated method stub
if (arg0 == send1Command) {
try {
strDest = dest.getString();
strMesg = textMesg.getString();

Thread fetchThread=new Thread(){
public void run(){
try
{
String addr = "sms://" + strDest + ":50001";
System.out.println("发送地址为:" + addr);
//建立连接
MessageConnection conn =(MessageConnection) Connector.open(addr);
//设置短信息类型为文本,短信息有文本和二进制两种类型
TextMessage msg =

(TextMessage) conn.newMessage(MessageConnection.TEXT_MESSAGE);
//设置信息内容
System.out.println("发送消息为:" + strMesg);
msg.setPayloadText( strMesg );
//发送信息
conn.send(msg);
//关闭连接
conn.close();
}
catch(Exception exc)
{
exc.printStackTrace();
}
}
};

fetchThread.start();//启动线程

}catch (Exception e) {
System.out.print("Error in start/n");
e.printStackTrace();
}
}

}
}

服务器端的代码也开发完成了,接下来是通过将其发布到真机上运行,测试效果。

在发布到真机之前,需要将上面的客户端和服务器端的代码分别打包成jar文件,并分别发布到两个手机上。发布可以通过OTA,也可以通过拷贝到手机上再安装。注意通过拷贝来安装的时候将jad文件也拷贝进去,jad文件记录了jar文件的相关配置属性。在安装时,注意通过jad来安装jar。

两个手机都安装完成之后,通过装有服务器端程序的手机进入我们自己开发的发送短信界面,输入装有客户端程序的手机号码,并输入发送内容。点击发送,如果一切正常,那么客户端的MIDlet就应该被触发了,并弹出提示是否运行该程序,如果看到这个界面,那么点击确定后,可以看到服务器端的消息就被发送到客户端来了。到此,SMS-Push技术就算是成功了。

注意:

1.服务器端发送短信的界面没有做发送成功的提示,也没有做退出界面,因此在点击发送按钮之后,没有任何提示。

2.在安装客户端jar包时,安装完成之后,无需运行jar包,否则看不到SMS-Push的效果。

最后该文章细节来自于http://www.cnblogs.com/bluespot/archive/2008/08/02/1258735.html,有不清楚的地方请查看该网址。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics