vidstige / jadb

ADB Client in pure Java.
Apache License 2.0
640 stars 178 forks source link

Screencap is generating corrupted PNG files #154

Open ilpersi opened 8 months ago

ilpersi commented 8 months ago

Describe the bug When I run the snippet below the generated PNG file is corrupted.

try (FileOutputStream outputStream = new FileOutputStream(aDevice.toString().replace(":", "")+".png")) {
    stdout = aDevice.executeShell("screencap", "-p");
    Stream.copy(stdout, outputStream);
}

The script is taken from the examples: https://github.com/vidstige/jadb/blob/fedca18ae1ca3e5167487f737e48877939ca8dc7/test/se/vidstige/jadb/test/integration/RealDeviceTestCases.java#L112

No error is raised during the run time.

I am able to correctly generate png file from the command prompt using a standard command like this:

adb.exe -s 127.0.0.1:5555 exec-out screencap -p > test.png

To Reproduce Steps to reproduce the behavior:

  1. Below you can find the full example class with the whole example code
  2. I am using Bluestacks emulator to perform the tests
  3. Run the code
  4. Check the generated PNG

Expected behavior The generated file is a valid PNG.

Screenshots Hex dump of the corrupted file generated via jadb image

Hex dump of the correct file generated via command line image

You can notice differences starting from byte number 4 (value is 0d instead of 0a).

Other Notes Apparently this is a know issue and I've found a relevant topic in stack overflow. https://stackoverflow.com/questions/13578416/read-binary-stdout-data-like-screencap-data-from-adb-shell

Suggestion there is to use exec-out command, but apparently I am not able to make it work with jdb. Looking into open issues, this may be related to #149 and #150.

Desktop (please complete the following information):

Full class source

package org.example;

import se.vidstige.jadb.*;

import java.io.*;
import java.net.InetSocketAddress;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        // we launch the ADB Server
        try {
            new AdbServerLauncher(new Subprocess(), "D:\\Android\\SDK\\platform-tools\\adb.exe").launch();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            System.out.println("AdbServerLauncher InterruptedException: " + e);
        }

        // We connect to the right device
        JadbConnection jadb = new JadbConnection();
        try {
            jadb.connectToTcpDevice(new InetSocketAddress("127.0.0.1", 5555));
        } catch (IOException e) {
            System.out.println("connectToTcpDevice IOException: " + e);
        } catch (JadbException e) {
            System.out.println("connectToTcpDevice JadbException: " + e);
        } catch (ConnectionToRemoteDeviceException e) {
            System.out.println("connectToTcpDevice ConnectionToRemoteDeviceException: " + e);
        }

        try {
            List<JadbDevice> devices = jadb.getDevices();
            devices.forEach(aDevice -> {
                System.out.println(aDevice.toString());

                // https://github.com/vidstige/jadb/blob/fedca18ae1ca3e5167487f737e48877939ca8dc7/test/se/vidstige/jadb/test/integration/RealDeviceTestCases.java#L112
                InputStream stdout;
                try {
                    try (FileOutputStream outputStream = new FileOutputStream(aDevice.toString().replace(":", "")+".png")) {
                        stdout = aDevice.executeShell("screencap", "-p");
                        Stream.copy(stdout, outputStream);
                    }

                } catch (IOException e) {
                    System.out.println("FileOutputStream IOException: " + e);
                } catch (JadbException e) {
                    System.out.println("FileOutputStream JadbException: " + e);
                }

            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (JadbException e) {
            System.out.println(e.getMessage());
        }

    }
}
vidstige commented 6 months ago

Thanks for this very detailed issue report. I didn't notice it until right now. I don't have time to look into it currently, and it seems none of the maintainers don't either. It seems like a very nice thing to add though!

I don't currently have java development setup with and IDE and Android emulator, etc. But if someone would like to look into it, that would be great. I would be glad to help in any way I can as I know my way around the source code in this project.