Chapter 9. The Network Methods of java.applet.Applet

Undoubtedly you’re familiar with applets, Java programs that can be embedded on a web page and run in a secure environment within a browser. All applets extend the java.applet.Applet class, which includes a number of methods that perform network-related operations. These methods allow an applet to find out where it came from, download images and sounds from a web server, and track the progress of the download. This chapter discusses the interaction between applets and the network. It doesn’t provide an introduction to the Applet class as a whole; for that, see an introductory book such as Niemeyer and Peck’s Learning Java (O’Reilly & Associates, Inc., 2000).

Using java.applet.Applet to Download Data

The methods of the Applet class discussed in this section are really just thin veneers over equivalent methods in the java.applet.AppletStub and java.applet.AppletContext interfaces. These interfaces describe services that the web browser or applet viewer provides to applets. The exact classes that implement these interfaces are undocumented and vary from implementation to implementation. Applets that you instantiate yourself (for example, an applet that also runs as an application by supplying a main( ) method that calls the applet’s init( ) and start( ) methods) will generally have null AppletStub and AppletContext members. Therefore, if you try to use these methods in such an applet, a NullPointerException will be thrown.

Figuring Out Where the Applet Came from

Most often, applets retrieve image files or other data from one of two directories: the directory the applet came from, or the directory the HTML page in which the applet was embedded came from. These directories are called the codebase and the document base, respectively. To make it easy to find other files, the Applet class has methods that return URL objects referring to the current page and the current applet. These methods are called getDocumentBase( ) and getCodeBase( ) respectively.

public URL getDocumentBase( )

The getDocumentBase( ) method returns the URL of the page containing the applet. Example 9.1 is a simple applet that displays the URL of the document in which it is embedded.

Example 9-1. An Applet That Shows Its Document Base

import java.applet.*;
import java.awt.*;

public class WhereAmI extends Applet {

  public void paint (Graphics g) {  
    g.drawString(this.getDocumentBase().toString(  ), 25, 50);    
  }

}

public URL getCodeBase( )

The getCodeBase( ) method returns the URL of the directory where the applet is located. If the applet is in a JAR archive, then the codebase is the URL of the directory where the JAR archive is. If the applet is in a package (e.g., com.macfaq.applets.MyApplet instead of just MyApplet), then the codebase is the directory or JAR archive containing the outermost package such as com. Security restrictions in applets are calculated relative to the codebase, not the document base. Example 9.2 is an applet that displays its document base and its codebase.

Example 9-2. An Applet That Displays Its Document Base and Its Codebase

import java.applet.*;
import java.awt.*;

public class AppletBases extends Applet {

  public void paint(Graphics g) {  
  
    g.drawString("Codebase:      " 
     + this.getCodeBase().toString(  ), 10, 40);
    g.drawString("Document base: " 
     + this.getDocumentBase().toString(  ), 10, 65);
    
  }

}

Figure 9.1 shows what happens when the applet runs; the result depends on the URLs of the applet and the document. It’s worth noting that getCodeBase( ) always returns the URL of a directory, not the URL of the applet itself, while getDocumentBase( ) always returns the URL of a file.

An applet that shows its document base and its codebase

Figure 9-1. An applet that shows its document base and its codebase

Downloading Images

In Chapter 7, you learned how to download data from an HTTP URL by using the getContent( ) and openStream( ) methods of the URL class. These methods are useful for text data such as an HTML file, but they don’t work as well for binary data, which usually requires some knowledge of the data’s structure. The Applet class includes several methods that understand more about what they’re downloading. The getImage( ) methods download image files and convert them into java.awt.Image objects:

public Image getImage(URL url)
public Image getImage(URL url, String name)

Like the other methods in this chapter, the two getImage( ) methods in the Applet class rely on an AppletContext field that is null for applets you instantiate yourself rather than being instantiated by a web browser or an applet viewer. However, the java.awt.Toolkit class includes identical getImage( ) methods that do not rely on an AppletContext. You can always get a Toolkit object by calling the static java.awt.Toolkit.getDefaultToolkit( ) method or the getToolkit( ) instance method of any subclass of java.awt.Component. Then you can use its getImage( ) methods just as you use the getImage( ) methods described here. The one difference is that you’ll need to prefix the calls to getImage( ) with a variable that refers to the Toolkit object. For example:

Toolkit t = java.awt.Toolkit.getDefaultToolkit(  );
URL u = new URL("http://metalab.unc.edu/javafaq/cup.gif")
Image theImage = t.getImage(u);

public Image getImage(URL u)

This method retrieves the image data at the specified URL and puts it in a java.awt.Image object. For example:

Image myLogo = getImage(new URL("http://metalab.unc.edu/java/cup.gif"));

The getImage( ) method relies on the AppletContext (provided by the web browser or applet viewer) to retrieve and interpret the image. Thus this method can get images only in formats understood by the AppletContext in which the applet is running. Currently, all contexts that run in a graphical environment understand the GIF format. (IBM’s Java environment for some of its mainframes and minicomputers is completely nongraphical because those platforms don’t support graphics.) Most contexts also understand JPEG though JPEG support was omitted from some vendors’ early alpha and beta releases. Finally, Java implementations derived from Sun’s source code often understand XBM. JDK 1.3 adds support for PNG. Example 9.3 is a complete applet that loads and displays the image referenced by the IMAGE parameter, which comes from a <PARAM> tag in the HTML file.

