MotionEvent.ACTION_CANCEL is blocking subsequent ACTION_UP on my button - Java for Android App Development

Hey guys,
I am not getting any response on Stack Overflow so I thought I would try here.
At this point I am suspicious that it is a Samsung device specific problem. A very basic app with just a single button produces the same issue on my S4 development device.
Here is me SO question:
I have a button on one of my fragments, that sits inside a relative layout.
It's a rather large button, and when I fat finger it I get a ACTION_CANCEL motion event rather than ACTION_DOWN (it works perfectly fine with finger tips). This prevents it from registering the subsequent ACTION_UP (I assume the view's parent is taking over). I tried using the requestDisallowInterceptTouchEvent() method on the parent, to no avail.
Here is my onTouch implementation:
Code:
@Override
public boolean onTouch(View view, MotionEvent event) {
//debugging
Log.v("TOUCH EVENT", event.toString());
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
mButton.getParent().requestDisallowInterceptTouchEvent(true);
//Do stuff...
return true;
} else if (action == MotionEvent.ACTION_UP) {
//Do other stuff...
return true;
} else if (action == MotionEvent.ACTION_CANCEL){
return false;
//Toast.makeText(context, "Your thumb is too fat.", Toast.LENGTH_SHORT).show();
}
return false;
}
Note that the button also uses custom background resources. I start an AsyncTask when the button is pressed and the background changes based on the progress of that task. I'm not sure if that has anything to do with the problem or not.
EDIT: I walked all the way up the View hierarchy to ViewRootImpl, and still no luck in calling requestDisallowInterceptTouchEvent() on it. Weird thing is this shows in the log when my button sticks:
Code:
08-26 11:06:15.287: D/ViewRootImpl(5428): [ViewRootImpl] action cancel - 1, s:31 s(atmel):-1.0 eccen:1.3333334
So obviously it seems that the action is either being cancelled before it even gets inside the ViewRootImpl or right after. How is this even possible?
Update: Still no progress on this... anyone?

masterjeff said:
Hey guys,
I am not getting any response on Stack Overflow so I thought I would try here.
At this point I am suspicious that it is a Samsung device specific problem. A very basic app with just a single button produces the same issue on my S4 development device.
Here is me SO question:
I have a button on one of my fragments, that sits inside a relative layout.
It's a rather large button, and when I fat finger it I get a ACTION_CANCEL motion event rather than ACTION_DOWN (it works perfectly fine with finger tips). This prevents it from registering the subsequent ACTION_UP (I assume the view's parent is taking over). I tried using the requestDisallowInterceptTouchEvent() method on the parent, to no avail.
Here is my onTouch implementation:
Code:
@Override
public boolean onTouch(View view, MotionEvent event) {
//debugging
Log.v("TOUCH EVENT", event.toString());
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
mButton.getParent().requestDisallowInterceptTouchEvent(true);
//Do stuff...
return true;
} else if (action == MotionEvent.ACTION_UP) {
//Do other stuff...
return true;
} else if (action == MotionEvent.ACTION_CANCEL){
return false;
//Toast.makeText(context, "Your thumb is too fat.", Toast.LENGTH_SHORT).show();
}
return false;
}
Note that the button also uses custom background resources. I start an AsyncTask when the button is pressed and the background changes based on the progress of that task. I'm not sure if that has anything to do with the problem or not.
EDIT: I walked all the way up the View hierarchy to ViewRootImpl, and still no luck in calling requestDisallowInterceptTouchEvent() on it. Weird thing is this shows in the log when my button sticks:
Code:
08-26 11:06:15.287: D/ViewRootImpl(5428): [ViewRootImpl] action cancel - 1, s:31 s(atmel):-1.0 eccen:1.3333334
So obviously it seems that the action is either being cancelled before it even gets inside the ViewRootImpl or right after. How is this even possible?
Update: Still no progress on this... anyone?
Click to expand...
Click to collapse
Mmmh strange problem you've got there... Just an idea, maybe try to always return true in your onTouchEvent() method since you may be losing the event when an ACTION_MOVE event comes up and you return false. Other than that, could you show us your layout file? I doubt the change in background color has any effect on this, but it could be that some part of your layout is causing this.

