I am using this guide:
Incorporating Socket Programming into your Applications
And in this portion of my code I am trying to make the server send messages in response to UI button presses:
public class MusicServerThread implements Runnable {
Socket client;
public void run() {
try {
if (SERVERIP != null) { //'Success' case when there is an Internet connection.
handler.post(new Runnable() {
@Override
public void run() {
Log.d(WiFiDirectActivity.TAG, "MusicServerThread_run: ServerIP = " + SERVERIP);
//TODO serverStatus can't be null. Fix this.
//serverStatus.setText("Listening on IP: " + SERVERIP);
}
});
serverSocket = new ServerSocket(SERVERPORT);
Log.d(WiFiDirectActivity.TAG, "MusicServerThread_run: serverSocket created on port " + SERVERPORT);
while (true) {
// listen for incoming clients
client = serverSocket.accept();
Log.d(WiFiDirectActivity.TAG, "MusicServerThread_run: Client connection recieved.");
handler.post(new Runnable() {
@Override
public void run() {
//serverStatus.setText("Connected.");
}
});
try {
//This line takes the client commands.
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
//TODO Stop endless loop from being a radge. Play music command
Log.d(WiFiDirectActivity.TAG, "Command issued " + line);
if (line.toLowerCase(Locale.getDefault()).trim().equals("play")){ //if the command is play
Log.d(WiFiDirectActivity.TAG, "Server says: client command accepted " + line);
//MediaPlayer mediaPlayer = MediaPlayer.create(getActivity(), R.raw.mse5251);
//mediaPlayer.start(); // no need to call prepare(); create() does that for you
handler.post(new Runnable() {
@Override
public void run() {
// do whatever you want to the front end
// this is where you can be creative
MediaPlayer mediaPlayer = MediaPlayer.create(getActivity(), R.raw.metallica_guitar);
mediaPlayer.start(); // no need to call prepare(); create() does that for you
}
});
}
if (line.toLowerCase(Locale.getDefault()).trim().equals("join")){ //if the command is join
Log.d(WiFiDirectActivity.TAG, "Server says: client command accepted " + line);
//Just for fun server will play as well.
//Todo: add a timer to delay start
MediaPlayer mediaPlayer = MediaPlayer.create(getActivity(), R.raw.metallica_guitar);
mediaPlayer.start(); // no need to call prepare(); create() does that for you
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client
.getOutputStream())), true);
// where you issue the commands
out.println("play");
} catch (Exception e) {
Log.e(WiFiDirectActivity.TAG, "S: Error", e);
}
handler.post(new Runnable() {
@Override
public void run() {
// do whatever you want to the front end
// this is where you can be creative
}
});
}
break;// Play command received, break.
}
break;
} catch (Exception e) {
handler.post(new Runnable() {
@Override
public void run() {
//serverStatus.setText("Oops. Connection interrupted. Please reconnect your phones.");
}
});
e.printStackTrace();
}
}
} else {
handler.post(new Runnable() {
@Override
public void run() {
//serverStatus.setText("Couldn't detect internet connection.");
}
});
}
} catch (Exception e) {
handler.post(new Runnable() {
@Override
public void run() {
//serverStatus.setText("Error");
}
});
e.printStackTrace();
}
}
/*Method used by the server to send command strings.*/
public void sendCommand(String command){
Log.d(WiFiDirectActivity.TAG, "MusicServerThread_sendCommand: Method reached.");
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client
.getOutputStream())), true);
// where you issue the commands
out.println("play");
} catch (Exception e) {
Log.e(WiFiDirectActivity.TAG, "S: Error", e);
}
}
But I receive a null pointer exception for what I think is the client in my SendCommands method.
Is it even possible to have the server thread running, waiting for commands, while I try to use it's SendCommands method for sending commands to the client?
UPDATE:
Here is the stack trace of the error:
03-04 16:35:44.055: E/wifidirectdemo(4202): S: Error
03-04 16:35:44.055: E/wifidirectdemo(4202): java.lang.NullPointerException
03-04 16:35:44.055: E/wifidirectdemo(4202): at com.example.android.wifidirect.DeviceDetailFragment$MusicServerThread.sendCommand(DeviceDetailFragment.java:465)
03-04 16:35:44.055: E/wifidirectdemo(4202): at com.example.android.wifidirect.DeviceDetailFragment$4.onClick(DeviceDetailFragment.java:201)
03-04 16:35:44.055: E/wifidirectdemo(4202): at android.view.View.performClick(View.java:3538)
03-04 16:35:44.055: E/wifidirectdemo(4202): at android.view.View$PerformClick.run(View.java:14330)
03-04 16:35:44.055: E/wifidirectdemo(4202): at android.os.Handler.handleCallback(Handler.java:608)
03-04 16:35:44.055: E/wifidirectdemo(4202): at android.os.Handler.dispatchMessage(Handler.java:92)
03-04 16:35:44.055: E/wifidirectdemo(4202): at android.os.Looper.loop(Looper.java:156)
03-04 16:35:44.055: E/wifidirectdemo(4202): at android.app.ActivityThread.main(ActivityThread.java:4977)
03-04 16:35:44.055: E/wifidirectdemo(4202): at java.lang.reflect.Method.invokeNative(Native Method)
03-04 16:35:44.055: E/wifidirectdemo(4202): at java.lang.reflect.Method.invoke(Method.java:511)
03-04 16:35:44.055: E/wifidirectdemo(4202): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-04 16:35:44.055: E/wifidirectdemo(4202): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-04 16:35:44.055: E/wifidirectdemo(4202): at dalvik.system.NativeStart.main(Native Method)
My guess is that you call sendCommand
before client
has been initialised, causing a NullPointerException
on line:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
client.getOutputStream())), true);
because client
is null.
According to the stack trace, sendCommand
is called from the onClick
method in the DeviceDetailFragment
class, line 201.
Your main options are:
sendCommand
, make sure that client
is not null and if it is, let the user know that you are not connected yet for example.onClick
method (for example by disabling the corresponding button) until a connection has been established and client
is not null