I am having trouble coding the socket side of a JavaFX chat client. This is my first time having to deal with socket in any sort of way, so some trouble was expected. I've been following this page to design the server-client side:
http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-client-server.html
My problem is getting text I enter into the GUI into a DataInputSteam and DataOutputStream so that others on the same server can see the changes. I do
not understand how to convert the text in the UI to something the sockets
can work with.
Here is part of my controller class:
#FXML
private TextArea messageArea;
#FXML
private Button sendButton;
private ChatClient client;
#FXML
public void initialize() {
client = new ChatClient(ChatServer.HOSTNAME, ChatServer.PORT);
sendButton.setOnAction(event -> {
client.handle(messageArea.getText());
});
}
The ChatClient class is a Runnable with a DataInputStream and DataOutputStream field that connects to a Socket. I haven't changed much from the link:
public class ChatClient implements Runnable {
private Socket socket;
private Thread thread;
private DataInputStream streamIn;
private DataOutputStream streamOut;
private ChatClientThread client;
public ChatClient(String serverName, int port) {
System.out.println("Establishing connection...");
try {
socket = new Socket(serverName, port);
System.out.println("Connected: " + socket);
start();
} catch (UnknownHostException e) {
System.out.println("Unknown host: " + e.getMessage());
} catch (IOException e) {
System.out.println("Unexpected: " + e.getMessage());
}
}
#Override
public void run() {
while (thread != null) {
try {
streamOut.writeUTF(streamIn.readUTF());
streamOut.flush();
} catch (IOException e) {
System.out.println("Sending error: " + e.getMessage());
stop();
}
}
}
public void handle(String msg) {
try {
streamOut.writeUTF(msg);
streamOut.flush();
} catch (IOException e) {
System.out.println("Could not handle message: " + e.getMessage());
}
System.out.println(msg);
}
public void start() throws IOException {
streamIn = new DataInputStream(socket.getInputStream());
streamOut = new DataOutputStream(socket.getOutputStream());
if (thread == null) {
client = new ChatClientThread(this, socket);
thread = new Thread(this);
thread.start();
}
}
So in the controller class, I am calling the handle method which deals with the streams. The original code just wrote to the console, so I had to change the line:
streamIn = new DataInputStream(System.in)
to
streamIn = new DataInputStream(socket.getInputStream());
There is also a ChatClientThread class that extends Thread and just calls ChatClient.handle() in its run method.
I guess my question is how to update a GUI whenever writeUTF and readUTF interact with the DataStreams. I understand that streamOut.writeUTF(msg) changes the DataOutputStream to "have" that string, but I'm not sure how I'm supposed to use that datastream to update my gui so that all clients using the application can see the update. The way I have it now, if I run two instances of the JavaFX app, they dont' communicate through the UI or the console. My program just stalls whenever I click the send button
Related
im writing a multithread chat program where i hope to have a server connected to multiple clients, the clients can talk to each and send messages to each other. I want all messages from the clients to be visible to the server, moreover that the server can send messages to all visible clients. My program only connects the server to one client and they can send messages.
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Server2 {
private static JTextField userInput; //
private static JTextArea theChatWindow; //
private static ObjectOutputStream output; // stream data out
private static ObjectInputStream input; // stream data in
private static ServerSocket server;
private static Socket connection; // socket means set up connetion between 2 computers
private static JFrame frame;
private static int n;
//Constructor
public static void main(String[] args) throws IOException {
Server2 obj = new Server2();
// Socket sock=new Socket("localhost",6789);
System.out.println("Hello 4");
obj.RunServer();
System.out.println("Hello 3");
try {
while (true) {
System.out.println("Hello 2");
Handler obj2 = new Handler();
//Handler obj3=new Handler();
obj2.start();
System.out.println("Accepted connection from "
+ connection.getInetAddress() + " at port "
+ connection.getPort());
n++;
System.out.println("Count " + n);
}
} finally {
connection.close();
}
}
public Server2() {
frame = new JFrame();
userInput = new JTextField();
userInput.setEditable(false); // set this false so you dont send messages when noone is available to chat
// action event listener to check when the user hits enter for example
userInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendMessage(event.getActionCommand()); // string entered in the textfield
userInput.setText(""); // reset text area to blank again
}
}
);
// create the chat window
frame.add(userInput, BorderLayout.NORTH);
theChatWindow = new JTextArea();
frame.add(new JScrollPane(theChatWindow));
frame.setSize(300, 150);
frame.setVisible(true);
}
// run the server after gui created
public void RunServer() {
try {
server = new ServerSocket(6789); // 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
waitForConnection(); // wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
showMessage("\n Server ended Connection");
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
private void waitForConnection() {
showMessage("waiting for someone to connect to chat room....\n");
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
showMessage("Now connected to" + connection.getInetAddress().getHostName());
showMessage(" at port " + connection.getPort());
}
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
// String message = "WAIT";
// sendMessage(message);
//showMessage("\n Connection streams are now setup \n");
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "WAIT ";
sendMessage(message);
allowTyping(true); // allow user to type when connection
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
showMessage("\n " + message);
System.out.println("Message from Client " + message);
} catch (ClassNotFoundException classnotfoundException) {
showMessage("\n i dont not what the user has sent");
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
showMessage("\n closing connections...\n");
allowTyping(true);
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush(); // send all data out
showMessage("\nServer - " + message);
System.out.println("Message to client " + message);
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
// update the chat window (GUI)
private void showMessage(final String text) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
theChatWindow.append(text);
}
}
);
}
// let the user type messages in their chat window
private void allowTyping(final boolean trueOrFalse) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userInput.setEditable(trueOrFalse);
}
}
);
}
public static class Handler extends Thread {
private Socket connection;
// static private ServerSocket server;
public Handler() {
// this.socket = socket;
String message = "WAIT";
}
//connection = server.accept();
public void run() {
System.out.println("Connect" + Server2.connection);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (IOException ex) {
Logger.getLogger(Server2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void waitForConnection() {
System.out.println("Heelo");
showMessage("waiting for someone to connect to chat room....\n");
System.out.println("server" + server);
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
System.out.println("Connection" + connection);
showMessage("Now connected to" + connection.getInetAddress().getHostName());
showMessage("AT port" + connection.getPort());
}
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
showMessage("\n Connection streams are now setup \n");
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = " You are now connected ";
sendMessage(message);
allowTyping(true); // allow user to type when connection
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
showMessage("\n " + message);
} catch (ClassNotFoundException classnotfoundException) {
showMessage("\n i dont not what the user has sent");
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
showMessage("\n closing connections...\n");
allowTyping(true);
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
static private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush(); // send all data out
showMessage("\nServer - " + message);
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
// update the chat window (GUI)
static private void showMessage(final String text) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
theChatWindow.append(text);
}
}
);
}
// let the user type messages in their chat window
private void allowTyping(final boolean trueOrFalse) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userInput.setEditable(trueOrFalse);
}
}
);
}
}
}
Here is the client :
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Client2 extends JFrame {
private JTextField userInput; //
private JTextArea theChatWindow; //
private ObjectOutputStream output; // stream data out
private ObjectInputStream input; // stream data in
private Socket connection; // socket means set up connetion between 2 computers
//Constructor
public Client2() {
super("My Chat Service");
userInput = new JTextField();
userInput.setEditable(false); // set this false so you dont send messages when noone is available to chat
// action event listener to check when the user hits enter for example
userInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendMessage(event.getActionCommand()); // string entered in the textfield
userInput.setText(""); // reset text area to blank again
}
}
);
// create the chat window
add(userInput, BorderLayout.NORTH);
theChatWindow = new JTextArea();
add(new JScrollPane(theChatWindow));
setSize(300, 150);
setVisible(true);
}
// run the server after gui created
public void RunServer() {
try {
connection = new Socket("localhost", 6789);// 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
// wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
showMessage("\n Server ended Connection");
} finally {
closeChat();
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
showMessage("\n Connection streams are now setup \n");
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "";
allowTyping(true); // allow user to type when connection
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
System.out.println("message " + message);
if (message.equals("WAIT")) {
ServerSocket server2 = new ServerSocket(5000);
System.out.println("Hello");
message = "5000";
sendMessage(message);
}
System.out.println("From server " + message);
showMessage("\n " + message);
} catch (ClassNotFoundException classnotfoundException) {
showMessage("\n i dont not what the user has sent");
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
showMessage("\n closing connections...\n");
allowTyping(true);
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(" - " + message);
output.flush(); // send all data out
showMessage("\nServer - " + message);
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
// update the chat window (GUI)
private void showMessage(final String text) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
theChatWindow.append(text);
}
}
);
}
// let the user type messages in their chat window
private void allowTyping(final boolean trueOrFalse) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userInput.setEditable(trueOrFalse);
}
}
);
}
public static void main(String[] args) {
Client2 obj = new Client2();
obj.RunServer();
}
}
I've tried two different ways to call a simple REST method from Android; said REST method - which works from other clients - simply returns an int val such as 17.
Both of the following attempts were based on code I found online. One is like so:
public void onFetchBtnClicked(View v){
if(v.getId() == R.id.FetchBtn){
Toast.makeText(getApplicationContext(), "You mashed the button, dude.", Toast.LENGTH_SHORT).show();
new NetworkTask().execute();
}
}
public static class NetworkTask extends AsyncTask {
#Override
protected String doInBackground(Void... params) {
final String TAG;
TAG = "callWebService";
String deviceId = "Android Device";
HttpClient httpclient = new DefaultHttpClient();
HttpGet request = new HttpGet("http://localhost:28642/api/Departments/GetCount");
request.addHeader("deviceId", deviceId);
ResponseHandler<String> handler = new BasicResponseHandler();
String result = "";
try
{
result = httpclient.execute(request, handler);
}
catch (ClientProtocolException e)
{
e.printStackTrace();
Log.e(TAG, "ClientProtocolException in callWebService(). " + e.getMessage());
}
catch (IOException e)
{
e.printStackTrace();
Log.e(TAG, "IOException in callWebService(). " + e.getMessage());
}
httpclient.getConnectionManager().shutdown();
Log.i(TAG, "**callWebService() successful. Result: **");
Log.i(TAG, result);
Log.i(TAG, "*****************************************");
return result;
}
#Override
protected void onPostExecute(String result) {
final String TAG;
TAG = "onPostExecute";
if (null != result)
Log.i(TAG, result);
}
With the code above, after the following line of code fails:
result = httpclient.execute(request, handler) ;
...I get, "*E/callWebService﹕ IOException in callWebService(). Connection to http://localhost:28642 refused*"
This problem may be a threading issue, as I read this in O'Reilly's "Programming Android" book by Mednieks, Dornin, Meike, and Nakamura: "AsyncTask is a convenenient tool for running small, asynchronous tasks. Just remember that the doInBackground method runs on a different thread! It must not write any state visible from another thread or read any state writable from another thread. This includes its parameters."
With my other attempt:
public void onFetchBtnClicked(View v){
if(v.getId() == R.id.FetchBtn){
Toast.makeText(getApplicationContext(), "You mashed the button, dude.", Toast.LENGTH_SHORT).show();
callWebService("http://localhost:28642/api/Departments/GetCount");
}
}
public String callWebService(String requestUrl)
{
final String TAG;
TAG = "callWebService";
String deviceId = "Android Device";
HttpClient httpclient = new DefaultHttpClient();
HttpGet request = new HttpGet(requestUrl);
request.addHeader("deviceId", deviceId);
ResponseHandler<String> handler = new BasicResponseHandler();
String result = "";
try
{
result = httpclient.execute(request, handler);
}
catch (ClientProtocolException e)
{
e.printStackTrace();
Log.e(TAG, "ClientProtocolException in callWebService(). " + e.getMessage());
}
catch (IOException e)
{
e.printStackTrace();
Log.e(TAG, "IOException in callWebService(). " + e.getMessage());
}
httpclient.getConnectionManager().shutdown();
Log.i(TAG, "**callWebService() successful. Result: **");
Log.i(TAG, result);
Log.i(TAG, "*****************************************");
return result;
}
...the debugger dumps me into View.class after hitting that same problem line (result = httpclient.execute(request, handler)). Why it does that, I don't know*, but I think the crux of the problem, as indicated by err msgs in logcat, is: "Caused by: android.os.NetworkOnMainThreadException"
*Maybe because something untoward is being attempted within the UI (View) thread.
Also (not a big deal, but "interesting," perhaps): the Toast doesn't pop up when a method call is made after it (it works otherwise).
The (Web API) server has a breakpoint set in its corresponding Controller method, but it is never reached. As mentioned, the server is running, and responds just fine to other (Windows app) clients.
There must be a somewhat straightforward way of calling a RESTful method from Android. But what/how?
UPDATE
I tried this, now, too, calling it like so:
RestClient client = new RestClient("http://localhost:28642/api/Departments/GetCount");
try {
client.Execute(RestClient.RequestMethod.GET);
} catch (Exception e) {
e.printStackTrace();
}
String response = client.getResponse();
Log.i("CZECH_THIS", response);
...but it also is (or seems, anyway) happy to throw the "NetworkOnMainThread" exception.
UPDATE 2
This is the closest I've gotten so far, I think. Maybe the server is the culprit in this case, because with this code:
public void onFetchBtnClicked(View v){
if(v.getId() == R.id.FetchBtn){
Toast.makeText(getApplicationContext(), "You mashed the button, dude.", Toast.LENGTH_SHORT).show();
new CallAPI().execute("http://localhost:28642/api/Departments/GetCount");
}
}
public static class CallAPI extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String urlString=params[0]; // URL to call
String resultToDisplay = "";
InputStream in = null;
// HTTP Get
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream());
} catch (Exception e ) {
System.out.println(e.getMessage());
return e.getMessage();
}
return resultToDisplay;
}
protected void onPostExecute(String result) {
Log.i("FromOnPostExecute", result);
}
} // end CallAPI
....the exception that is thrown is:
libcore.io.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
failed to connect to localhost/127.0.0.1 (port 28642): connect failed: ECONNREFUSED (Connection refused)
...and the Android app continues to run (it falls over in the other examples).
Why is my server refusing the connection?
UPDATE 3
I thought for a minute I had it: I forgot to pass the serial Num with the URL. But even after doing so, it fails.
I have a breakpoint in the server app, in the Controller method; also, in the Repository method, but they are never reached.
What could be wrong?
Is "localhost" the wrong thing to use (in the URL)? Should I use the name of the computer instead?
Does the URL (passed literally as "http://localhost:28642/api/Departments/GetCount?serialNum=4242") need to be verbatimized?
UPDATE 4
Changing the "locohost" to the machine name, I get "No address associated with hostname" so that's not the problem...
Oddly, though, this line runs fine:
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
...whereas this is the last line before the exception is thrown/caught:
in = new BufferedInputStream(urlConnection.getInputStream());
Looking at this, though, perhaps I need to escape my whacks; but when you already have double-whacks, as in after "http:", do you have to do triple-whacks? Or quadruple whacks? Surely not ceiling wax...?
I've got it working now. There's an article about it here.
This is the code from there without any explanation:
public class MainActivity extends ActionBarActivity {
private GetDepartmentsCount _getDeptsCount;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button getDeptsCountBtn = (Button)findViewById(R.id.DeptsCountBtn);
getDeptsCountBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
_getDeptsCount = new GetDepartmentsCount();
_getDeptsCount.execute("http://10.0.2.2:28642/api/Departments/GetCount?serialNum=4242");
}
});
}
#Override
public void onStop() {
super.onStop();
_getDeptsCount.cancel(true);
}
private class GetDepartmentsCount extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String urlString = params[0]; // URL to call
String result = "";
// HTTP Get
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
if (null != inputStream)
result = IOUtils.toString(inputStream);
} catch (Exception e) {
System.out.println(e.getMessage());
return e.getMessage();
}
return result;
}
#Override
protected void onPostExecute(String result) {
EditText dynCount = (EditText)findViewById(R.id.dynamicCountEdit);
dynCount.setText(result + " records were found");
Log.i("FromOnPostExecute", result);
}
}
}
I have a client/server app to manage a line of some sort.
all the clients add objects to my line.
I want the server to send a screen capture of the jpanel to the clients every time there is a change in the line, line inserted or removed.
I managed to capture the jpanel to a jpeg and even send it.
but the flow of my app is stopped, after the first update I get eofexception that terminates my listening server socket.
what is the correct way to update a client ? should I set a serversocket to always listen on the client side too ?
please help, im stuck with this for like 2 weeks.
This is my listening thread (Server):
public class ListeningThread implements Runnable {
static boolean listening = true;
public BufferedReader in;
public void run() {
ServerSocket echoServer = null;
String line;
DataInputStream is = null;
PrintStream os = null;
Socket clientSocket = null;
try {
echoServer = new ServerSocket(RequestReciever._communicationPort);
}
catch (IOException e) {
System.out.println(e);
}
// Create a socket object from the ServerSocket to listen and accept
// connections.
// Open input and output streams
try {
// As long as we receive data, send it to be phrased to a request.
while (true) {
clientSocket = echoServer.accept();
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
// An option for a stop listening button. currently not available !
if( listening==true ) {
line = is.readUTF();
os.println(line);
System.out.println(line);
RequestReciever.pharseToRequest(line);
// clientSocket = null;
}
else {
echoServer.close();
is.close();
os.close();
break;
}
}
}
catch (IOException e) {
e.printStackTrace();
System.out.println("Listening Thread Unknown error");
}
}
}
This is my Pharse Method:
public static void pharseToRequest(String input) {
List<String> list = new ArrayList<String>(Arrays.asList(input.split(";;;")));
if (list.get(0).equalsIgnoreCase("Login") && list.get(1).equalsIgnoreCase ("Login") && list.get(2).equalsIgnoreCase("5"))
{
_adminClients.add(list.get(4));
updateScreenCapture();
AdminClientUpdate tmp = new AdminClientUpdate(list.get(4));
Thread aCU = new Thread (tmp);
aCU.start();
}
else
{
ServerRequest newReq = new ServerRequest(list.get(0), list.get(1), Integer.parseInt(list.get(2)),list.get(3),list.get(4));
addRequest(newReq);
}
}
and This is the AdminClientUpdate Class
public class AdminClientUpdate implements Runnable {
static boolean listening = true;
public BufferedReader in;
public String _ip;
public AdminClientUpdate(String ip)
{
_ip = ip;
}
public void run() {
try {
Socket socket = new Socket(_ip, RequestReciever._communicationPort);
InputStream in = new FileInputStream("Capture/tmp.jpg");
java.io.OutputStream out = socket.getOutputStream();
copy(in, out);
System.out.println("Sent Image !");
socket.close();
out.close();
in.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
System.out.println("Cant find tmp.jpg");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void copy(InputStream in, java.io.OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}
eliminate this
echoServer.close();
this line closes the socket. due which the connection is aborted.
After a few brain meltdowns , I have decided that putting a server socket on the client side to listen for updates from the server is the best way.
I fixed a few things :
* The server should start a new thread to handle every accepted connection, instead of processing each one in-line in the accept thread.
* I tried to get the first update via the server socket instead of the login initialization.
now, after getting the 1st update while logging in, I added a Server Socket on the client side so it will keep listening for further updates from server.
I'm implementing an JavaFX application which is communicating with a mobile phone via wifi (android).
Therefore I have a server thread on the JavaFX running in a background process:
public class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
private RoutePlannerJFX application;
private UserData userData;
public NetworkService(ExecutorService pool,
ServerSocket serverSocket,
RoutePlannerJFX app,
UserData data) {
this.serverSocket = serverSocket;
this.pool = pool;
application = app;
userData = data;
}
public void run() {
try {
while ( true ) {
Socket cs = serverSocket.accept();
pool.execute(new Handler(serverSocket, cs, application, userData));
}
} catch (IOException ex) {
System.out.println("--- Interrupt NetworkService-run");
}
finally {
System.out.println("--- Ende NetworkService(pool.shutdown)");
pool.shutdown(); //keine Annahme von neuen Anforderungen
try {
pool.awaitTermination(4L, TimeUnit.SECONDS);
if ( !serverSocket.isClosed() ) {
System.out.println("--- Ende NetworkService:ServerSocket close");
serverSocket.close();
}
} catch ( IOException e ) { }
catch ( InterruptedException ei ) { }
}
}
}
which has a handler:
public class Handler implements Runnable {
private final Socket client;
private final ServerSocket serverSocket;
private RoutePlannerJFX application;
private UserData userData;
Handler(ServerSocket serverSocket,Socket client, RoutePlannerJFX app, UserData data) {
this.client = client;
this.serverSocket = serverSocket;
application = app;
userData = data;
}
public void run() {
StringBuffer sb = new StringBuffer();
PrintWriter out = null;
try {
System.out.println( "running service, " + Thread.currentThread() );
out = new PrintWriter( client.getOutputStream(), true );
BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
client.getInputStream()));
char[] buffer = new char[100];
int anzahlZeichen = bufferedReader.read(buffer, 0, 100);
String nachricht = new String(buffer, 0, anzahlZeichen);
String[] werte = nachricht.split("\\s");
System.out.println(nachricht+"\n");
POI poi = new POI(nachricht);
userData.addItemToPoiList(poi);
application.setScene("INSTRUCT");
} catch (IOException e) {System.out.println("IOException, Handler-run");}
finally {
System.out.println(sb); //Rückgabe Ergebnis an den Client
if ( !client.isClosed() ) {
System.out.println("****** Handler:Client close");
try {
client.close();
} catch ( IOException e ) { }
}
}
}
}
The application has a public method to change the scene (setScene()).
That's the way I wish I could do it, but now I know, that I cannot switch the scene in my backgroundprocess.
Has anyone an idea how to implement this problem? I need to fire an action, when my backgroundprocess receives a message from the the client, but I don't know what's the best way to do that… I already found javafx.concurrent, but which do I have to use and how?
Thank's in advance!
For the client side you can use either a Task or a Service to run in a separate thread & update the GUI as described in the documentation
You can check this post too JavaFX Async Task
Hi I am new to android and I am learning by example. I am trying to make an activity that has a list view of all songs in my raw folder with media player controls at the bottom. I have everything working so far but I can't seem to get the SeekBar to stop force closing.
Here is the code:
public class music extends ListActivity implements Runnable {
private ArrayList<sound> mSounds = null;
private soundadapter mAdapter = null;
private ImageButton playbtn;
private SeekBar seekbar;
private int total;
private MediaPlayer mp = null;
private TextView selelctedFile = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.music);
selelctedFile = (TextView) findViewById(R.id.selectedfile);
seekbar = (SeekBar) findViewById(R.id.seekbar);
seekbar.setProgress(0);
// create a simple list
mSounds = new ArrayList<sound>();
sound s = new sound();
s.setDescription("Rudolph The Red Nosed Reindeer");
s.setSoundResourceId(R.raw.rudolphtherednosereindeer);
mSounds.add(s);
s = new sound();
s.setDescription("Battery");
s.setSoundResourceId(R.raw.battery);
mSounds.add(s);
mAdapter = new soundadapter(this, R.layout.listitem, mSounds);
setListAdapter(mAdapter);
playbtn = (ImageButton) findViewById(R.id.play);
playbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
try {
if (mp.isPlaying()) {
mp.pause();
playbtn.setImageResource(android.R.drawable.ic_media_play);
} else {
mp.start();
playbtn.setImageResource(android.R.drawable.ic_media_pause);
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
});
}
#Override
public void onListItemClick(ListView parent, View v, int position, long id) {
sound s = (sound) mSounds.get(position);
if (mp != null) {
mp.reset();
mp.release();
}
mp = MediaPlayer.create(this, s.getSoundResourceId());
selelctedFile.setText(s.getDescription());
playbtn.setImageResource(android.R.drawable.ic_media_pause);
mp.start();
total = mp.getDuration();
seekbar.setMax(total);
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekbar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekbar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
if (fromUser) {
mp.seekTo(progress);
seekBar.setProgress(progress);
}
}
});
Thread currentThread = new Thread(this);
currentThread.start();
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
while (mp != null) {
int currentPosition = mp.getCurrentPosition();
Message msg = new Message();
msg.what = currentPosition;
threadHandler.sendMessage(msg);
Thread.sleep(100);
}
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
}
}
private Handler threadHandler = new Handler() {
public void handleMessage(Message msg) {
// super.handleMessage(msg);
// txt.setText(Integer.toString(msg.what));
seekbar.setProgress(msg.what);
}
};
#Override
protected void onPause() {
// TODO Auto-generated method stub
mp.stop();
mp.release();
mp = null;
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
if(mp != null) {
mp.stop();
mp.release();
mp = null;
}
}
}
and here is the error i keep getting when i click several times on different songs:
04-14 02:53:00.452: W/dalvikvm(27452): threadid=19: thread exiting with uncaught exception (group=0x40018560)
04-14 02:53:00.466: E/AndroidRuntime(27452): FATAL EXCEPTION: Thread-22
04-14 02:53:00.466: E/AndroidRuntime(27452): java.lang.IllegalStateException
04-14 02:53:00.466: E/AndroidRuntime(27452): at android.media.MediaPlayer.getCurrentPosition(Native Method)
04-14 02:53:00.466: E/AndroidRuntime(27452): at net.cybercore.collapsingfromwithin.music.run(music.java:145)
04-14 02:53:00.466: E/AndroidRuntime(27452): at java.lang.Thread.run(Thread.java:1019)
Line error 145 is :
int currentPosition = mp.getCurrentPosition();
I cannot for the life of me figure out why it works for 3 or 4 times playing and then it kills the app.
Any help is appreciated. I have already looked at several other sites for examples including http://www.androidhive.info/2012/03/android-building-audio-player-tutorial/ and http://www.androiddevblog.net/android/playing-audio-in-android
**
UPDATE
**
I think I fixed it. thanks for your help I found Thread using for seekbar on android mediaplayer so i changed it to
#Override
public void run() {
// TODO Auto-generated method stub
try {
while (mp != null) {
int currentPosition = mp.getCurrentPosition();
Message msg = new Message();
msg.what = currentPosition;
threadHandler.sendMessage(msg);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("interrupt exeption" + e);
}
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("My exeption" + e);
}
}
I still get the errors but they are not killing my app. I don't think this is right way to do it but its working.
You should prepare your media player when instanciating it.
A MediaPlayer object must first enter the Prepared state before playback can be started.
There are two ways (synchronous vs. asynchronous) that the Prepared state can be reached: either a call to prepare() (synchronous) which transfers the object to the Prepared state once the method call returns, or a call to prepareAsync() (asynchronous) which first transfers the object to the Preparing state after the call returns (which occurs almost right way) while the internal player engine continues working on the rest of preparation work until the preparation work completes. When the preparation completes or when prepare() call returns, the internal player engine then calls a user supplied callback method, onPrepared() of the OnPreparedListener interface, if an OnPreparedListener is registered beforehand via setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener).
Read it here
so you should call mp.prepare() after instanciating the player.
also you should make sure the media player in playing to run the run method. I'd start by adding
mp.isPlaying() to the while line.
while (mp != null && mp.isPlaying()) {
...
}
IllegalStateException means that you are on an illegal state to call that method, like for instance, if the player is stopped.
I'm not sure, but I think this will stop the run method when you pause the music. So you should try to avoid this. I create a boolean to identify that the player is playing or paused and use it on the while.