Example 9-3. Display an Image via a URL

import java.applet.*;
import java.awt.*;
import java.net.*;

public class ImageView extends Applet {

  Image picture;

  public void init(  ) {
  
    try {
      URL u = new URL(this.getCodeBase(  ), this.getParameter("IMAGE"));
      this.picture = this.getImage(u);
      System.err.println(u);
    }
    catch (MalformedURLException e) {
      // shouldn't happen, the codebase is never malformed
    }
   
  }
  
  public void paint (Graphics g) {
    g.drawImage(this.picture, 0, 0, this);
  }

}

The getImage( ) method returns immediately, even before it knows whether the image actually exists. The image isn’t loaded until some other part of the program actually tries to draw it, or you explicitly force the image to start loading—you’ll see how to do that shortly. At that point, the virtual machine starts a separate thread to download and process the image file.

public Image getImage(URL path, String filename)

This is similar to the previous method, except that it uses the path argument (a URL) to find the image’s directory and the filename argument (a String) to get the name of the image file. For example:

Image logo = this.getImage(new URL("http://metalab.unc.edu/java/"), 
 "cup.gif");

This version of getImage( ) is frequently used with getCodeBase( ) or getDocumentBase( ). You would use getCodeBase( ) in an applet that might be used on many different web servers but whose images would always be in the same directory as the applet. For example:

Image logo = this.getImage(this.getCodeBase(  ), "logo.gif"));

If the applet exists on only one web server but is embedded on many different pages, each of which loads different images, you would use getDocumentBase( ) to locate the images:

Image logo = this.getImage( this.getDocumentBase(  ), "logo.gif"));

This technique would be useful in an animator applet; the applet would probably read the names of some image files from parameters included in the HTML. You can use the filename argument to add to the path you get from the URL component. For example, if the pictures are in a directory called images, which is in the same directory as the HTML page, you would load the file logo.gif like this:

Image logo = this.getImage(this.getDocumentBase(  ), "images/logo.gif"));
                  
                  

Downloading Sounds

The Applet class has five methods that download sounds from the web. The two play( ) methods download a sound file and play it immediately. The two getAudioClip( ) methods and the static Applet.newAudioClip( ) method save a sound for later playing. The AppletContext, which is provided by the web browser or applet viewer, does the actual work of downloading and playing the sound file. Most Java 1.1 and earlier virtual machines support only Sun’s .au format and a very restricted form at that (8-bit sampling, 8 kilohertz, mono, -law encoded). Java 1.2 adds many more formats, including AIFF, WAV, MIDI Type 0, MIDI Type 1, and Rich Music Format (RMF). Furthermore, it supports 8- and 16-bit sampling, in both mono and stereo, with sampling rates from 8 kHz to 48 kHz in linear, a-law, or -law encoding. For pre-1.2 VMs, there are a number of freeware, shareware, and payware tools that convert sounds to the .au format, including SoX on Linux and Unix systems (http://home.sprynet.com/~cbagwell/sox.html ); SoundHack (http://shoko.calarts.edu/~tre/SndHckDoc/ ), Ulaw (http://www.kagi.com/rod/ ), and SoundEdit 16 (http://www.macromedia.com/software/sound/ ) on the Mac; and GoldWave on Windows (http://www.goldwave.com/ ).

public void play(URL u)

The play( ) method looks for a sound file at the URL u. If the sound file is found, then it is downloaded and played. Otherwise, nothing happens. For example:

try {
  URL soundLocation = new URL( 
   "http://metalab.unc.edu/java/course/week9/spacemusic.au" );
  play(soundLocation);
}
catch (MalformedURLException e) {
  System.err.println(e);
}

Example 9.4 is a simple applet that plays a sound file. The name of the file is taken from the parameter sound, which is supplied by a <PARAM> tag in the HTML file. The sound file should be in the same directory as the applet.

Example 9-4. Play a Sound

import java.applet.*;
import java.awt.*;
import java.net.*;

public class PlaySound extends Applet {

  public void init(  ) {
  
    try {
      URL u = new URL(this.getCodeBase(  ), this.getParameter("sound"));
      this.play(u);
    }
    catch (MalformedURLException e) {
    }
   
  }

}

public void play(URL url, String filename)

This is similar to the presious method, except that it uses the url argument to find the sound file’s directory and the filename argument to get the actual filename. For example:

play(new URL("http://www.macfaq.com/", "gong.au"));

The URL argument is frequently a call to getCodeBase( ) or getDocumentBase(). You use getCodeBase( ) if you know that the sound files will always be in the same directory as the applet, even if you don’t know in advance where the applet will be located. For example:

this.play(this.getCodeBase(  ), "gong.au"));

