onKeyDown and onKeyLongPress

Here is the code that I wrote. It works like a charm. May be you can optimize it for better logic. But you will get the point with it. The key is to use flags. Short press is a press where we press volume button for short time and release. So onKeyUp is the one which will help us detect short presses.

package com.example.demo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;

public class TestVolumeActivity extends Activity {
    boolean flag = false;

    boolean flag2 = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_splash_screen, menu);
        return true;
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            Log.d("Test", "Long press!");
            flag = false;
            flag2 = true;
            return true;
        }
        return super.onKeyLongPress(keyCode, event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            event.startTracking();
            if (flag2 == true) {
                flag = false;
            } else {
                flag = true;
                flag2 = false;
            }

            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {

            event.startTracking();
            if (flag) {
                Log.d("Test", "Short");
            }
            flag = true;
            flag2 = false;
            return true;
        }

        return super.onKeyUp(keyCode, event);
    }
}

Logcat for all long presses(No short press detected):

10-18 02:06:15.369: D/Test(16834): Long press!
10-18 02:06:18.683: D/Test(16834): Long press!
10-18 02:06:21.566: D/Test(16834): Long press!
10-18 02:06:23.738: D/Test(16834): Long press!

Logcat for all short presses:

10-18 02:07:42.422: D/Test(16834): Short
10-18 02:07:43.203: D/Test(16834): Short
10-18 02:07:43.663: D/Test(16834): Short
10-18 02:07:44.144: D/Test(16834): Short

Correct way according to the SDK to handle long button presses.

import android.app.Activity;
import android.util.Log;
import android.view.KeyEvent;


public class TestVolumeActivity extends Activity
{
    private static final String TAG = TestVolumeActivity.class.getSimpleName();

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if( keyCode == KeyEvent.KEYCODE_VOLUME_UP || 
            keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
        {
            event.startTracking();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event)
    {
        if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
            Log.d(TAG, "Long press KEYCODE_VOLUME_UP");
            return true;
        }
        else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
            Log.d(TAG, "Long press KEYCODE_VOLUME_DOWN");
            return true;
        }
        return super.onKeyLongPress(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event)
    {
        if((event.getFlags() & KeyEvent.FLAG_CANCELED_LONG_PRESS) == 0){
            if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
                Log.e(TAG, "Short press KEYCODE_VOLUME_UP");
                return true;
            }
            else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
                Log.e(TAG, "Short press KEYCODE_VOLUME_DOWN");
                return true;
            }
        }
        return super.onKeyUp(keyCode, event);
    }
}

When i was about to post my answer i found out some one already got some kind of solution....

But here is mine, simple and works like a charm. Just one flag ;)

This code detects shortpresses and longpresses, when a longpress occurs no shortpress will be fired!

Note: if you want the normal volume up and down behavior change the return true in the onKeyPress method to the super call like this:

event.startTracking();
if(event.getRepeatCount() == 0){
    shortPress = true;
}
//return true;
return super.onKeyDown(keyCode, event);

Code without the super call:

private boolean shortPress = false;

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        shortPress = false;
        Toast.makeText(this, "longPress", Toast.LENGTH_LONG).show();
        return true;
    }
    //Just return false because the super call does always the same (returning false)
    return false;
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        if(event.getAction() == KeyEvent.ACTION_DOWN){
            event.startTracking();
            if(event.getRepeatCount() == 0){
                shortPress = true;
            }
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        if(shortPress){
            Toast.makeText(this, "shortPress", Toast.LENGTH_LONG).show();
        } else {
            //Don't handle longpress here, because the user will have to get his finger back up first
        }
        shortPress = false;
        return true;
    }
    return super.onKeyUp(keyCode, event);
}

Code down here is with the volume up key added, just pick your side ;)

private boolean shortPress = false;

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        shortPress = false;
        Toast.makeText(this, "longPress Volume Down", Toast.LENGTH_LONG).show();
        return true;
    } else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
        shortPress = false;
        Toast.makeText(this, "longPress Volume Up", Toast.LENGTH_LONG).show();
        return true;
    }
    //Just return false because the super call does always the same (returning false)
    return false;
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
        if(event.getAction() == KeyEvent.ACTION_DOWN){
            event.startTracking();
            if(event.getRepeatCount() == 0){
                shortPress = true;
            }
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        if(shortPress){
            Toast.makeText(this, "shortPress Volume Down", Toast.LENGTH_LONG).show();
        } else {
            //Don't handle longpress here, because the user will have to get his finger back up first
        }
        shortPress = false;
        return true;
    } else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
        if(shortPress){
            Toast.makeText(this, "shortPress Volume up", Toast.LENGTH_LONG).show();
        } else {
            //Don't handle longpress here, because the user will have to get his finger back up first
        }
        shortPress = false;
        return true;

    }
    return super.onKeyUp(keyCode, event);
}