Not able to find element in pop up in appium - android

In my app profile I want to select Religion, so when I am clicking on Religion one pop up is opening and I have to choose one element from there,
Only "Index" and "text" values are different for each element, "Id" same for all element.
But while taking "xpath" using "text" and "index" values, not getting the element.
I am using scroll to method also but not getting the element.
Thanks in advance.

You can click by using click method:
driver.findElementByName("your religion name").click();
and scroll by using this method:
public void keepScrollingUntilElementFound(String name) {
for (int i = 0; i < 10; i++) {
if (isElementPresent("name=" + name)) {
break;
} else {
scrollDown();
scrollDown();
}
}
}
public void scrollDown() {
Dimension size = driver.manage().window().getSize();
int x = size.width / 2;
int starty = (int) (size.height * 0.60);
int endy = (int) (size.height * 0.10);
driver.swipe(x, starty, x, endy, 2000);
}
public boolean isElementPresent(String name) {
try {
driver.findElementByName(name);
return true;
} catch (Exception e) {
return false;
}
}

get all the index and its corresponding religions and click by index number
List<WebElement> ls = driver.findElementsById("android:id/numberpicker_input");
System.out.println("no of religions" + ls.size());
ls.get(0).click

Related

How to move to element and press on in mob app

How to move to element, that not visible on the screen using xpath and then click on it in mobile app?
This element located in the bottom, so need to swipe up.
Here is a small example of scroll and click :
public void scrollDown() {
Dimension size = driver.manage().window().getSize();
int startHeight = (int) (size.height * 0.5);
int startWidth = (int) (size.width * 0.5);
int endHeight = (int) (size.height * 0.25);
int endWidth = (int) (size.width * 0.5);
new TouchAction(driver).press(PointOption.point(startWidth, startHeight)).waitAction().moveTo(PointOption.point(endWidth, endHeight)).release().perform();
}
public void scrollUntilElementIsVisible(WebElement element) {
try {
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
boolean flag = element.isDisplayed();
while (!flag) {
scrollDown();
}
element.click();
} catch (NoSuchElementException e) {
System.out.println(e.toString());
} finally {
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
}
}
You need to use findElementByAndroidUIAutomator method. It scrolls to your particular element and when it finds it, you can call click() on this element:
driver.findElementByAndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text(\"" + Element_text + "\").instance(0))");
driver.findElementByAndroidUIAutomator("new UiSelector().text(\"Element_text\")").click();
I did it with:
TouchAction ta = new TouchAction(driver);
ta.press(button).moveTo(x, y).release().perform();

How to detect touch move over a large number of views?