SimplicityApks said:
Mmmh strange problem you've got there... Just an idea, maybe try to always return true in your onTouchEvent() method since you may be losing the event when an ACTION_MOVE event comes up and you return false. Other than that, could you show us your layout file? I doubt the change in background color has any effect on this, but it could be that some part of your layout is causing this.
Click to expand...
Click to collapse
Does anyone have a solution to this yet? More specifically, I think it's the Samsung's own implementation of ViewRootImpl that is causing this problem. I've been trying to figure out for a long time how to either pre-empt ViewRootImpl to intercept MotionEvents, or completely override ViewRootImpl. I found no success in either of these.
I also thought about reading from /dev/input/eventX directly, but this isn't feasible since it requires the phone to be rooted first. For myself it's ok, but if I'm writing an app for other devices that's not a solution.
Can someone from Samsung help?

Related

[REQ]Remapping Camera shot key to volume button?

Hi there,
First of all I tried searching on google and also in this forum itself but I cant find anything related and so i decided to create a new thread on this.
If there anyway via tweaking the registry that i can make use of the volume key on the blackstone to take pictures instead of using the touchscreen? I believe this is possible
I find taking picture using a touchscreen is really difficult.
I read from http://wiki.xda-developers.com/index.php?pagename=HTC_Blackstone_Overview that this is possible by remapping the volume rocker.
Does any know how?
Will anyone be able to help?
I'm requesting this also. HTC should have made an option for us to choose for this from the beginning.
Request also here!
Sorry, I added this "remap volume rocker Solution" because I thought it was possible, but I actually didn't try it. So let's keep this thread to find a way to do it.
Remapping keys is through AE Button Plus or MobileMagic.
Right now we only have the choice of "touch" or "touch and hold" the virtual on-screen button to "auto-focus + shot".
We need to find out if there is any keyboard shortcut associated to that function.
I tried to use the "enter key" fonction remaped to Volume Up with AE Button Plus, but it didn't work.
Does the HTC Touch Pro have HTC's Camera application? maybe they know a keyboard shortcut? Let's ask.
I guess it will be possible.... just that we need the experts here to show us how to...
[APP] CameraButton
To solve this problem. I thought of a very simple solution:
Instead of us clicking the on-screen camera button, we need an application "CameraButton", which will click on the screen for us, then we just need to map a hardware button to that application.
Simple isn't it?
So here is the C# code for the CameraButton application:
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace CameraButton
{
class Program
{
[System.Runtime.InteropServices.DllImport("coredll.DLL", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
[System.Runtime.InteropServices.DllImport("coredll.DLL", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("coredll.dll")]
static extern bool SetCursorPos(int X, int Y);
[System.Runtime.InteropServices.DllImport("coredll.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
[Flags]
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
static void Main(string[] args)
{
IntPtr cameraHandle;
cameraHandle = FindWindow(null, "Camera");//search camera app
if (cameraHandle == IntPtr.Zero)// cannot find it then launch it
{
Process cam = Process.Start(new ProcessStartInfo("Camera.exe", ""));
//cameraHandle = cam.MainWindowHandle;
}
else // can find it then set position then click
{
//SetForegroundWindow(cameraHandle);// we assume we already have the focus on the camera app
SetCursorPos(240, 750 );//set position to the on-screen camera button
mouse_event((uint)MouseEventFlags.LEFTDOWN, 0, 0, 0, 0);
mouse_event((uint)MouseEventFlags.LEFTUP, 0, 0, 0, 0);
}
}
}
}
Why do I give the code rather than the binary?
Because unfortunately this code doesn't work (yet).
Let me explain a bit more:
This application doesn't need to keep running in the background, it just can do 2 things. Start the camera app if it's not already started, or just click at a specifically chosen position.
If I set the position to (0,0), my program will click at the upper-left corner of the screen, and hit the start button, therefore the start menu appears.
However if I try to click on the camera application, it doesn't have any effect!
Actually if I click somewhere else than the on-screen camera button, it should still react to the click: the little cross should move to the clicked place as part of the Touch Focus feature of HTC's camera app.
But here again, nothing happen.
Since it's my first app on WiMo, I might have done a mistake somewhere, but I can't see where.
Any XDA-developer can spot what's wrong with my code?
please see http://forum.xda-developers.com/showthread.php?t=471321
The Problem is the HTC Application, it blocks any keydown event
I did it Application released soon!
http://www.scilor.com/leocameraanykey.html

AppWidget problem when process is running

So I'm programming a application with a widget.
On my widget I got a button that starts an activity with a PendingIntent. This activity that's getting launched isn't my main activity.
Now when I'm doing it like this I get a Strange problem:
- Launching App as normal over appdrawer -> main activity opens up
- Pressing Home or Back button
- Add widget to homescreen
- Click button on widget -> nothing happens!
If I force stop my application before adding the widget to the homescreen, a click on the button on the widget opens up the activity like it should. Now I can also launch my main activity, pause it and the widget still works. So the widget only fully works if I my application isn't running in the background while adding the widget.
Has anyone of you experienced something like that?
Thank you in advance!
it is really dependent on how your onClickListener is added to the button. ive had problems where the first widget i create doesnt have the onClickListener attached but the second one will. do you mind sharing your code that you use to attach the onClickListener?
here is mine:
Code:
/** Called when the activity is first created. */
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Toast.makeText(context, "onUpdate()", Toast.LENGTH_SHORT).show();
//super.onUpdate(context, appWidgetManager, appWidgetIds);
//attach an onClick intent to the layout
final Intent onClick = new Intent(context, GITextCloud.class);
onClick.setAction(LAUNCH_GMAIL_GAPPS);
PendingIntent onClickPending = PendingIntent.getBroadcast(context, 0, onClick, 0);
RemoteViews rv1 = new RemoteViews(context.getPackageName(), R.layout.gitc_html);
rv1.setOnClickPendingIntent(R.id.full_widget, onClickPending);
for (int appWidgetId : appWidgetIds) {
appWidgetManager.updateAppWidget(appWidgetId, rv1);
}
}
My code is really almost the same. Just that I need PendingIntent.getActivity instead of getBroadcast.
what flags do you set for your intent? cause if your activity is already running and thats when the button wont work it could be that you need a Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT or some other flags in the PendingIntent
try setting onClick.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) or what ever your Intent is called. i think the fact that your widget and your app are going to be seperate programs means they must start in different threads. cause not all widgets need an Activity running to function
I got it now! I somehow managed to screw up my remoteviews, they didn't got updated properly.
Anyway, thanks a lot for your answers

Display update regularity weirdness @ 1Hz w/video example (code, not NoRefresh issue)

At it's core... a simple clock app. I'm firing off updates scheduled on each second. On each second, I read the time, then display the time. This is not complicated. And it works, just fine, on my phone. Tick, tick, tick and it looks like a clock. Why wouldn't it, right?
Ok, so the same code on the nook doesn't update regularly. Here's an early video:
http://www.youtube.com/watch?v=URRrYhumt1Y
You can see there's a "double beat". It's like every other update gets displayed for maybe 1.5 seconds. So the overall rate doesn't change, it's still two updates in two seconds, and no updates are missed.
These are being done with a regular myView.setText(), no fancy graphics or anything.
Now, here's more interesting data. If I run the updates twice as often, or five times as often, it changes nothing. I assume the screen/OS is internally detecting no pixels have changed, and so it does nothing. However, if I add, to a totally different view on the screen, an area where I'm toggling from some text to no text (from " " to "+", in actuality, so, a blinking plus sign) AND I run everything at five times a second then the seconds area updates with a steady one hertz beat, just like you would expect from a clock.
Additionally, if I run the code so it only updates every other second, it will click along very predictably at every other second. So it's not a "some code problem with every other update".
I wonder if there's some internal timer in the OS watching for screen updates, and managing them? Perhaps "pushing" the display with a toggling update every 200ms keeps it active and within some timeout limit?
Or are there some nook-specific calls on this?
Cheers,
Anders
I believe that some of the super-duper fast-mode or-whatever-you-call-it throws away some screen updates.
Are you using such a thing or a kernel with such a thing?
No, I'm not attempting any speedy-screen stuff in this code. In the video you can see the grey in the bar, so I'm not in any kind of a 1-bit mode. Because really, one update a second should be no problem.
But if it was throwing away an update... why would the update show up half a second later? I would expect it to skip displaying that second entirely, and so jump to the next.
NoRefresh is installed on this device, but not set to start at boot (and honestly, I don't think I've actually gotten NoRefresh working yet, busy with other things). But I'll uninstall it to be sure and retest.
Is it possible some kind of low-power mode / sleep mode is kicking in? It wakes up half a second later, realizes it has an update, stays away for the next half second, makes the NEXT update (on time) then goes back to sleep after a 0.9ish seconds?
Anders
Yep, even after uninstalling NoRefresh, and rebooting, the behavior is the same. So that's definitely not related.
And running the normal updates to the screen at both 2Hz and 5Hz have the same result, so it's not related to the number of times the updates are called.
Anders
Here's an interesting video... watching the ADB output click along at a clean 1Hz, and the screen updates clearly not synced with the actual writes to the screen.
http://www.youtube.com/watch?v=sL299EUH3T0
Again, all on "stock" system, no special video modes / refresh / magic enabled.
Anders
Actually, I have run into this.
There's no documentation on modes or theory of operating a frame buffer for eInk.
I ran into this on the time display on my audio recorder app.
I ended up using a DL region in my app.
I'll have to look closer into how bad it looks without that.
Are those numbers a TextView or an ImageView?
If it isn't a TextView try one to see if it works better.
There may be slowness in caching/using images.
More questions:
Are you using Timer & TimerTask?
Are you using runOnUiThread?
I wrote a demo app that counts.
It works fine by itself on stock 1.2.1
Renate NST said:
Actually, I have run into this.
There's no documentation on modes or theory of operating a frame buffer for eInk.
I ran into this on the time display on my audio recorder app.
I ended up using a DL region in my app.
I'll have to look closer into how bad it looks without that.
Click to expand...
Click to collapse
DL region? Not familiar with the acronym.
Are those numbers a TextView or an ImageView?
Click to expand...
Click to collapse
It's a text view. Just a big blocky TTF font. (Although the same issue is present using stock fonts).
Are you using Timer & TimerTask?
Are you using runOnUiThread?
Click to expand...
Click to collapse
Using scheduled handlers. They are triggering normally, since A] the ADB output is firing at nice one second intervals, and B] the SystemClock.uptimeMillis shows a 1000 count between each wake up. It's off by one or two millis which is understandable given that it's not a hard-realtime system.
But I'm not familiar with Timer and runOnUiThread, so I'll google those and do some reading.
(In the below code, the "nookPing" area is a tiny spot where I just toggle some pixels. If I do this and run the whole thing at faster than 1Hz, the seconds digit updates on schedule. Turn off this toggling, (which is in a totally unrelated textarea) and back to wonky updates, even at the same update rate. )
Code:
// //////////////////////////////////////////////////////////////////////////////////////////////////
// The Tick task itself /////////////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////////////////////////////
private Handler mHandler = new Handler();
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
Log.d(TAG, "---------------------Tick Called: " +String.valueOf(SystemClock.uptimeMillis()) );
Log.d(TAG, "---------------------");
updateTimeOnScreen();
scheduleNextScreenUpdate();
}
};
// //////////////////////////////////////////////////////////////////////////////////////////////////
// Schedule next update /////////////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////////////////////////////
private void scheduleNextScreenUpdate()
{
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postAtTime(mUpdateTimeTask,UtilitiesTime.calculateNextScreenUpdateTime());
}
// //////////////////////////////////////////////////////////////////////////////////////////////////
// Show the time ////////////////////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////////////////////////////
static int nookPing=0;
private void updateTimeOnScreen() {
String hhmm;
int militaryhours,hour;
int minutes;
int seconds;
int tenths;
int milliseconds;
Calendar rightNow = Calendar.getInstance();
militaryhours=rightNow.get(Calendar.HOUR_OF_DAY);
hour=rightNow.get(Calendar.HOUR);
minutes=rightNow.get(Calendar.MINUTE);
seconds=rightNow.get(Calendar.SECOND);
milliseconds=rightNow.get(Calendar.MILLISECOND);
tenths=milliseconds/100;
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
if(true==settings.getBoolean("appSettingNookPingActive", false))
{
if(0==nookPing)
{
nookPing=1;
nookPingView.setText(".");
//nookPingView.setText(" ");
}
else{
nookPing=0;
nookPingView.setText(" ");
}
}
else{
nookPingView.setText(" ");
}
if(Configuration.ORIENTATION_PORTRAIT==getScreenOrientation())
{
if(1==MainActivity.appSettingMilitaryTimeFlag)
{
hhmm=String.format(Locale.US,"%02d:%02d",militaryhours, minutes);
}
else{
if(0==hour)
hour=12;
hhmm=String.format("%2d:%02d",hour, minutes);
}
}
else
{
if(1==MainActivity.appSettingMilitaryTimeFlag)
{
hhmm=String.format("%02d\n--\n%02d",militaryhours, minutes);
}
else{
if(0==hour)
hour=12;
hhmm=String.format("%2d\n--\n%02d",hour, minutes);
}
}
int secondsTens=seconds/10;
int secondsOnes=seconds%10;
secondsLeftView.setText(String.format("%d",secondsTens));
secondsRightView.setText(String.format("%d",secondsOnes));
hhmmView.setText(hhmm);
}

