Tuesday, March 18, 2008

I started a joke - Bee Gees

I started a joke, which started the whole world crying,
but I didn't see that the joke was on me, oh no.

I started to cry, which started the whole world laughing,
oh, if I'd only seen that the joke was on me.

I looked at the skies, running my hands over my eyes,
and I fell out of bed, hurting my head from things that I'd said.

Til I finally died, which started the whole world living,
oh, if I'd only seen that the joke was on me.

I looked at the skies, running my hands over my eyes,
and I fell out of bed, hurting my head from things that I'd said.

'Til I finally died, which started the whole world living,
oh, if I'd only seen that the joke was one me.

Saturday, March 15, 2008

How to write a Java Application without a main method

You can write a runnable Java program which does not have main method at all. This can be done using the static block of the class.

The reason this works is that static initialization blocks get executed as soon as the class is loaded, even before the main method is called. During run time JVM will search for the main method after exiting from this block. If it does not find the main method, it throws an exception. To avoid the exception System.exit(0); statement is used which terminates the program at the end of the static block itself.

class MainMethodNot
{
static
{
System.out.println("This java program have run without the run method");
System.exit(0);

}
}

Sunday, March 09, 2008

How to use System class to copy Array

arrayCopy() method of System class copy data from one array into another. The arrayCopy method requires five arguments:

     public static void arraycopy(Object source, int srcIndex,
Object dest, int destIndex, int length)

The two Object arguments indicate the source and destination array. The three integer arguments indicate the starting location in each the source and the destination array, and the number of elements to copy.

This method will copy ‘length’ number of elements of array ‘source’ starts from the location ‘srcIndex’ to the array ‘dest’ starts from ‘destIndex’.

public class ArrayCopyDemo {

public static void main(String[] args) {

char[] Src = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd' };
char[] dst = new char[7];
System.arraycopy(src, 2, dst, 0, 7);
System.out.println(new String(dst));

}
}

Tuesday, March 04, 2008

Capturing Audio with Java Sound API

This Tech Tip reprinted with permission by java.sun.com

The Java Sound API has been a part of the standard libraries of the Java 2 Platform since the 1.3 release. Found in the javax.sound.sampled package, the Java Sound API provides support for playing and capturing audio. In addition, the library offers a software-based audio mixer and MIDI (Musical Instrument Digital Interface) device access. In this tip, you'll learn how to capture audio through the Java Sound API and play it back.

The javax.sound.sampled package consists of eight interfaces, twelve top-level classes, twelve inner classes, and two exceptions. To record and play audio, you only need to deal with a total of seven parts of the package.

Let's examine recording first. The basic recording process is as follows:

Describe the audio format in which you want to record the data. This includes specifying the sampling rate and the number of channels (mono versus stereo) for the audio. You specify these properties using the aptly named AudioFormat class. There are two constructors for creating an AudioFormat object:

AudioFormat(AudioFormat.Encoding encoding,
float sampleRate, int sampleSizeInBits,
int channels, int frameSize, float frameRate,
boolean bigEndian)

AudioFormat(float sampleRate, int sampleSizeInBits,
int channels, boolean signed, boolean bigEndian)

The first constructor lets you explicitly set the audio format encoding, while the latter uses a default. The available encodings are ALAW, PCM_SIGNED, PCM_UNSIGNED, and ULAW. The default encoding used for the second constructor is PCM. Here is an example that uses the second constructor to create an AudioFormat object for single channel recording in 8 kHz format:

float sampleRate = 8000;
int sampleSizeInBits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
AudioFormat format = new AudioFormat(sampleRate,
sampleSizeInBits, channels, signed, bigEndian);

After you describe the audio format, you need to get a DataLine. This interface represents an audio feed from which you can capture the audio. You use a subinterface of DataLine to do the actual capturing. The subinterface is called TargetDataLine. To get the TargetDataLine, you ask the AudioSystem. However when you do that, you need to specify information about the line. You make the specification in the form of a DataLine.Info object. In particular, you need to create a DataLine.Info object that is specific to the DataLine type and audio format. Here are some lines of source that get the TargetDataLine.

DataLine.Info info = new DataLine.Info(
TargetDataLine.class, format);
TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);

If the TargetDataLine is unavailable, a LineUnavailableException is thrown.

At this point you have your input source. You can think of the TargetDataLine like an input stream. However, it requires some setup before you can read form it. Setup in this case means first opening the line using the open() method, and then initializing the line using the start() method:

line.open(format);
line.start();

Your data line is ready, so you can start recording from it as shown in the following lines of code. Here you save a captured audio stream to a byte array for later playing. You could also save the audio stream to a file. Notice that you have to manage when to stop outside the read-loop construct.

