Vous êtes sur la page 1sur 25

J.E.D.I.

Chapter 09
Optional Packages
9.1 Objectives
In this section, we will be delving into writing, building, using the emulator and packaging
J2ME applications. The Integrated Programming Environment that we will be using is
Netbeans (www.netbeans.org).
After finishing this lesson, the student should be able to:
know the functionalities provided by the Mobile Media API
play simple tones
play an audio file from the network and from the JAR
send and receive SMS messages

9.2 Overview
Not all devices are created equal and each device class comes with different features. It
would be very difficult to create a standard specification that encompass all the existing
devices.
To accomodate the different capabilities of devices, MIDP has defined several optional
packages. These packages are specific to and cater only to the specific device feature.
In this section, we will be discussing how to start using the Mobile Media API (MMAPI) and
the Wireless Messaging API (WMA).

9.3 Mobile Media API (MMAPI)


The Mobile Media API (MMAPI) allows us to generate tones, play and record audio and
video on compatible devices.
Playing or recording media is handled by two objects: the DataSource and the Player.

Mobile Application Development

J.E.D.I.

The DataSource handles the details of getting the data from the source. The source may
be a file from the JAR or from the network (via HTTP), a record from the RMS, a streaming
connection from a server or other proprietary source. The Player does not have to worry
about where the data came from or the manner in which it would be fetched. All the Player
has to do is to read the data from the DataSource, process and display or playback the
media to the output device.
A third actor in our scene is the Manager. The Manager creates players from DataSources.
The Manager has methods to create Players from media locators (URL locations),
DataSources and InputStreams.

You can query MMAPI properties via the String System.getProperty(String key).

Key

Description

microedition.media.version

The version of the MMAPI specification


implemented by the device. Example: "1.1"

supports.mixing

Returns "true" if the device supports audio


mixing: can play at least two tones
simultaneously, can have at least two
Players playing audio simultaneously and
can play a tone even if at least one Player is
playing audio at the same time.

Mobile Application Development

J.E.D.I.

Key

Description

supports.audio.capture

returns the String "true" if audio capture is


supported. returns "false", otherwise.

supports.video.capture

returns the String "true" if video capture is


supported. returns "false", otherwise.

supports.recording

returns "true" if recording is supported.

9.3.1

Tone generation

Playing a tone is as simple as calling the static method Manager.playTone(int tone, int
duration, int volume). The valid values for the tone is from 0 to 127. The duration of the
playing of the tone is specified in milliseconds. The volume parameter is from 0 to 100.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;

import java.io.*;

