2017-09-14 107 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访问