Errors happen when Android screen is horizontal

Asked by Action on 2017-04-22

Hi, Sir, first of all, thanks for developing this amazing SikuliX !

    I get an error when I try to control my android phone by SikuliX-java. These are my codes:

 public class Test {
 public static void main(String[] args) throws FindFailed {
  System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  ADBScreen android=new ADBScreen();
   android.click("imgs/5.png");
 }
}

When the android screen is vertical, the codes work fine. But when screen is horizontal, below error happens:

[error] ADBDevice: captureDeviceScreenMat: width or height differ from device values
Exception in thread "main" java.lang.NullPointerException: Attempt to dereference null cv::Mat
 at org.sikuli.natives.VisionProxyJNI.FindInput_setSource__SWIG_1(Native Method)
 at org.sikuli.natives.FindInput.setSource(FindInput.java:81)
 at org.sikuli.script.Finder.setScreenImage(Finder.java:164)
 at org.sikuli.script.Finder.initScreenFinder(Finder.java:131)
 at org.sikuli.script.Finder.<init>(Finder.java:113)
 at org.sikuli.script.Region.doCheckLastSeenAndCreateFinder(Region.java:3015)
 at org.sikuli.script.Region.checkLastSeenAndCreateFinder(Region.java:2971)
 at org.sikuli.script.Region.doFind(Region.java:2900)
 at org.sikuli.script.Region.access$500(Region.java:29)
 at org.sikuli.script.Region$RepeatableFind.run(Region.java:3144)
 at org.sikuli.script.Region$Repeatable.repeat(Region.java:3100)
 at org.sikuli.script.Region.wait(Region.java:2733)
 at org.sikuli.script.Region.find(Region.java:2336)
 at org.sikuli.script.Region.getLocationFromTarget(Region.java:3213)
 at org.sikuli.script.Region.click(Region.java:3698)
 at org.sikuli.script.Region.click(Region.java:3683)
 at Test.main(Test.java:12)

    My android version is 4.4.4, I heard about it works fine on android 6.x. My question is : is there any solution for android v4.x?

Question information

RaiMan (raimund-hocke) said : #1

I am sorry, but I do not have the time and resources currently to test or even augment this experimental feature.

... but looking into the code:
I guess, that currently the implementation does not realise the orientation change.

BTW:
- according to the docs your usage is not recommended (admitted: a little bit disguised with the reference to VNCScreen)
ADBScreen adbScreen = ADBCScreen.start();

So in the same script, you have to issue
AdbScreen.stop()

when you change the orientation and another
ADBScreen adbScreen = ADBCScreen.start();

to get a valid screen object for the new situation.

For the next months you have to live with this situation ( see above).

Action (actionwind) said : #2

Hello, Sir, thank you for providing the solution. But unfortunately it's not working.

     After I did some study on the codes of ADBDevice.java, I found it uses adb command "screencap" to capture Android screen:

      InputStream stdout = device.executeShell("screencap");
      stdout.read(imagePrefix);

      And I think that's the reason of the error. Because the captured image by "screencap" is always vertical even when the Android screen is horizontal( at least on Android v4.4.4).

    And when these codes of ADBDevice.java compare the captured image to Android screen, will trigger the error:

     if (byte2int(imagePrefix, 0, 4) != devW || byte2int(imagePrefix, 4, 4) != devH) {
        //TODO check orientation might have changed
        log(-1, "captureDeviceScreenMat: width or height differ from device values");
        return null;
      }

    So I think the solution should be rotated the captured image 90 degrees to the left, instead of "return null;". Actually I try to write some codes to fix this problem today, but I found it's totally beyond my programimg ability. After all, I am just a software tester.

    So, still looking forward to fix the problem by you if you have enough time. Thanks again for sharing this amazing project to everyone for free.
    And if you need a software tester in this project, I hope I can help, for free, until i find a job.

Action (actionwind) said : #3

Hello, Sir, I have written some codes to fix this problem, and it works fine on my program. This picture rotate function will take about 0.16s--0.32s, I think it's acceptable.
     I will test it on ADBDevice.java if I can figure out how. Plan to do it in these two days.

    These are the codes:

  BufferedImage oldImage = ImageIO.read(stdout);
  int newWidth = oldImage.getHeight(null);
  int newHeight = oldImage.getWidth(null);
  BufferedImage image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_BGR);
  Graphics2D g2 = image.createGraphics();
  g2.rotate(Math.PI * 1.5, newHeight / 2, newWidth / 2);
  g2.translate((newWidth - newHeight) / 2, (newWidth - newHeight) / 2);
  g2.drawImage(oldImage, 0, 0, newHeight, newWidth, null);
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  ImageIO.write(image, "png", out);
  stdout = new ByteArrayInputStream(out.toByteArray());

    Hope these could help a little for this project.

RaiMan (raimund-hocke) said : #4

ok, I think I have fixed the problem.
Tested on my Nexus 7 (6.0.1) with 1200x1920.
In portrait mode I get a portrait image (1200x1920) and in landscape mode I now get a landscape image (1920x1200) showing up, as it is on the screen.

Everything (that works ;-) should now work as expected in both portrait and landscape (tested a click in both modes).

I will today start the 1.1.2 nightly builds (http://nightly.sikuli.de).
Watchout during the next 24 h.

Some tests and feedback would be appreciated.

dinev (ndinev) said : #5

Just wondering is there a sample for jython usage or any other documentation for Android screen

RaiMan (raimund-hocke) said : #6

@ dinev:
very basic yet only:
http://sikulix-2014.readthedocs.io/en/latest/screen.html#connecting-to-an-android-device-or-emulator-adbscreen

in Jython:
import org.sikuli.script.android.ADBScreen as ADB
as = ADB.start()
as.click("someimage")
...
as.stop()

In the IDE in menu Tools is an android entry.

dinev (ndinev) said : #7

I tried to run the script in SikuliIDE but got error when importing

[error] script [ adb_test ] stopped with error in line 1
[error] ImportError ( No module named android )

RaiMan (raimund-hocke) said : #8

@dinev
sorry, for only having tried to remember, but did not check - it must be:

import org.sikuli.android.ADBScreen as ADB

dinev (ndinev) said : #9

Thanks

I just unpacked jar file and found the location :-)

Seems that there is some sample in ide tools menu - where is the code for this?
Just wondering if there are more key constant specific for Android.

 I am trying to type Key.ENTER while entering text but seems I need Key.SEARCH :-)

Anyhow it works and have potential!

RaiMan (raimund-hocke) said : #10

The implementation is in the package org.sikuli.android (ADBDevice)

The implementation of the IDE Tool menu entry is in org.sikuli.android.ADBTest

... and there are aTap, aKey, aInput, aSwipe... implementations in section "Mobile actions (Android)" in
org.sikuli.script.Region

If you want to learn more about the implementation details, you have to look into the sources at
https://github.com/RaiMan/SikuliX-2014

RaiMan (raimund-hocke) said : #11

a nightly build of version 1.1.2 is now available, that contains the fix for portrait/landscape
http://nightly.sikuli.de/

Just use the download links and run setup.

Action (actionwind) said : #12

Hello, Sir
     I have tested it with this new version, and my phone's os is Android v4.4.4. It still not works when the screen is horizontal, but the error message is different now:
"
Exception in thread "main" FindFailed: imgs/wifi.png: (176x185) in ADBScreen: Android device: ECAXB7009447 (1280 x 720)
  Line 2757, in file Region.java

 at org.sikuli.script.Region.wait(Region.java:2757)
 at org.sikuli.script.Region.find(Region.java:2334)
 at org.sikuli.script.Region.getLocationFromTarget(Region.java:3211)
 at org.sikuli.script.Region.click(Region.java:3696)
 at org.sikuli.script.Region.click(Region.java:3681)
 at run.Test.main(Test.java:141)
"

    my code:
  ADBScreen a = new ADBScreen();
  a.click("imgs/wifi.png");

    And the same code and same "wifi.png" work fine when screen is vertical. "wifi.png" is taken from horizontal screen.

RaiMan (raimund-hocke) said : #13

Ok, seems I have to check again (not sure wether I tested the find operation :-(

Can you help with this problem?

Provide an answer of your own, or ask Action for more information if necessary.

To post a message you must log in.