ANDROID - 发送截图从Java通过TCP套接字到Android [英] ANDROID - Send a screenshot from java to android via tcp socket

查看:335
本文介绍了ANDROID - 发送截图从Java通过TCP套接字到Android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了通过套接字客户端 - 服务器聊天和它的伟大工程。现在,我想包括服务器(Android手机)一个选项,虎视眈眈从客户端(PC应用程序)的屏幕截图。创建截图工作正常,但是从客户端转移到服务器的每一次失败。

客户端/发件人:

在我直接写的图像输出流,但我得到一个错误在服务器端,所以我尝试了这种方式,但它仅仅是相同的。

 公共类ClientScreenshotThread实现Runnable {

//  - 软件初始化 -  //
私人插槽transferSocket;
私人的BufferedImage截图;
私人机器人的机器人;
私人BufferedWriter将outToServer;
私人的FileInputStream inStream中;
私人DataOutputStream类outStream;

//  - 瓦尔初始化 -  //
私人最终诠释SERVER_TRANSFER_PORT = 65000;

私人诠释屏幕宽度,screenHeight;

// ------------------------------------------------ -  //

公共ClientScreenshotThread(){

}

@覆盖
公共无效的run(){
    尝试 {
        为SocketAddress sockaddr的=新的InetSocketAddress(Client.SERVER_IP,SERVER_TRANSFER_PORT);
        transferSocket =新的Socket();
        transferSocket.connect(套接字地址,5000); // 5秒超时

        维维= Toolkit.getDefaultToolkit()getScreenSize()。
        机器人=新的机器人();

        屏幕宽度= dimension.width;
        screenHeight = dimension.height;

        矩形屏幕=新的Rectangle(屏幕宽度,screenHeight);

        截图= robot.createScreenCapture(屏幕);
        ImageIO.write(截屏,PNG,新的文件(/用户/克里斯/下载/ screenshot.png));

        档案文件=新的文件(/用户/克里斯/下载/ screenshot.png);
        inStream中=新的FileInputStream(文件);
        byte []的缓冲区=新的字节[4096];

        // prepare服务器接收截图
        outToServer =新的BufferedWriter(新OutputStreamWriter(transferSocket.getOutputStream()));
        outToServer.write(#<!CMD>截屏);
        outToServer.newLine();
        outToServer.flush();

        //发送截图到服务器
        outStream =新DataOutputStream类(transferSocket.getOutputStream());

        INT N;
        INT I = 0;
        而((N = inStream.read(缓冲液))!=  -  1){
            我++;
            的System.out.println(I +。字节[+ N +]);
            outStream.write(缓冲液,0,n)的;
            outStream.flush();
        }

    }赶上(的AWTException E1){
        的System.out.println(AWT:+ e1.getMessage()的toString());
    }赶上(IOException异常E2){
        的System.out.println(IO:+ e2.getMessage()的toString());
    } 最后 {
        尝试 {
            //关闭流和插座
            inStream.close();
            outToServer.close();
            transferSocket.close();
        }赶上(IOException异常E){
            的System.out.println(e.getMessage()的toString());
        }
    }
}
}
 

服务器端/接收器:

我总是得到一个NullPointerException异常的:

bmp.com preSS(Bitmap.Com pressFormat.PNG,100,fileOutStream);

 公共类ServerTransferThread实现Runnable {

//  - 软件初始化 -  //
私人的ServerSocket serverTransferSocket;
私人处理程序处理程序;
私人的BufferedReader inFromClient;
私人的DataInputStream inStream中;
私人ByteArrayOutputStream内容;
私人的FileOutputStream fileOutStream;

//  - 瓦尔初始化 -  //
私人最终字符串变量=XXX;

私人最终诠释SERVER_TRANSFER_PORT = 65000;

// ------------------------------------------------ -  //

公共ServerTransferThread(处理器_handler){
    this.handler = _handler;
}

@覆盖
公共无效的run(){
    Log.d(TAG,ServerTransferThread:run()的);

    尝试 {
        serverTransferSocket =新的ServerSocket(SERVER_TRANSFER_PORT);

        而(ServerActivity.SERVER_STATE ==真){
            Socket套接字= serverTransferSocket.accept();
            Log.d(TAG,ServerTransferThread:接受());

            inFromClient =新的BufferedReader(新的InputStreamReader(socket.getInputStream()));
            Log.d(TAG,ServerTransferThread:的BufferedReader());

            字符串消息=;
            如果((消息= inFromClient.readLine())!= NULL){
                如果(message.equals(#<!CMD>截屏)){
                    receiveScreenshot(插座);
                }
            }
        }
    }赶上(IOException异常E){
        Log.e(TAGServerTransferThread 1:+ e.getMessage()的toString());
    } 最后 {
        尝试 {
            inFromClient.close();
            serverTransferSocket.close();
        }赶上(IOException异常E){
            Log.e(TAG,ServerTransferThread 2:+ e.getMessage()的toString());
        }
    }
}

私人无效receiveScreenshot(插座socketX){
    Log.d(TAG,ServerTransferThread:receiveScreenshot());

    尝试 {
        handler.sendMessage(buildMessage(>接收截图..));
        inStream中=新的DataInputStream(socketX.getInputStream());

        byte []的缓冲区=新的字节[4096];
        内容=新ByteArrayOutputStream();

        inStream中=新的DataInputStream(socketX.getInputStream());

        INT N;
        而((N = inStream.read())!=  -  1){
            content.write(缓冲液,0,n)的; //我在这里内存不足
            content.flush();
        }

        文件目录=新的文件(ServerActivity.APP_FOLDER_PATH);
        文件截图=新的文件(ServerActivity.APP_FOLDER_PATH +/+screenshot.png);

        如果(!directory.exists())
            directory.mkdirs();

        如果(!screenshot.exists()){
            screenshot.createNewFile();
        }
        其他 {
            screenshot.delete();
            screenshot.createNewFile();
        }

        fileOutStream =新的FileOutputStream(截图);
        BMP位= BitmapFactory.de codeByteArray(content.toByteArray(),0,content.size());
        bmp.com preSS(Bitmap.Com pressFormat.PNG,100,fileOutStream);

        handler.sendMessage(buildMessage(>屏幕截图成功地接收到!));

    }赶上(IOException异常E1){
        Log.e(TAGServerTransferThread 3:+ e1.getMessage()的toString());
    } 最后 {
        尝试 {
            inStream.close();
            content.close();
            fileOutStream.close();
            socketX.close();
        }赶上(IOException异常E){
            Log.e(TAG,ServerTransferThread 4:+ e.getMessage()的toString());
        }
    }
}

悄悄话buildMessage(字符串文本){
    Log.d(TAG,ServerTransferThread:buildMessage());

    消息味精= handler.obtainMessage();
    束束=新包();
    bundle.putString(消息,文本);
    msg.setData(包);
    返回味精;
}
 

这是我的logcat的输出:

  08-20 19:01:18.285:D / Skia的(5383):--- SkImageDe codeR ::厂返回null
08-20 19:01:18.295:W / dalvikvm(5383):主题ID = 12:线程退出与未捕获的异常(组= 0x40c6b1f8)
08-20 19:01:18.295:E / AndroidRuntime(5383):致命异常:螺纹3051
08-20 19:01:18.295:E / AndroidRuntime(5383):显示java.lang.NullPointerException
08-20 19:01:18.295:E / AndroidRuntime(5383):在net.api.speak.wifi.ServerTransferThread.receiveScreenshot(ServerTransferThread.java:114)
08-20 19:01:18.295:E / AndroidRuntime(5383):在net.api.speak.wifi.ServerTransferThread.run(ServerTransferThread.java:58)
08-20 19:01:18.295:E / AndroidRuntime(5383):在java.lang.Thread.run(Thread.java:856)
08-20 19:01:27.820:D /无线讲话(5383):服务器:的onDestroy()
08-20 19:01:27.830:E /无线讲话(5383):服务器:套接字关闭
08-20 19:01:27.830:E /无线讲话(5383):ServerThread:插座关闭
 


编辑:经过一些麻烦,我发现了文件传输问题的最终解决方案!在那里,它是:


最后服务器端:

  INT BYTECOUNT = 2048;
            byte []的BUF =新的字节[BYTECOUNT]

            的OutputStream OUT = socket.getOutputStream();
            的BufferedOutputStream BuffOUT =新的BufferedOutputStream(OUT,BYTECOUNT);
            在的FileInputStream =新的FileInputStream(itemPath);

            INT I = 0;
            而((ⅰ= in.read(buf中,0,BYTECOUNT))!=  -  1){
                BuffOUT.write(BUF,0,I);
                BuffOUT.flush();
            }
 

最终客户端:

 的FileOutputStream outToFile =新的FileOutputStream(文件名);

        INT BYTECOUNT = 2048;
        byte []的BUF =新的字节[BYTECOUNT]

        //创建一个InputStream的文件数据到达
        InputStream的IN = socket.getInputStream();
        的BufferedInputStream BuffIN =新的BufferedInputStream(IN,BYTECOUNT);

        //接收文件..
        INT I = 0;
        INT文件长度= 0;
        而((ⅰ= BuffIN.read(buf中,0,BYTECOUNT))!=  -  1){
            文件长度+ =我;
            outToFile.write(BUF,0,I);
            outToFile.flush();
        }
 

解决方案

该NullPointerException异常是因为 BitmapFactory.de codeByteArray 返回:德codeD位图,或者如果图像不能德code空。

服务器端(里面receiveScreenshot()方法),写入InputStream的部分字节到ByteArrayOutputStream内容变量是不正确的,因为 inStream.read() inStream.read(缓冲区)

可以是内存不足的错误解释说,由于阅读()方法一次只能读取一个字节,然后对每一个字节,你老是写4096的全缓冲字节。

编辑:对COM preSS的OutputStream为PNG,一旦你写的所有字节的FileOutputStream里面,当你不想直接提供字节(因为在你的情况下,有什么不工作):

 里面fileOutStream //写字节

BMP位= BitmapFactory.de codeFILE(screenshot.getAbsolutePath());
bmp.com preSS(Bitmap.Com pressFormat.PNG,100,fileOutStream);
fileOutStream.close();
 

这应该为你的需求,但它是一个可惜脱code中的文件,因为你应该已经知道里面的字节数。

I made a Client-Server chat via sockets and it works great. Now I want to include an option for the server(Android phone) to grap a screenshot from the client(pc application). Creating the screenshot works fine, but the transfer from the client to the server fails every time.

CLIENT-SIDE / SENDER:

Before I wrote the image directly to an output stream, but I get an error on the server side and so I tried this way, but it's just 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-SIDE / 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 troubles I've found a final solution for the file transfer problem! There it is:


Final Server side:

            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();
            }

Final Client 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();
        }

解决方案

The NullPointerException is because the BitmapFactory.decodeByteArray returns: The decoded bitmap, or null if the image could not be decode.

Server-side (inside receiveScreenshot() method), the part that writes the InputStream bytes into the ByteArrayOutputStream 'content' variable is not correct, because inStream.read() should be inStream.read(buffer)

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

Edit: To compress OutputStream to png once you have written all the bytes inside the fileOutputStream and when you don't want to directly provide the bytes (because in your case it is what didn't work):

// 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's a pity to decode the file since you should already know the bytes inside..

这篇关于ANDROID - 发送截图从Java通过TCP套接字到Android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