⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oct01_ericg.txt

📁 TechTips j2me的常用技巧. 网络功能
💻 TXT
📖 第 1 页 / 共 2 页
字号:

 J 2 M E    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC)
Java(tm) 2 Platform, Micro Edition (J2ME(tm)) 
Tech Tips, for October 15, 2001. This issue covers:

     * Using Passwords to Protect Your MIDlets
     * Adapting Images for MIDP Devices
         
The J2ME Tech Tips are written by Eric Giguere
(http://www.ericgiguere.com), an engineer at iAnywhere 
Solutions, inc. Eric is the author of the book "Java 2 Micro
Edition: Professional Developer's Guide" and co-author of the 
upcoming "Mobile Information Device Profile for Java 2 Micro 
Edition," both books in John Wiley & Sons' Professional 
Developer's Guide series.

You can view this issue of the J2ME Tech Tips on the Web at
http://java.sun.com/jdc/J2METechTips/2001/tt1015.html

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
USING PASSWORDS TO PROTECT YOUR MIDLETS

Security is always a concern when you are writing an application 
that deals with sensitive data. It's especially so on handheld 
devices, which are more apt to be lost or stolen than a desktop
computer. A handheld device is likely to hold truly personal 
information that you don't want strangers to know, things such as 
important phone numbers and addresses. Safeguarding that 
information should always be a priority.

MIDP security prevents MIDlets in different MIDlet suites from 
interacting with each other or with their data. The MIDP runtime 
environment also disallows the dynamic loading of new classes 
over the network. Apart from system classes, a MIDlet can only 
use classes found in its suite's JAR file. If you want any further 
security, for example, protecting sensitive information from 
disclosure, you need to program it into the MIDlet itself.

The simplest way for a MIDlet to safeguard sensitive information, 
is to prompt the user for a password. You can program this into
the MIDlet so that the MIDlet does this when it starts or the 
first time it accesses sensitive data. You can also have the
MIDlet ask the user to confirm certain sensitive operations by 
reentering the password.

Prompting the user for a password is easily done using either 
the TextBox or the TextField class, both part of the 
javax.microedition.lcdui package. The TextBox class displays a 
top-level window consisting of a title, an optional label, and
a text entry field. No other user interface components can be 
added to a TextBox. So for more flexibility, you can use a 
TextField component. A TextField is a text entry field that can 
be placed on a Form, that is, a top-level window that can
display multiple user interface components. Both components have 
an identical interface, so what's being discussed here applies 
to either component.

Before looking at some code, however, let's answer an important 
question: what kind of password should you prompt for -- 
alphanumeric or just numeric? Your first thought might be to 
allow for alphanumeric passwords, because that's what is 
typically used with desktop computers. The reality, however, is 
that numeric-only passwords are the only ones that make sense in 
a MIDP context. Remember that a MIDP device might have a numeric 
keypad instead of a full keyboard -- think MIDP-enabled cellular 
telephone, for example. Entering text on a keypad is done by 
assigning multiple characters to individual keys and letting the 
user press the same key multiple times to cycle through its set 
of characters. This is a tedious and error-prone process that can 
frustrate the user. It is also more of a security risk, because 
password masking, that is, displaying a masking character instead 
of the actual character, must be disabled to allow users to 
view which characters they are actually entering. But anyone 
looking over the user's shoulder also has a clear view of the 
password! Using a numeric password makes for quicker and easier
password input. Think of it more like the personal identification
number you enter at an automated banking machine. 

Here's the code for a simple password prompter using the TextBox 
class:

// Defines a class that prompts the user
// for a numeric password.

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

public class PasswordPrompter
          extends TextBox
          implements CommandListener {

    private Display     display;
    private Displayable next;
    private int         pin;

    // Constructor with a default title

    public PasswordPrompter( int pin,
                             int maxchars,
                             Display display,
                             Displayable next ){
        this( defaultTitle, pin, maxchars,
              display, next );
    }

    // Constructor with a specific title

    public PasswordPrompter( String title,
                             int pin,
                             int maxchars,
                             Display display,
                             Displayable next ){
        super( title, "", maxchars,
              TextField.NUMERIC | TextField.PASSWORD );

        addCommand( okCommand );
        setCommandListener( this );

        this.display = display;
        this.next    = next;
        this.pin     = pin;

        display.setCurrent( this );
    }

    // Responds to the one-and-only command event
    // by checking the entered password against
    // the pin.  If it's OK, the user is "forwarded"
    // to the next displayable, otherwise an alert
    // is displayed.

    public void commandAction( Command c,
                               Displayable d ){
        String pinStr = getString();

        try {
            if( Integer.parseInt( pinStr ) == pin ){
                display.setCurrent( next );
                return;
            }
        }
        catch( NumberFormatException e ){
        }

        Alert alert = new Alert( "Error!",
                                 "Invalid password",
                                 null,
                                 AlertType.ERROR );

        setString( "" );
        display.setCurrent( alert, this );
    }

    private static final Command okCommand =
              new Command( "OK", Command.OK, 1 );

    private static final String defaultTitle =
             "Enter Password";
}

To invoke the prompter, just create an instance of the 
PasswordPrompter class, passing it the password to check against 
(as an integer), the maximum number of characters to allow for 
the password, the Display instance for the MIDlet, and the screen 
to display if the correct password is entered. Here is a simple
MIDlet that demonstrates the use of the prompter:

// A MIDlet that demonstrates the use of the
// password prompter.

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

public class PasswordTester extends MIDlet
                      implements CommandListener {

    private Display display;
    private Command exitCommand
             = new Command( "Exit", Command.EXIT, 1 );

    public PasswordTester(){
    }

    protected void destroyApp( boolean unconditional )
                   throws MIDletStateChangeException {
        exitMIDlet();
    }

    protected void pauseApp(){
    }

    protected void startApp()
                throws MIDletStateChangeException {
        if( display == null ){ // first time called...
            initMIDlet();
        }
    }

    private void initMIDlet(){
        display = Display.getDisplay( this );

        // First time through, ask for the password.

        new PasswordPrompter( 1234, 4, display,
                              new TrivialForm() );
    }

    public void exitMIDlet(){
        notifyDestroyed();
    }

    public void commandAction( 
                            Command c, Displayable d ){
        exitMIDlet();
    }

    // A trivial UI screen

    class TrivialForm extends Form {
        TrivialForm(){
            super( "MainApp" );
            addCommand( exitCommand );
            setCommandListener( PasswordTester.this );
        }
    }
}

In the example above, the password is hardcoded to be "1234." 
Of course, you wouldn't do this in a real application. What you
would do is get the password either from a record store
maintained by the application or else from an application 
property. An application property is a value stored in either the 
MIDlet suite manifest or the suite's application descriptor. To 
retrieve an application property just call the MIDlet's 
getAppProperty method. For example:

    MIDlet midlet = ....;
    int    password;
    
    try {
        String p = midlet.getAppProperty( "Password" );
        password = Integer.parseInt( p );
    }
    catch( NumberFormatException e ){
    }

Using an application property allows you to customize a MIDlet 
suite for a particular customer. For example, as part of a 
servlet-controlled download process, the customer could be asked 
to enter an email address. The process could then generate a 
random password and a custom version of the MIDlet suite, and
send the password to the customer by email. The customer would 
have to enter the password to activate the application, once it's 
on the device.
 
A word of caution in all of this: no security measure is 
foolproof, and password protection might not be enough security 
to protect every application. Data stored in the application 
manifest or descriptor is easily read by anyone with access to 
those files. Even data stored in a record store isn't secure. On 
a Palm device, for example, it's trivial for an experienced 
developer to examine the native Palm database that underlies a 
record store. If data is truly important, then it should be 
stored in an encrypted format.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ADAPTING IMAGES FOR MIDP DEVICES

The Mobile Information Device Profile (MIDP) supports the display 
of bitmapped images, but not with the flexibility of Java(tm) 2 
Standard Edition (J2SE(tm)). The MIDP specification only 
requires support for a single format, the Portable Network 
Graphics (PNG) format. PNG was developed primarily as a 
replacement for the older Graphics Interchange Format (GIF), and
has the support of the World Wide Web consortium. (See 
http://www.w3.org/Graphics/PNG/ for information about PNG.) 
Modern web browsers and image editors can load and save images 
in PNG format.

Still, many images on the World Wide Web are in GIF or JPEG (a 
"lossy" image format better suited for photographs) format, not 
PNG. This is a problem for MIDP applications that need to fetch 
and display web images. While it is certainly possible to add 
the necessary Java code to a MIDlet to perform GIF-to-PNG and 
JPEG-to-PNG conversions, it makes more sense to do the 
conversion on a server instead of the client. Not only does this 
make your application smaller, it is likely to be much faster.
Because you're already fetching images across the network,
fetching the image through a web server extension you've written 
is not going to be much slower.

Even images already in PNG format can benefit from being 
funneled through a server, because the server can adapt the 
image to fit the device's characteristics. For example, the width 
and height of the display varies from device to device, so the 
server could scale the image appropriately. The server can also
change the bit-depth of the image based on the number of colors 
the device supports. One approach, then, is to not package an 
application's images with the application but to download them 
dynamically the first time the application is run, storing
the customized images locally using the MIDP's Record Management 
System (RMS).

In effect, what you need is a "web service" (in a generic sense) 
that can dynamically fetch, convert and adapt an image for a 
particular device. An obvious way to do this is to write the 
service as a Java servlet, which the MIDP application can then 
access using HTTP. The basics of how to do this were covered in 
a previous J2ME Tech Tip, "Client-Server Communication Over HTTP 
Using MIDlets and Servlets", which you can read at
http://java.sun.com/jdc/J2METechTips/2001/tt0820.html#tip2.
This Tech Tips builds on those concepts.

The first thing you need to do is locate some image conversion 
code. There are many free and commercial packages available. But 
for our purposes let's use Sun's Jimi (Java Image Management 
Interface) software development kit, available for download from
http://java.sun.com/products/jimi. The Jimi SDK enhances the 
basic image support found in J2SE by providing encoders and 
decoders for various image formats. As a bonus, it runs under
Java 1.1.x as well as the Java 2 Platform. Note that a new set of 
imaging I/O extensions for the Java 2 Platform, developed under 
the Java Community Process, is available starting with J2SE 1.4, 
but given that J2SE 1.4 is currently in Beta, and that many 
servlet containers are still running with J2SE 1.2 or even
Java 1.1.8, Jimi is a reasonable choice to start with. Download 
the Jimi SDK and place the JimiProClasses.zip file in your
servlet container's classpath so that the servlet can use the 
Jimi classes.

With the Jimi classes, the servlet is almost trivial to write, 
but it's too long to include here. You can download the source
for the servlet from the following URL:
http://www.ericgiguere.com/techtips/ImageAdapter.zip. 

Compile the code and install it on your web server. As a test, 
you should be able to use a standard web browser to invoke the 
servlet. The web browser will display an image of Duke, the 
official Java mascot, fetched from the Sun Web site.  

Note that the servlet can handle any image supported by Jimi, 
including the JPEG, GIF and PNG formats.

Once the servlet is running, it's time to write a MIDlet that 
uses it to fetch images. Here is the code for the MIDlet:

import java.io.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -