Suroor Ahmmad
Suroor Ahmmad

Reputation: 1162

TCP Socket connection gets closed even though it is running in Android Service

As I am creating a Remote PC application where android is the client and Java is the server. In the below code I am getting screenshots from the Java and displaying it in ImageView of android program. Here Socket connection is running in the background that is Service and I am getting the Socket object to the below Activity using Gson library.

AndroidClient.Java

public class ScreenCast extends Activity {
MyService conn_obj;
public static Socket client;
PrintWriter printwriter;
static ImageView iv;
static Drawable ob;
Socket socket;
Bitmap bitmap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);                             setContentView(R.layout.activity_screen_cast);
    Gson obj=new Gson();
    String src=getIntent().getStringExtra("clientobj");
    conn_obj= obj.fromJson(src, MyService.class);
    client=MyService.client;
    Log.i("Client Socket",""+client);
    MyTask task=new MyTask();
    task.execute();
}

private class MyTask extends AsyncTask<Void, Void, Bitmap>{
    @SuppressWarnings("deprecation")
    @Override
    protected void onPostExecute(Bitmap result) {
        if(bitmap!=null){
            iv=(ImageView) findViewById(R.id.screenView);
            ob=new BitmapDrawable(getResources(),bitmap);
            iv.setBackgroundDrawable(ob);
        }else{
            Log.d("Bitmap null","Empty");
        }
        MyTask task=new MyTask();
        task.execute();
    }

    @Override
    protected Bitmap doInBackground(Void... arg0){
        try {
            Log.i ("Client Obj",""+client);//check result in log below.
            ObjectInputStream ois=new ObjectInputStream(client.getInputStream());
            byte[] buffer=(byte[]) ois.readObject();
            BitmapFactory.Options options=new BitmapFactory.Options();
            options.inMutable=true;
            bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length,options);
     Ois.close ();
            return bitmap;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Problem I am facing is: The Socket connection is active till the first screen shot is displayed, after that the Socket connection gets closed and I don’t know where it is getting closed. But strange thing is client is not null at that point. (See log cat before the socket closed error)

LogCat:

2-23 12:39:27.515: I/Client Socket(24599): Socket[address=/192.168.237.1,port=3434,localPort=44496]
02-23 12:39:27.585: D/dalvikvm(24599): GC_FOR_ALLOC freed 319K, 7% free 17667K/18951K, paused 26ms, total 26ms
02-23 12:39:27.620: I/dalvikvm-heap(24599): Grow heap (frag case) to 22.136MB for 4196368-byte allocation
02-23 12:39:27.660: D/dalvikvm(24599): GC_FOR_ALLOC freed 2472K, 17% free 19293K/23111K, paused 41ms, total 41ms
02-23 12:39:27.700: D/dalvikvm(24599): GC_CONCURRENT freed 0K, 17% free 19293K/23111K, paused 12ms+5ms, total 40ms
02-23 12:39:27.815: E/SpannableStringBuilder(24599): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
02-23 12:39:27.815: E/SpannableStringBuilder(24599): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
02-23 12:39:27:815: I/Client Socket(24599): Socket[address=/192.168.237.1,port=3434,localPort=44496]
02-23 12:39:27.815: W/System.err(24599): java.net.SocketException: Socket is closed
02-23 12:39:27.835: W/System.err(24599):    at java.net.PlainSocketImpl.checkNotClosed(PlainSocketImpl.java:134)
02-23 12:39:27.835: W/System.err(24599):    at java.net.PlainSocketImpl.getInputStream(PlainSocketImpl.java:216)
02-23 12:39:27.835: W/System.err(24599):    at java.net.Socket.getInputStream(Socket.java:343)
02-23 12:39:27.835: W/System.err(24599):    at com.qubelab.smartcontrol.ScreenCast$MyTask.doInBackground(ScreenCast.java:65)
02-23 12:39:27.835: W/System.err(24599):    at com.qubelab.smartcontrol.ScreenCast$MyTask.doInBackground(ScreenCast.java:1)
02-23 12:39:27.840: W/System.err(24599):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-23 12:39:27.840: W/System.err(24599):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
02-23 12:39:27.840: W/System.err(24599):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
02-23 12:39:27.840: W/System.err(24599):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-23 12:39:27.840: W/System.err(24599):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
02-23 12:39:27.840: W/System.err(24599):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
02-23 12:39:27.840: W/System.err(24599):    at java.lang.Thread.run(Thread.java:856)

Updated Code:

try { 
     if (client.isConnected){ 
         Log.i ("Client Obj",""+client);
         ObjectInputStream ois=new ObjectInputStream(client.getInputStream()); 
         byte[] buffer=(byte[]) ois.readObject(); 
         BitmapFactory.Options options=new BitmapFactory.Options();  
         options.inMutable=true; 
         bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length,options); 
         Ois.close (); 
         return bitmap; 
    } else { 
         Log.d ( " Client", " closed"); 
    } 
} catch(Exception e){ 
     e.printstacktrace();   
}

Upvotes: 2

Views: 2567

Answers (2)

Sushant Patekar
Sushant Patekar

Reputation: 473

insted of using

import java.io*;

use

import java.nio*;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

these helps to bind your connection persistently. just search for example on SocketChannel in java

Upvotes: 0

Olaf Dietsche
Olaf Dietsche

Reputation: 74078

I tried a modified version of Oracle's echo server and client from Reading from and Writing to a Socket, e.g. client side

Socket echoSocket = new Socket(hostName, portNumber);
ObjectInputStream in = new ObjectInputStream(echoSocket.getInputStream());
/* ... */
in.close();
if (echoSocket.isClosed())
    System.out.println("Socket is closed.");

and as a result, the echo client prints

Socket is closed.

So, when you close the ObjectInputStream for whatever reason, the socket becomes closed as well. And this is the cause for the exception you get

java.net.SocketException: Socket is closed

This means, if you want to read more than one image, you need to reconnect to the server or try to keep the socket open.


To keep the connection open, do not close ois or recreate the ObjectInputStream, e.g.

public class ScreenCast extends Activity {
    private Socket client;

    /* ... */

    private class MyTask extends AsyncTask<Void, Void, Bitmap> {
        private ObjectInputStream ois;

        @Override
        protected void onPreExecute() {
            if (client == null || client.isClosed()) {
                /* reconnect to server somehow */

                ois = null;
            }

            if (ois == null)
                ois = new ObjectInputStream(client.getInputStream());
        }

        @Override
        protected Bitmap doInBackground(Void... arg0) {
            byte[] buffer = (byte[]) ois.readObject();
            /* process image, do *not* close ois */
        }

        @Override
        protected void onPostExecute() {
            /* ... */
        }
    }
}

Upvotes: 1

Related Questions