public class ToneMIDlet extends MIDlet implements CommandListener{

private Command exitCommand, playCommand;


private Form form;
private Gauge volumeGauge;
private Gauge durationGauge;
private Gauge toneGauge;
private Display display;
private int duration = 2; // seconds
private int volume = 100;
private int tone = ToneControl.C4;
private static int MAX_VOLUME = 100;
private static int MAX_TONE = 127;
private static int MAX_DURATION = 5;

public ToneMIDlet() {
playCommand = new Command("Play", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
volumeGauge = new Gauge("Volume", true, MAX_VOLUME, volume);

Mobile Application Development

J.E.D.I.

toneGauge = new Gauge("Tone", true, MAX_TONE, tone);


durationGauge = new Gauge("Duration",true,MAX_DURATION,duration);

form = new Form("Tone Player");


form.addCommand(playCommand);
form.addCommand(exitCommand);
form.append(volumeGauge);
form.append(durationGauge);
form.append(toneGauge);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
if (c == playCommand){
try {
volume = volumeGauge.getValue();
tone = toneGauge.getValue();
duration = durationGauge.getValue();
Manager.playTone(tone, duration*1000, volume);
} catch (MediaException mex){}
}
}
}

9.3.2

Audio playback

The convenience method Manager.createPlayer(String URI) creates a player which will play
the data from the URI.

Mobile Application Development

J.E.D.I.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;

import java.io.*;

public class NetAudioMidlet extends MIDlet implements CommandListener{

private Command exitCommand, playCommand;


private Form form;
private Gauge volumeGauge;
private Display display;
private int volume = 100;
private static int MAX_VOLUME = 100;
Player player;

public NetAudioMidlet() {
playCommand = new Command("Play", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
volumeGauge = new Gauge("Volume", true, MAX_VOLUME, volume);

form = new Form("Audio Player");


form.addCommand(playCommand);
form.addCommand(exitCommand);
form.append(volumeGauge);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);

try {
player = Manager.createPlayer(
"http://localhost:8084/Chapter07/bong.wav");

player.realize();

// pre-fetch media to reduce latency

Mobile Application Development

J.E.D.I.

player.prefetch();
} catch (IOException ioex) {
display.setCurrent(new Alert("IO Exception",
ioex.getMessage(),
null, AlertType.ERROR));
}

catch (MediaException mex) {


display.setCurrent(new Alert("Media Exception",
mex.getMessage(),
null, AlertType.ERROR));

}
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
if (c == playCommand){
try {
VolumeControl control = (VolumeControl)
player.getControl("VolumeControl");
if (control != null){
control.setLevel(volumeGauge.getValue());
}

player.start();
}

catch (MediaException mex) {


display.setCurrent(new Alert("Media Exception",
mex.getMessage(),

null, AlertType.ERROR));

} catch (Exception ex){


display.setCurrent(new Alert("Exception",
ex.getMessage(),

null, AlertType.ERROR));

}
}
}
}
You can also play media from a file in the JAR by creating a Stream from the file resource

Mobile Application Development

J.E.D.I.

and passing it to Manager.createPlayer().

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;

import java.io.*;

public class AudioMidlet extends MIDlet implements CommandListener{

private Command exitCommand, playCommand;


private Form form;
private Gauge volumeGauge;
private Display display;
private int volume = 100;
private static int MAX_VOLUME = 100;
Player player;

public AudioMidlet() {
playCommand = new Command("Play", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
volumeGauge = new Gauge("Volume", true, MAX_VOLUME, volume);

form = new Form("Audio Player");


form.addCommand(playCommand);
form.addCommand(exitCommand);
form.append(volumeGauge);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d) {

Mobile Application Development

J.E.D.I.

if (c == exitCommand) {
notifyDestroyed();
}
if (c == playCommand){
try {
InputStream stream = getClass().
getResourceAsStream("bong.wav");
player = Manager.createPlayer(stream, "audio/x-wav");
player.realize();

VolumeControl control = (VolumeControl)


player.getControl("VolumeControl");
if (control != null){
control.setLevel(volumeGauge.getValue());
}

player.start();
}

catch (MediaException mex) {


display.setCurrent(new Alert("Media Exception",
mex.getMessage(), null, AlertType.ERROR));

} catch (Exception ex){


display.setCurrent(new Alert("Exception",
ex.getMessage(),

null, AlertType.ERROR));

}
}
}
}

9.4 Wireless Messaging API (WMA)


9.4.1

Sending SMS

Using the Wireless Messaging API is very similar to connection via Sockets and Datagrams.
In fact, it uses the same framework the Generic Connection Framework (GCF). The
connection URL format to use is "sms://+639178888888", where "+639178888888" is the
number of the phone you want to send messages to.

public void sendSMS(String number, String message) throws Exception{

Mobile Application Development

J.E.D.I.

String url = "sms://" +

number;

MessageConnection connection =
(MessageConnection) Connector.open(url);
TextMessage msg = (TextMessage) connection.newMessage(
MessageConnection.TEXT_MESSAGE);
msg.setPayloadText(message);
connection.send(msg);
connection.close();
}
Development of wireless applications on Netbeans 6.5 is very convenient. You don't have
to send actual SMS messages just to test your application. Netbeans (with mobility pack)
comes with J2ME Wireless Toolkit. This toolkit comes with an emulator. It also includes
tools for testing sending and receiving SMS messages. You can configure the phone
number (address) of the emulated phone by opening the WMA preferences.
Tools
Java Platforms
Sun Java Wireless Toolkit 2.5.2 for CDLC
Tools and Extensions
Open Preferences -> WMA
Open Utilities -> WMA: Open Console

Mobile Application Development

J.E.D.I.

Mobile Application Development

10

J.E.D.I.

Mobile Application Development

11

J.E.D.I.

Mobile Application Development

12

J.E.D.I.

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

public class SMSMidlet extends MIDlet implements CommandListener, Runnable


{

private Command exitCommand, sendCommand;


private Form form;
private TextField addressField, mesgField;
private Display display;

public SMSMidlet() {
sendCommand = new Command("Send", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);

addressField = new TextField(


"Phone Number", "+5550000", 32, TextField.ANY);
mesgField = new TextField(
"Message", "hello, world!", 160, TextField.ANY);

form = new Form("SMS Message");


form.append(addressField);
form.append(mesgField);
form.addCommand(sendCommand);
form.addCommand(exitCommand);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {

Mobile Application Development

13

J.E.D.I.

notifyDestroyed();
}
if (c == sendCommand) {
Thread thread = new Thread( this );
thread.start();
}
}

/**
* Sends an SMS message to number. This method will throw an exception
* if there is an error in connecting or sending the message.
* @param number
* @param message
*/
public void sendSMS(String number, String message) throws Exception{
String url = "sms://" +

number;

MessageConnection connection =
(MessageConnection) Connector.open(url);
TextMessage msg = (TextMessage) connection.newMessage(
MessageConnection.TEXT_MESSAGE);
msg.setPayloadText(message);
connection.send(msg);
connection.close();
}

public void run() {


try {
String address = addressField.getString();
String message = mesgField.getString();
sendSMS(address, message);
display.setCurrent(new Alert("SMS Message",
"Message Sent\n"
+ "To: " + address + "\n"
+ "Message: " + message,
null, AlertType.INFO));
} catch (Exception ex) {
display.setCurrent(new Alert("SMS Error", ex.getMessage(),
null, AlertType.ERROR));
}
}

Mobile Application Development

14

J.E.D.I.

Mobile Application Development

15

J.E.D.I.

Mobile Application Development

16

J.E.D.I.

Mobile Application Development

17

J.E.D.I.

9.4.2

Receiving SMS

To receive a text message, open a MessageConnection specifying a port. The protocol


string for SMS messaging is "sms". This command will listen for incoming SMS messages
from port 8888:

conn = (MessageConnection) Connector.open("sms://:8888");


We must register our application to be a Message Listener so that the AMS will notify our
MIDlet of incoming messages.

conn.setMessageListener(this);
The notifyIncomingMessage will be called by the AMS once a message is received by the
device. We will need to create a separate Thread for reading messages so that the Listener
callback method can exit immediately.

public void notifyIncomingMessage(MessageConnection messageConnection) {


if (thread == null){
thread = new Thread(this);
thread.start();
}
}
In our run() method, we are now ready to get the message:

Mobile Application Development

18

J.E.D.I.

public void run(){


try {
// wait for and receive message
Message mesg = conn.receive();

// Received a message
// Check if this is a text message (and not MMS, etc.)
if (mesg != null && mesg instanceof TextMessage) {
TextMessage text = (TextMessage) mesg;
addressField.setText(text.getAddress());
mesgField.setText(text.getPayloadText());
dateField.setText("" + text.getTimestamp());
statusField.setText("Message received.");
}
} catch (Exception e) {
statusField.setText("Error: " + e.getMessage());
}
thread = null;
}
Here is the complete source code listing for our SMS Receiver:

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

public class SMSReceiverMidlet extends MIDlet


implements CommandListener, MessageListener, Runnable

private Command exitCommand, sendCommand;


private Form form;
private StringItem statusField, addressField, mesgField, dateField;
private Display display;
private MessageConnection conn;
private Thread thread;
private String port = "8888";

public SMSReceiverMidlet() {
exitCommand = new Command("Exit", Command.EXIT, 1);

Mobile Application Development

19

J.E.D.I.

statusField = new StringItem("Status:", "");


addressField = new StringItem("From:", "");
mesgField = new StringItem("Message:", "");
dateField = new StringItem("Timestamp:", "");

form = new Form("SMS Receiver");


form.append(statusField);
form.append(addressField);
form.append(mesgField);
form.append(dateField);
form.addCommand(exitCommand);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);

startReceiver();
display.setCurrent(form);
}

public void pauseApp() {


thread = null;
}
public void destroyApp(boolean unconditional) {
thread = null;
if (conn != null){
try {
conn.close();
} catch (Exception ex){}
}
}

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
}

Mobile Application Development

20

J.E.D.I.

private void startReceiver(){


try {
String addr = "sms://:" + port;
if (conn == null){
conn = (MessageConnection) Connector.open(addr);

conn.setMessageListener(this);
statusField.setText(
"waiting for message at port " + port);
}
} catch (Exception ex){
statusField.setText("Cannot open connection on port "
+ port + ":" + ex.getMessage());
}

thread = new Thread(this);


thread.start();
}

public void notifyIncomingMessage(MessageConnection messageConn){


if (thread == null){
thread = new Thread(this);
thread.start();
}
}

public void run(){


try {
// wait for and receive message
Message mesg = conn.receive();

// Received a message
// Check if this is a text message (and not MMS, etc.)
if (mesg != null && mesg instanceof TextMessage) {
TextMessage text = (TextMessage) mesg;
addressField.setText(text.getAddress());
mesgField.setText(text.getPayloadText());
dateField.setText("" + text.getTimestamp());
statusField.setText("Message received.");
} else {

Mobile Application Development

21

J.E.D.I.

statusField.setText(
"Non-text message received: "
+ mesg.getClass().toString());
}
} catch (Exception e) {
statusField.setText("Error: " + e.getMessage());
}
thread = null;
}

Mobile Application Development

22

J.E.D.I.

Mobile Application Development

23

J.E.D.I.

9.5 Exercises

Mobile Application Development

24

J.E.D.I.

9.5.1

Audio Player

Create a MIDlet that will play an audio file for an idefinite number of times (loop). The
audio file should be read from the JAR. Hint: you must set a property on the Player to
control the looping.

9.5.2

SMS Auto-Responder

Create a MIDlet that will automatically reply when it receives a text message. Hint: you
can modify the SMSReceiverMidlet and use the same connection to send the reply
message.

Mobile Application Development

25

Vous aimerez peut-être aussi