【问题标题】:Android - How to detect action media button long pressAndroid - 如何检测动作媒体按钮长按
【发布时间】:2016-04-07 13:30:26
【问题描述】:

我正在开发一个检测耳机按钮单击和双击的应用程序(代码如下)。单击和双击工作正常,但长按不起作用。下面的代码在一个扩展 BroadcastReceiver 的类中。我该如何解决这个问题?非常感谢。

@Override
public void onReceive(Context context, Intent intent)
{
    context1=context;
    intent1=intent;
    String intentAction=intent.getAction();
    if (!Intent.ACTION_MEDIA_BUTTON.equalsIgnoreCase(intentAction))
    {
        return;
    }
    KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
    if (event == null) {
        return;
    }
    int action = event.getAction();
    if (action == KeyEvent.ACTION_DOWN)
    {
        // do something

            d++;
            Handler handler = new Handler();
            Runnable r = new Runnable()
            {
                @Override
                public void run()
                {
                    // single click *******************************
                    if (d == 1)
                    {
                        Toast.makeText(context1, "single click!", Toast.LENGTH_SHORT).show();
                    }
                    // double click *********************************
                    if (d == 2)
                    {
                        Toast.makeText(context1, "Double click!!", Toast.LENGTH_SHORT).show();
                    }
                    d = 0;
                }
            };
            if (d == 1)
            {

                handler.postDelayed(r, 500);
            }
    }
    /**
     * for long click
     */
    if (action == KeyEvent.ACTION_UP)
    {
        if (SystemClock.uptimeMillis() - event.getDownTime() > 2000)
        {
            Toast.makeText(context, "Long click!", Toast.LENGTH_SHORT).show();
        }
    }
    abortBroadcast();
}

更新

这是 Main.class

public class Main extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener
{
private static final String TAG = "MainActivity";
PreferenceFragment pf;
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_main);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FragmentManager fragmentManager= getFragmentManager();
    SingoloClick singoloClick= new SingoloClick();
    FragmentTransaction ft=fragmentManager.beginTransaction();
    ft.replace(R.id.content_frame, singoloClick);
    ft.commit();

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);//"android.intent.action.MEDIA_BUTTON"
    MediaButtonIntentReceiver r = new MediaButtonIntentReceiver();
    filter.setPriority(999); //this line sets receiver priority
    registerReceiver(r, filter);
((AudioManager)getSystemService(AUDIO_SERVICE)).registerMediaButtonEventReceiver(new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName()));
}

@Override public void onResume()
{
    super.onResume();
}

@Override
public void onBackPressed()
{
    moveTaskToBack(true);
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START))
    {
        drawer.closeDrawer(GravityCompat.START);
    }
    /*else
    {
        super.onBackPressed();
    }*/
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings)
    {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    if (id == R.id.nav_singoloClick)
    {
        setTitle(""+getResources().getString(R.string.singoloClick));
        FragmentManager fragmentManager= getFragmentManager();
        SingoloClick singoloClick= new SingoloClick();
        FragmentTransaction ft=fragmentManager.beginTransaction();
        ft.replace(R.id.content_frame, singoloClick);
        ft.commit();
    } else if (id == R.id.nav_doppioClick)
    {
        setTitle(""+getResources().getString(R.string.doppioClick));
        FragmentManager fragmentManager= getFragmentManager();
        DoppioClick doppioClick= new DoppioClick();
        FragmentTransaction ft=fragmentManager.beginTransaction();
        ft.replace(R.id.content_frame, doppioClick);
        ft.commit();
    } else if (id == R.id.nav_lungoClick)
    {
    } 

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}


@Override
protected void onDestroy()
{
    super.onDestroy();
    android.os.Process.killProcess(android.os.Process.myPid());*/
}

@Override public void onPause()
{
    super.onPause();
}
}

这是 Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
    android:supportsRtl="true" android:theme="@style/AppTheme">
    <activity android:name=".Main" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <receiver android:name=".MediaButtonIntentReceiver">
        <intent-filter android:priority="999">
            <action android:name="android.intent.action.MEDIA_BUTTON" />
        </intent-filter>
        <intent-filter android:priority="0">
            <action android:name="android.intent.action.VOICE_COMMAND" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
</application>

【问题讨论】:

  • 您可以存储ACTION_DOWN 的实际时间,并与ACTION_UP 的实际时间进行比较,以供您检查&gt; 2000

标签: android broadcastreceiver development-environment headset


【解决方案1】:

尝试使用另一个关键事件 KeyEvent.OTHER...我在文档中找到的内容:

  /**
     * This flag is set for the first key repeat that occurs after the
     * long press timeout.
     */
    public static final int FLAG_LONG_PRESS = 0x80;

更新:另一种解决方案,用于捕获按下按钮时的时间。

final Timer timer = new Timer();
button.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View arg0, MotionEvent arg1) {
        switch ( arg1.getAction() ) {
        case MotionEvent.ACTION_DOWN:
            //start timer
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    // invoke intent
                }
            }, 5000); //time out 5s
            return true;
        case MotionEvent.ACTION_UP:
            //stop timer
            timer.cancel();
            return true;
        }
        return false;
    }
});

更新 2:

看起来您的问题是您在 onTouchEvent 中处理触摸事件的方式。该方法 ACTION_UP - 不起作用!如果要处理触摸事件,则需要从 onTouchEvent 返回 true。因此,如果您收到 ACTION_DOWN 并从 onTouchEvent 返回 false,系统将不会再向您发送任何相关的触摸事件,直到下一个 ACTION_DOWN 事件。

如果您想接收除 ACTION_DOWN 之外的任何触摸事件,您需要从该按钮的 onTouchEvent 返回 true。但你不能这样做,所以需要考虑另一种解决方案。

更新 3

正如我所说,需要创建其他解决方案,因为 KEY_ACTION_UP 不起作用。也许也可以尝试this 解决方案。

【讨论】:

  • 但此代码适用于 Button。我会检测到长按硬件键(耳机按钮)。
  • 好吧。如果没有其他 KeyEvents,请尝试使用计时器。只需在动作事件 KEY_DOWN 上初始化它并在 KEY_UP 上停止计时器。长按时检查计时器大小。
  • 不起作用。我的应用程序没有检测到长按并且总是启动 ok google。我该如何解决这个问题??
  • @AlessandroMarino 你能提供代码、发送意图和其他内容吗?我以前没看到,你发送信息 KeyEvent.ACTION_DOWN 并且他们中止 BR。
  • 现在我把调用 BR IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);//"android.intent.action.MEDIA_BUTTON" MediaButtonIntentReceiver r = new MediaButtonIntentReceiver(); filter.setPriority(999); //此行设置接收器优先级 registerReceiver(r, filter); ...onReceive 方法在问题的上方。我已经在 logcat 中看到,如果我长按耳机按钮,则会有更多 ActionDown,然后是一个 ActionUp,但我的代码没有检测到 ActionUp。为什么?附言对不起我的英语:)
【解决方案2】:

对于长按按键的句柄:

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        // TODO Auto-generated method stub
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多