How to compare screenshots to a reference image using appium - android

I am able to successfully take the screenshot one of the page of my application JainLibrary using below code. I am using junit and appium.
public String Screenshotpath = "Mention the folder Location";
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(Screenshotpath+"Any name".jpg"));
Now I want to compare the screenshot with a reference image so that I can move forward with the test case.

A simple solution would be to compare each pixel with the reference screenshoot:
// save the baseline screenshot
driver.get("https://www.google.co.uk/intl/en/about/");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\\temp\\screenshot.png"));
// take another screenshot and compare it to the baseline
driver.get("https://www.google.co.uk/intl/en/about/");
byte[] pngBytes = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
if (IsPngEquals(new File("c:\\temp\\screenshot.png"), pngBytes)) {
System.out.println("equals");
} else {
System.out.println("not equals");
}
public static boolean IsPngEquals(File pngFile, byte[] pngBytes) throws IOException {
BufferedImage imageA = ImageIO.read(pngFile);
ByteArrayInputStream inStreamB = new ByteArrayInputStream(pngBytes);
BufferedImage imageB = ImageIO.read(inStreamB);
inStreamB.close();
DataBufferByte dataBufferA = (DataBufferByte)imageA.getRaster().getDataBuffer();
DataBufferByte dataBufferB = (DataBufferByte)imageB.getRaster().getDataBuffer();
if (dataBufferA.getNumBanks() != dataBufferB.getNumBanks()) {
return false;
}
for (int bank = 0; bank < dataBufferA.getNumBanks(); bank++) {
if (!Arrays.equals(dataBufferA.getData(bank), dataBufferB.getData(bank))) {
return false;
}
}
return true;
}
Note that you need to save the reference screenshot as a PNG. A JPEG format will alter the pixels.

Related

ZXing BarcodeReader Don't Decode Some Barcodes

I am developing a barcode reader with Xamarin.Forms. And I'm trying to scan the image on Android device.
First I select the image from the gallery with Xamarin.Essentials MediaPicker and from the path of this image I get an RGBLuminance with the Dependency class.
Then I am trying to decode this RGBLuminance with the Decode() method of the ZXing BarcodeReaderGeneric class.
The application successfully decodes the barcodes in some images. However, sometimes it returns null when decoding. I might have made a mistake while converting the image to Bitmap or creating the RGBLuminanceSource.
I would like to find out how a class that can decode both color, black and white and grayscale images should be.
public RGBLuminanceSource GetRGBLuminanceSource(string imagePath)
{
if (File.Exists(imagePath))
{
Android.Graphics.Bitmap bitmap = BitmapFactory.DecodeFile(imagePath);
List<byte> rgbBytesList = new List<byte>();
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
var c = new Android.Graphics.Color(bitmap.GetPixel(x, y));
rgbBytesList.AddRange(new[] { c.A, c.R, c.G, c.B });
}
}
byte[] rgbBytes = rgbBytesList.ToArray();
return new RGBLuminanceSource(rgbBytes, bitmap.Width, bitmap.Height, RGBLuminanceSource.BitmapFormat.RGB32);
}
return null;
}
Command in the ViewModel class:
public ICommand PickCommand => new Command(PickImage);
private async void PickImage()
{
var pickResult = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Select a barcode."
});
var path = pickResult.FullPath;
var RGBLuminance = DependencyService.Get<ILuminance>().GetRGBLuminanceSource(path);
var reader = new BarcodeReaderGeneric();
var result = reader.Decode(RGBLuminance);
}
I am using this code in xamarin.android and i never had issues with it:
var scanner = new MobileBarcodeScanner();
var result = await scanner.Scan(_context, MobileBarcodeScanningOptions.Default);
It opens the camera, user takes a pic of barcode and result.Text contains the scanned barcode.

Multiple page print using iText pdf in landscape orientation