int bufferSize = (int)format.getSampleRate() *
format.getFrameSize();
byte buffer[] = new byte[bufferSize];
out = new ByteArrayOutputStream();
while (externalTrigger) {
int count = line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();

Now let's examine playing audio. There are two key differences in playing audio as compared to recording audio. First, when you play audio, the bytes come from an AudioInputStream instead of a TargetDataLine. Second, you write to a SourceDataLine instead of into a ByteArrayOutputStream. Besides that, the process is the same.

To get the AudioInputStream, you need to convert the ByteArrayOutputStream into the source of the AudioInputStream. The AudioInputStream constructor requires the bytes from the output stream, the audio format encoding used, and the number of sample frames:

byte audio[] = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
AudioInputStream ais = new AudioInputStream(input,
format, audio.length / format.getFrameSize());

Getting the DataLine is similar to the way you get it for audio recording, but for playing audio, you need to fetch a SourceDataLine instead of a TargetDataLine:

DataLine.Info info = new DataLine.Info(
SourceDataLine.class, format);
SourceDataLine line =
(SourceDataLine)AudioSystem.getLine(info);

Setup for the line is identical to the setup for audio recording:

line.open(format);
line.start();

The last step is to play the audio as shown below. Notice that this step is similar to the last step in recording. However, here you read from the buffer and write to the data line. There is also an added drain operation that works like a flush on an output stream.

int bufferSize = (int) format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];

int count;
while ((count =
ais.read(buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();

The following program puts these steps together to demonstrate using the Java Sound the API to record and play audio. The program also presents a GUI. Press the Capture button to start recording the audio, the Stop button to stop recording, and the Play button to play back the audio.

Note: Depending on the audio support your platform provides, you might need to change the format returned by the getFormat method in the program. If you don't know what format is supported by your platform, download the demo program from the Java Sound Demo page, and run it. Click on the CapturePlayback tab, and find a set of format settings that work for you. You can load an audio file from the audio subdirectory, and then try various settings on the left until something works. Use those settings in the creation of the AudioFormat returned by getFormat().

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;

public class Capture extends JFrame {

protected boolean running;
ByteArrayOutputStream out;

public Capture() {
super("Capture Sound Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container content = getContentPane();

final JButton capture = new JButton("Capture");
final JButton stop = new JButton("Stop");
final JButton play = new JButton("Play");

capture.setEnabled(true);
stop.setEnabled(false);
play.setEnabled(false);

ActionListener captureListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
capture.setEnabled(false);
stop.setEnabled(true);
play.setEnabled(false);
captureAudio();
}
};
capture.addActionListener(captureListener);
content.add(capture, BorderLayout.NORTH);

ActionListener stopListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
capture.setEnabled(true);
stop.setEnabled(false);
play.setEnabled(true);
running = false;
}
};
stop.addActionListener(stopListener);
content.add(stop, BorderLayout.CENTER);

ActionListener playListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
playAudio();
}
};
play.addActionListener(playListener);
content.add(play, BorderLayout.SOUTH);
}

private void captureAudio() {
try {
final AudioFormat format = getFormat();
DataLine.Info info = new DataLine.Info(
TargetDataLine.class, format);
final TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);
line.open(format);
line.start();
Runnable runner = new Runnable() {
int bufferSize = (int)format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];

public void run() {
out = new ByteArrayOutputStream();
running = true;
try {
while (running) {
int count =
line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-1);
}
}
};
Thread captureThread = new Thread(runner);
captureThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-2);
}
}

private void playAudio() {
try {
byte audio[] = out.toByteArray();
InputStream input =
new ByteArrayInputStream(audio);
final AudioFormat format = getFormat();
final AudioInputStream ais =
new AudioInputStream(input, format,
audio.length / format.getFrameSize());
DataLine.Info info = new DataLine.Info(
SourceDataLine.class, format);
final SourceDataLine line = (SourceDataLine)
AudioSystem.getLine(info);
line.open(format);
line.start();

Runnable runner = new Runnable() {
int bufferSize = (int) format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];

public void run() {
try {
int count;
while ((count = ais.read(
buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-3);
}
}
};
Thread playThread = new Thread(runner);
playThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-4);
}
}

private AudioFormat getFormat() {
float sampleRate = 8000;
int sampleSizeInBits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
return new AudioFormat(sampleRate,
sampleSizeInBits, channels, signed, bigEndian);
}

public static void main(String args[]) {
JFrame frame = new Capture();
frame.pack();
frame.show();
}
}

You can find a more complete example of using the Java Sound API at the Java Sound Demo page. That example also shows an oscilloscope of the sound wave as it is playing back.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.

Thursday, February 28, 2008

Deploying BlackBerry Applications Over the Air

Deploying BlackBerry Applications Over the Air

