Counting headset button clicks in BroadcastReceiver
<p>Inside of the <code>onReceive(Content context, Intent intent)</code> method of my <code>public class MediaButtonIntentReceiver extends BroadcastReceiver</code> I need to count the number of headset button clicks (single, double, triple), which is denoted by <code>KeyEvent.ACTION_DOWN</code> of the <code>ACTION_MEDIA_BUTTON</code>. </p>

<p>What I have almost works, but my current algorithm sucks and is unreliable after a few times. Basically every successive <code>ACTION_DOWN</code> (hit within a certain number of milliseconds to the previous <code>ACTION_DOWN</code>) I do <code>numClicks++</code>. But also I need to see when the user is done pressing, so after each event I start a <code>CountDownTimer</code>, and if by the time it runs out there are no new clicks, then I'm done and now know the number of clicks. </p>

<p>The problems I'm running into are as follows: for one, the button itself seems noisy - if I press it too fast I usually miss a click. Two, after a few trials when the app it loaded, it starts getting random and I'm assuming that there are multiple <code>CountDownTimer</code> threads (is that the right word?) still running which screws my stuff up. </p>

<p>Anyways here's the main code snippet: </p>

<p>//note: <code>thisClickTime</code> uses <code>System.currentTimeMillis()</code></p>

<pre><code>   if (action == KeyEvent.ACTION_UP) {
        if (isDown == true) {
            if (numClicks == 0 &amp;&amp; lastClickTime == 0) {
                //we have a new click
                numClicks++;
                lastClickTime = thisClickTime; //update the click time
                isDown = false;
                elapsedTime = thisClickTime - lastClickTime;    
            } else if (thisClickTime - lastClickTime &lt; clickDelay) { //&amp;&amp; thisClickTime - lastClickTime &gt; 10
                numClicks++;
                lastClickTime = thisClickTime; 
                isDown = false; 
            }

            final int oldNumClicks = numClicks;
            final CountDownTimer checkIfDone = new CountDownTimer(clickDelay, 10) {
            public void onTick(long millisUntilFinished) {
                if (oldNumClicks != numClicks) {
                    cancel(); 
                }
            }
            public void onFinish() { //code that executes when counter is done
                if (oldNumClicks == numClicks) {
                    //if user doesn't click anymore in time clickDelay + X milliseconds, then it's done
                    Toast.makeText(context, "Number of clicks: " + Integer.toString(numClicks), Toast.LENGTH_SHORT).show();
                    //reset state variables 
                    numClicks = 0;
                    lastClickTime = 0; 
                }
            }
           }.start();

        } else {
            //? 
        }
    }
</code></pre>

<p>For reference, I've been looking around at stuff like: </p>

<p><a href="http://musicqueueproject.googlecode.com/svn-history/r83/trunk/src/com/yannickstucki/android/musicqueue/old/PlayerService.java" rel="nofollow">http://musicqueueproject.googlecode.com/svn-history/r83/trunk/src/com/yannickstucki/android/musicqueue/old/PlayerService.java</a> </p>

<p>To see if there's a good way to register number of clicks. I don't really understand their code too well though, and from what I can see they only deal with single/double clicks (I may need triple and quadruple). </p>

<p>EDIT - uploaded the current code I'm working with. It works pretty decently most of the time. Here's what I've noticed though: if I do my button testing too close together in time, the results start screwing up and under counting the clicks. I think this is because other CountDownTimers from previous attempts are still open, and when they finish, they reset certain state variables (numClicks = 0, for one). So am I misusing the timer? I can't think of another solution though as I need some concept of elapsed time after the last click to determine when the clicking is done.</p>

<p>Thanks for any help.  </p>