My Requirement : I need to animate a 7*16 LED Display by passing frames through the Android App over BluetoothLE. I have created the design of the display on the app and added empty views with gradient drawable background to them. The colour of these views need to change when my touch moves into them. Adding a touch listener to each view isn't going to help in my case.
What I have achieved : I have a large number of views (100+) added programmatically with a tag set to each of them. I have set an OnTouch Event Handler for the parent view in which these views have been added.
By tracking the absolute coordinates of the touch event (x and y) and comparing with the absolute bounds of a few individual views that I am looping in the touch event handler, I am able to detect hover like touch move (out of bounds to in bounds) over 3-4 views properly.
I have referred the solution from https://stackoverflow.com/a/21903640
Where I am stuck : However, when I try to increase the loop size to cover all the added views, the app response slows down and hover detection fails on most of the views. I know this is happening because of heavy computation in the OnTouch Event Handler which I am not supposed to do.
What I need : I need an improvement on this solution in terms of performance or an alternative way to go about reaching my goal.
Code Snippet
void DrawScreen()
{
for (int column = 0; column < 8; column++)
{
for (int row = 0; row < 17; row++)
{
relativeLayout.AddView(DrawRect(row, column));
}
}
}
View DrawRect(int row, int column)
{
View customView = new View(Context);
GradientDrawable shape = new GradientDrawable();
shape.SetShape(ShapeType.Rectangle);
shape.SetCornerRadii(new float[] { 10, 10, 10, 10, 10, 10, 10, 10 });
shape.SetColor(Color.ParseColor("#3F0000"));
RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
param.LeftMargin = ((column-1) * (width + h_spacing)) + h_spacing;
param.Width = width;
param.Height = height;
param.TopMargin = ((row-1) * (height + v_spacing)) + v_spacing;
customView.Background = shape;
customView.LayoutParameters = param;
customView.Tag = (8 - column).ToString() + "," + (17 - row).ToString();
return customView;
}
private void RelativeLayout_Touch(object sender, View.TouchEventArgs e)
{
if(e.Event.Action == MotionEventActions.Up)
{
out_of_bounds = true;
view_in_bound = null;
}
else
{
for (int row = 1; row < 8; row++)
{
for (int column = 1; column < 17; column++)
{
View view = relativeLayout.FindViewWithTag(row.ToString() + "," + column.ToString());
if (CheckInterSection(view, e.Event.RawX, e.Event.RawY))
{
if (out_of_bounds == true)
{
view_in_bound = view;
out_of_bounds = false;
Log.Debug("Touch", "Inside");
//ToggleViewState(view);
}
else
{
Log.Debug("Touch", "Still Inside");
}
}
else
{
if (view == view_in_bound)
{
out_of_bounds = true;
view_in_bound = null;
Log.Debug("Touch", "Outside");
}
}
}
}
}
}
bool CheckInterSection(View view, float rawX, float rawY)
{
int[] location = new int[2];
view.GetLocationOnScreen(location);
int x = location[0] - h_spacing/2;
int y = location[1] - v_spacing/2;
int width = (view.Width + h_spacing/2);
int height = (view.Height + v_spacing/2);
return (!(rawX < x || rawX > (x + width) || rawY < y || rawY > (y + height)));
}
I tried to use trajectory angles to further reduce the loop size but the performance was never up to my expectations and touch events over views were getting missed regularly.
Then I realized that I was going in the wrong direction and found a much simpler solution. Since my views were being added programmatically and were of same size, I knew the coordinates and bounds of each view in the layout. So I divided the layout into a grid and depending upon the touch coordinates, I was able to identify over which section the touch was on. Below is my solution which has been working perfectly. However, I will wait a while till I mark this as a solution since someone could have a better implementation of my technique or an alternative solution.
void DrawScreen()
{
for (int column = 1; column < 17; column++)
{
for (int row = 1; row < 8; row++)
{
relativeLayout.AddView(DrawRect(row, column));
}
}
}
View DrawRect(int row, int column)
{
View customView = new View(Context);
if (!CheckBit(row - 1, column - 1))
{
customView.SetBackgroundResource(Resource.Drawable.off_rounded_btn);
}
else
{
customView.SetBackgroundResource(Resource.Drawable.rounded_btn);
}
RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
param.LeftMargin = ((column-1) * (width + h_spacing)) + h_spacing;
param.Width = width;
param.Height = height;
param.TopMargin = ((row-1) * (height + v_spacing)) + v_spacing;
customView.LayoutParameters = param;
customView.Tag = row.ToString() + "," + column.ToString();
return customView;
}
void RelativeLayout_Touch(object sender, View.TouchEventArgs e)
{
if (e.Event.Action == MotionEventActions.Up)
{
view_in_bound = null;
}
else
{
int row = CheckTouchArea(e.Event.RawX, e.Event.RawY)[0];
if (row != 0)
{
int column = CheckTouchArea(e.Event.RawX, e.Event.RawY)[1];
check_view = GetView(row, column);
if (check_view != view_in_bound)
{
ChangeViewState(check_view, Touch_CheckBit(row - 1, column - 1), row - 1, column - 1);
view_in_bound = check_view;
}
}
}
}
int[] CheckTouchArea(float rawX, float rawY)
{
int[] tag = new int[2];
int[] location = new int[2];
relativeLayout.GetLocationOnScreen(location);
float x = location[0] + h_padding / 2;
int y = location[1] + v_padding / 2;
float width = relativeLayout.Width - h_padding;
int height = relativeLayout.Height - v_padding;
if ((!(rawX < x || rawX > (x + width) || rawY < y || rawY > (y + height))))
{
int column = (int)Math.Ceiling((rawX - x) * 16 / width);
int row = (int)(Math.Ceiling((rawY - y) * 7 / height));
tag[0] = row;
tag[1] = column;
}
return tag;
}

