|
MID Profile | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--javax.microedition.io.PushRegistry
The PushRegistry
maintains a list of inbound
connections. An application can register the inbound
connections with an entry in the application descriptor file
or dynamically by calling the
registerConnection
method.
While an application is running, it is responsible for
all I/O operations associated with the inbound connection.
When the application is not running, the application
management software(AMS) listens for inbound notification
requests. When a notification arrives for a registered
MIDlet
, the AMS will start the MIDlet
via the normal invocation of MIDlet.startApp
method.
To avoid collisions on inbound generic connections, the application
descriptor file MUST include information about static connections
that are needed by the MIDlet
suite.
If all the static Push declarations in the application descriptor
can not be fulfilled during the installation, the user MUST be
notified that there are conflicts and the MIDlet suite MUST NOT be
installed. (See Over The Air User Initiated Provisioning
Specification section for errors reported in the event
of conflicts.)
Conditions
when the declarations can not be fulfilled include: syntax errors in
the Push attributes, declaration for a connection end point (e.g. port
number) that is already reserved in the device, declaration for a
protocol that is not supported for Push in the device, and declaration
referencing a MIDlet
class that is not listed in
the MIDlet-<n>
attributes of the same
application descriptor.
If the MIDlet
suite
can function meaningfully even if a Push registration can't be
fulfilled, it MUST register the Push connections using the dynamic
registration methods in the PushRegistry
.
A conflict-free installation reserves each requested connection for
the exclusive use of the
MIDlets
in the suite. While the suite is
installed, any attempt by other applications to open one of the
reserved connections will fail with an
IOException
. A call from a
MIDlet
to
Connector.open()
on a connection reserved for its suite will always
succeed, assuming the suite does not already have the connection open.
If two MIDlet
suites have a static push connection in
common, they cannot be installed together and both function
correctly. The end user would typically have to uninstall one before
being able to successfully install the other.
Each push registration entry contains the following information :
where :
MIDlet-Push-<n>: <ConnectionURL>,
<MIDletClassName>, <AllowedSender>
MIDlet-Push-<n>
=
the Push registration attribute name. Multiple push
registrations can be provided in a MIDlet
suite. The numeric value for <n> starts from 1 and
MUST use consecutive ordinal numbers for additional entries.
The first missing entry terminates the list. Any
additional entries are ignored.
ConnectionURL
=
the connection string used in Connector.open()
MIDletClassName
=
the MIDlet
that is responsible for the connection.
The named MIDlet
MUST be registered in the
descriptor file or the jar file manifest with a
MIDlet-<n>
record.
(This information is needed when displaying messages to
the user about the application when push connections are detected,
or when the user grants/revokes priveleges for the application.)
If the named MIDlet
appears more than once in the
suite, the first matching entry is used. AllowedSender
= a designated filter that restricts which
senders are valid for launching the requested MIDlet
.
The syntax and semantics of the AllowedSender
field
depend on the addressing format used for the protocol.
However, every syntax for this field MUST support using the wildcard
characters "*" and "?". The semantics of those wildcard are:
datagram
and
socket
URLs (if supported by the platform), this field
contains a numeric IP address in the same format for IPv4 and IPv6 as
used in the respective URLs (IPv6 address including the square
brackets as in the URL).
It is possible to use the wildcards also in these IP addresses,
e.g. "129.70.40.*" would allow subnet resolution. Note that the port
number is not part of the filter for datagram
and
socket
connections.
The MIDP 2.0 specification defines the syntax for
datagram
and socket
inbound
connections. When other specifications
define push semantics for additional connection types, they
must define the expected syntax for the filter field, as well as
the expected format for the connection URL string.
The following is a sample descriptor file entry that would reserve a stream socket at port 79 and a datagram connection at port 50000. (Port numbers are maintained by IANA and cover well-known, user-registered and dynamic port numbers) [See IANA Port Number Registry]
MIDlet-Push-1: socket://:79, com.sun.example.SampleChat, *
MIDlet-Push-2: datagram://:50000, com.sun.example.SampleChat, *
The requirements for buffering of messages are specific
to each protocol used for Push and are defined separately
for each protocol. There is no general requirement related
to buffering that would apply to all protocols. If the
implementation buffers messages, these messages MUST
be provided to the MIDlet
when the
MIDlet
is started and it opens the related
Connection
that it has registered for Push.
When datagram connections are supported with Push, the
implementation MUST guarantee that when a MIDlet
registered for datagram Push is started in response to an incoming
datagram, at least the datagram that caused the startup of the
MIDlet
is buffered by the implementation and will be
available to the MIDlet
when the MIDlet
opens the UDPDatagramConnection
after startup.
When socket connections are supported with Push, the
implementation MUST guarantee that when a MIDlet
registered for socket Push is started in response to
an incoming socket connection, this connection can
be accepted by the MIDlet
by opening the
ServerSocketConnection
after startup, provided
that the connection hasn't timed out meanwhile.
Not all generic connections will be appropriate for use
as push application transport. Even if a protocol is supported
on the device as an inbound connection type, it is not required
to be enabled as a valid push mechanism. e.g. a platform might
support server socket connections in a MIDlet
,
but might not support inbound socket connections for push
launch capability.
A ConnectionNotFoundException
is thrown from
the registerConnection
and from the
registerAlarm
methods, when the platform
does not support that optional capability.
Responsibility for registered push connections is shared between
the AMS and the MIDlet
that handles the I/O
operations on the inbound connection. To prevent any data
from being lost, an application is responsible for
all I/O operations on the connection from the time it calls
Connector.open()
until it calls Connection.close()
.
The AMS listens for inbound connection notifications. This MAY be handled via a native callback or polling mechanism looking for new inbound data. The AMS is responsible for enforcing the Security of PushRegistry and presenting notifications (if any) to the user before invoking the MIDlet suite.
The AMS is responsible for the shutdown of any running
applications (if necessary) prior to the invocation of
the push MIDlet
method.
After the AMS has started the push application, the
MIDlet
is responsible for opening the
connections and for all subsequent I/O operations.
An application that needs to perform blocking I/O
operations SHOULD use a separate thread to allow
for interactive user operations.
Once the application has been started and the connection
has been opened, the AMS is no longer responsible for
listening for push notifications for that connection.
The application is
responsible for reading all inbound data.
If an application has finished with all inbound data
it MAY close()
the connection.
If the connection is closed,
then neither the AMS nor the application
will be listening for push notifications. Inbound data
could be lost, if the application closes the connection
before all data has been received.
When the application is destroyed, the AMS resumes its responsiblity to watch for inbound connections.
A push application SHOULD behave in a predictable manner when handling asynchronous data via the push mechanism. A well behaved application SHOULD inform the user that data has been processed. (While it is possible to write applications that do not use any user visible interfaces, this could lead to a confused end user experience to launch an application that only performs a background function.)
There are cases when defining a well known port registered
with IANA is not necessary.
Simple applications may just wish to exchange data using a private
protocol between a MIDlet
and server application.
To accomodate this type of application, a mechanism is provided
to dynamically allocate a connection and to register
that information, as if it was known, when the application was
installed. This information can then be sent to an agent on the network to
use as the mechanism to communicate with the registered
MIDlet
.
For instance, if a
UDPDatagramConnection
is opened and a port number,
was not specified, then the application is
requesting a dynamic port
to be allocated from the ports that are currently available. By
calling PushRegistry.registerConnection()
the
MIDlet
informs the AMS that it is the target for
inbound communication, even
after the MIDlet
has been destroyed (See
MIDlet
life cycle for
definition of "destroyed" state). If the application is deleted from the
phone, then its dynamic communication connections are unregistered
automatically.
During installation each MIDlet
that is expecting
inbound communication
on a well known address has the information recorded with the
AMS from the push registration attribute in the manifest or
application descriptor file. Once the installation has been
successfully completed,
(e.g. For the OTA recommended practices - when the Installation
notification message has been successfully transmitted, the
application is officially installed.)
the MIDlet
MAY then receive inbound communication.
e.g. the push notification event.
When the AMS is started, it checks the list of registered
connections and begins listening for inbound communication.
When a notification arrives the AMS starts the registered
MIDlet
.
The MIDlet
then opens
the connection with Connector.open()
method to
perform whatever I/O operations are needed for the particular
connection type. e.g. for a server socket the application
uses acceptAndOpen()
to get the socket connected
and for a datagram connection the application uses
receive()
to read the delivered message.
For message oriented transports the inbound message MAY be
read by the AMS and saved for delivery to the MIDlet
when it requests to read the data. For stream oriented transports
the connection MAY be lost if the connection is not
accepted before the server end of the connection request
timeouts.
When a MIDlet
is started in response to a registered
push connection notification, it is platform dependent what
happens to the current running application. The MIDlet
life cycle defines the expected behaviors that an interrupted
MIDlet
could see from a call to pauseApp()
or from destroyApp()
.
Usage scenario 1:
The suite includes a MIDlet
with a well
known port for communication.
During the startApp
processing
a thread is launched to handle the incoming data.
Using a separate thread is the recommended practice
for avoiding conflicts between blocking I/O operations
and the normal user interaction events. The
thread continues to receive messages until the
MIDlet
is destroyed.
In this sample, the descriptor file includes
a static push
connection registration. It also includes
an indication that this MIDlet
requires permission to use a datagram connection
for inbound push messages.
(See
Security of Push Functions in the package
overview for details about MIDlet
permissions.)
Note: this sample is appropriate for bursts of
datagrams.
It is written to loop on the connection, processing
received messages.
MIDlet-Name: SunNetwork - Chat Demo
MIDlet-Version: 1.0
MIDlet-Vendor: Sun Microsystems, Inc.
MIDlet-Description: Network demonstration programs for MIDP
MicroEdition-Profile: MIDP-2.0
MicroEdition-Configuration: CLDC-1.0
MIDlet-1: InstantMessage, /icons/Chat.png, example.chat.SampleChat, *
MIDlet-Push-1: datagram://:79, example.chat.SampleChat, *
MIDlet-Permissions: javax.microedition.io.PushRegistry, \\
javax.microedition.io.Connector.datagramreceiver
public class SampleChat extends MIDlet {
// Current inbound message connection.
DatagramConnection conn;
// Flag to terminate the message reading thread.
boolean done_reading;
public void startApp() {
// List of active connections.
String connections[];
// Check to see if this session was started due to
// inbound connection notification.
connections = PushRegistry.listConnections(true);
// Start an inbound message thread for available
// inbound messages for the statically configured
// connection in the descriptor file.
for (int i=0; i < connections.length; i++) {
Thread t = new Thread (new MessageHandler(
connections[i]));
t.start();
}
...
}
}
// Stop reading inbound messages and release the push
// connection to the AMS listener.
public void destroyApp(boolean conditional) {
done_reading = true;
if (conn != null)
conn.close();
// Optionally, notify network service that we're
// done with the current session.
...
}
// Optionally, notify network service.
public void pauseApp() {
...
}
// Inner class to handle inbound messages on a separate thread.
class MessageHandler implements Runnable {
String connUrl ;
MessageHandler(String url) {
connUrl = url ;
}
// Fetch messages in a blocking receive loop.
public void run() {
try {
// Get a connection handle for inbound messages
// and a buffer to hold the inbound message.
DatagramConnection conn = (DatagramConnection)
Connector.open(connUrl);
Datagram data = conn.newDatagram(conn.getMaximumLength());
// Read the inbound messages
while (!done_reading) {
conn.receive(data);
...
}
} catch (IOException ioe) {
...
}
...
Usage scenario 2:
The suite includes a MIDlet
that dynamically allocates port the first time
it is started.
In this sample, the descriptor file includes an entry indicating that the application will need permission to use the datagram connection for inbound push messages. The dynamic connection is allocated in the constructor the first time it is run. The open connection is used during this session and can be reopened in a subsequent session in response to a inbound connection notification.
MIDlet-Name: SunNetwork - Demos
MIDlet-Version: 1.0
MIDlet-Vendor: Sun Microsystems, Inc.
MIDlet-Description: Network demonstration programs for MIDP
MicroEdition-Profile: MIDP-2.0
MicroEdition-Configuration: CLDC-1.0
MIDlet-1: JustCallMe, /icons/Ping.png, example.ping.SamplePingMe, *
MIDlet-Permissions: javax.microedition.io.PushRegistry, \\
javax.microedition.io.Connector.datagramreceiver
public class SamplePingMe extends MIDlet {
// Name of the current application for push registration.
String myName = "example.chat.SamplePingMe";
// List of registered push connections.
String connections[];
// Inbound datagram connection
UDPDatagramConnection dconn;
public SamplePingMe() {
// Check to see if the ping connection has been registered.
// This is a dynamic connection allocated on first
// time execution of this MIDlet.
connections = PushRegistry.listConnections(false);
if (connections.length == 0) {
// Request a dynamic port for out-of-band notices.
// (Omitting the port number let's the system allocate
// an available port number.)
try {
dconn = (UDPDatagramConnection)
Connector.open("datagram://");
String dport = "datagram://:" + dconn.getLocalPort();
// Register the port so the MIDlet will wake up, if messages
// are posted after the MIDlet exits.
PushRegistry.registerConnection(dport, myName, "*");
// Post my datagram address to the network
...
} catch (IOException ioe) {
...
} catch (ClassNotFoundException cnfe) {
...
}
}
public void startApp() {
// Open the connection if it's not already open.
if (dconn == null) {
// This is not the first time this is run, because the
// dconn hasn't been opened by the constructor.
// Check if the startup has been due to an incoming
// datagram.
connections = PushRegistry.listConnections(true);
if (connections.length > 0) {
// There is a pending datagram that can be received.
dconn = (UDPDatagramConnection)
Connector.open(connections[0]);
// Read the datagram
Datagram d = dconn.newDatagram(dconn.getMaximumLength());
dconn.receive(d);
} else {
// There are not any pending datagrams, but open
// the connection for later use.
connections = PushRegistry.listConnections(false);
if (connections.length > 0) {
dconn = (UDPDatagramConnection)
Connector.open(connections[0]);
}
}
}
public void destroyApp(boolean unconditional) {
// Close the connection before exiting
if(dconn != null){
dconn.close()
dconn = null
}
}
...
Method Summary | |
static String |
getFilter(String connection)
Retrieve the registered filter for a requested connection. |
static String |
getMIDlet(String connection)
Retrieve the registered MIDlet for a requested connection. |
static String[] |
listConnections(boolean available)
Return a list of registered connections for the current MIDlet suite. |
static long |
registerAlarm(String midlet,
long time)
Register a time to launch the specified application. |
static void |
registerConnection(String connection,
String midlet,
String filter)
Register a dynamic connection with the application management software. |
static boolean |
unregisterConnection(String connection)
Remove a dynamic connection registration. |
Methods inherited from class java.lang.Object |
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Method Detail |
public static void registerConnection(String connection, String midlet, String filter) throws ClassNotFoundException, IOException
The arguments for the dynamic connection registration are the same as the Push Registration Attribute used for static registrations.
If the connection
or filter
arguments are null
,
then an IllegalArgumentException
will be thrown.
If the midlet
argument is null
a
ClassNotFoundException
will be thrown.
connection
- generic connection protocol, host
and port number
(optional parameters may be included
separated with semi-colons (;))midlet
- class name of the MIDlet
to be launched,
when new external data is available.
The named MIDlet
MUST be registered in the
descriptor file or the jar file manifest with a
MIDlet-<n> record. This parameter has the same semantics
as the MIDletClassName in the Push registration attribute
defined above in the class description.filter
- a connection URL string indicating which senders
are allowed to cause the MIDlet
to be launchedIllegalArgumentException
- if the connection string is not
valid, or if the filter string is not validConnectionNotFoundException
- if the runtime system does not
support push delivery for the requested
connection protocolIOException
- if the connection is already
registered or if there are insufficient resources
to handle the registration requestClassNotFoundException
- if the MIDlet
class name can not be found in the current MIDlet
suite or if this class is not included in any of the
MIDlet-<n> records in the descriptor file or the jar file
manifestSecurityException
- if the MIDlet
does not
have permission to register a connectionunregisterConnection(java.lang.String)
public static boolean unregisterConnection(String connection)
connection
- generic connection protocol,
host and port numbertrue
if the unregistration was successful,
false
if the connection was not registered
or if the connection argument was null
SecurityException
- if the connection was
registered by another MIDlet
suiteregisterConnection(java.lang.String, java.lang.String, java.lang.String)
public static String[] listConnections(boolean available)
MIDlet
suite.available
- if true
, only return the list of
connections with input available, otherwise return the
complete list of registered connections for the current
MIDlet
suitepublic static String getMIDlet(String connection)
MIDlet
for a requested connection.connection
- generic connection protocol, host
and port number
(optional parameters may be included
separated with semi-colons (;))MIDlet
to be launched,
when new external data is available, or
null
if the connection was not
registered by the current MIDlet
suite
or if the connection argument was null
registerConnection(java.lang.String, java.lang.String, java.lang.String)
public static String getFilter(String connection)
connection
- generic connection protocol, host
and port number
(optional parameters may be included
separated with semi-colons (;))MIDlet
to be
launched or null
, if the connection was not
registered by the current MIDlet
suite
or if the connection argument was null
registerConnection(java.lang.String, java.lang.String, java.lang.String)
public static long registerAlarm(String midlet, long time) throws ClassNotFoundException, ConnectionNotFoundException
PushRegistry
supports one outstanding wake up
time per MIDlet
in the current suite. An application
is expected to use a TimerTask
for notification
of time based events while the application is running.
If a wakeup time is already registered, the previous value will be returned, otherwise a zero is returned the first time the alarm is registered.
midlet
- class name of the MIDlet
within the
current running MIDlet
suite
to be launched,
when the alarm time has been reached.
The named MIDlet
MUST be registered in the
descriptor file or the jar file manifest with a
MIDlet-<n> record. This parameter has the same semantics
as the MIDletClassName in the Push registration attribute
defined above in the class description.time
- time at which the MIDlet
is to be executed
in the format returned by Date.getTime()
MIDlet
was scheduled to occur,
in the format returned by Date.getTime()
ConnectionNotFoundException
- if the runtime system does not
support alarm based application launchClassNotFoundException
- if the MIDlet
class name can not be found in the current MIDlet
suite or if this class is not included in any of the
MIDlet-<n> records in the descriptor file or the jar file
manifest or if the midlet
argument is
null
SecurityException
- if the MIDlet
does not
have permission to register an alarmDate.getTime()
,
Timer
,
TimerTask
|
MID Profile | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |