2017-09-14 144 views
1

當應用程序處於後臺時,應該如何保持服務器正常運行和收聽?在後臺連接Android套接字

我目前正在拋出一個錯誤:我無法建立連接,因爲目標計算機正在主動拒絕連接。

我有在pc和python上的android和客戶端上的服務器。

任何人都可以解釋我將不勝感激。 代碼與我的服務器。

public class MainActivity extends Activity { 

private ServerSocket serverSocket; 

Handler updateConversationHandler; 

Thread serverThread = null; 

private TextView text; 

public static final int SERVERPORT = 8080; 

@Override 
public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    text = (TextView) findViewById(R.id.textView); 

    updateConversationHandler = new Handler(); 

    this.serverThread = new Thread(new ServerThread()); 
    this.serverThread.start(); 

} 

@Override 
protected void onStop() { 
    super.onStop(); 
    try { 
     serverSocket.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

class ServerThread implements Runnable { 

    public void run() { 
     Socket socket = null; 
     try { 
      serverSocket = new ServerSocket(SERVERPORT); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     while (!Thread.currentThread().isInterrupted()) { 

      try { 

       socket = serverSocket.accept(); 

       CommunicationThread commThread = new CommunicationThread(socket); 
       new Thread(commThread).start(); 

      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

class CommunicationThread implements Runnable { 

    private Socket clientSocket; 

    private BufferedReader input; 

    public CommunicationThread(Socket clientSocket) { 

     this.clientSocket = clientSocket; 

     try { 

      this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void run() { 

      try { 

       String read = input.readLine(); 

       updateConversationHandler.post(new updateUIThread(read)); 

      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

    } 

} 

class updateUIThread implements Runnable { 
    private String msg; 

    public updateUIThread(String str) { 
     this.msg = str; 
    } 
    @Override 
    public void run() { 
     if (msg == null) { 
      text.setText(msg); 
     } 
     else{ 
      text.setText(msg); 
      createNotification(); 
     } 
    } 
} 
void createNotification() { 

    Intent intent = new Intent(this, MainActivity.class); 
    PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0); 

    Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); 

    Notification noti = new NotificationCompat.Builder(this) 
      .setContentTitle("NOTIFICATION") 
      .setContentText("NOTIFICATION") 
      .setTicker("NOTIFICATION") 
      .setSmallIcon(android.R.drawable.ic_dialog_info) 
      .setLargeIcon(icon) 
      .setAutoCancel(true) 
      .setContentIntent(pIntent) 
      .build(); 

    NotificationManager notificationManager = 
      (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 

    notificationManager.notify(0, noti); 
}} 

回答

1

要在Android中執行後臺任務,您應該使用服務。
爲服務器的服務看起來像:

public class MyService extends Service { 

    public static final String START_SERVER = "startserver"; 
    public static final String STOP_SERVER = "stopserver"; 
    public static final int SERVERPORT = 8080; 

    Thread serverThread; 
    ServerSocket serverSocket; 

    public MyService() { 

    } 

    //called when the services starts 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     //action set by setAction() in activity 
     String action = intent.getAction(); 
     if (action.equals(START_SERVER)) { 
      //start your server thread from here 
      this.serverThread = new Thread(new ServerThread()); 
      this.serverThread.start(); 
     } 
     if (action.equals(STOP_SERVER)) { 
      //stop server 
      if (serverSocket != null) { 
       try { 
        serverSocket.close(); 
       } catch (IOException ignored) {} 
      } 
     } 

     //configures behaviour if service is killed by system, see documentation 
     return START_REDELIVER_INTENT; 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     // TODO: Return the communication channel to the service. 
     throw new UnsupportedOperationException("Not yet implemented"); 
    } 

    class ServerThread implements Runnable { 

     public void run() { 
      Socket socket; 
      try { 
       serverSocket = new ServerSocket(SERVERPORT); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      while (!Thread.currentThread().isInterrupted()) { 

       try { 

        socket = serverSocket.accept(); 

        CommunicationThread commThread = new CommunicationThread(socket); 
        new Thread(commThread).start(); 

       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

    class CommunicationThread implements Runnable { 

     private Socket clientSocket; 

     private BufferedReader input; 

     public CommunicationThread(Socket clientSocket) { 

      this.clientSocket = clientSocket; 

      try { 

       this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); 

      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     public void run() { 

      try { 

       String read = input.readLine(); 

       //update ui 
       //best way I found is to save the text somewhere and notify the MainActivity 
       //e.g. with a Broadcast 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

     } 
    } 
} 

在你的活動,你可以通過調用啓動服務:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    //will start the server 
    Intent startServer = new Intent(this, MyService.class); 
    startServer.setAction(MyService.START_SERVER); 
    startService(startServer); 

    //and stop using 
    Intent stopServer = new Intent(this, MyService.class); 
    stopServer.setAction(MyService.STOP_SERVER); 
    startService(stopServer); 
} 

也必須聲明Internet權限在AndroidManifest.xml中。將這些添加到代碼上方的行中:

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
0

您是在局域網或互聯網(WAN)上測試它嗎?

必須考慮到,目前許多手機提供商不會將公有IP地址分配給連接的設備,它們會分配私有IP,因此設備無法充當服務器,因爲它的端口無法從WAN訪問