views:

302

answers:

2

I am using a ServerSocket port to run one instance only of my Java Swing application, so if a user tries to open another instance of the program, i show him a warning that "Another instance is already open". This works fine, but instead of showing this message i want to set focus on the running application itself, like some programs does (MSN Messenger), even if it was minimized.

Is there a solution for this for various operating systems ?

+2  A: 

Since you use a server socket I assume that you use the java.net.BindException to detect that you application is already running. If you start a second instance you could send a control message which instructs you first app to normalize (if minimized) before exiting.

if (msg == BRING_TO_FRONT ) {
   frame.setState(Frame.NORMAL);
   frame.toFront();
}
stacker
I do use BindException but how to get the "frame" instance ?
Brad
I think the idea here is to open a socket client from the second app instance, connect it to the socket server of the 1st app instance, and use this connection to tell the 1st app to put itself into front.
jfpoilpret
Exactly 2nd app establishes a connection to 1st app and sends a message. The 1st app already knows its frame and can execute the snippet provided in my answer. You can't enumerate windows in a portable way.
stacker
I do not understand ... What i know is that app(2) will check if the port is already open or not, if 'yes' it will fire a message or whatever and exit the application ... I do not understand how will app(1) know about all this ?
Brad
@Brad app1 should receive the message send by app2 and execute the snippet above.
stacker
Can you give me an example for how to send a msg from app2 to app1 ?
Brad
@Brad http://java.sun.com/developer/onlineTraining/Programming/BasicJava2/socket.html
stacker
Thank you a lot stacker ... I am not so good in networking, that's why i've asked that ... After some trials it worked fine. I've put my code down here if any1 needs it. I hope its logic is right.
Brad
A: 

I don't know if this is absolutely right, but here's the final code i've used and it works fine for me :

public class Loader {
private static final int PORT = 9999;
private static ServerSocket serverSocket = null;  // Server
private static Socket socket = null;  // CLient
private static final String focusProgram = "FOCUS";

public static void main(String[] args) {
    if( !isProgramRunning() ) {
        Main main = new Main();
        main.setVisible( true );
    }
    else {
        System.exit( 2 );
    }
}

private static boolean isProgramRunning() {
    try {
        serverSocket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));  // Bind to localhost adapter with a zero connection queue. 
        SwingWorker<String, Void> anotherThread = new SwingWorker<String, Void>() {  // Do some code in another normal thread.
            @Override
            public String doInBackground() {  // This method is to execute a long code in the other thread in background.
                serverSocketListener();
                return "";
            }
        };
        anotherThread.execute();  // Execute the other tread.
    }
    catch (BindException e) {
        System.err.println("Already running.");
        clientSocketListener();

        return true;
    }
    catch (IOException e) {
        System.err.println("Unexpected error.");
        e.printStackTrace();

        return true;
    }

    return false;
}

public static void serverSocketListener() {  // Server socket
    try {
        System.out.println( "Listener socket opened to prevent any other program instance." );
        socket = serverSocket.accept();
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        if( in.readLine().equals( focusProgram ) ) {  // Restore the opened instance however you want.
            Global.getCurrentFrame().setState(Frame.NORMAL);
            Global.getCurrentFrame().toFront();
        }       
    } catch (IOException e) {
        e.printStackTrace();
        System.exit(-1);
    }
}

public static void clientSocketListener() {  // Client socket
    try{
        socket = new Socket(InetAddress.getByAddress( new byte[] {127,0,0,1}), PORT );
        PrintWriter out = new PrintWriter( socket.getOutputStream(), true );
        out.println( focusProgram );
    } catch  (IOException e) {
        System.out.println("No I/O");
        System.exit(1);
    }
}

}

Brad