[Q] Need Help with a problem

I am using one edit text view and one OK button to input a large amount of user data during a setup function but can't figure out how to pause the thread execution unit the OK button is pressed. I don't want to have to register and use a ton of different buttons and listeners to call individual functions for each user input and so far I've found out the hard way that a while look will lock the UI thread and running the loop in a separate thread will not make the program wait. Any Ideas?
public class SetupMenuActivity extends Activity
{
private TextView setupPrompt;
boolean okButtonPressed = false;
@override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.setup_menu);
setup();
}
private OnClickListener okButtonListener = new OnClickListener()
{
@override
public void onClick(View v)
{
okButtonPressed = true;
}
};
private void setup()
{
Button okButton = (Button) findViewById(R.id.okButton);
okButton.setOnClickListener(okButtonListener);
setupPrompt = (TextView) findViewById(R.id.setupPrompt);
setupPrompt.setText("Please Enter Your Name");
// Make program wait for ok button clicked
setupPrompt.setText("Please Enter a Name for your Account");
}
}
What else could the user click/etc that you want to prevent from happening? If you want to block another button, then you can either do button.setClickable(false) or even button.setVisibility(View.GONE) until the ok button is clicked. Instead blocking the whole thread doesn't make much sense
The only two things the user can interact with is the button and the edit text box. I want to prevent the changing of the setupPrompt text view until the Ok button is pressed. The easy way to do it would be to put it into the onClickListener but there is a whole series of the prompts and waiting for user input so I'm trying to avoid creating a ton of different button listeners for each piece of user input.
TShipman1981 said:
The only two things the user can interact with is the button and the edit text box. I want to prevent the changing of the setupPrompt text view until the Ok button is pressed. The easy way to do it would be to put it into the onClickListener but there is a whole series of the prompts and waiting for user input so I'm trying to avoid creating a ton of different button listeners for each piece of user input.
Click to expand...
Click to collapse
The way you think this would work is not right, you have to think through it again, sorry . In Android, you can almost never wait for user events (because they might not happen). Instead, you have to do what you can during setup and everything that can only happen after a certain event has to be in the onEvent method (for instance onClick). What you can do to make it less complex is one method which is called only from the onClickListener. The method keeps track of how many times it has been called with an int step instance variable. That method has to execute what should happen at each step.
SimplicityApks said:
The way you think this would work is not right, you have to think through it again, sorry . In Android, you can almost never wait for user events (because they might not happen). Instead, you have to do what you can during setup and everything that can only happen after a certain event has to be in the onEvent method (for instance onClick). What you can do to make it less complex is one method which is called only from the onClickListener. The method keeps track of how many times it has been called with an int step instance variable. That method has to execute what should happen at each step.
Click to expand...
Click to collapse
Yeah Agreed with Simp. I would honestly make one method with all the info you need then get all the info and call it only when the button is clicked. If I knew a bit more of what your trying to accomplish I might be able to help you code it more efficiently.