I have tried itextPdf_page_orientation but the problem is - only first page is proper rest all pages are printed in half area.
Here is an image which will help you understand the issue.
I have tried both setting the page size PdfPage.A4.rotate() and setting the event to PdfWritter.
Here is the code snipet.
#Override
protected String doInBackground(Void... params) {
final String PARENT_PATH =
Environment.getExternalStorageDirectory().getPath() + "/.GSTInvoice";
Document document = null;
try {
File file = new File(PARENT_PATH);
if (!file.exists()) {
file.mkdirs();
}
File pdfFile = new File(file, "last_sales_summary");
document = new Document();
document.setPageSize(PageSize.A4.rotate());
event = new RotateEvent();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
writer.setPageEvent(event);
document.open();
event.setOrientation(PdfPage.LANDSCAPE);
taxList = new ArrayList<>();
PdfContentByte cb = writer.getDirectContent();
printPage(document, writer, cb);
if (document != null && document.isOpen()) {
document.close();
}
return pdfFile.getPath();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document != null && document.isOpen()) {
document.close();
}
}
return null;
}
private void printPage(Document document, PdfWriter pdfWriter, PdfContentByte pdfContentByte) throws Exception{
int noOfPages = getNoOfPages();
BaseFont latoLight = BaseFont.createFont("assets/Lato-Light.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font light = new Font(latoLight, 8);
for (int i=1;i<=noOfPages;i++) {
if (i != 1) {
document.newPage();
pdfWriter.setPageSize(PageSize.A4.rotate());
event.setOrientation(PdfPage.LANDSCAPE);
document.setPageSize(PageSize.A4.rotate());
}
addTopPart(document);
addMiddleTable(document, i);
if (noOfPages>1) {
Paragraph paragraph = new Paragraph(new Phrase("Page " + i + "/" + noOfPages, light));
paragraph.setAlignment(Element.ALIGN_CENTER);
paragraph.setSpacingBefore(8f);
ColumnText.showTextAligned(pdfContentByte, Element.ALIGN_CENTER,
paragraph,
(document.right() - document.left()) / 2 + document.leftMargin(),
document.bottom() - 10, 0);
}
event.setOrientation(PdfPage.LANDSCAPE);
}
}
Any input will be appreciated
The only peculiarity of the PDF is that the first page has a page rotation of 0 while the second one has a page rotation of 90.
This is due to what I hinted at in my first comment: By doing event.setOrientation(PdfPage.LANDSCAPE) after document.open() the first page is not rotated by the event listener, only all following ones. Other than that all pages have a mediabox of a portrait A4 page with rotated, page-filling content.
As you indicate that changing the order of event.setOrientation and document.open does not change the behavior, the print manager in question seems to be buggy.
You might try to remove all event.setOrientation(PdfPage.LANDSCAPE) calls; this should result in all pages to become like the first one.
Or you might want to remove all that code setting and changing rotation and instead instantiate the Document document using new Document(new RectangleReadOnly(842,595)), i.e. without any rotation at all; as the print manager appears not to handle rotation properly, this might also result in a desired behavior.
As the OP reported in a comment,
your suggestion to use RectangleReadOnly(842,595) worked.

Get personal app code and display it

I am trying to get the app code and display it, for an example if button X starts a new activity then a textView displays the whole method
I reached only how can I display code in HTML format from this question
But is there is a way to get the code of my app out, I think that there are 2 ways
An Internal one by getting it by the app itself
An External one by reading the java file then filtering it and getting the text of the method
Is there are any ideas about that?
Thanks in advance
The above is not currently possible as mentioned by others is the comments. What i can suggest is shipping your application with the source code in the assets folder and using a helper function to extract a certain methods from the source at runtime (your second proposed approach). I have written example code but it is in pure java and needs to be ported to android (a few lines).
NB: You may need to reformat the code after extraction depending on your use case.
Hope it helps :)
The code for the helper method:
static String getTheCode(String classname ,String methodSignature ) throws FileNotFoundException {
//**********************A few lines of code below need changing when porting ***********//
// open file, your will be in the assets folder not in the home dir of user, don't forget the .java extension when porting
File file = new File(System.getProperty("user.home") +"/"+ classname +".java");
// get the source, you can use FileInputReader or some reader supported by android
Scanner scanner = new Scanner(file);
String source = "";
while(scanner.hasNext()) {
source += " "+ scanner.next();
}
//**********************The above code needs changing when porting **********//
// extract code using the method signature
methodSignature = methodSignature.trim();
source = source.trim();
//appending { to differentiate from argument as it can be matched also if in the same file
methodSignature = methodSignature+"{";
//making sure we find what we are looking for
methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "(");
methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")");
methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ",");
methodSignature = methodSignature.replaceAll("\\s+", " ");
source =source.replaceAll("\\s*[(]\\s*", "(");
source = source.replaceAll("\\s*[)]\\s*", ")");
source = source.replaceAll("\\s*[,]\\s*", ",");
source = source.replaceAll("\\s+", " ");
if(!source.contains(methodSignature)) return null;
// trimming all text b4 method signature
source = source.substring(source.indexOf(methodSignature));
//getting last index, a methods ends when there are matching pairs of these {}
int lastIndex = 0;
int rightBraceCount = 0;
int leftBraceCount = 0;
char [] remainingSource = source.toCharArray();
for (int i = 0; i < remainingSource.length ; i++
) {
if(remainingSource[i] == '}'){
rightBraceCount++;
if(rightBraceCount == leftBraceCount){
lastIndex = (i + 1);
break;
}
}else if(remainingSource[i] == '{'){
leftBraceCount++;
}
}
return source.substring(0 ,lastIndex);
}
Example usage (getTheCode methods is static and in a class called GetTheCode):
public static void main(String... s) throws FileNotFoundException {
System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut()"));
System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut(String word)"));
}
Output:
private static void shoutOut(){ // nothing to here }
private static void shoutOut(String word){ // nothing to here }
NB: When starting your new activity create a method eg
private void myStartActivty(){
Intent intent = new Intent(MyActivity.this, AnotherActivity.class);
startActivity(intent);
}
Then in your onClick:
#Override
public void onClick(View v) {
myStartActivity();
myTextView.setText(GetTheCode.getTheCode("MyActivity","private void myStartActivity()"));
}
Update: Ported the Code for android:
import android.content.Context;
import java.io.IOException;
import java.util.Scanner;
public class GetTheCode {
static String getTheCode(Context context, String classname , String methodSignature ) {
Scanner scanner = null;
String source = "";
try {
scanner = new Scanner(context.getAssets().open(classname+".java"));
while(scanner.hasNext()) {
source += " "+ scanner.next();
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
scanner.close();
// extract code using the method signature
methodSignature = methodSignature.trim();
source = source.trim();
//appending { to differentiate from argument as it can be matched also if in the same file
methodSignature = methodSignature+"{";
//making sure we find what we are looking for
methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "(");
methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")");
methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ",");
methodSignature = methodSignature.replaceAll("\\s+", " ");
source =source.replaceAll("\\s*[(]\\s*", "(");
source = source.replaceAll("\\s*[)]\\s*", ")");
source = source.replaceAll("\\s*[,]\\s*", ",");
source = source.replaceAll("\\s+", " ");
if(!source.contains(methodSignature)) return null;
// trimming all text b4 method signature
source = source.substring(source.indexOf(methodSignature));
//getting last index, a methods ends when there are matching pairs of these {}
int lastIndex = 0;
int rightBraceCount = 0;
int leftBraceCount = 0;
char [] remainingSource = source.toCharArray();
for (int i = 0; i < remainingSource.length ; i++
) {
if(remainingSource[i] == '}'){
rightBraceCount++;
if(rightBraceCount == leftBraceCount){
lastIndex = (i + 1);
break;
}
}else if(remainingSource[i] == '{'){
leftBraceCount++;
}
}
return source.substring(0,lastIndex);
}
}
Usage:
// the method now takes in context as the first parameter, the line below was in an Activity
Log.d("tag",GetTheCode.getTheCode(this,"MapsActivity","protected void onCreate(Bundle savedInstanceState)"));
Let's start with a broader overview of the problem:
Display App code
Press X button
Open new activity with a textview which displays the method
The goal is to do the following:
Viewing app method by extracting it and then building & running it.
There are some methods we can use to run Java/Android code dynamically. The way I would personally do it is DexClassLoader and with Reflection.
If you need more details, let me know. Here is what it'd do though:
View app method
Upon pressing X, launch intent with extra to new Activity
Parse and compile code dynamically and then run it with DexClassLoader and Reflection
Sources:
Sample file loading Java method from TerminalIDE Android App
Android Library I made for Auto-Updating Android Applications without needing the Play Store on non-root devices

Compare 2 images appium [duplicate]

I am able to successfully take the screenshot one of the page of my application JainLibrary using below code. I am using junit and appium.
public String Screenshotpath = "Mention the folder Location";
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(Screenshotpath+"Any name".jpg"));
Now I want to compare the screenshot with a reference image so that I can move forward with the test case.
A simple solution would be to compare each pixel with the reference screenshoot:
// save the baseline screenshot
driver.get("https://www.google.co.uk/intl/en/about/");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\\temp\\screenshot.png"));
// take another screenshot and compare it to the baseline
driver.get("https://www.google.co.uk/intl/en/about/");
byte[] pngBytes = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
if (IsPngEquals(new File("c:\\temp\\screenshot.png"), pngBytes)) {
System.out.println("equals");
} else {
System.out.println("not equals");
}
public static boolean IsPngEquals(File pngFile, byte[] pngBytes) throws IOException {
BufferedImage imageA = ImageIO.read(pngFile);
ByteArrayInputStream inStreamB = new ByteArrayInputStream(pngBytes);
BufferedImage imageB = ImageIO.read(inStreamB);
inStreamB.close();
DataBufferByte dataBufferA = (DataBufferByte)imageA.getRaster().getDataBuffer();
DataBufferByte dataBufferB = (DataBufferByte)imageB.getRaster().getDataBuffer();
if (dataBufferA.getNumBanks() != dataBufferB.getNumBanks()) {
return false;
}
for (int bank = 0; bank < dataBufferA.getNumBanks(); bank++) {
if (!Arrays.equals(dataBufferA.getData(bank), dataBufferB.getData(bank))) {
return false;
}
}
return true;
}
Note that you need to save the reference screenshot as a PNG. A JPEG format will alter the pixels.

Read random files from assets on Android

Hello I'm having problem reading random files on Eclipse, Android programming...
At assets folders I have a folder called "fytyra" and there are jpg pictures with mumbers like 1.jpg 2.jpg...
I tried to debug the app, list was null always.. ???
//Gets a random number from 0 to 431,.. I think it is !
private int nasiqim (){
int i = 0;
Random nasiqimi = new Random();
i=nasiqimi.nextInt(431);
return i;
}
//This need to fill list with integers and to not repeat the same number...
private void listaEFotove(){
int nse=-1,i=0,numriRandom;
while (nse<0){
numriRandom = nasiqim();
nse = Arrays.binarySearch(numrat, numriRandom);
if (nse <0 ){
numrat[i] = numriRandom;
i++;
}
if (i == 11)break;
}
}
This is to fill imageView with photos...
private void merrFytyrat(){
int fotoNr=0;
String emri;
listaEFotove();
for (int i=0; i<11;i++){
fotoNr=numrat[i];
if (i==0){
try
{
emri = Integer.toString(fotoNr);
// get input stream
InputStream ims = getAssets().open( "fytyra/" + emri +".jpg");
// load image as Drawable
Drawable d = Drawable.createFromStream(ims, null);
// set image to ImageView
i11.setImageDrawable(d);
}
catch(IOException ex)
{
return;
};
}
else if (i==1){ ... Continues until 12...
I got the answer, thank you greenapps, for trying to help mee...
My mistake was on declaration of array... so my new code is this :
int[] numrat = new int[12];
it was like this :
int[] numrat = null;
another mistake was on the getAssets, like greenapps told me
getAssets().open( "/fytyra/" + emri +".jpg");
now thanks to him i changed that code to :
getAssets().open( "fytyra/" + emri +".jpg");
No everything works perfect,.,
This site is the best, Thank you...

Categories

Resources