ANDROID - Send a screenshot from java to android via tcp socket

I did Client-Server chat over sockets and it works great. Now I want to enable the option for the server (Android phone) to take a screenshot from the client (PC application). Creating a screenshot works fine, but the transfer from the client to the server is interrupted every time.

CUSTOMER PARTY / SENDING:

Before I wrote the image directly to the output stream, but I get an error on the server side, and so I tried this way, but it is the same.

public class ClientScreenshotThread implements Runnable { // - Software Init - // private Socket transferSocket; private BufferedImage screenshot; private Robot robot; private BufferedWriter outToServer; private FileInputStream inStream; private DataOutputStream outStream; // - Var Init - // private final int SERVER_TRANSFER_PORT = 65000; private int screenWidth, screenHeight; // -------------------------------------------------- // public ClientScreenshotThread() { } @Override public void run() { try { SocketAddress sockaddr = new InetSocketAddress(Client.SERVER_IP, SERVER_TRANSFER_PORT); transferSocket = new Socket(); transferSocket.connect(sockaddr, 5000); // 5sec Timeout Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); robot = new Robot(); screenWidth = dimension.width; screenHeight = dimension.height; Rectangle screen = new Rectangle(screenWidth, screenHeight); screenshot = robot.createScreenCapture(screen); ImageIO.write(screenshot, "png", new File("/Users/chris/Downloads/screenshot.png")); File file = new File("/Users/chris/Downloads/screenshot.png"); inStream = new FileInputStream(file); byte[] buffer = new byte[4096]; // prepare server for receiving the screenshot outToServer = new BufferedWriter(new OutputStreamWriter(transferSocket.getOutputStream())); outToServer.write("#!<cmd>screenshot"); outToServer.newLine(); outToServer.flush(); // send the screenshot to the server outStream = new DataOutputStream(transferSocket.getOutputStream()); int n; int i = 0; while((n = inStream.read(buffer)) != -1) { i++; System.out.println(i + ". Byte[" + n + "]"); outStream.write(buffer, 0, n); outStream.flush(); } } catch(AWTException e1) { System.out.println("AWT: " + e1.getMessage().toString()); } catch(IOException e2) { System.out.println("IO: " + e2.getMessage().toString()); } finally { try { // close streams and socket inStream.close(); outToServer.close(); transferSocket.close(); } catch(IOException e) { System.out.println(e.getMessage().toString()); } } } } 

SERVER / RECEIVER:

I always get a "NullPointerException" at:

bmp.compress (Bitmap.CompressFormat.PNG, 100, fileOutStream);

 public class ServerTransferThread implements Runnable { // - Software Init - // private ServerSocket serverTransferSocket; private Handler handler; private BufferedReader inFromClient; private DataInputStream inStream; private ByteArrayOutputStream content; private FileOutputStream fileOutStream; // - Var Init - // private final String TAG = "xxx"; private final int SERVER_TRANSFER_PORT = 65000; // -------------------------------------------------- // public ServerTransferThread(Handler _handler) { this.handler = _handler; } @Override public void run() { Log.d(TAG, "ServerTransferThread: run()"); try { serverTransferSocket = new ServerSocket(SERVER_TRANSFER_PORT); while(ServerActivity.SERVER_STATE == true) { Socket socket = serverTransferSocket.accept(); Log.d(TAG, "ServerTransferThread: accepted()"); inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); Log.d(TAG, "ServerTransferThread: bufferedReader()"); String message = ""; if((message = inFromClient.readLine()) != null) { if(message.equals("#!<cmd>screenshot")) { receiveScreenshot(socket); } } } } catch(IOException e) { Log.e(TAG, "ServerTransferThread 1: " + e.getMessage().toString()); } finally { try { inFromClient.close(); serverTransferSocket.close(); } catch (IOException e) { Log.e(TAG, "ServerTransferThread 2: " + e.getMessage().toString()); } } } private void receiveScreenshot(Socket socketX) { Log.d(TAG, "ServerTransferThread: receiveScreenshot()"); try { handler.sendMessage(buildMessage("> Receiving screenshot..")); inStream = new DataInputStream(socketX.getInputStream()); byte[] buffer = new byte[4096]; content = new ByteArrayOutputStream(); inStream = new DataInputStream(socketX.getInputStream()); int n; while((n = inStream.read()) != -1) { content.write(buffer, 0, n); // HERE I "OUT OF MEMORY" content.flush(); } File directory = new File(ServerActivity.APP_FOLDER_PATH); File screenshot = new File(ServerActivity.APP_FOLDER_PATH + "/" + "screenshot.png"); if(!directory.exists()) directory.mkdirs(); if(!screenshot.exists()) { screenshot.createNewFile(); } else { screenshot.delete(); screenshot.createNewFile(); } fileOutStream = new FileOutputStream(screenshot); Bitmap bmp = BitmapFactory.decodeByteArray(content.toByteArray(), 0, content.size()); bmp.compress(Bitmap.CompressFormat.PNG, 100, fileOutStream); handler.sendMessage(buildMessage("> Screenshot received sucessfully!")); } catch(IOException e1) { Log.e(TAG, "ServerTransferThread 3: " + e1.getMessage().toString()); } finally { try { inStream.close(); content.close(); fileOutStream.close(); socketX.close(); } catch (IOException e) { Log.e(TAG, "ServerTransferThread 4: " + e.getMessage().toString()); } } } private Message buildMessage(String text) { Log.d(TAG, "ServerTransferThread: buildMessage()"); Message msg = handler.obtainMessage(); Bundle bundle = new Bundle(); bundle.putString("MESSAGE", text); msg.setData(bundle); return msg; } 

Here is my Logcat output:

