2013-02-28 20 views
-1

我使用本指南:如何從線程運行的ServerSocket向客戶端發出命令?

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方法向客戶端發送命令時,是否甚至可以讓服務器線程運行,等待命令?

UPDATE:

以下是錯誤的堆棧跟蹤:

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

空指針的任何堆棧跟蹤禁用onClick方法? – 2013-03-04 16:34:23

回答

3

我的猜測是,你叫sendCommandclient之前已經被初始化,上線造成NullPointerException

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
        client.getOutputStream())), true); 

,因爲client爲空。

根據堆棧跟蹤,sendCommand是從DeviceDetailFragment類的onClick方法調用,線201

你的主要選項有:

  • 進入sendCommand時,請確保client不如果它是空的,例如讓用戶知道你還沒有連接。
  • (通過禁用相應的按鈕例如),直到已經建立連接和client不爲空
相關問題