Kenny
Kenny

Reputation: 1152

TCP connection stops listening when app is sent to background

My service stops listening to the server when I move my app to the background, connection is not dropped, that's what the server log says. Why is this behavior happening? Service is started using startService.

public class LocalService extends Service {
    Socket socket = null;
    public String SERVER_IP = "192.168.1.10";
    public boolean connected = false;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            if (intent.hasCategory("connection")) {
                if (connected) {
                    try {
                        if (socket != null) {
                            socket.close();
                            connected = false;
                            // sendBroadcast(intent1);
                        }
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                else {
                    connect();
                }
            }
        }

        return START_STICKY;
    }

    public void connect() {
        Thread thread = new Thread() {
            @Override
            public void run() {
                // sendBroadcast(intent1);

                try {
                    socket = new Socket(SERVER_IP, 5000);
                    socket.setSoTimeout(5000);

                    connected = true;
                    // sendBroadcast(intent2);

                    OutputStream out = socket.getOutputStream();
                    PrintWriter output = new PrintWriter(out);
                    BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                    while (true) {
                        String event = input.readLine();
                        // sendBroadcast(intent3);

                        if (event.substring(0, 3).equals("msg")) {
                            String notificationTitle = event.substring(4, event.indexOf("::"));
                            CharSequence tickerText = event.substring(event.indexOf("::") + 2);
                            String notificationContent = event.substring(event.indexOf("::") + 2);

                            Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

                            NotificationCompat.Builder mBuilder =
                                    new NotificationCompat.Builder(LocalService.this)
                                            .setSmallIcon(R.drawable.ic_launcher)
                                            .setLargeIcon(largeIcon)
                                            .setTicker(tickerText)
                                            .setContentTitle(notificationTitle)
                                            .setContentText(notificationContent)
                                            .setOnlyAlertOnce(true);

                            Intent resultIntent = new Intent(LocalService.this, ResultActivity.class);
                            TaskStackBuilder stackBuilder = TaskStackBuilder.create(LocalService.this);
                            stackBuilder.addParentStack(ResultActivity.class);
                            stackBuilder.addNextIntent(resultIntent);
                            PendingIntent resultPendingIntent =
                                    stackBuilder.getPendingIntent(
                                            0,
                                            PendingIntent.FLAG_UPDATE_CURRENT
                                    );
                            mBuilder.setContentIntent(resultPendingIntent);
                            NotificationManager mNotificationManager =
                                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                            mNotificationManager.notify(mId, mBuilder.build());
                            mId = mId + 1;
                        }
                    }
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (java.net.ConnectException e) {
                    e.printStackTrace();
                    // sendBroadcast(intent4);
                } catch (SocketTimeoutException e) {
                    e.printStackTrace();
                } catch(java.net.SocketException e) {
                    e.printStackTrace();
                    connected = false;
                    // sendBroadcast(intent5);
                } catch (IndexOutOfBoundsException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                    connected = false;
                    // sendBroadcast(intenty);
                }
            }
        };

        thread.start();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private final IBinder mBinder = new LocalBinder();
}

Upvotes: 1

Views: 588

Answers (2)

Sadegh
Sadegh

Reputation: 2669

Seems that you have some problem in bounding and unbounding you activity to your service. I guess you do not unbound the activity that is bounded to this service, so after you activity stoped/killed you service stops working and because of START_STICKY it will starts again by system. you should unbound the activity in onPause() and also disconnect the socket in onDestory method in your service.

Upvotes: 1

rupesh jain
rupesh jain

Reputation: 3430

What you need is sticky service

You can do this by returning following flag

  @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("LocalService", "Received start id " + startId + ": " + intent);
        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

As per enter link description here

Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service. Because it is in the started state, it will guarantee to call onStartCommand(Intent, int, int) after creating the new service instance; if there are not any pending start commands to be delivered to the service, it will be called with a null intent object, so you must take care to check for this.

This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback.

I feel its the following loop which is getting called when service is restarted and closing the connection:

if (connected) {
                    try {
                        if (socket != null) {
                            socket.close();
                            connected = false;
                            // sendBroadcast(intent1);
                        }
                    }

Upvotes: 1

Related Questions