If the sound files are always located in the same directory as the HTML file that loads the applet, you would use getDocumentBase( ). In this scenario, one applet, residing in one directory, might be used by several web pages located in different directories on that server; each page might use a <PARAM> tag to specify its own sound file. Such an applet might call play( ) like this:

this.play(this.getDocumentBase(  ), this.getParameter("sound")));

You can use the filename argument to add to the path you get from the URL argument. For example, if the sounds are in a directory called sounds, which is a subdirectory of the directory containing the HTML page, you would call play( ):

this.play(this.getDocumentBase(  ), "sounds/gong.au"));

public AudioClip getAudioClip(URL u)

The java.applet.AudioClip interface represents a sound. You can download a sound from a web site with the getAudioClip( ) method. Once you have an AudioClip object, play it at your leisure by calling the clip’s play( ) and loop( ) methods; play( ) plays the file once, and loop( ) plays it repeatedly. Both of these methods let you keep the audio clip around for future use—unlike the play( ) method of the last section, which discarded the audio data after it had finished.

Using the AudioClip interface is simple. Make sure you’ve imported java.applet.AudioClip (many programmers, out of habit, import only java.applet.Applet); declare an AudioClip variable, and call getAudioClip( )to retrieve the sound file. As usual, the URL constructor needs to be wrapped in a try block because of a potential MalformedURLException. For example:

AudioClip theGong;
      
try {
  URL u = new URL(http://metalab.unc.edu/javafaq/gong.au);
  theGong = this.getAudioClip(u);
}
catch (MalformedURLException e) {
  System.err.println(e);     
}

public AudioClip getAudioClip(URL url, String filename)

This is similar to the previous method, except that it uses url to find the directory in which the sound file is located and filename to supply the name of the audio file. For example:

AudioClip ac = getAudioClip(new URL("http://www.macfaq.com/", "gong.au"));

This version of getAudioClip( ) is frequently used with getCodeBase( ) or getDocumentBase( ). For example, if you are writing an applet that will be stored on many different servers but whose sound files will always be in the same directory as the applet, you would call getAudioClip( ) like this:

AudioClip ac = this.getAudioClip(this.getCodeBase(  ), "gong.au"));

Or, if you’re writing an applet that will reside on one server but be used by many web pages with different sound files, you might call getAudioClip( ) like this:

String filename = this.getParameter("sound");
if (filename != null) {  // HTML included necessary PARAM tag
  AudioClip ac = this.getAudioClip(this.getDocumentBase(  ), filename);
}

In this case, getDocumentBase( ) returns the location of the HTML file, and getParameter( ) retrieves the name of an audio file from a <PARAM> tag in the HTML. You can use the filename argument to getAudioClip( ) to add to the path supplied by the URL. For example, in the following code, the sound file is located in the directory sounds, which is a subdirectory of the document’s directory:

this.getAudioClip(this.getDocumentBase(  ), "sounds/gong.au"));

Example 9.5 is a complete applet that downloads a sound file called gong.au, which is located in the same directory as the applet, and then spawns a Thread to play the sound every five seconds.

Example 9-5. Download a Sound via a Relative URL and Play It at Five-Second Intervals

import java.applet.*;
import java.awt.*;

public class RelativeBeep extends Applet implements Runnable {

  private AudioClip beep;
  private boolean stopped = false;

  public void init(  ) {

    beep = this.getAudioClip(this.getDocumentBase(  ), "sounds/beep.au");
    if (beep != null) {
      Thread t = new Thread(this);
      t.start(  );
    }
  
  }

  public void start(  ) {
    this.stopped = false;
  }
  
  public void stop(  ) {
    this.stopped = true;
  }
  
  public void run(  ) {
    
    Thread.currentThread(  ).setPriority(Thread.MIN_PRIORITY);
    while (true) {
      if (!stopped) beep.play(  );
      try {
        Thread.sleep(5000);
      }
      catch (InterruptedException e) {
      }
    }
  
  }

}

public static final AudioClip newAudioClip(URL url) // Java 1.2

Java 1.2 adds the static Applet.newAudioClip( ) method so that applications can download audio clips too. Why, you may ask, if this method is intended for the use of standalone applications, is it in the Applet class? The only answer I can suggest is that it was a quick hack designed to answer a long-standing request and that nobody gave a lot of thought to exactly what a sensible API for this would look like. Perhaps the underlying, undocumented infrastructure on which the play( ) and getAudioClip( ) methods depend was easily accessible only from inside the Applet class. Regardless of the reason, the Applet class is where the newAudioClip( ) method resides, and you’ll need to use that class even in non-applets that want to load audio clips.

The Applet.newAudioClip( ) method returns an AudioClip, just like getAudioClip( ). Therefore, you can invoke the same loop( ) and play( ) methods on it. For example, this code fragment loads the sound file at http://metalab.unc.edu/java/course/week9/spacemusic.au and plays it continuously. It can do this from an applet or an application. It does not need a web browser or AppletContext:

try {
  URL sound 
   = new URL("http://metalab.unc.edu/java/course/week9/spacemusic.au");
  AudioClip ac = new AudioClip(sound);
  ac.loop(  );
}
catch (MalformedURLException e) {
  // shouldn't happen
}
                  
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.76.0