我正在使用本指南:
Incorporating Socket Programming into your Applications
在我的代码的这部分中,我试图让服务器发送消息以响应按下UI按钮:
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);
}
}
但我收到一个空指针异常,我认为我的SendCommands方法中的客户端。
甚至可以让服务器线程运行,等待命令,而我尝试使用它的SendCommands方法向客户端发送命令?
更新:
以下是错误的堆栈跟踪:
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)
答案 0 :(得分:3)
我的猜测是,您在sendCommand
初始化之前致电client
,导致NullPointerException
上线:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
client.getOutputStream())), true);
因为client
为空。
根据堆栈跟踪,sendCommand
类{201}中的onClick
方法调用DeviceDetailFragment
。
您的主要选项是:
sendCommand
时,请确保client
不为空,如果是,请告知用户您尚未连接。onClick
方法(例如,通过禁用相应的按钮),直到建立连接并且client
不为空