jadb
jadb copied to clipboard
Screencap is generating corrupted PNG files
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:
- Below you can find the full example class with the whole example code
- I am using Bluestacks emulator to perform the tests
- Run the code
- Check the generated PNG
Expected behavior The generated file is a valid PNG.
Screenshots
Hex dump of the corrupted file generated via jadb
Hex dump of the correct file generated via command line
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):
- OS: Windows 11
- Version 1.2.1
- Java 17.0.1
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());
}
}
}
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.