La
possibilità di inviare e ricevere messaggi sms
da un dispositivo wireless, utilizzando librerie Java,
può, a prima vista, sembrare superflua: è
vero, infatti, che la maggior parti di tali apparati
(non solo cellulari e smart-phone ma anche numerosi
PDA) sono già dotati di tali funzionalità.
I sistemi di gestione degli sms di un dato apparato
non sono però accessibili alle applicazioni Java
(per ragioni di sicurezza imposte dal Sandbox Model
e per la mancanza del supporto di Java Native Interface
da parte di CLDC/MIDP) se non ricorrendo all'utilizzo
di librerie proprietarie fornite dal produttore del
dispositivo stesso. Quest'ultima soluzione porta però
alla realizzazione di applicazioni "troppo dedicate"
ad una determinata marca di apparati o addirittura di
modelli, limitando pesantemente la portabilità
del codice. Le Wireless Messaging API (WMA) invece,
essendo una vera e propria java-extension, possono garantire
lo stesso grado di portabilità software offerto
dall'ambiente Java stesso (CLDC e MIDP in questo caso).
Quello che, infatti, può variare, rispetto ai
vari dispositivi utilizzati, è l'implementazione
delle librerie mentre il loro utilizzo, a livello di
applicazione, è completamente cross-platform.
Questo da la possibilità di eseguire il medesimo
applicativo in tutti gli apparati per i quali esiste
un'implementazione delle WMA (e dell'ambiente J2ME -
es: MIDP/CLDC).
L'architettura
delle WMA
Le
classi e le interfacce che compongono le Wireless Messaging
API possono essere suddivise in tre diversi strati:
questi corrispondono ad altrettanti livelli di astrazione
rispetto al dispositivo host. Come è possibile
osservare in figura 1, le applicazioni Java (Midlet)
hanno accesso solo al livello più alto dell'architettura.
Tale livello fornisce un insieme di interfacce che contengono
la definizione dei metodi, di cui un'applicazione Java
potrà disporre, per l'invio e la ricezione di
messaggi sms. Lo strato inferiore rappresenta l'implementazione
di tali interfacce, mentre il livello più basso,
quello più "vicino" alla piattaforma
hardware, implementa i protocolli di trasporto per l'effettiva
trasmissione e ricezione dei messaggi.
Figura
1 - Architettura delle WMA
Le interfacce delle Wireless Messaging API (figura 2),
permettono di "nascondere" i dettagli implementativi
alle MIDlet (e ai programmatori...).In particolare esse
si preoccupano di garantire funzionalità per
la gestione delle connessione (invio e ricezione dei
messaggi), e la definizione degli oggetti (java) che
rappresentano il messaggio stesso.
Figura 2 - Interfacce delle WMA
Message rappresenta la "definizione base"
di un messaggio: essa fornisce i seguenti tre metodi:
public
String getAddress( )
public void setAddress( )
public Date getTimestamp( )
i
primi due permettono rispettivamente di ottenere e settare
l'indirizzo di un messaggio, mentre l'ultimo consente
di ricavare l'istante di invio del messaggio.
L'interfaccia
Message è estesa da BinaryMessage e TextMessage
(Figura 2):
BinaryMessage rappresenta un messaggio il cui campo
dati è in formato binario:
public
byte[ ] getPayloadData( )
public void setPayloadData(byte[ ] data)
permettono
di leggere (get) e scrivere (set) il campo dati (payload)
del messaggio.
TextMessage
definisce un messaggio di puro testo, con i metodi:
public
String getPayloadText( )
public void setPayloadText(String data)
è
possibile ottenere la rappresentazione stringa del campo
dati, mentre setPayloadText ne permette il settaggio.
La differenza principale tra un messaggio di tipo "text"
e uno "binary" sta nel tipo di codifica utilizzato
( 7-bit o UCS-2 nel primo caso, 8-bit nel caso di messaggi
binari come previsto dallo standard GSM 03.38).
L'interfaccia
MessageConnection rappresenta la connessione per l'invio
e la ricezione dei messaggi. Un oggetto di tipo MessageConnection
viene istanziato con una chiamata a Connector.open()
(javax.microedition.io):
MessageConnection
messConn = (MessageConnection) Connector.open(String
connectionString);
La
stringa "connectionString", passata come parametro
al metodo open permette al Generic Connection Framework
della CLDC di stabilire il tipo di connessione da attivare.
Nel caso delle WMA il formato previsto è del
tipo:
"sms://address : port"oppure "sms://:
port"a seconda che si desideri attivare una connessione
in modalità client (primo caso) oppure server
(indicando il solo numero della porta). Una connessione
di tipo client, può essere utilizzata esclusivamente
per l'invio dei messaggi mentre la modalità server
ne permette sia l'invio sia la ricezione. Esempi di
stringhe di connessione possono essere:
"sms://+3922728821"
"sms://+3922728821:9000"
"sms://:9002"
(In
realtà le WMA supportano anche i Cell Broadcast
Sms, un particolare tipo di sms che, trasmesso da una
stazione radio base vengono ricevuti da tutti i terminali
mobili in ascolto con quella stazione. Le stringhe di
connessione in questo caso hanno il seguente formato:
"sms://:8000").
Poiché
alcune porte sono riservate ad usi specifici le applicazioni
Java non possono, per ragioni di sicurezza, aprire connessioni
in ascolto su tali porte (un elenco delle porte riservate
è riportato in appendice).
Una volta attivata la connessione la si può utilizzare
per l'invio e la ricezione dei messaggi.
Il metodo newMessage consente la creazione di nuovi
messaggi e prevede due diverse firme:
public
Message newMessage(String type)
public Message newMessage(String type, String address)
nella
prima occorre specificare il tipo (variabili statiche:
BINARY_MESSAGE - TEXT_MESSAGE) nella seconda anche l'indirizzo
(del destinatario).
Utilizzando
i metodi di Message e delle sue estensioni (TextMessage
e BinaryMessage) è possibile manipolare il campo
dati e il campo indirizzo del messaggio, che, una volta
pronto, può essere inviato con il metodo:
public
void send(Message msg)
Per
quanto riguarda la ricezione il metodo:
public
Message receive()
rimane
in attesa (è bloccante) dell'arrivo di un messaggio
o della chiusura della connessione.
In
alternativa all'utilizzo del metodo receive si può
ricorrere ad un meccanismo di listening:
public
void setMessageListener(MessageListener listener)
permette
l'aggancio di un listener ad una connessione.
Implementando
poi l'interfaccia MessageListener è possibile
gestire la ricezione di un messaggio. attraverso il
metodo (unico):
public
void notifyIncomingMessage(MessageConnection connection)
che
viene richiamato alla ricezione di ogni messaggio sulla
connessione aperta (alla quale è stato "collegato"
il listener).
Concludiamo
la trattazione delle interfacce delle WMA con il metodo:
public
int numberOfSegments(Message msg)
esso
ritorna il numero di segmenti (parti) in cui il protocollo
di trasporto deve dividere il messaggio passato come
parametro per poterlo inviare. Occorre precisare, che
nell'attuale implementazione delle WMA, questo metodo
non esegue l'invio dei messaggi ma solo il conteggio
dei segmenti.
Una
volta terminate le operazioni si può procedere
alla chiusura della connessione con il metodo
public
void close( )
ereditato
da javax.microedition.io.Connection.
Attualmente
esiste una sola implementazione delle librerie WMA:
quella di riferimento della Sun Microsystem. Vediamo
brevemente il suo funzionamento (Figura 3).
La classe Protocol rappresenta l'implementazione dell'interfaccia
MessageConnection, vista precedentemente. Essa si occupa
di verificare la validità e la sintassi dei parametri
di connessione, rilanciando eventuali eccezioni al livello
applicazione, recupera, a run-time, eventuali parametri
di configurazione ( che vedremo tra breve), la gestione
di un eventuale listener collegato alla connessione,
gestisce la segmentazione e la concatenazione dei messaggi
per i protocolli di trasporto. TextObject e BinaryObject
implementano rispettivamente TextMessage e BinaryMessage
ed entrambe estendono la classe MessageObject. Quest'ultima
è l'implementazione dell'interfaccia Message
e costituisce "un messaggio java", mentre
TextMessage rappresenta un messaggio di testo e BinaryMessage
uno binario puro.
Figura 3 - Implementazione delle WMA
Il
"livello trasporto" (vedi figura 4), ha il
compito di fornire un insieme di classi (usate a run-time)
per la gestione dei meccanismi di trasporto dei messaggi,
cioè per le effettive operazioni di invio e ricezione
delle informazioni. L'attuale implementazione di riferimento
prevede due tipi di "protocolli di trasporto":
uno via datagram (utile per lo sviluppo e il testing
di applicazioni) l'altro via porta seriale utilizzabile
su reti GSM reali (inviando comandi AT ad un telefono
o ad un modem GSM).
Figura 4 - Il livello di trasporto
Prima di concludere con un esempio di utilizzo delle
librerie, facciamo un breve passo indietro e riprendiamo
il discorso della configurazione precedentemente accennato.
Per poter utilizzare le WMA occorre modificare il file
di configurazione del MIDP. Si tratta del file internal.config
(solitamente ne sono presenti due: internal.config e
system.config, le proprietà del primo sono accessibili
con com.sun.midp.Configuration.getProperty(propName)
quelle presenti in system con System.getProperty(propName)
) al quale vanno aggiunte le seguenti righe:
Specifica
il tipo di protocollo di trasporto da utilizzare
com.sun.midp.io.j2me.sms.Impl:
com.sun.midp.io.j2me.sms.DatagramImpl
il valore alternativo può essere (nell'implementazione
di riferimento)
com.sun.midp.io.j2me.sms.Impl=com.sun.midp.io.j2me.sms.DatagramImpl
Parametri
di configurazione per l'utilizzo dei datagram ( host-porte)
com.sun.midp.io.j2me.sms.DatagramHost: localhost
com.sun.midp.io.j2me.sms.DatagramPortIn: 54321
com.sun.midp.io.j2me.sms.DatagramPortOut: 12345
Permessi
di ricezione/invio dei messaggi Sms
com.sun.midp.io.j2me.sms.permission.receive: true
com.sun.midp.io.j2me.sms.permission.send: true
Permesso
per la ricezione di messaggi di tipo cbs
com.sun.midp.io.j2me.cbs.permission.receive:
true
Permesso
per l'utilizzo delle connessioni (sms/cbs)
javax.microedition.io.Connector.sms:
true
javax.microedition.io.Connector.cbs: true
Settaggio
di una porta alternativa per l'emulazione dei messaggi
cbs
com.sun.midp.io.j2me.sms.CBSPort: 24680
Abilitazione all'utilizzo delle connessioni comm (seriale)
e datagram
com.sun.midp.io.enable_extra_protocols:
true
Indirizzo
del centro servizi SMS
wireless.messaging.sms.smsc: +17815511212
Quello
che segue è un esempio di utilizzo delle librerie
WMA. La parte "server" è composta dalle
seguenti due classi:
package
smstest;
import
java.awt.*;
public
class SmsTester {
public static void main(String[] args) {
SmsFrame frame = new SmsFrame();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height)
frameSize.height = screenSize.height;
if (frameSize.width > screenSize.width)
frameSize.width = screenSize.width;
frame.setLocation((screenSize.width - frameSize.width)
/ 2, (screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
frame.validate();
}
}
package
smstest;
import
java.io.*;
import java.net.*;
import java.util.*;
import java.text.SimpleDateFormat;
import java.awt.*;
import java.awt.event.*;
import com.sun.tck.wma.*;
import com.sun.tck.wma.sms.*;
public
class SmsFrame extends Frame {
Panel smsPanel = new Panel();
GridBagLayout gridBagLayout1 = new GridBagLayout();
TextField smsNumber = new TextField();
TextField smsText = new TextField();
java.awt.List smsIncomingList = new java.awt.List();
Label label1 = new Label();
Label label2 = new Label();
Label label3 = new Label();
Button sendButton = new Button();
static MessageConnection messageConnection;
public SmsFrame() {
try {
//Apre una connessione sulla porta 9001 (modalità
server)
messageConnection = new SMSConnector().open("sms://:9001");
//Crea e manda in esecuzione un nuovo thread per la
ricezione dei messaggi SMS in arrivo
new Thread(new ReceiverMessage()).start();
init();
} catch( Exception ee)
{
ee.printStackTrace();
}
}
private void init() throws Exception {
this.setBackground(new Color(157, 157, 173));
this.setSize(new Dimension(400, 493));
this.setResizable(false);
this.addWindowListener(new java.awt.event.WindowAdapter()
{
public void windowClosing(WindowEvent e) {
this_windowClosing(e);
}
});
smsPanel.setLayout(gridBagLayout1);
smsNumber.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e) {
smsNumber_actionPerformed(e);
}
});
label1.setFont(new java.awt.Font("Dialog",
1, 12));
label1.setText("Sms Number");
label2.setFont(new java.awt.Font("Dialog",
1, 12));
label2.setText("Sms Text");
label3.setFont(new java.awt.Font("Dialog",
1, 12));
label3.setText("Sms List");
sendButton.setBackground(Color.lightGray);
sendButton.setFont(new java.awt.Font("Dialog",
1, 12));
sendButton.setLabel("Send Sms");
smsText.setBackground(Color.gray);
smsText.setForeground(Color.black);
smsNumber.setBackground(Color.gray);
smsNumber.setForeground(Color.black);
smsIncomingList.setBackground(Color.lightGray);
smsIncomingList.setFont(new java.awt.Font("Dialog",
1, 12));
sendButton.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e) {
sendButton_actionPerformed(e);
}
});
smsIncomingList.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e) {
smsIncomingList_actionPerformed(e);
}
});
smsText.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e) {
smsText_actionPerformed(e);
}
});
smsNumber.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e) {
smsNumber_actionPerformed(e);
}
});
smsIncomingList.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e) {
smsIncomingList_actionPerformed(e);
}
});
smsIncomingList.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e) {
smsIncomingList_actionPerformed(e);
}
});
this.add(smsPanel,
BorderLayout.CENTER);
smsPanel.add(smsText, new GridBagConstraints(0, 3, 4,
1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.NONE, new
Insets(0, 10, 0, 0), 331, 0));
smsPanel.add(smsNumber, new GridBagConstraints(0, 1,
3, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.NONE, new
Insets(0, 10, 0, 2), 197, 0));
smsPanel.add(label1, new GridBagConstraints(0, 0, 3,
1, 0.0, 0.0
,GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE,
new Insets(0, 10, 0, 0), 0, 0));
smsPanel.add(label2, new GridBagConstraints(0, 2, 3,
1, 0.0, 0.0
,GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE,
new Insets(1, 10, 0, 0), 0, 3));
smsPanel.add(smsIncomingList, new GridBagConstraints(0,
6, 3, 1, 0.0, 0.0
,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new Insets(10, 30, 10, 43), 204, 218));
smsPanel.add(label3, new GridBagConstraints(0, 5, 2,
1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE,
new Insets(0, 10, 0, 96), 0, 0));
smsPanel.add(sendButton, new GridBagConstraints(0, 4,
1, 1, 0.0, 7.0
,GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE,
new Insets(1, 10, 18, 0), 2, 2));
this.setTitle(" SMS Tester");
}
void smsNumber_actionPerformed(ActionEvent e) {
}
void sendButton_actionPerformed(ActionEvent e) {
sendSms();
}
void smsIncomingList_actionPerformed(ActionEvent e)
{
}
void this_windowClosing(WindowEvent e) {
System.exit(0);
}
void smsText_actionPerformed(ActionEvent e) {
}
private void sendSms() {
//Stringa di connessione nel formato "sms://address:port"
String destAddress = "sms://"+smsNumber.getText()+":9002";
//Lettura del testo inserito nel textfield
String message = smsText.getText();
try {
// Creazione di un nuovo messaggi (di tipo Text)
Message mess = messageConnection.newMessage(MessageConnection.TEXT_MESSAGE);
// Inserimento del testo all'interno del messaggio
((TextMessage)mess).setPayloadText(message);
// Settaggio dell'indirizzo di destinazione del messaggio
mess.setAddress(destAddress);
// Invio del messaggio sms
messageConnection.send(mess);
} catch (Exception ioe) {
ioe.printStackTrace();
}
}
class ReceiverMessage implements Runnable {
public void run() {
while (true) {
try {
// Resta in attesa dell'arrivo di un nuovo messaggio
Message receivedMessage = messageConnection.receive();
// All'arrivo di un nuovo sms:
// Viene recuperato l'indirizzo
String destAddress = receivedMessage.getAddress();
int numberStart = destAddress.lastIndexOf("/");
int numberEnd = destAddress.indexOf(":",numberStart
);
numberEnd = numberEnd == -1 ? destAddress.length() :
numberEnd;
String senderNumber = destAddress.substring(numberStart
+1 , numberEnd );
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy
HH:mm:ss");
// Viene letto il timestamp relativo al momento dell'invio
del messaggio
String timestamp = sdf.format(receivedMessage.getTimestamp());
// Per recuperare il contenuto occorre valutare se si
tratta di un messaggio di testo
// o binario
if ( receivedMessage instanceof TextMessage)
{
// Si tratta di un messaggio di testo
TextMessage tm = (TextMessage) receivedMessage;
// Visualizza le informazioni del messaggio nella lista
smsIncomingList.add(" SMS : "+ senderNumber
+ " -- "+ timestamp +" -- " + tm.getPayloadText());
}
else
if ( receivedMessage instanceof BinaryMessage)
{
// Si tratta di un messaggio di binario
BinaryMessage bm = (BinaryMessage) receivedMessage;
// Visualizza le informazioni del messaggio nella lista
smsIncomingList.add(" SMS : "+ senderNumber
+ " -- "+ timestamp +" -- " + new
String(bm.getPayloadData()));
}
} catch (Exception ioe)
{
ioe.printStackTrace();
}
}
}
}
}.
Codice
del client MIDP
package
midpsms;
import
java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.wireless.*;
import javax.wireless.messaging.*;
public
class SmsManager extends MIDlet implements CommandListener,
MessageListener {
private Display display;
private Form mainForm;
private Command exit;
private Command openMessage;
private Command sendMessage;
private Ticker ticker;
private MessageConnection smsConnection;
private MessageList messageList;
public static String smscAddress;
public SmsManager() {
try{
smscAddress = com.sun.midp.Configuration.getProperty("wireless.messaging.sms.smsc");
// Stringa di connessione per la connessione sms - modalità
server sulla porta 9002
String smsReceivePort = "sms://:9002";
// Apertura della connessione
smsConnection = (MessageConnection) Connector.open(smsReceivePort);
// Collegamento di un listener per la notifica dei messaggi
in arrivo (ricevuti)
smsConnection.setMessageListener(this);
}catch( Exception e)
{
e.printStackTrace();
}
mainForm = new Form(" SMS MANAGER ");
exit = new Command("exit",Command.EXIT, 1);
openMessage = new Command("list",Command.EXIT,
1);
sendMessage = new Command("send",Command.OK,
1);
mainForm.addCommand(exit);
mainForm.addCommand(openMessage);
mainForm.addCommand(sendMessage);
mainForm.setCommandListener(this);
ticker = new Ticker("New message incoming");
}
public void startApp() {
display = Display.getDisplay(this);
messageList = new MessageList(display, mainForm );
display.setCurrent(mainForm);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void notifyIncomingMessage(MessageConnection
smsConnection)
{
// Questo metodo viene richiamato automaticamente all'arrivo
di un nuovo messaggio
try {
// Ricezione del messaggio
Message inMessage = smsConnection.receive();
// Aggiunta del messaggio alla lista
messageList.addIncomingMessage(inMessage);
// Un messaggio scorrevole (Ticker) segnala la ricezione
del nuovo messaggio
if ( mainForm.getTicker() == null )
{
mainForm.setTicker(ticker);
}
} catch( Exception e)
{
System.out.println(" Error : "+ e.toString()
);
}
}
public void commandAction(Command command, Displayable
displayable)
{
if ( command == exit && displayable == mainForm)
{
this.destroyApp(true);
this.notifyDestroyed();
}
if ( command == sendMessage && displayable ==
mainForm )
{
new SendMessageForm(display, mainForm);
}
if ( command == openMessage && displayable ==
mainForm )
{
display.setCurrent(messageList);
}
}
}
package
midpsms;
import
java.io.*;
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.wireless.*;
import javax.wireless.messaging.*;
public
class MessageList extends List {
private Command back;
private Display display;
private Displayable oldDisplayable;
private Vector messages = new Vector();
private boolean toRead = false;
public MessageList(Display d, Displayable dy) {
super("Message List", List.IMPLICIT);
this.display = d;
this.oldDisplayable = dy;
setCommandListener(new CommandListener() {
public void commandAction(Command command, Displayable
displayable) {
commandPerformed(command, displayable);
}
});
back = new Command("back",Command.BACK, 1);
this.addCommand(back);
}
public void addIncomingMessage( Message message ) {
Image envelope = null;
try {
envelope = Image.createImage("/icons/envelope.png");
} catch (IOException e) {}
this.append("new Message", envelope);
messages.addElement(new SmsMessage(message));
}
public boolean messageToRead () {
for ( Enumeration e = messages.elements(); e.hasMoreElements();)
{
if( ((SmsMessage)e.nextElement()).getIsToRead() == true
)
return true;
}
return false;
}
public void commandPerformed(Command command, Displayable
displayable) {
if( command == back )
{
display.setCurrent(oldDisplayable);
}
if( command == this.SELECT_COMMAND )
{
display.setCurrent( new SmsMessageForm( (SmsMessage)
messages.elementAt(this.getSelectedIndex()), display,
this ));
}
}
}
package
midpsms;
import
java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.wireless.*;
import javax.wireless.messaging.*;
public class SendMessageForm extends Form {
private TextField smsDestNumber;
private TextField smsMessage;
private Command back;
private Command send;
private Display display;
private Displayable oldDisplayable;
private MessageConnection smsConnection;
private String smscAddress = SmsManager.smscAddress;
public SendMessageForm(Display d, Displayable dy) {
super("Send Message");
this.display = d;
this.oldDisplayable = dy;
this.setCommandListener(new CommandListener() {
public void commandAction(Command command, Displayable
displayable) {
commandPerformed(command, displayable);
}
});
send = new Command("send",Command.OK, 1);
back = new Command("back",Command.BACK, 1);
smsDestNumber = new TextField(" Number ",
"", 15, TextField.PHONENUMBER);
smsMessage = new TextField(" Message ", "",
160, TextField.ANY);
this.append(smsDestNumber);
this.append(smsMessage);
this.addCommand(send);
this.addCommand(back);
display.setCurrent(this);
}
/** Handle command events*/
public void commandPerformed(Command command, Displayable
displayable) {
if( command == back )
{
display.setCurrent(oldDisplayable);
}
if( command == send )
{
sendSmsMessage( smsDestNumber.getString(), smsMessage.getString()
);
}
}
private void sendSmsMessage( String smsDestNum, String
smsMsgBody )
{
// Dopo aver effettuato alcuni controlli sui dati inseriti
nella form provvede all'invio dell' SMS
Image alertImg;
Alert alert;
try {
alertImg = Image.createImage("/icons/alert.png");
alert = new Alert("", "" , alertImg,
AlertType.ERROR);
alert.setTimeout(Alert.FOREVER);
}catch (IOException e)
{
alert = new Alert("", "" , null,
AlertType.ERROR);
}
if( !"".equals(smsDestNum) )
{
try {
String destAddress = "sms://"+smsDestNum;
// Apertura della connessione con un ipotetico centro
servizi sms
smsConnection = (MessageConnection) Connector.open("sms://"+smscAddress+":9001");
// Creazione di un nuovo messaggio di tipo "testo"
TextMessage smsTextMessage = (TextMessage)smsConnection.newMessage(MessageConnection.TEXT_MESSAGE);
// Settaggio dell'indirizzo del destinatario
smsTextMessage.setAddress(destAddress+":9001");
// Inserimento del contenuto dati (testo)
smsTextMessage.setPayloadText(smsMsgBody);
// Invio del messaggio
smsConnection.send(smsTextMessage);
// Chiusura della connessione
smsConnection.close();
} catch (Exception e)
{
alert.setString("\n ERROR SENDING \n SMS MESSAGE
");
e.printStackTrace();
display.setCurrent(alert , this);
}
}
else
{
alert.setString("\n INVALID\n NUMBER");
display.setCurrent(alert , this);
}
}
}
package
midpsms;
import
java.io.*;
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.wireless.*;
import javax.wireless.messaging.*;
public
class SmsMessageForm extends TextBox {
private Command back;
private Command datails;
private Display display;
private Displayable oldDisplayable;
private SmsMessage smsMessage;
private boolean showDetails = false;
public SmsMessageForm( SmsMessage smsMessage, Display
d, Displayable dy) {
super("Message", "", 50, TextField.ANY);
this.display = d;
this.oldDisplayable = dy;
this.smsMessage = smsMessage;
setCommandListener(new CommandListener() {
public void commandAction(Command command, Displayable
displayable) {
commandPerformed(command, displayable);
}
});
back = new Command("back",Command.BACK, 1);
datails = new Command("details",Command.OK,
1);
this.addCommand(back);
this.addCommand(datails);
this.setMaxSize(smsMessage.getMessageBody().length());
this.setString(smsMessage.getMessageBody());
smsMessage.setIsToRead(false);
}
public void commandPerformed(Command command, Displayable
displayable) {
if( command == back && showDetails == false
)
{
display.setCurrent(oldDisplayable);
}
if( command == back && showDetails == true )
{
showDetails = false;
this.setMaxSize(smsMessage.getMessageBody().length());
this.setString(smsMessage.getMessageBody());
}
if( command == datails )
{
showDetails = true;
this.setMaxSize(smsMessage.getMessageDetails().length());
this.setString(smsMessage.getMessageDetails());
}
}
}
package midpsms;
import
java.util.*;
import javax.wireless.messaging.*;
public
class SmsMessage {
private String address;
private String timestamp;
private String messageBody;
private boolean toRead = true;
public SmsMessage(Message message) {
// Ottiene l'indirizzo del messaggio sms (del mittente)
address = message.getAddress();
// Ottiene il timestamp del messaggio
timestamp = getTimeStamp( message.getTimestamp() );
// Per ottenere il campo dati occorre valutare se si
tratta di un messaggio di testo o binario
if (message instanceof TextMessage) {
TextMessage textSmsMessage = (TextMessage)message;
messageBody = textSmsMessage.getPayloadText();
}
else
if (message instanceof BinaryMessage) {
BinaryMessage binarySmsMessage = (BinaryMessage)message;
messageBody = new String (binarySmsMessage.getPayloadData());
}
}
public String getMessageDetails () {
return "Sender : "+ address + "\n Date
: "+ timestamp;
}
public String getMessageBody () {
return messageBody;
}
public boolean getIsToRead () {
return toRead;
}
public void setIsToRead (boolean read ) {
toRead = read;
}
private String getTimeStamp (Date timestamp ) {
Calendar c = Calendar.getInstance();
c.setTime(timestamp);
String ts = "";
ts += " " + c.get(Calendar.DAY_OF_MONTH);
ts += "/" + (c.get(Calendar.MONTH) + 1);
ts += "/" + c.get(Calendar.YEAR);
ts += " " + c.get(Calendar.HOUR_OF_DAY);
ts += ":" + c.get(Calendar.MINUTE);
ts += ":" + c.get(Calendar.SECOND);
ts += ":" + c.get(Calendar.MILLISECOND);
return ts;
}
}
Il funzionamento di tale applicazione è visibile
nelle figure seguenti.
Figura 5 - Invio di un Sms dal dispositivo wireless
Figura
6
- Ricezione del messaggio da parte del "server"
Figura
7 - Invio di un Sms al dispositivo wireless e sua
ricezione.
In alto a destra è visibile il ticker che segnala
la ricezione del nuovo messaggio
Figura 8 - Visualizzazione del contenuto del
messaggio Sms ricevuto
Tabella
1 - le porte riservate
Bibliografia
e riferimenti
Sito
di riferimento su J2ME
http://java.sun.com/j2me
Configurazione CLDC:
http://www.mokabyte.it/2002/02/j2me_2.htm
Generic Connection Framework:
http://www.mokabyte.it/2002/07/j2me-6.htm
JavaComm e GSM:
http://www.mokabyte.it/2002/09/javasms.htm
http://www.gsmworld.com/index.shtml
Protocollo GSM
http://www.etsi.org
|