I built an android app where the user uses a stopwatch to try to get it to stop on exactly 1 second. There is also a second gamemode where the user tries to start and stop the stopwatch as fast as possible and get the lowest time. There are several auto clicker apps that you can install that will start and stop the stopwatch exactly 1 second apart and also double click the screen within milliseconds.
My question is what is the best way to prevent cheating by this method? Are there libraries designed for this? Thanks for any help!
This question has been answered here.
Basically, use an API to check for clicks using accessibility services, but you can't straight out block artificial clicks because people who use accessibility features need them. Instead you can measure the time between clicks or the frequency of clicks and block the ones that are 'too perfect'.
E.g. if someone gets exactly 1 second between clicks 10 times in a row, they're probably cheating. If someone clicks however many times per second at exactly the same timing of 0.X ms between clicks, they're definitely cheating.
I was focusing on tap or touch event so that I can differentiate between human behaviour and other than human. Here's what I have done:
#Override
public boolean dispatchTouchEvent (MotionEvent event) {
if(event.getToolType(0) == MotionEvent.TOOL_TYPE_UNKNOWN) {
return false;
} else {
return super.dispatchTouchEvent(event);
}
}
Related
I am developing an Android app and at some point want to give the user ability to long press a view and after a short vibrate do some action.
I have tried onLongClick but it is triggered even on a very very short touch. I have read that the wait time cannot be changed; which makes it useless in my case. Am I missing something about that event?
If no, onTouchEvent is the only solution I guess. Is there a way to capture a long press with that event?
It sounds like you have not enabled long clicks. Please check whether calling the following method helps (taken from Android View Reference):
public void setLongClickable (boolean longClickable)
I'm trying to create a turn based game using a 1v1 battle for android. My basic game loop checks if the two fighters are dead, if not then checks who is to go next. If its the player's turn then it should wait for an attack button to be clicked. If its the computer's turn, then it will execute a random attack. I'm having trouble getting the program to wait for the user input. I tried setting the button listener here but that's not doing it.
[edit] The determination for which character goes is based on a recovery integer. Each attack has a recovery value (50-100) which is added to the character's recovery. The nextMove() method checks to see which is closer to 0 and subtracts the difference from both characters. This allows the game to require more strategy because you don't attack just once a turn.
What can I do to get the game to pause at that point
Here's the code
public void battle(){
boolean playerGo;
while(!checkDead()){
playerGo=nextMove(); //returns true if its the players turn to go
if(playerGo){
//The game should wait here for the user input
moveButton1.setOnClickListener(this);
}
else{
randomMove(); //game automatically goes
}
}
}
When your app starts up, there's one thread on which everything runs, including event handlers. After you do your setup and call battle(), that thread is sitting there going around and around the loop. It's so busy going around and around the loop that it doesn't notice that there's a click event waiting to be processed!
There's a few options:
Restructure your code. It looks like the basic structure is that the player moves, then the game moves. You could remove this loop entirely, and instead call randomMove() after each time you handle the player's move. Handle the player's move in the OnClickListener for moveButton1. That way everything just happens on events. This would be simpler overall, and is probably the Right Thing to do.
Make the smallest possible change to your code to get it working. This would probably mean pulling the contents of your while loop into a Runnable, which you schedule by calling Handler.post. The first line calls checkDead and returns if true. The last line reschedules the Runnable. In between is the body of the while loop. The effect of this is that your loop body runs, then the event handler gets a turn, then your loop body runs, then the event handler runs. This is probably a bad idea.
Run battle() in another thread. This is probably a bad idea.
Why are 2. and 3. bad ideas? On a mobile device, battery life is precious, and running a check to see if you need to do something over and over again will keep the CPU busy chewing up battery life. Much better to sit there idle until you need to do something - this is what option 1 achieves.
So if 2. and 3. are bad ideas, why mention them? Welllllll, 2. I mention because it's the closest thing I've got to an answer to the question you actually asked. I mention 3. because there's a sense in which your current code is a fairly clear embodiment of the game logic. You could rework it so it runs in a separate thread, and instead of nextMove() returning true, nextMove() waits until the player makes a move (this would involve semaphores or mutexes or promises). But this would be an explicitly multi-threaded program, and as such would be difficult to write correctly. I recommend you don't attempt it at this stage in your programming career - the most likely outcome is a program that stops and waits forever, or that corrupts its data structures, in a way that is exceedingly difficult to diagnose.
Button.SetOnClickListener() function will be triggered, only when the user clicks on the button. As such it doesn't wait\block till the user input. This is by design in Android, that you cannot have a blocking window waiting for user input. Instead change your design to display hint saying 'now its user's move'.
User does first move by clicking the button.
SetOnclickListener() will be invoked. Have the user action code inside it.
Towards end of SetOnclickListener() have the computer action code.
With this cycle you can have user move and computer move chained.
I guess, I have a generic logic problem. I want to logout a user after 15 if there is no activity. How do I find any "activity" in android. How should I go about it...
Experts please help...
You'll need to invest a little thought into exactly what your requirements are here, but from what I can tell, you want to keep track of the user interactions and if a time limit expires since the last interaction, perform some action, in your case logging them out of your application.
Firstly, you'll need some place that you can track when the last interaction occured, since you'll want this to be application wide you could use a singleton to hold this, or override the Application class, either way should do.
Next, you'll need to start tracking user interactions. From your activities, you can override the onUserInteraction method, this gets invoked anytime the user interacts with the application such as key event. Each time you hit this method, update your singleton and let it know something has happened, with a timestamp.
Finally, you'll need some kind of looping check to constantly check if anything has happened recently. Theres various was of doing this, you could have a continuous loop that compares current timestamp to the last recorded event, a bit of draft code :
while(true)
{
if (timeLastEventRecorded < (now - 15))
{
//nothing has happened in 15 minutes, so take corrective action
}
}
Presumably you'll already have some code in your application that takes care of logouts, such as when the user clicks "logout", you should just be able to invoke that in the sample above.
Hope this helps
You should have all activities inherit from a parent activity that overrides onUserInteraction(). In that callback you should reset a static app wide timer that will perform your logout code when the time reaches the end.
I have just upgraded jquery mobile to beta 2(from beta 1) and I am now receiving multiple click events if i go back into a page after pressing back, each time I go back in it adds another to the click so the alert fires however many times you go into the page
I have also noticed that clicks/taps seem to go through the current page and clicking on pages hidden by view - seems really strange but I am thinking they are probably linked.
It is as if it is creating multiple versions of the same page and when you go back into it loads a new one causing there to be two click events.
Here is a snippet of the code which is being fired
$('#click_me').live('vclick', function() {
alert('clicked');
});
Hopefully this makes sense and anyone can shed any light on what might be going on?
You've probably solved this by now, but you need to use the pagecreate event.
#Phill's suggestion of:
$('div').live('pageshow',function(event, ui){
$('#click_me').click(function() {
alert('clicked');
});
});
Unfortunately won't help, but you can solve the issue if you change pageshow to pagecreate
$('div').live('pagecreate',function(){
$('#click_me').click(function() {
alert('clicked');
});
});
If you're not using AJAX to load your pages, make sure also to change live to bind.
I had this same issue myself and this has solved it completely for me.
UPDATED:
I think the reason is you have the click event tied to the live event, so evrytime you navigate to that page it triggers the click event. try something like this:
$('div').live('pageshow',function(event, ui){
$('#click_me').click(function() {
alert('clicked');
});
});
or just use the click event
$('#click_me').click(function() {
alert('clicked');
});
When Beta 2 was released they are deprecating vclick
http://jquerymobile.com/blog/2011/08/03/jquery-mobile-beta-2-released/
Backtrack: We’ve switched back from vclick to click for links
In Beta 1, we decided to use our custom vclick event for handling Ajax
links to improve responsiveness and to hide the URL bar on the iPhone
and Android phones. Even though we did quite a bit of testing before
landing this for Beta 1, we began to hear feedback that this change
was causing some significant issues out in the wild including:
Multiple click events causing navigation and form element issue –
In certain situations, when tapping an element, tap/click events seem
to fire twice on links and is due to edge cases where the target of
the touch event and mouse event don’t match due to how the browsers
calculate tolerances for these events. This is most pronounced on
Android 2.1, but affected most WebKit-based browsers to varying
degrees when a tap events occured near the edge of an element.
Click handlers in custom scripts didn’t “work” anymore – if a
script bound only to click events on the document, the global vclick
feature could interfere because the touch events may supercede click
events so it events wouldn’t appear to trigger.
I have a Live Wallpaper that uses various screen touches to trigger certain events. At the moment it is working but I seem to get all touch events. For example, when the user touches an icon to launch an app, I seem to get that event too.
Is it possible to determine whether the user has touched the background screen (i.e. the inter-icon gaps.) so that I can only take my actions at that time and ignore the others.
Failing that, (and assuming – possibly erroneously – that if I am first in the queue than there is no other application on top of me on the screen) can I determine where I am in the touch event queue so that I can only take actions when I am the first one in the queue?
Or any other suggestions please.
Thanks
Richard
Ran into the same problem and ended up looking at the source for the Nexus wallpaper to see how it's implemented there.
I don't think it's possible to determine whether the actual home screen has consumed the touch. However, the default Android home screen does send a command to the wallpaper when you tap on empty space. So in your Engine, you can write:
#Override
public Bundle onCommand(String action, int x, int y, int z, Bundle extras, boolean resultRequested) {
if (action.equals(WallpaperManager.COMMAND_TAP)) {
// do whatever you would have done on ACTION_UP
}
return null;
}