 08-20 19:01:18.285: D/skia(5383): --- SkImageDecoder::Factory returned null 08-20 19:01:18.295: W/dalvikvm(5383): threadid=12: thread exiting with uncaught exception (group=0x40c6b1f8) 08-20 19:01:18.295: E/AndroidRuntime(5383): FATAL EXCEPTION: Thread-3051 08-20 19:01:18.295: E/AndroidRuntime(5383): java.lang.NullPointerException 08-20 19:01:18.295: E/AndroidRuntime(5383): at net.api.speak.wifi.ServerTransferThread.receiveScreenshot(ServerTransferThread.java:114) 08-20 19:01:18.295: E/AndroidRuntime(5383): at net.api.speak.wifi.ServerTransferThread.run(ServerTransferThread.java:58) 08-20 19:01:18.295: E/AndroidRuntime(5383): at java.lang.Thread.run(Thread.java:856) 08-20 19:01:27.820: D/Speak WiFi(5383): Server: onDestroy() 08-20 19:01:27.830: E/Speak WiFi(5383): Server: Socket closed 08-20 19:01:27.830: E/Speak WiFi(5383): ServerThread: Socket closed 

EDIT: After some problems, I found a final solution to the file transfer problem! There he is:


End side of the server:

  int bytecount = 2048; byte[] buf = new byte[bytecount]; OutputStream OUT = socket.getOutputStream(); BufferedOutputStream BuffOUT = new BufferedOutputStream(OUT, bytecount); FileInputStream in = new FileInputStream(itemPath); int i = 0; while ((i = in.read(buf, 0, bytecount)) != -1) { BuffOUT.write(buf, 0, i); BuffOUT.flush(); } 

End customer side:

  FileOutputStream outToFile = new FileOutputStream(FileName); int bytecount = 2048; byte[] buf = new byte[bytecount]; // Create an inputstream for the file data to arrive InputStream IN = socket.getInputStream(); BufferedInputStream BuffIN = new BufferedInputStream(IN, bytecount); // Receiving file.. int i = 0; int filelength = 0; while((i = BuffIN.read(buf, 0, bytecount)) != -1) { filelength += i; outToFile.write(buf, 0, i); outToFile.flush(); } 
+6
source share
2 answers

Could you write the received bytes directly to FileOutputStream. Converting png to a bitmap on a fairly limited device such as a smartphone sometimes causes problems.

Do you need to create a Bitmap object on the receiver side?

If not, you can do something like this:

 InputStream is = socketX.getInputStream(); FileOutputStream outputFile = new FileOutputStream(screenshot); int n; while ((n = is.read(data, 0, data.length)) != -1) { outputFile.write(data, 0, n); } 

I have not tested the code.

0
source

A NullPointerException is BitmapFactory.decodeByteArray because BitmapFactory.decodeByteArray returned: a decoded bitmap or null if the image cannot be decoded.

On the server side (inside the receiveScreenshot () method), the part that writes the InputStream bytes to the content content content ByteArrayOutputStream variable is incorrect because inStream.read() must be inStream.read(buffer)

The Out of Memory error can be explained because the read() method reads only one byte at a time, and then for each byte you always write a full buffer of 4096 bytes.

Edit: Compressing an OutputStream to png after you have written all the bytes inside fileOutputStream and when you do not want to provide the bytes directly (because in your case this was not working):

 // Write bytes inside fileOutStream Bitmap bmp = BitmapFactory.decodeFile(screenshot.getAbsolutePath()); bmp.compress(Bitmap.CompressFormat.PNG, 100, fileOutStream); fileOutStream.close(); 

This should work for your needs, but it is unfortunate that you should decode the file, as you should already know the bytes inside.

0
source

Source: https://habr.com/ru/post/923304/


All Articles