You can download both standard MIDlets and BlackBerry-specific applications applications over the air, wirelessly. The provider puts up on a server both a .jad file to describe the application, and either a .cod or a .jar file holding the application itself. To download, you select the .jad file from a browser.

To enable you to download standard MIDlets to a BlackBerry, the Mobile Data Service feature of the BES provides a built-in transcoder that converts .jar files into .cod files. Note that the web server must identify the MIME types for .jad and .cod files, text/vnd.sun.j2me.app-descriptor and application/vnd.rim.cod respectively.

Be aware that you can download a .jar file to a BlackBerry only if the MDS feature is enabled, so it can convert the file to .cod format. If your access to the network is through a WAP gateway, you can download only .cod files.

Conclusion

RIM's BlackBerry handheld devices are becoming quite popular for both data and voice, and wireless carriers all over the world are distributing them. Several BlackBerry devices are Java-enabled, supporting CLDC and MIDP, while also providing API extensions for BlackBerry-specific features. The BlackBerry Java Development Environment enables developers to create CLDC-based, BlackBerry-specific applications that will run only on a BlackBerry, as well as standard MIDlets that will run on any MIDP-enabled device, including those bearing the BlackBerry brand.

This article provided an overview of the BlackBerry architecture, and a tutorial on developing J2ME applications for the BlackBerry. The sample code gave a flavor of the CLDC-based BlackBerry programming style. The article described how to load existing standard MIDlets into a BlackBerry, as well as how to download applications over the air.

For more information
Acknowledgments

Thanks to RIM and Telus Mobility for lending me the devices I used to deploy, run, and test Java applications for this article. Also, special thanks to Roger Riggs of Sun Microsystems, whose feedback helped me improve this article.

About the author

Qusay H. Mahmoud provides Java technology consulting and training services. He has published dozens of Java articles, and is the author of Distributed Programming with Java (Manning Publications, 1999) and Learning Wireless Java (O'Reilly, 2002).



1As used in this document, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.

Tuesday, February 26, 2008

RIM's Extensions to JAD Files

The JDE generated the following JAD file for the FirstApp project:

Manifest-Version: 1.0
MIDlet-Version: 0.0
MIDlet-Jar-Size: 1692
RIM-COD-Module-Dependencies: net_rim_os,net_rim_cldc
MicroEdition-Configuration: CLDC-1.0
MIDlet-Jar-URL: FirstApp.jar
RIM-MIDlet-Flags-1: 0
RIM-COD-Module-Name: FirstApp
MIDlet-Name: FirstApp
RIM-COD-Size: 1496
RIM-COD-Creation-Time: 1107707260
RIM-MIDlet-Position-1: 0
RIM-COD-URL: FirstApp.cod
RIM-MIDlet-NameResourceId-1: 0
MicroEdition-Profile: MIDP-1.0

As you can see, this .jad file includes both standard JAD properties and RIM-specific properties. It's a dual-purpose JAD, that supports downloading of MIDlets to BlackBerry devices, and to other devices as well. The properties RIM-COD-URL and MIDlet-Jar-URL ensure that BlackBerry users can download the .cod file, while users of other devices download the .jar.

Some of RIM's JAD properties are required, others are optional. Here are the required properties:

  • RIM-COD-Creation-Time: the time the .cod file was created
  • RIM-COD-Module-Dependencies: a list of modules the .cod file requires
  • RIM-COD-Module-Name: the name of the module contained in the .cod file
  • RIM-COD-SHA1: the SHA1 hash of the .cod file
  • RIM-COD-SIZE: the size of the .cod file, in bytes
  • RIM-COD-URL: the URL from which the .cod file can be downloaded

The optional properties are:

  • RIM-Library-Flags: reserved for use by RIM
  • RIM-MIDlet-Flags: reserved for use by RIM
  • RIM-MIDlet-NameResourceBundle: the name of the resource bundle the application depends on
  • RIM-MIDlet-Position: the suggested position of the application icon on the home screen

Saturday, February 23, 2008

Deploying Applications Using the BlackBerry Desktop Manager

To deploy the application using the BlackBerry Desktop Manager, you need to generate an .alx file, which is an XML-based BlackBerry application descriptor. Select the project FirstApp, then from the Project menu choose Generate ALX file. The resulting file, FirstApp.alx, looks like this:














MyCompany



Copyright (c) 2005 MyCompany




MyCompany



FirstApp.cod








Now you can use the BlackBerry Desktop Manager and a USB cable to load the .alx file, which contains a reference to the .cod file, into a BlackBerry device. Figure 9 shows the BlackBerry Desktop Manager, and Figure 10 shows the application to be installed:

Figure 9: BlackBerry Desktop Manager
Figure 9: BlackBerry Desktop Manager

Figure 10: Application to Be Installed
Figure 10: Application to Be Installed