1 / 33

MIDP 2.0 Push Registry

MIDP 2.0 Push Registry. Khanh Le. Objectives. Cover the new mechanism called the push registry, introduced in MIDP 2.0 (JSR 118). Find out what the push registry comprises, see an overall description of its exposed API Learn how to use this API to push-enable your application.

Download Presentation

MIDP 2.0 Push Registry

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. MIDP 2.0 Push Registry Khanh Le

  2. Objectives • Cover the new mechanism called the push registry, introduced in MIDP 2.0 (JSR 118). • Find out what the push registry comprises, see an overall description of its exposed API • Learn how to use this API to push-enable your application. • Use of the version of the J2ME Wireless Toolkit that supports MIDP 2.0 to test your push-enabled MIDP application.

  3. The Push Registry • The push registry enables MIDlets to set themselves up to be launched automatically, without user initiation. • The push registry manages network- and timer-initiated MIDlet activation; that is, it enables an inbound network connection or a timer-based alarm to wake a MIDlet up. • The push registry is part of the application management system (AMS), the software in the device that's responsible for each application's life-cycle (installation, activation, execution, and removal). • The push registry is the component of the AMS that exposes the push API and keeps track of push registrations.

  4. The Push Registry • The PushRegistry API allows you to register push alarms and connections, and to retrieve information about push connections. A typical push registry maintains lists of connection and alarm registrations in both memory and persistent storage.

  5. The PushRegistry API • The push registry is part of the Generic Connection Framework (GCF) and is encapsulated within a single class, javax.microedition.io.PushRegistry, which exposes all the push-related methods. • With the PushRegistry API you can register a MIDlet for push events (inbound network connections and time-based alarms), discover whether the MIDlet was activated by an inbound connection, and retrieve push-specific information for a particular connection.

  6. MIDlet Activation and Life-Cycle • The advent of the push registry doesn't change the MIDlet life-cycle, but it does introduce two new ways a MIDlet may be activated: • By inbound network connections • By timer-based alarms

  7. Sharing the Responsibility for Push • In MIDP 2.0 the responsibility for push is shared between the MIDlet and the AMS. Once a MIDlet has registered itself with the push registry, the responsibility for push processing is split as follows: • When the MIDlet is not active, the AMS monitors registered push events on behalf of the MIDlet. When a push event occurs, the AMS activates the appropriate MIDlet to handle it. • If the MIDlet is active (running), the MIDlet itself is responsible for all push events. It must set up and monitor inbound connections, and schedule any cyclic tasks it needs - basically standard networking and timer processing.

  8. About Inbound Connections • To support network-based push activation, the platform must support inbound connection types. MIDP 2.0 defines new connection types beyond HTTP, including TCP sockets and UDP datagrams, that can be set up as inbound connections, making them suitable for push. In addition, the Wireless Messaging API (WMA, JSR 120) makes SMS-based push activation possible as well. • Inbound connections can be message-based (such as SMS), stream-based (such as TCP socket) or packet-based (such as datagrams). • An inbound network connection is based on either a static or a dynamic local address. Ports may also be static or dynamically assigned • To create an inbound connection based on a static address, call Connector.open() with a URL that describes both a protocol and a local inbound port; for example: Connector.open("socket://:5000") Connector.open("datagram://:5000") Connector.open("sms://:5000")

  9. About Inbound Connections • To create an inbound connection based on a dynamic address, call Connector.open() with a URL that describes just a protocol (and not a local inbound port), to indicate you want the system to assign an address; for example: Connector.open("socket://") Connector.open("datagram://") • When using a system-assigned address, you must publish this address so that external systems can connect to your application. If you're using a ServerSocketConnection or a UDPDatagramConnection you can get the dynamically assigned address from the getLocalAddress() and getLocalPort() methods. You can also retrieve the hostname assigned to your device, by invoking System.getProperty("microedition.hostname"). To publish the dynamic address on an external system you can simply use HTTP.

  10. Push Registration • To become push-enabled, MIDlets must register with the push registry, using one of two types of registration: • Static Registration - Registrations of static (well known) connections occur during the installation of the MIDlet suite. You specify them by listing MIDlet-Push attributes in the MIDlet suite's JAD file or JAR manifest. The installation will fail if you attempt to register an address that's already bound. Uninstalling a MIDlet suite automatically unregisters the connection. • Dynamic Registration - You register dynamic connections and timer alarms at runtime, using the PushRegistry API. • Note that, while you can use either method to register inbound connections, timer-based activation can be registered only at runtime.

  11. Static registrations are defined by listing one or more MIDlet-Push attributes in the JAD file or JAR manifest. The AMS performs static registration when the MIDlet suite is installed. Similarly, when the MIDlet suite is uninstalled, the AMS automatically unregisters all its associated push registrations. The format of the MIDlet-Push attribute is... MIDlet-Push-<n>: <ConnectionURL>, <MIDletClassName>, <AllowedSender> MIDlet-1: PushMIDlet,,j2medeveloper.basicpush.PushMIDlet MIDlet-2: WMAMIDlet,,j2medeveloper.wma.WMAMIDlet MIDlet-Name: MyMIDletSuite MIDlet-Vendor: Sun Microsystems, Inc. MIDlet-Version: 1.0 MIDlet-Jar-Size: 4735 MIDlet-Jar-URL: basicpush.jar MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-1.0 MIDlet-Push-1: socket://:5000, j2medeveloper.basicpush.PushMIDlet, * MIDlet-Permissions: javax.microedition.io.PushRegistry, javax.microedition.io.Connector.serversocket Static Registration - Using the MIDlet-Push Attribute

  12. Dynamic Registration • You'll use the PushRegistry API to accomplish dynamic registration of both inbound network connections and timer-based alarms, at runtime. Let's look at each push type individually.

  13. Registering a Timer Alarm • Your MIDlet may be required to perform some cyclic processing every so often. For example, it may need to synchronize with a server every 30 minutes. Your MIDlet will typically use a TimerTask to schedule a thread for cyclic processing ... // cyclic background task info. long REFRESH_TIME = 1000*60*5; // every 5 minutes Timer aTimer = new Timer(); MyTask myTask = new MyTask(); aTimer.schedule(myTask, 0, REFRESH_TIME); ... class MyTask extends TimerTask { // Constructor. public MyTask() { } ...// Thread run method. public void run() { ... Your Task Logic } } ...

  14. Registering a Timer Alarm • If your MIDlet needs to continue its cyclic processing even when it's not running, you can use push alarms to schedule your MIDlet for future execution. • To schedule a MIDlet launch by the AMS the MIDlet invokes the PushRegistry.registerAlarm() method, passing as arguments the fully qualified class name of the MIDlet to launch, and the time for the launch. • Passing a time of zero disables the alarm. • Note that only one outstanding alarm per MIDlet is supported, and invoking this method overwrites any previously scheduled alarm.

  15. Registering a Timer Alarm /** * Schedule this MIDlet's launch. * @param deltatime the length of time in * milliseconds before expiration. */ private void scheduleMIDlet(long deltatime) throws ClassNotFoundException, ConnectionNotFoundException, SecurityException { String cn = this.getClass().getName(); // Get the current time by calling Date.getTime() Date alarm = new Date(); long t = PushRegistry.registerAlarm(cn, alarm.getTime()+deltatime); }

  16. Registering a Timer Alarm • Note that the PushRegistry API doesn't provide a way to discover whether the MIDlet was activated by an alarm. If that knowledge is important, you must implement your own detection method. One way is to save information, such as the time of launch, in the RMS, then compare the saved time with the current time when the MIDlet is launched. • A MIDlet that requires push alarms must schedule them before it exits. The following code snippet uses the scheduleMIDlet() method on Listing 3 to schedule the MIDlet's launch before exiting:

  17. Registering a Timer Alarm /** * Destroyed state. Release resources (connection, * threads, etc). Also, schedule the future launch of * the MIDlet. @param uc If true when this method is * called, the MIDlet must cleanup and release all * resources. If false the MIDlet may throw * a MIDletStateChangeException to indicate it does * not want to be destroyed at this time. * @throw MIDletStateChangeException to indicate * it does not want to be destroyed at this time. */ public void destroyApp(boolean uc) throws MIDletStateChangeException { // Release resources ... // Set up the alarm and force the MIDlet to exit. scheduleMIDlet(defaultDeltaTime); display = null; }

  18. Registering an Inbound Connection • The MIDlet calls registerConnection() to register the newly created inbound (server) socket connection ...// MIDlet class name.String midletClassName = this.getClass().getName();// Register a static connection.String url = "socket://:5000";// Use an unrestricted filter.String filter = "*";try { // Open the connection. ServerSocketConnection ssc = (ServerSocketConnection)Connector.open(url); // Register the connection now so that when this // MIDlet exits (is destroyed), the AMS can activate // our MIDlet when network activity is detected. // The AMS will remember the registered URL // even when the MIDlet is not active. PushRegistry.registerConnection(url, midletClassName, filter); // Now wait for inbound network activity. SocketConnection sc = (SocketConnection)ssc.acceptAndOpen(); // Read data from inbound connection. InputStream is = sc.openInputStream(); // ..... read from the input stream. // Here process the inbound data. // .....}catch(SecurityException e) { System.out.println("SecurityException, insufficient permissions"); e.printStackTrace();}catch(ClassNotFoundException e) { System.out.println("ClassNotFoundException, MIDlet name not found"); e.printStackTrace();}catch(IOException e) { System.out.println("IOException, possibly port already in use."); e.printStackTrace();}...

  19. Registering an Inbound Connection • Registering an inbound datagram connection is done much the same way. You just use a DatagramConnection and a Datagram instead. • This example registered a user-defined port. Let's look at an example where you let the system allocate the port for you. Because the port is system-assigned, the MIDlet must discover the assigned port and publish it:

  20. Registering an Inbound Connection ...// MIDlet class name. String midletClassName = this.getClass().getName(); // Register a dynamic connection.String url = "socket://"; // Use an unrestricted filter. String filter = "*"; try { // Open the connection. ServerSocketConnection ssc = (ServerSocketConnection)Connector.open(url); // Discover the system-assigned port. url = "socket://:" + ssc.getLocalPort(); // Register the connection now. The AMS will remember // the registered URL even when the MIDlet is not active. PushRegistry.registerConnection(url, midletClassName, filter); // Now publish the push URL. We can use an HTTP // POST or a socket or datagram for this. String purl; purl = "socket://"+ssc.getLocalAddress()+": "+ssc.getLocalPort(); publishInboundConnection(purl, midletClassName); } catch(SecurityException e) { ...

  21. Registering an Inbound Connection • To use an HTTP connection to publish this MIDlet's URL to an external agent, invokes publishInboundConnection: /** * An example of a method to publish dynamic inbound * address. * @param url is the inbound address * @param midlet is the name of the midlet */private void publishInboundConnection(String url, String midlet) { String hostToPostTo = "j2medeveloper:8080/pushagent"; OutputStream os = null; HttpConnection hc = null; try { if (hostToPostTo.startsWith("http://") == false) { hostToPostTo = "http://" + hostToPostTo; } hc = (HttpConnection)Connector.open(hostToPostTo); // Set HTTP request method, set Content-Type, // send body. int len = url.length() + midlet.length(); String pushinfo = "pushurl=" + url + ", pushmidlet=" + midlet ;hc.setRequestMethod(HttpConnection.POST); hc.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0" ); hc.setRequestProperty("Content-Language", "en-US"); hc.setRequestProperty("Accept", "text/xml"); hc.setRequestProperty("Connection", "close"); hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); hc.setRequestProperty ("Content-Length", ""+pushinfo.length()); os = hc.openOutputStream(); os.write(pushinfo.getBytes()); } catch(Exception e) { e.printStackTrace(); } finally { try { if (os != null) os.close(); if (hc != null) hc.close(); } catch (IOException e) { e.printStackTrace(); } } }

  22. Unregistering an Inbound Connection • Because the AMS maintains the registration even after the MIDlet exits, it's important that the MIDlet unregister the connection when it's no longer needed. To unregister an inbound connection, use the unregisterConnection() method: ... try { boolean status; // unregisterConnection returns false if it was // unsuccessful and true if successful. status = PushRegistry.unregisterConnection(url); } catch(SecurityException e) { System.out.println("SecurityException, insufficient permissions"); e.printStackTrace(); } ...

  23. Discovering Whether a MIDlet Was Push-Activated • The PushRegistry.listConnections() method allows you to discover all the inbound connections registered by the MIDlet suite. You can also use it to discover whether the MIDlet was activated by an incoming connection. • If you pass false to listConnections(), the method returns a string array that identifies all the inbound connections registered by the MIDlet suite, but if you pass a true argument the method reports only the registered connections with available data - indicating that MIDlet activation was due to incoming network data

  24. Discovering Whether a MIDlet Was Push-Activated /** * Determine if activated due to inbound connection and * if so dispatch a PushProcessor to handle incoming * connection(s). @return true if MIDlet was activated * due to inbound connection, false otherwise */ private boolean handlePushActivation() { // Discover if there are pending push inbound // connections and if so, dispatch a // PushProcessor for each one. String[] connections = PushRegistry.listConnections(true); if (connections != null && connections.length > 0) { for (int i=0; i < connections.length; i++) { PushProcessor pp = new PushProcessor(connections[i]); } return(true); } return(false); } • For each inbound connection returned, handlePushActivation() dispatches a PushProcessor that opens the connection, and waits for and consumes incoming data.

  25. Getting Information About a Push Connection • The push registry provides two other methods to retrieve information about a registered connection - specifically, the information defined by the MIDlet-Push property or by a call to registerConnection(): • getMIDlet() retrieves the MIDlet responsible for a particular connection. • getFilter() retrieves the <Allowed-Sender> filter for a particular connection.

  26. Getting Information About a Push Connection /** * Output push info for all push connections for the MIDlet suite */ private void outputPushInfo() { // Discover if there are pending push inbound // connections and if so, output the push info // for each one. String[] connections = PushRegistry.listConnections(false); if (connections != null && connections.length > 0) { for (int i=0; i < connections.length; i++) { String midlet = PushRegistry.getMIDlet(connections[i]); String filter = PushRegistry.getFilter(connections[i]); // Output the info. System.out.println("PushInfo -> " + connections[i] + " " + midlet + " " + filter); form.append(connections[i] + " " + midlet + " " + filter); } } }

  27. Security Considerations • MIDP 2.0 introduces two highly useful security concepts, application signing and privileged domains. • Application signing enables the platform to determine whether to trust another application, basing the decision on that application's origin and integrity, and on the use of an X.509 digital certificate. • Privileged domains allow the platform to use a policy definition to restrict access to APIs. Policy definitions are transparent to the MIDlet and are typically owned by the service provider, in the case of a phone, the wireless carrier ,for example. • Network and push operations are considered restricted: applications must request permission before using them. Attempting to use a restricted operation without proper permission causes the system to throw a SecurityException.

  28. Security Considerations • You request permissions in the JAD file or the JAR manifest, by creating MIDlet-Permissions property entries. • Permission names follow the hierarchical naming convention used in Java packages. • For example, to request permission to use the PushRegistry and ServerSocketConnection APIs, define the following property entry: MIDlet-Permissions: javax.microedition.io.PushRegistry, javax.microedition.io.Connector.serversocket

  29. Other Important Considerations • There are other push-related considerations worth mentioning: • PushRegistry and WMA - While MIDP 2.0 defines socket and datagram connection types, it does not define message-oriented connection types, such as SMS. The Wireless Messaging API introduces MessageConnection, a special connection type for message-oriented connections. You can set up a MessageConnection for inbound connections and use it for push. • User interface and headless applications - Even though it's possible to create a push-activated MIDlet that exposes no user interface, doing so may confuse the user - at a minimum, provide a simple screen that tells the user what your application is attempting to do.

  30. Using the Wireless Toolkit Emulator • The J2ME Wireless Toolkit, version 2.0, includes an implementation of MIDP 2.0. With it you can test your push registry alarms and inbound socket and datagrams connections. • Once you have developed your push-enabled MIDlet, you can install it in the device emulator for testing. • Note that for static push registrations to work properly you must install the application using the AMS, which in the toolkit is the Java Application Manager (JAM) - in other words, running the MIDlet from the command line is not sufficient.

  31. Summary • The push registry implements a MIDlet-activation model that allows MIDlets to become active as a result of network activity or timer alarms. • To become push-enabled, a MIDlet must register with the push registry. • The push registry supports static and dynamic push registrations. • Static registrations occur at installation and are defined by entries in the JAD file. • Dynamic registrations occur at runtime by calls to the registerConnection() method. • The push registry also provides methods to retrieve information about the push connections associated with the MIDlet suite. • PushRegistry's methods throw security and other exceptions that you should catch to make your MIDlet robust.

  32. Summary • The responsibility for push is shared between the MIDlet and the push registry in the AMS. • The MIDlet is responsible for registering and unregistering inbound connections and timer alarms. • When it's active, it's responsible for setting up and waiting for connections, and for the scheduling of any cyclic tasks, typically by using a TimerTask. • When the MIDlet is not running, the AMS will do the timer and inbound connection monitoring and will activate the appropriate MIDlet when it detects push activity is detected.

  33. Summary • To support push, the platform must support inbound connection types, typically socket, datagram, or WMA. • For a MIDlet to be able to receive a push event, it must have an address that allowed senders know. • For SMS messages, the push address is the phone's number (and port). • For socket and datagram connection types, it's an IP address. If the IP address is static (well known) then it's easy for anyone to push to the device, but if the IP address is dynamic, the MIDlet is responsible for publishing this address so external agents can push information to it. • You must request permission to use the push registry and inbound network connections using the new MIDP 2.0 permission framework. • You can use version 2.0 of the J2ME Wireless Toolkit to test your push MIDlets.

More Related