I have been trying to make the accessibility service dispatchGesture with a click and not a swipe.
This code is just swiping down on the screen, and not actually clicking on the x,y cords.
What I have tried.
Path clickPath = new Path();
clickPath.moveTo(Float.intBitsToFloat(x), Float.intBitsToFloat(y));
GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
gestureBuilder.addStroke(new GestureDescription.StrokeDescription(clickPath, 0, 1));
dispatchGesture(gestureBuilder.build(), null, null);
I have also tried replaced the clickPath.moveTo to add clickPath.addCircle, and clickPath.addRect, But both of those just crash the application.
I know this question was a few months ago, but from what I've seen, your duration is too short. I wasn't able to get touch events to register with a duration of less than 50ms. I also passed a custom handler:
val handler = Handler(Looper.myLooper()!!)
It's possible that one or both of these could be the source of the reason it wasn't working for you. In general, you seem to be doing the same thing that I am, and I'm having some success with it.
Related
I have challenged myself to code an in house app similar to Google's assistant voice tapping app. Everything is finished except the auto tap feature. When I launch the app it spins up a foreground service that draws a 8x8 grid that is always on top. Even when the main activity is minimized. The service uses an imageview that is set drawable. I then wrote an algorithm that draws a grid within it numbered 1 through 64. The user says which number to tap and the service does just that but nothing happens. I Log.wtf the tap coordinates x,y and it works perfectly when my main activity is open. when minimized it doesnt log the event OR its taping the wrong view.
Any suggestions?
Here is the code inside my custom window class that pops the window and sets the tap transperency so that taps pass through to the target app behind it. tPars is different for testing purposes. Both are window parameters.
`
mPars=new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
lInflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
gridView = lInflater.inflate(R.layout.window_overlay,null);
iv = gridView.findViewById(R.id.iv);
ivHolder= gridView.findViewById(R.id.ivHolder);
((ImageView)iv).setImageDrawable(new Draw());
mPars.gravity=Gravity.CENTER;
mWManager=(WindowManager) context.getSystemService(WINDOW_SERVICE);
`
Ive even tried using System.exec("Touch X,Y"). Still same issue. Broadcast receivers wont work as the goal is to stay within the service WHILE using other apps. Its an auto tap assistant app like googles.
I would like to utilize this ---> MOTION EVENT
To reiterate, Once Main Activity spins up the service I no longer want or need it as the user will be using other apps. My app allows them to Tap/Scroll with their voice via the foreground service overlay.
Thanks in advance.
I tried MotionEvent, System.exec, and a few 3rd party APIs. It will only tap withing Main Activities view.
EDIT
Here is my tap and recognition code.
else if(sentence.get(0).equalsIgnoreCase("tap")){
mWManager.addView(gridView, mPars);
grid.draw(new Canvas());
tap(548F,946F);
}
and execution
private void tap(Float x, Float y) {
gridView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis()+100, (int)MotionEvent.ACTION_DOWN, x, y, 0));
gridView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis()+100, (int)MotionEvent.ACTION_UP, x, y, 0));
}
When making the application full screen with the following call:
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
I no longer have signals from my controller. The issue is not solved by changing the display back from full screen like:
Gdx.graphics.setWindowedMode(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
I'm using Gdx version: 1.9.8. It appears this was an issue fixed in a previous version, but I'm not sure what the necessary steps are to get the work around functioning.
Here's some posts I found about the issue:
https://github.com/libgdx/libgdx/issues/4723
https://github.com/GoranM/bdx/issues/518
(this one is old) http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=10692
Any help is much appreciated.
*Edit: This is using the controller extension that can be checked from the libgdx set up application. *
Edit2: I can get a responsive controller if I re-poll the controllers like the following:
Array<Controller> controllers = Controllers.getControllers();
However, this cannot be done instantly after changing the display mode; I have to wait some amount of time after. I'm not sure what I need to poll to determine how long I have to wait until the controller instances are valid (also, when it is valid to assign a listener).
Edit3: The only solution I've been able to come up with is to set a flag inside the resize callback like the following
#Override
public void resize(int width, int height) {
resizeDirty = true;
resizeTimestamp = System.currentTimeMillis();
}
Then in my main loop call:
private void controllerCheck() {
if (resizeDirty) {
long currentTime = System.currentTimeMillis();
if (currentTime > resizeTimestamp + controllerResetDelay) {
resizeDirty = false;
//get new controller instance | re-add a controller listener
}
}
}
This isn't ideal, I'd rather find a way to listen to when the change in context is done initializing then update the controllers. But I haven't been able to find a hook for that. I'd appreciate it if anyone knows a better way to go about maintaining controllers with change in display mode.
Why don't you try to use the immersive fullscreen?
If the objective is to set the fullscreen mode, I think this is the better way to.
I want to automate a hybrid app using appium.
My app uses touchend events instead of click events for div
How do I automate this touchend events in appium?
For simple click I can find an element and then perform click by simply doing WebElement.click();
How to fire an event for touchend?
I have spend the last few days looking into this same issue. Eventually what I have found is that the Appium touch actions only work on the NATIVE context. However when you are testing/automating a web application you are in WEBVIEW context. So you have to switch to NATIVE, perform the touch actions, then switch back.
Ok, so that doesn't sound to bad. But they can't let it be that simple. So you can not use your Selenium WebElement as an argument in the Touch Actions. You will either have to re-find it using the NATIVE context, or use the elements location and dimensions to calculate a touch position and use that. However, the X and Y coordinates in the NATIVE context are different than those in the WEBVIEW context. So if you need them to be exact, then you have to translate them.
Well, at least that is where I am now. Perhaps someone else can provide some more or better details.
Here is some sample code for a tap which ignores the pixel translation issue. I have only tested this with iOS, but it should work with Android as well.
private void tapElement(AppiumDriver appiumDriver, WebElement element) {
// Locate center of element
Point location = element.getLocation();
Dimension size = element.getSize();
int tapX = location.getX() + (size.getWidth() / 2);
int tapY = location.getY() + (size.getHeight() / 2);
// Execute tap
String originalContext = appiumDriver.getContext();
appiumDriver.context("NATIVE_APP");
TouchAction action = new TouchAction(appiumDriver);
action.tap(tapX, tapY).perform();
appiumDriver.context(originalContext);
}
Have you looked through documentation?
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/touch-actions.md
I have this.setVolumeControlStream(AudioManager.STREAM_MUSIC); at the start of all activities in my application so when the user presses the volume up or down buttons, he controls the media volume.
I have a popup window in my program and when that appears the user can no longer control the volume.
Looking at similar questions it seems that setting up onKeyup/down listeners can interfere with the process - but I have not set any up - the only listeners I have for the popup window are setOnClickListeners for the buttons and a setOnDismissListener for the window.
How can I fix this?
Looks like you have to call setOwnerActivity on the Dialog object.
Documentation from the method:
Sets the Activity that owns this dialog. An example use: This Dialog will use the suggested volume control stream of the Activity.
While not tested, this should do the trick. There is also the possibility to use setVolumeControlStream.
I had been creating the popup window with
my_popup_window = new PopupWindow(layout, x, y, true);
I then change it to this...
my_popup_window = new PopupWindow(layout);
my_popup_window.setWidth(x);
my_popup_window.setHeight(y);
and the volume control started to work again. I don't understand why - but it worked.
I just do this pop.setFocusable(false). and it worked.
though the Mick's answer didn't work for me, this is for posterity.
//Declaration
PopupWindow mWindow;
...
//Constructor
mWindow = new PopupWindow(context);
...
//Prepare to Show
mWindow.setContentView();
mWindow.setBackgroundDrawable();
mWindow.setFocusable(false);
...
setting setFocusable to false helped my activity capture onKeyDown() again.
I want to make an activity that can be opened above ANY app.
Normally, even when the activity is set as dialog, when you switch to my app, you see my app, and in the background you see the launcher:
BUT, I want the app will go above any app like this: (made in photoshop):
I did see this question Creating a system overlay window (always on top), but in ICS there is no functionallity to the layout.
Furthermore, I want to give a dialog box from my app without minimizing the other app...
there are plenty of apps that show a floating view on top of everything like : airbrowser , LilyPad , Stick it , AirTerm , Smart Taskbar , aircalc ...
anyway , in order to achieve this feature , you must have a special permission called "android.permission.SYSTEM_ALERT_WINDOW" , and use something like that:
final WindowManager.LayoutParams param=new WindowManager.LayoutParams();
param.flags=WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
final View view=findViewById(R.id.my_floating_view);
final ViewGroup parent=(ViewGroup)view.getParent();
if(parent!=null)
parent.removeView(view);
param.format=PixelFormat.RGBA_8888;
param.type=WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
param.gravity=Gravity.TOP|Gravity.LEFT;
param.width=parent!=null?LayoutParams.WRAP_CONTENT:view.getLayoutParams().width;
param.height=parent!=null?LayoutParams.WRAP_CONTENT:view.getLayoutParams().height;
final WindowManager wmgr=(WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
wmgr.addView(view,param);
// TODO handle overlapping title bar and/or action bar
// TODO you must add logic to remove the view
// TODO you must use a special permission to use this method :android.permission.SYSTEM_ALERT_WINDOW
// TODO if you wish to let the view stay when leaving the app, make sure you have a foreground service running.
I'm one of the developers of the Tooleap SDK, and we also dealt with this issue.
Basically, you don't need to use the SYSTEM_ALERT_WINDOW to display an activity on top of another one. You can just display a regular "shrinked" Activity with a transparent background.
To make a "shrinked Activity, change the activity window layout params of height and width:
WindowManager.LayoutParams params = getWindow().getAttributes();
params.x = ...;
params.y = ...;
params.width = ...;
params.height = ...;
this.getWindow().setAttributes(params);
To make a transparent background add to your activity definition in the manifest file:
android:theme="#android:style/Theme.Translucent"
That way, you can create the illusion of a floating activity:
Note that only the foreground activity will be resumed, while the background one is paused. But for most apps this shouldn't be an issue.
Now all that remains is when to launch the floating activity.
Here is an example of a "floating" calculator app using a regular activity. Note that the activity below the calculator belongs to another app.