Arithmetic Operation

hello guys I am having this problem. When I enter a score in the editText, I want the app to generate the equivalent in the Textview(w/ red box). But the app crashes with this code.
private void calculateEquivalent(){
double x , y;
y = Double.valueOf(total_score.toString());
x = Double.valueOf(editScore.getText().toString());
if (x >= y * 0.65){
double equivalent = (Math.round((100 + (72 * (x - y)) / y)));
String equi = String.valueOf(equivalent);
textEquivalent.setText(equi);
} else {
double equivalent = (Math.round((75 + (23 * (x - y * 0.65)) / y)));
String equi = String.valueOf(equivalent);
textEquivalent.setText(equi);
}
}
The error is empty string when convert from string to double
In this code
y = Double.valueOf(total_score.toString());
x = Double.valueOf(editScore.getText().toString());
May be total_score.toString() or editScore.getText().toString() was empty
And what is type of total_score variable
You have a problem when trying to convert empty string to a double. You should check first that the text field is not empty and that it doesn't contain characters by catching NumberFormatException
As the error log suggests, you need to make sure that you have proper values before you start the calculation.
So before calling this function you need to check for below conditions:
try
{
if((total_score.toString() != null && !total_score.toString().isEmpty()) && (editScore.getText().toString()!=null && !editScore.getText().toString().isEmpty()))
{
y = Double.valueOf(total_score.toString());
x = Double.valueOf(editScore.getText().toString()); //chances of getting a Numberformat exception if entered value is not a number
calculateEquivalent();
}
}
catch(NumberFormatException e)
{
//Toast.makeText(m_context, "You entered a wrong value,Please enter only numeric values", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
catch(Throwable e)
{
e.printStackTrace();
}
Also in your calculateEquivalent(); method, you need to make sure that value of y should not be zero.
Hope this helps you :)
Hey #callmejeo the main problem with the function you wrote above is that you are coverting "NULL" values into String so one thing you can do is that to HANDLE exception.
private void calculateEquivalent(){
try{
double x , y;
y = Double.valueOf(total_score.toString());
x = Double.valueOf(editScore.getText().toString());
if (x >= y * 0.65){
double equivalent = (Math.round((100 + (72 * (x - y)) / y)));
String equi = String.valueOf(equivalent);
textEquivalent.setText(equi);
} else {
double equivalent = (Math.round((75 + (23 * (x - y * 0.65)) / y)));
String equi = String.valueOf(equivalent);
textEquivalent.setText(equi);
}
}
catch(Exception e){
Toast.makeText(this,"Please Enter some value",Toast.LENGTH_LONG).show();
}
}
Thanks a lot guys without your suggestions I probably stuck in this problem :)
and then I've come up with this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_student_quiz);
TextWatcher inputTextWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
calculateEquivalent();
}
};
editScore.addTextChangedListener(inputTextWatcher);
}
private void calculateEquivalent(){
try {
y = Double.parseDouble(total_score);
x = Double.parseDouble(editScore.getText().toString());
if (x >= y * 0.65){
double equivalent = (Math.round((100 + (72 * (x - y)) / y)));
String equi = String.valueOf(equivalent);
textEquivalent.setText(equi);
} else {
double equivalent = (Math.round((75 + (23 * (x - y * 0.65)) / y)));
String equi = String.valueOf(equivalent);
textEquivalent.setText(equi);
}
}catch (Exception e){
Toast.makeText(getApplicationContext(), "Please Enter a Number", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}

How can I make each individual frog stop using onTouch?

I am making a game where there there are frogs hopping around the screen. Once a frog is touched, I change the game image to what I have set as "deadFrog" and its movement stops. I have them all created under and array-list, and I am unsure as to how to only make changes to the individual frog. Right now, if one frog is tapped, all of the frogs stop moving and change to deadFrog. Hopefully you can help me fix the tactical nuke of a tap ;) *If you need any more information, just comment and I'll be sure to provide it!
Edit Is there not a way to access a single element in the blocks arraylist? I've tried doing blocks(1) for example but that's invalid.
Here is where the frogs are declared:
public void init() {
blocks = new ArrayList<Block>();
for (int i = 0; i < 5; i++) {
Block b = new Block(i * 200, MainActivity.GAME_HEIGHT - 95,
BLOCK_WIDTH, BLOCK_HEIGHT);
blocks.add(b);
tapped = false;
}
}
They are rendered with this:
private void renderFrogs(Painter g) {
if (!tapped) {
for (int i = 0; i < blocks.size(); i++) {
Block b = blocks.get(i);
if (b.isVisible()) {
Assets.runAnim.render(g, (int) b.getX(), (int) b.getY());
}
}
}
if (tapped) {
for (int i = 0; i < blocks.size(); i++) {
Block b = blocks.get(i);
if (b.isVisible()) {
g.drawImage(Assets.deadfrog, (int) b.getX(), (int) b.getY());
}
}
}
}
And this is the onTouchListener:
public boolean onTouch(MotionEvent e, int scaledX, int scaledY) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
recentTouchY = scaledY;
} else if (e.getAction() == MotionEvent.ACTION_UP) {
for (int i = 0; i < blocks.size(); i++) {
Block b = blocks.get(i);
if ((scaledY >= b.getY() - BLOCK_HEIGHT || scaledY <= b.getY()) && (scaledX >= b.getX() || scaledX <= b.getX() + BLOCK_WIDTH)) {
tapped = true;
}
}
}
return true;
}
Of course all frogs turn dead, you are supposed to keep "tapped" variable for each frog, your tapped variable is for all frogs at once.
Declare a class
public class Frog extends View{
public Drawable liveFrog;
public Drawable deadFrog;
public boolean isDead;
public Point location;
public int width;
public int height;
public Frog(Context context, int x, int y,int width,int height){
super(context);
this.isDead = false;
this.location = new Point(x,y);
this.width = width;
this.height = height;
}
public void onDraw(Canvas c){
super.onDraw(c);
if(!isDead){
//draw live frog at x,y
}else {
//draw dead frog at x,y
}
}
}
then you array is supposed to contain frogs
public void init(Context context) {
blocks = new ArrayList<Frog>();
for (int i = 0; i < 5; i++) {
Frog b = new Frog(context,i * 200, MainActivity.GAME_HEIGHT - 95,
BLOCK_WIDTH, BLOCK_HEIGHT);
blocks.add(b);
}
}
private void renderFrogs() {
for(Frog f : blocks){
//cause redraw
f.invalidate();
}
}
here comes the fun part, when you tap the frog
public boolean onTouch(MotionEvent e, int scaledX, int scaledY) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
recentTouchY = scaledY;
} else if (e.getAction() == MotionEvent.ACTION_UP) {
for (int i = 0; i < blocks.size(); i++) {
Frog frog = blocks.get(i);
if ((scaledY >= frog.getY() - BLOCK_HEIGHT || scaledY <= frog.getY()) && (scaledX >= frog.getX() || scaledX <= frog.getX() + BLOCK_WIDTH)) {
frog.isDead = true;
//cause one frog redraw
frog.invalidate();
//if the event was handled, stop here (unless you can have multiple frogs one on top of the other ?
return true;
}
}
}
//if the event was not handled, let it bubble up
return false;
}
From what I can see, your "tapped" boolean is not a property of EACH frog. It is declared once, and when triggered, per your for loop, will make every frog dead (obviously, since that's what you're experiencing).
Once "tapped" is true, your for loop is going through every block and assigning a dead frog to it.
I think you need to create a Frog class, and store instances of those in your ArrayList. A variable of the new frog class will be "touched", and when that is triggered you will do something to that specific instance only.