[Q] assign Menu tu child of TabActivity

Hi there
I'm working on an application for light controll. I start a TabActivity with 2 childs tab "A" and tab "B". in the "onCreateOptionsMenu()" of the TabActivity I am creating the menu for the activitys.
How can I make, that the Activity in tab "A" reacts on clickt on the menu buttons?
I tryed out everything but nothing worked. Im searching at least since 15h.
Greez LoXeras
LoXeras said:
Hi there
I'm working on an application for light controll. I start a TabActivity with 2 childs tab "A" and tab "B". in the "onCreateOptionsMenu()" of the TabActivity I am creating the menu for the activitys.
How can I make, that the Activity in tab "A" reacts on clickt on the menu buttons?
I tryed out everything but nothing worked. Im searching at least since 15h.
Greez LoXeras
Click to expand...
Click to collapse
Something like this question? You need to override onPrepareOptionsMenu for different menus based on what tab is currently active. Then, in the onOptionsItemSelected just pass the selected item to the specific tab.
SimplicityApks said:
Something like this question? You need to override onPrepareOptionsMenu for different menus based on what tab is currently active. Then, in the onOptionsItemSelected just pass the selected item to the specific tab.
Click to expand...
Click to collapse
Thanks for the answere. This is what I tried. but I get crashes every time. A NullPointerException occurs every time. And if I try to select the hitten items in menu with the menu button it crasshes instantly.
Source:
Code:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
command co = new command();
switch (item.getItemId()) {
case R.id.action_load:
co.LoadFile();
return true;
case R.id.action_clear:
co.clearlist();
return true; case R.id.action_save:
co.SaveFile();
return true;
case R.id.action_as:
co.AutoScroll();
return true;
case R.id.action_info:
co.showInfo();
return true;
default:
return super.onOptionsItemSelected(item); //Return selected item
}

Categories

Resources