Reputation: 1162
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
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
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