How can i pass a view reference from Object Animator OfObject(..) method animation?

I need to move circles along a circular path for that i am using Object Animator and Path evaluator.All the information is dynamic means it is changing when i receive response so that total number of circles can be changed at runtime.Here is the 1 part of method where all circles are positioning themselves according to their position on screen that is if user release the touch then this method gets called -:
public void slideDownSetToCenter() {
for (int i = 0; i < leftCurrentRunningAnimation.length; i++) {
Logger.i(TAG, "in slide down animation");
if (leftReadyToMove[i]) {
if (leftUpQueue.contains(i)) {
leftUpQueue.remove(i);
}
leftAngle = leftSlice * ++leftAllCirclesAngles[i];
Logger.i("circle leftAngle points of curve down", String.valueOf(leftAllCirclesAngles[i]));
if (leftAngle > leftAngleTop) {
if (i < leftCurrentRunningAnimation.length - 1) {
leftReadyToMove[i + 1] = true; // set next circle to
// move
}
}
Arrays.fill(leftCurrentRunningAnimation, false);
leftCurrentRunningAnimation[i] = true;
Logger.i(TAG, "leftAngle" + leftAngle);
if (leftReadyToMove[i] == true && leftAngle == leftAngleDownOut) {
leftReadyToMove[i] = false;
leftDownStack.add(i);
}
xPosition = (int) (leftCircleCenterX + leftCircleX * Math.cos(leftAngle));
yPosition = (int) (leftCircleCenterY + leftCircleY * Math.sin(leftAngle));
Path = new AnimatorPath();
Path.moveTo(xPosition, yPosition);
Path.lineTo(xPosition, yPosition);
while (true) {
if (leftAngle == leftAngleDownOut) {
break;
}
leftAngle = leftSlice * ++leftAllCirclesAngles[i];
xPosition = (int) (leftCircleCenterX + leftCircleX * Math.cos(leftAngle));
yPosition = (int) (leftCircleCenterY + leftCircleY * Math.sin(leftAngle));
Path.lineTo(xPosition, yPosition);
Logger.i(TAG, "path.........");
}
slideCircleAnimator = ObjectAnimator.ofObject(DynamicCircleSwipeAnimation.this, "leftButtonLocationDynamic", new PathEvaluator(), Path.getPoints().toArray());
slideCircleAnimator.setInterpolator(linearInterpolator);
slideCircleAnimator.setDuration(500);
context.runOnUiThread(new Runnable() {
#Override
public void run() {
slideCircleAnimator.start();
}
});
}
break;
}
}
Here is the Object animator's animation method -:
public void setLeftButtonLocationDynamic(final PathPoint newLoc) {
for (int i = 0; i < leftCurrentRunningAnimation.length; i++) {
if (leftCurrentRunningAnimation[i] == true) {
Logger.i("current button id", String.valueOf(i));
leftArrayOfButtons[i].setTranslationX(newLoc.mX);
leftArrayOfButtons[i].setTranslationY(newLoc.mY);
break;
}
}
}
Here my animation is not happening in correct way that' why i need to pass my view reference from Object.OfObject() method so that i can get it in setLeftButtonLocationDynamic(final PathPoint newLoc,View v).Is anyone has any idea how can i do this?I searched a lot and tried to develop custom class of ObjectAnimator,ValueAnimator and ProperyViewHolder classes but when i copied it from google open source then i get errors in that.Any help is appreciable?
Here to achieve this i changed the approach to move all circles.Previously, i was using ObjectAnimator to move circles one by one and now i am using Animator set for x position and y position.I play both animation together.
Here is the example -:
public void SlideDownFromRightAnimation() {
int rightArrayOfButtonsLength = rightArrayOfButtons.length;
Logger.i(TAG, "queue " + rightUpQueue.size() + "= stack " + rightDownStack.size());
if (rightUpQueue.size() == rtNumberOfButtons) {
Arrays.fill(rightReadyToMove, false);
rightReadyToMove[0] = true;
rightUpQueue.poll();
} else if (rightDownStack.size() == rtNumberOfButtons) {
rightUpQueue.clear();
for (int i = 0; i < rightArrayOfButtonsLength; i++) {
rightUpQueue.add(rightDownStack.pop());
rightAllCirclesAngles[i] = rightCircleUpOutPosition;
}
Arrays.fill(rightReadyToMove, false);
rightReadyToMove[0] = true;
}
for (int i = 0; i < rightArrayOfButtonsLength; i++) {
Logger.i(TAG, "in slide down animation");
if (rightReadyToMove[i]) {
if (rightUpQueue.contains(rightArrayOfButtons[i].getTag())) {
rightUpQueue.remove(i);
}
rightAngle = rightSlice * --rightAllCirclesAngles[i];
Logger.i("circle rightAngle points of curve down", String.valueOf(rightAllCirclesAngles[i]));
if (rightAngle <= rightAngleTop) {
if (i < rightArrayOfButtonsLength - 1) {
rightReadyToMove[i + 1] = true; // set next circle to
// move
}
}
Logger.i(TAG, "rightAngle" + rightAngle);
if (rightAngle <= rightAngleDownOut) {
rightReadyToMove[i] = false;
rightDownStack.add((Integer)rightArrayOfButtons[i].getTag());
rightAllCirclesAngles[i] = rightCircleDownOutPosition;
rightStartAnimation(rightAngle, null, i);
} else {
double rightAngleNext = rightSlice * rightAllCirclesAngles[i];
if (rightAngleNext <= rightAngleDownOut) {
rightReadyToMove[i] = false;
rightDownStack.add((Integer)rightArrayOfButtons[i].getTag());
}
rightStartAnimation(rightAngle, rightAngleNext, i);
}
}
}
}
and here is the right wheels animation function -:
public void rightStartAnimation(Double rightAngle, Double rightAngleNext, int bttnId) {
xPosition = (int) (rightCircleCenterX + rightCircleX * Math.cos(rightAngle));
yPosition = (int) (rightCircleCenterY + rightCircleY * Math.sin(rightAngle));
if (rightAngleNext != null) {
xPosition = (int) (rightCircleCenterX + rightCircleX * Math.cos(rightAngleNext));
yPosition = (int) (rightCircleCenterY + rightCircleY * Math.sin(rightAngleNext));
}
final ObjectAnimator animation1 = ObjectAnimator.ofFloat(rightArrayOfButtons[bttnId], "x", rightArrayOfButtons[bttnId].getX(), xPosition);
animation1.setDuration(0);
animation1.setInterpolator(linearInterpolator);
final ObjectAnimator animation2 = ObjectAnimator.ofFloat(rightArrayOfButtons[bttnId], "y", rightArrayOfButtons[bttnId].getY(), yPosition);
animation2.setDuration(0);
animation2.setInterpolator(linearInterpolator);
final AnimatorSet set = new AnimatorSet();
set.setInterpolator(linearInterpolator);
context.runOnUiThread(new Runnable() {
#Override
public void run() {
set.playTogether(animation1, animation2);
set.start();
}
});
}

Categories

Resources