|
MIDP3.0 | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectjavax.microedition.io.PushRegistry
public class PushRegistry
The PushRegistry
maintains a list of inbound connections. A
MIDlet can register the inbound connections with an entry in the
application descriptor or dynamically by calling the
registerConnection
method.
The connection strings are URIs that are used with Connector.open
to open the appropriate server connection.
While a MIDlet is running and has Connections open, it is responsible for
all I/O operations associated with the inbound connection using the appropriate
Generic Connection Framework API. When the MIDlet is not running or
and MIDlet does not have the URI open, the application management software(AMS)
listens for inbound notification requests. When a notification arrives for a
registered MIDlet, the AMS will start the MIDlet, if necessary, via the normal
invocation of MIDlet.startApp
method.
Implementations MUST guarantee that each inbound connection successfully registered (statically or dynamically) is logically unique. The logical uniqueness is determined by using the comparison ladder scheme as defined in [RFC3986]. Implementations MUST perform at least the simple string comparison, and SHOULD perform one or more of the latter steps of the comparison ladder scheme.
To avoid collisions on inbound generic connections, the application
descriptor 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
MIDP 3.0 Provisioning 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 not be fulfilled, it must register the Push connections using
the dynamic registration with
PushRegistry.registerConnection
method.
A conflict-free installation reserves each requested connection for the
exclusive use of a MIDlet in the suite. While the suite is installed, any
attempt by other MIDlets 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 the MIDlet will always succeed, assuming the MIDlet
does not already have the connection open.
If two MIDlet Suites have a static push connection in common, they can not be installed together. The end user would typically have to delete one before being able to successfully install the other.
In some cases the MIDlet may not function properly if it cannot listen to a certain protocol or port for incoming traffic. The static push registration has been designed for these cases. The MIDlet that must have access to certain protocol or port announces this need in the application descriptor or in the JAR manifest. The implementation check already at installation time that the requested protocol or port is available and registers the MIDlet to listen to the incoming traffic. If the request cannot be fulfilled because protocol or port is already reserved, the installation of the application fails.
Static Push registrations are done in the application descriptor or in the
JAR manifest with MIDlet-Push-<n>
attribute. Each push
registration entry contains the following information:
MIDlet-Push-<n>: <ConnectionURI>,
<MIDletClassName>, <AllowedSender>
where:
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. ConnectionURI
= the connection string used in
Connector.open()
MIDletClassName
= the MIDlet that is responsible for the
connection. The named MIDlet MUST be registered in the application descriptor
or the JAR manifest with a MIDlet-<n>
record. (This
information is needed when displaying messages to the user about the MIDlet
when Push connections are detected, or when the user grants/revokes
privileges for the MIDlet.) 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:
When the value of AllowedSender
field is just the wildcard character
"*", connections will be accepted from any originating source. For Push attributes
using the datagram
and socket
URIs (if supported by the
platform), AllowedSender
field contains a numeric IP address in the
same format for IPv4 and IPv6 as used in the respective URIs (IPv6 address
including the square brackets as in the URI). It is possible to use the wildcards
also in these IP addresses, e.g. "129.70.40.*" would allow subnet resolution. The
wildcards can also be used to match address delimiters, e.g. "72.5.1*" will match
"72.5.124.161". Note that the port number is not part of the filter for
datagram
and socket
connections. In every protocol,
the AllowedSender
field MUST match with the appropriate address field
of the incoming event. The address field to use and the exact syntax and semantics
of the address depend on the protocol. However, the address and the
AllowedSender
filter MUST be compared by exact string matching where
the strings are compared character by character and the characters need to match
exactly except as allowed by the two wildcard characters: asterisk(*) and question
mark(?).
This 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 URI string.
The following is a sample application descriptor 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, *
There are cases when defining a well known port registered with IANA is not necessary. Simple MIDlets may just wish to exchange data using a private protocol between a MIDlet and server MIDlet.
To accommodate this type of MIDlet, a mechanism is provided to dynamically allocate a connection and to register that information, as if it was known, when the MIDlet 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 MIDlet is requesting a
dynamic port to be allocated from the ports that are currently available. By
calling PushRegistry.registerConnection()
method 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).
Once the MIDlet has registered the connection with PushRegistry.registerConnection
method, the connection is listed in the PushRegistry.listConnetions(false)
return value. If the MIDlet has an open connection to the registered connection,
the AMS starts listening to the inbound connection once the connection has been
closed with Connector.close
method. If the MIDlet is deleted from
the phone, then its dynamic communication connections are unregistered automatically.
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, a MIDlet 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 MIDlets (if necessary) prior to the invocation of the push MIDlet.
After the AMS has started the Push application, the MIDlet is responsible for opening the connections and for all subsequent I/O operations. A MIDlet that needs to perform blocking I/O operations SHOULD use a separate thread to allow for interactive user operations. Once the MIDlet has been started and the connection has been opened, the AMS is no longer responsible for listening for Push notifications for that connection. The MIDlet is responsible for reading all inbound data.
If a MIDlet has finished with all inbound data it MAY the connection with
Connector.close()
method. If the connection is closed, then
the AMS resumes listening for Push notifications. This avoids the loss of data
that might occur if neither the MIDlet nor the AMS was listening.
When a registered Push MIDlet is not running the AMS listens for incoming connections and launches the MIDlet as necessary. If a Push MIDlet exits and there are incoming connections, either new or unhandled, for the MIDlet, then the MIDlet MUST be started to handle the available input.
A Push MIDlet SHOULD behave in a predictable manner when handling asynchronous data via the Push mechanism. A well behaved MIDlet SHOULD inform the user that data has been processed. (While it is possible to write MIDlets that do not use any user visible interfaces, this could lead to a confused end user experience to launch a MIDlet that only performs a background function.)
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. Once the installation has been successfully completed, (e.g. via provisioning - when the Installation notification message has been successfully transmitted, the MIDlet 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 MIDlet uses
acceptAndOpen()
to get the socket connected and for a datagram
connection the MIDlet 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 MIDlet. The MIDlet
life cycle defines the expected behaviors that an interrupted MIDlet could see
from a call to destroyApp()
.
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 MUST 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
method
when the platform does not support that optional capability.
The registerAlarm
method MUST be supported.
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 application descriptor 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-3.0 MicroEdition-Configuration: CLDC-1.1 MIDlet-1: InstantMessage, /icons/Chat.png, example.chat.SampleChat, * MIDlet-Push-1: datagram://:79, example.chat.SampleChat, * MIDlet-Permission-1: javax.microedition.io.PushRegistry "datagram://" MIDlet-Permission-2: javax.microedition.io.Connector "datagram://"
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 application descriptor. 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. ... } // Inner class to handle inbound messages on a separate thread. class MessageHandler implements Runnable { String connUrl ; MessageHandler(String uri) { connUri = uri ; } // 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(connUri); 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 application descriptor includes an entry indicating that the MIDlet 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-3.0 MicroEdition-Configuration: CLDC-1.1 MIDlet-1: JustCallMe, /icons/Ping.png, example.ping.SamplePingMe, * MIDlet-Permission-1: javax.microedition.io.PushRegistryPermission "datagram:" "static,dynamic" MIDlet-Permission-2: javax.microedition.io.DatagramProtocolPermission "datagram://"
public class SamplePingMe extends MIDlet { // Name of the current MIDlet 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 java.lang.String |
getFilter(java.lang.String connection)
Retrieve the registered filter for a requested connection. |
static java.lang.String |
getMIDlet(java.lang.String connection)
Retrieve the registered MIDlet for a requested connection. |
static java.lang.String[] |
listConnections(boolean available)
Return a list of registered connections for the current MIDlet. |
static long |
registerAlarm(java.lang.String midlet,
long time)
Register a time to launch the specified MIDlet. |
static void |
registerConnection(java.lang.String connection,
java.lang.String midlet,
java.lang.String filter)
Register a dynamic connection with the application management software. |
static boolean |
unregisterConnection(java.lang.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(java.lang.String connection, java.lang.String midlet, java.lang.String filter) throws java.lang.ClassNotFoundException, java.io.IOException
Register a dynamic connection with the application management software. Once registered, the dynamic connection acts just like a connection preallocated from the application descriptor.
While the MIDlet has opened the connection with Connector.open()
,
the AMS will NOT be listening for input. The MIDlet is responsible for the
connection. If the MIDlet has not opened a connection to the registered URI,
the AMS MUST listen for input regardless of whether the MIDlet is running
or not.
The arguments for the dynamic connection registration are the same as the Push Registration Attribute used for static registrations.
connection
- the URI for the connectionmidlet
- class name of the midlet
to be launched when
new external data is available. The named midlet
MUST be registered in the application descriptor or the JAR
manifest with a MIDlet-<n> record. This parameter has
the same semantics as the MIDletClassName
in the Push
registration attribute defined in the class description.filter
- a connection URI string indicating which senders are allowed
to cause the midlet
to be launched
java.lang.IllegalArgumentException
- if the connection string is null
or is not valid,
or if the filter string is null
or not valid
ConnectionNotFoundException
- if the runtime system does not support push delivery for
the requested connection protocol
java.io.IOException
- if the connection is already registered or if there are
insufficient resources to handle the registration request
java.lang.ClassNotFoundException
- if midlet
is null
or
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 application descriptor or the JAR manifest
java.lang.SecurityException
- if the midlet
does not have permission to
register a connectionunregisterConnection(java.lang.String)
public static boolean unregisterConnection(java.lang.String connection)
connection
- the URI for the connection
true
if the unregistration was successful,
false
if the connection was not registered or if
the connection argument was null
java.lang.SecurityException
- if the connection was registered by another MIDlet suiteregisterConnection(java.lang.String, java.lang.String, java.lang.String)
public static java.lang.String[] listConnections(boolean available)
Return a list of registered connections for the current MIDlet.
The URI of every registered connection is returned from
listConnections(false)
.
The URI of every connection that has available input is returned from
listConnections(true)
. URI's of connections opened with
Connector.open(URI)
are not returned. After the Connection
is closed new input may become available and the URI will again be included
in the return of listConnections(true)
. URIs of connections
that timeout or otherwise no longer have available input are not returned
from listConnections(true)
. Due to race conditions, a call to
listConnections(true)
may return URIs that will fail to open
with Connector.open
because timeouts or other connection errors.
When the MIDlet opens the URI, the MIDlet takes over listening for input
and the AMS stops listening. The listConnections(true)
method
will only see URIs with available input during the time that the MIDlet does
NOT have the connection open.
available
- if true
, only return the list of connections
ready for the handoff to the MIDlet,
otherwise return the complete list of
registered connections for the current MIDlet
public static java.lang.String getMIDlet(java.lang.String connection)
connection
- a registered generic connection URI string
null
if the
connection was not registered by the current MIDlet
or if the connection argument was null
registerConnection(java.lang.String, java.lang.String, java.lang.String)
public static java.lang.String getFilter(java.lang.String connection)
connection
- a registered generic connection URI string
null
, if
the connection was not registered by the current
MIDlet or if the connection argument was
null
registerConnection(java.lang.String, java.lang.String, java.lang.String)
public static long registerAlarm(java.lang.String midlet, long time) throws java.lang.ClassNotFoundException, javax.microedition.io.ConnectionNotFoundException
Register a time to launch the specified MIDlet. The PushRegistry
supports one outstanding wake up time per MIDlet in the current suite. A
MIDlet is expected to use java.util.TimerTask
for notification
of time based events while the MIDlet is running.
If a wakeup time was registered and is still pending, the wakeup time will be returned, otherwise zero is returned. If the wakeup time has passed then the wakeup is no longer pending and zero is returned.
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 application descriptor or the JAR
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()
.
If the time is zero, or is in the past, or the MIDlet
is already running at the time
then
the MIDlet MUST not be launched.
midlet
was scheduled to occur, in the format
returned by Date.getTime()
ConnectionNotFoundException
- if the runtime system does not support alarm based
application launch
java.lang.ClassNotFoundException
- 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 application descriptor or the JAR manifest or
if the midlet
argument is null
java.lang.SecurityException
- if the midlet
does not have permission to
register an alarmDate.getTime()
|
MIDP3.0 | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |