Capturing Android screenshot with appium - java

I currently have something working to capture screenshots on iOS for appium tests using java and junit. Before a test finishes it runs this code to get the last visible thing on the screen before killing the connection
#After
public void tearDown() throws Exception {
if (platform.equals(iOS)) {
captureScreenshot(testName.getMethodName());
}
driver.quit();
}
#SuppressWarnings("Augmenter")
public void captureScreenshot(String testName) {
String imagesLocation = "target/surefire-reports/screenshot/" + platform + "/";
new File(imagesLocation).mkdirs(); // Insure directory is there
String filename = imagesLocation + testName + ".jpg";
try {
Thread.sleep(500);
WebDriver augmentedDriver = new Augmenter().augment(driver);
File scrFile = ((TakesScreenshot)augmentedDriver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(filename), true);
} catch (Exception e) {
System.out.println("Error capturing screen shot of " + testName + " test failure.");
// remove old pic to prevent wrong assumptions
File f = new File(filename);
f.delete(); // don't really care if this doesn't succeed, but would like it to.
}
}
This sorta works for android but lately it has completely killed the running test but this might have to do with the device it is trying to get the snapshot of. Before it would save the file but the image would come up blank or broken.
Anyone know how to get image/screen capturing working on android using appium? Perhaps something with UIAutomator?

You can use this method:
public void screenshot(String path_screenshot) throws IOException{
File srcFile=driver.getScreenshotAs(OutputType.FILE);
String filename=UUID.randomUUID().toString();
File targetFile=new File(path_screenshot + filename +".jpg");
FileUtils.copyFile(srcFile,targetFile);
}
It works fine for me.

I happened to find this via Google search with nearly the same problem - Appium screenshots in the Android emulator come up blank. I'm using both the 'native' method much like you describe above - and - the method within the ATU framework.
WebElement appArea = wd.findElementByXPath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]");
ATUReports.add("Main Screen Area Screenshot", LogAs.INFO, new CaptureScreen(appArea));
and both come back blank/transparent. The marginally good news is that the dimension of that blank/transparent image is exactly the size I want to capture - avoiding the status bar where date diffs would cause error on image comparison. That said, it's not much use without actual viewable pixels (for eventual matching of object area grabs to validated baseline images).
I tried setting context to "NATIVE_APP" and nothing seems to help. I am - in a word - vexed. If you've made any progress with this I'd love to read/hear how you got it working. Maybe the next step is to go to the Appium Google Group.
EDIT: I found the core issue in my case - using HAXM acceleration causes the blank screen shots. Note this also affects test run on physical devices if the base device profile set in the test's capabilities is defined with "Host GPU" selected.

Related

Appium XCUITest iOSDriver sendkeys() not working

TLDR:
sendKeys() not working in web application text field, but only with IOSDriver/XCUITest and only on my web app's page. When running the same test in an Android simulator it works fine on my page, and everywhere else that I've tested (google and ask.com search inputs), but when I test in an iOS simulator, sendKeys() does not work on my web app's page, but works everywhere else (google and ask.com) and I have no idea why.
Capabilities config file:
["Safari", "12.2", "iOS", "iPhone Simulator", "XCUITest", "1.12.1"]
The test:
public class AppiumFieldsTest extends TestBase {
#Test(dataProvider = "appium", groups = "Appium", description = "appium fields test")
public void appiumFieldsTest(String browser, String version, String platform, String device, Method method, String automationName, String appiumVersion) throws Exception {
IOSDriver<WebElement> driver;
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, platform);
caps.setCapability(MobileCapabilityType.PLATFORM_VERSION, version);
caps.setCapability(MobileCapabilityType.DEVICE_NAME, device);
caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, automationName);
caps.setCapability(MobileCapabilityType.BROWSER_NAME, browser);
caps.setCapability("autoAcceptAlerts", true);
caps.setCapability("connectHardwareKeyboard", false);
caps.setCapability("sendKeyStrategy", "oneByOne");
System.out.println(caps);
String url = "http://127.0.0.1:4723/wd/hub";
driver = new IOSDriver(new URL(url), caps);
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
driver.get("https://dev-app.pactsafe.com/sign?r=5cd32b47e89fc12f110449ca&s=5b2a6a597a7a3c1e4fa39c0b&signature=kto0Xohrz52ss7kc5z6t0grRbzUPsg6TrfbCbKtRuC5nQM82lNEhFL-zPgN7LaTvGG8mhuifNSc0nayvch1Rgc858Ptx8yRRD9MWJSoD4mEuHFg7LmJ-FHP~UsVEypv-gwwy-6N14BnhdkN94OZ73Kq9mBfS8QGlYKTqa76uclW0FIdnclRfA8NvK0z8CxjPcA8Luv9orw6Ye7wEuHAGqhqFURa15WeFrjrFKW9PNf6NkLVURNvOwqH4xBsfJubCkETMfjtnD4xT7PFSpgykAuU-Av0HehxCFNCYaHmyj5qvB3l9h7xgm8KKoSOO0c9VH1HpnLtwG6KAwwItawcsjg__");
String textFieldtext = "some random text";
Thread.sleep(10000);
WebElement ele = driver.findElementByXPath("//*[#data-name=\"field-5b6305f656bcff936a3c53ca\"]");
ele.click();
Thread.sleep(3000);
ele.sendKeys(textFieldtext);
Assert.assertEquals(ele.getAttribute("data-value"), textFieldtext);
...
...
...
I am trying to do a .click() then a .sendKeys() on the first field at the top of the page, but it is not sending any text. If you run the test you can see that the field is actually being clicked, as it turns a darker blue color, as expected, but then then the sendKeys() function does nothing. Also, when testing on Android, the keyboard opens on click() but not on iOS.
I've tried all the different sendKeyStratey capabilities and still nothing.
I've tried different iOS simulators and appium/safari versions, and still get the same results.
I've tried setting the connectHardwareKeyboard to true, as well as false, and still the same results.
I've added Thread.sleep() in-between commands - nuthin
And again, testing on android works fine on my app, google and ask, but when testing on iOS, my app does not work, but google and ask do
The appium logs show that it is indeed trying to send the text after successfully finding the element:
[HTTP] {"id":"5000","text":"some random text","value":["s","o","m","e"," ","r","a","n","d","o","m"," ","t","e","x","t"]}
[W3C (bf5882ff)] Calling AppiumDriver.setValue() with args: [["s","o","m","e"," ","r","a","n","d","o","m"," ","t","e","x","t"],"5000","bf5882ff-f1a1-4ce1-bb79-02836762cb88"]
[XCUITest] Executing command 'setValue'
Any and all help/suggestions are greatly appreciated
You can try using one of these options:
setValue() This clears the value before sending the string.
Add maxTypingFrequency capability, this is ONLY for IOS when you notice errors during typing, for example the wrong keys being pressed or visual oddities you notice while watching a test, try slowing the typing down. Set this cap to an integer and play around with the value until things work. Lower is slower, higher is faster! The default is 60.

Maximize browser window in LeanFT

I am looking for some solution, like this in Selenium WebDriver:
ChromeOptions options = new ChromeOptions();options.addArgument("--start-maximized");
So browser window should be maximized when test is executed.
I found a profile based solution for this problem, but it opens a lot of tabs, which is maybe caused by escape characters.
#Test
public void chromeWithProfileLaunch() throws Exception {
String profileDir = "--user-data-dir=\"c:\\Temp\\profile1\""; //should be different folder every time
String leanftChromeExtension = "--load-extension=C:\\Program Files (x86)\\HPE\\LeanFT\\Installations\\Chrome\\Extension"; //to load the LeanFT extension
String homePage = "www.google.com"; //the homepage to start with
new ProcessBuilder("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", profileDir, leanftChromeExtension, homePage)
.start();
Thread.sleep(2000); //wait for Chrome process to load
Browser openedBrowser = BrowserFactory.attach(new BrowserDescription.Builder().title("Google").type(BrowserType.CHROME).build());
Verify.areEqual(homePage, openedBrowser.getURL());
}
I don't know about maximized but LeanFT supports putting the browser in fullScreen mode.
LeanFT doesn't support maximize() out of the box yet.
However, you could use sendKeys() method.
I'm not entirely sure if you can to it on the browser instance directly, or you need to getPage() first, but you can definitelly send Super key (win key) + ↑ as specified here. ↓ for restoring back to the initial state.
Here's an example using sendKeys with Java SDK if you need it.

Java Selenium Web Scraping Upload Image [duplicate]

I have seen lots of questions and solutions on File upload using Selenium WebDriver on Stack Overflow. But none of them are working for following scenario.
Someone has given a solution as following
// assuming driver is a healthy WebDriver instance
WebElement fileInput = driver.findElement(By.name("uploadfile"));
fileInput.sendKeys("C:/path/to/file.jpg");
But still I can't find window handle. How can I work on that?
I am looking for a solution for the scenario above.
Please check this on any of the following websites.
http://www.uploadify.com/demos/
http://www.zamzar.com/
// assuming driver is a healthy WebDriver instance
WebElement fileInput = driver.findElement(By.name("uploadfile"));
fileInput.sendKeys("C:/path/to/file.jpg");
Hey, that's mine from somewhere :).
In case of the Zamzar web, it should work perfectly. You don't click the element. You just type the path into it. To be concrete, this should be absolutely ok:
driver.findElement(By.id("inputFile")).sendKeys("C:/path/to/file.jpg");
In the case of the Uploadify web, you're in a pickle, since the upload thing is no input, but a Flash object. There's no API for WebDriver that would allow you to work with browser dialogs (or Flash objects).
So after you click the Flash element, there'll be a window popping up that you'll have no control over. In the browsers and operating systems I know, you can pretty much assume that after the window has been opened, the cursor is in the File name input. Please, make sure this assumption is true in your case, too.
If not, you could try to jump to it by pressing Alt + N, at least on Windows...
If yes, you can "blindly" type the path into it using the Robot class. In your case, that would be something in the way of:
driver.findElement(By.id("SWFUpload_0")).click();
Robot r = new Robot();
r.keyPress(KeyEvent.VK_C); // C
r.keyRelease(KeyEvent.VK_C);
r.keyPress(KeyEvent.VK_COLON); // : (colon)
r.keyRelease(KeyEvent.VK_COLON);
r.keyPress(KeyEvent.VK_SLASH); // / (slash)
r.keyRelease(KeyEvent.VK_SLASH);
// etc. for the whole file path
r.keyPress(KeyEvent.VK_ENTER); // confirm by pressing Enter in the end
r.keyRelease(KeyEvent.VK_ENTER);
It sucks, but it should work. Note that you might need these: How can I make Robot type a `:`? and Convert String to KeyEvents (plus there is the new and shiny KeyEvent#getExtendedKeyCodeForChar() which does similar work, but is available only from JDK7).
For Flash, the only alternative I know (from this discussion) is to use the dark technique:
First, you modify the source code of you the flash application, exposing
internal methods using the ActionScript's ExternalInterface API.
Once exposed, these methods will be callable by JavaScript in the browser.
Second, now that JavaScript can call internal methods in your flash app,
you use WebDriver to make a JavaScript call in the web page, which will
then call into your flash app.
This technique is explained further in the docs of the flash-selenium project.
(http://code.google.com/p/flash-selenium/), but the idea behind the technique
applies just as well to WebDriver.
Below code works for me :
public void test() {
WebDriver driver = new FirefoxDriver();
driver.get("http://www.freepdfconvert.com/pdf-word");
driver.findElement(By.id("clientUpload")).click();
driver.switchTo()
.activeElement()
.sendKeys(
"/home/likewise-open/GLOBAL/123/Documents/filename.txt");
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.findElement(By.id("convertButton"));
Using C# and Selenium this code here works for me, NOTE you will want to use a parameter to swap out "localhost" in the FindWindow call for your particular server if it is not localhost and tracking which is the newest dialog open if there is more than one dialog hanging around, but this should get you started:
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OpenQA.Selenium;
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public static void UploadFile(this IWebDriver webDriver, string fileName)
{
webDriver.FindElement(By.Id("SWFUpload_0")).Click();
var dialogHWnd = FindWindow(null, "Select file(s) to upload by localhost");
var setFocus = SetForegroundWindow(dialogHWnd);
if (setFocus)
{
Thread.Sleep(500);
SendKeys.SendWait(fileName);
SendKeys.SendWait("{ENTER}");
}
}
I made use of sendkeys in shell scripting using a vbsscript file. Below is the code in vbs file,
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.SendKeys "C:\Demo.txt"
WshShell.SendKeys "{ENTER}"
Below is the selenium code line to run this vbs file,
driver.findElement(By.id("uploadname1")).click();
Thread.sleep(1000);
Runtime.getRuntime().exec( "wscript C:/script.vbs" );
Find the element (must be an input element with type="file" attribute) and send the path to the file.
WebElement fileInput = driver.findElement(By.id("uploadFile"));
fileInput.sendKeys("/path/to/file.jpg");
NOTE: If you're using a RemoteWebDriver, you will also have to set a file detector. The default is UselessFileDetector
WebElement fileInput = driver.findElement(By.id("uploadFile"));
driver.setFileDetector(new LocalFileDetector());
fileInput.sendKeys("/path/to/file.jpg");
There is a simpler way to solve this then what Slanec described. Hes solution works when you are using an English keyboard, if not you will have a hard time trying to "map" the key for special characters.
Instead of robot.keyPress and robot.keyRelease every single key you can use Toolkit to copy the String to the clipboard and then paste it.
StringSelection s = new StringSelection("Path to the file");
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(s, null);
Robot robot = new Robot();
robot.keyPress(java.awt.event.KeyEvent.VK_ENTER);
robot.keyRelease(java.awt.event.KeyEvent.VK_ENTER);
robot.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
robot.keyPress(java.awt.event.KeyEvent.VK_V);
robot.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
Thread.sleep(3000);
robot.keyPress(java.awt.event.KeyEvent.VK_ENTER);
First add the file to your project resource directory
then
public YourPage uploadFileBtnSendKeys() {
final ClassLoader classLoader = getClass().getClassLoader();
final File file = new File(classLoader.getResource("yourFile.whatever").getPath());
uploadFileBtn.sendKeys(file.getPath());
return this;
}
Walla, you will see your choosen selected file, and have skipped the file explorer window
Import System.Windows.Forms binary to the test solution and call the following two LOC on clicking the Upload button on the UI.
// Send the file path and enter file path and wait.
System.Windows.Forms.SendKeys.SendWait("complete path of the file");
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
An alternative solution would be to write a script to automate the Open File dialog. See AutoIt.
Also, if you can't "click" the element, my workaround is generally to do this:
element.SendKeys(Keys.Enter);
Hope this helps (Even though it's an old post)
Below code works for me:
// wait for the window to appear
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.alertIsPresent());
// switch to the file upload window
Alert alert = driver.switchTo().alert();
// enter the filename
alert.sendKeys(fileName);
// hit enter
Robot r = new Robot();
r.keyPress(KeyEvent.VK_ENTER);
r.keyRelease(KeyEvent.VK_ENTER);
// switch back
driver.switchTo().activeElement();
You have put double slash \\ for the entire absolute path to achieve this
Example:- D:\\images\\Lighthouse.jpg
Steps
- use sendkeys for the button having browse option(The button which will open
your window box to select files)
- Now click on the button which is going to upload you file
driver.findElement(By.xpath("//input[#id='files']")).sendKeys("D:\\images\\Lighthouse.jpg");
Thread.sleep(5000);
driver.findElement(By.xpath("//button[#id='Upload']")).click();
Use AutoIt Script To Handle File Upload In Selenium Webdriver. It's working fine for the above scenario.
Runtime.getRuntime().exec("E:\\AutoIT\\FileUpload.exe");
Please use below link for further assistance:
http://www.guru99.com/use-autoit-selenium.html
webDriver.FindElement(By.CssSelector("--cssSelector--")).Click();
webDriver.SwitchTo().ActiveElement().SendKeys(fileName);
worked well for me. Taking another approach provided in answer above by Matt in C# .net could also work with Class name #32770 for upload box.
The below one had worked for me
webDriver.findElement(By.xpath("//input[#type='file' and #name='importFile']")).sendKeys("C:/path/to/file.jpg");
Double the backslashes in the path, like this:
driver.findElement(browsebutton).sendKeys("C:\\Users\\Desktop\\Training\\Training.jpg");

AssetManager - which one to use

Both versions work but I am not sure which one to use and why to use that version? Do you need to dispose the TextureAtlas if you unload the assets already?
Version 1: Load the pack file (TexturePacker file with positions data) along with the png.
gameSpriteSheet = new TextureAtlas(Gdx.files.internal(DATA_DIR_PATH + "GameSpritesPack.txt"));
assetManager.load(DATA_DIR_PATH + "GameSpritesPack.txt");
assetManager.load(DATA_DIR_PATH + "GameSpritesPack.png");
// Call only if assetmanager's update method returns true
headerRegion = getTexture("MainMenuHeader", gameSpriteSheet);
To unload:
if (assetManager.isLoaded(DATA_DIR_PATH + "GameSpritesPack.txt")) {
assetManager.unload(DATA_DIR_PATH + "GameSpritesPack.txt");
}
if (assetManager.isLoaded(DATA_DIR_PATH + "GameSpritesPack.png")) {
assetManager.unload(DATA_DIR_PATH + "GameSpritesPack.png");
}
if(gameSpriteSheet != null) {
gameSpriteSheet.dispose();
}
Version 2: Load only the pack file (TexturePacker file with positions data).
assetManager.load(DATA_DIR_PATH + "GameSpritesPack.txt");
// Call only if assetmanager's update method returns true
gameSpriteSheet = assetManager.get(DATA_DIR_PATH + "GameSpritesPack.txt", TextureAtlas.class);
headerRegion = getTexture("MainMenuHeader", gameSpriteSheet);
To unload:
if (assetManager.isLoaded(DATA_DIR_PATH + "GameSpritesPack.txt")) {
assetManager.unload(DATA_DIR_PATH + "GameSpritesPack.txt");
}
if(gameSpriteSheet != null) {
gameSpriteSheet.dispose();
}
Note: I have read Mario's post on AssetManager and other blogs on that but I don't seem to get why the both versions above work fine.
The AssetManager is for loading assets "in the background". The first version you listed just loads the atlas synchronously in the current thread. Its not actually using the AssetManager at all. This is fine and will work, the downside is that if your atlas is large (or you have a lot of them that you're doing this for), your app will "hang" for a moment while:
gameSpriteSheet = new TextureAtlas(Gdx.files.internal(DATA_DIR_PATH + "GameSpritesPack.txt"));
runs. You could delete the two assetManager lines in your first example, as they're not doing anything (useful) in this case.
The second version is a "correct" usage of the AssetManager. Basically you're asking the asset manager to run the code you used in the first version ( ... new TextureAtlas(...)) on a background thread. You must wait until that background thread completes (i.e., update() returns true). The idea is that you can do other stuff on the render thread in the foreground (i.e., animate pretty patterns on the screen to distract the user while you load up game assets) while periodically checking if the loading is complete.

Capturing video from multiple usb cams and showing in a UI side by side using JAVA + Java applet

I have to make 2 applets which will run in a TOMCAT like server and when I access the webpage[HTML page] at a client side, I have 2 cameras attached to that client PC and I want to show the videos from both cameras on the 2 web pages at the client side at the same time.
I have tried using JMF. Out put is
It doesnt work simultaneously for both cameras in most machines. It works for one camera capture at a time
It works on some machines, but you have to select the cameras everytime you open the web pages. Select camera 1 for the first applet and camera 2 for the second applet.
Is there a way with/without JMF that I can open 2 webpages on one client PC with 2 applets for the same running on a remote server and show the videos from each USBCAM on each page?
I have used this while working with JMF.
private void StartStreaming()
{
String mediaFile = "vfw:Micrsoft WDM Image Capture (Win32):0";
try
{
MediaLocator mlr = new MediaLocator(mediaFile);
_player = Manager.createRealizedPlayer(mlr);
if (_player.getVisualComponent() != null)
{
setSize(480, 320);
jpnVideoStream.add("South", _player.getVisualComponent());
}
}
catch (Exception e)
{
System.err.println("Got exception " + e);
}
_player.start();
}
This is what is present in my both applets. But as I said, most of the times, it starts one CAM and then gives the device is in use and cannot capture message.
Please suggest any solution.
The Problem is that you are trying to use the same webcam in both the applets.
Instead use :
String mediaFile = "webcam 1" in applet 1
String mediaFile = "webcam 2" in applet 2
Your first webcam is : vfw:Micrsoft WDM Image Capture (Win32):0
You can check your second webcam by :using JMStudio.
select File->Preferences->Capture Devices and then click on Detect Capture devices.
This can also be done using code but the above one is simpler. Still I m listing the code :
Vector list = CaptureDeviceManager.getDeviceList(null);
int i;
CaptureDeviceInfo tempDevice;
// List all the devices ...
if( list!=null) {
if( list.size() == 0)
{
System.out.println("the device list is zero : ");
System.exit(1);
}
System.out.println("The devices are : ");
for( i=0;i< list.size() ;i++ ) {
tempDevice = (CaptureDeviceInfo) list.elementAt(i);
System.out.println(tempDevice.getName());
}
}
NOTE : Try Running the code as admin if it dosent work.
If I recall correctly then in your code (JMF implementation), there should be list/array of devices (resources) java is trying to read the data (webcam stream) from. My guess would be, that you need to change code in such a way that if resource one is busy, then try to read from resource two. Essentially you are going over entire list of resources trying to read whatever is available to you.
Hope that helps.
It may work with JavaCV http://code.google.com/p/javacv/

Categories