Android Studio TV 遥控器按钮

Ani*_*asu 6 android android-studio android-tv

我正在尝试为 android 电视制作一个应用程序,它将使用电视遥控器上的以下按钮:up, down, left, right, center/enter, home, back

我需要什么课程/活动来做到这一点?我一直在尝试使用Dpad此处找到的代码:Link dev android。

但是,当我尝试在带有方向键输入的电视上使用 android 模拟器对其进行测试时,它不起作用。有很多日志语句,我发现我的问题是以下几行代码:

if (event instanceof MotionEvent) {
    // Use the hat axis value to find the D-pad direction
    MotionEvent motionEvent = (MotionEvent) event;
    float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X);
    float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y);
    Log.d("test", "xaxis = " + String.valueOf(xaxis) +
                  " yaxis = " + String.valueOf(yaxis));
}
Log.d("test", "returning directionPressed as - " +
               String.valueOf(directionPressed));

return directionPressed;
Run Code Online (Sandbox Code Playgroud)

我得到的输出如下(并打印 2 次,即使我只按一次按钮):

09-13 14:45:05.643 1489-1489/omgandroid D/test: is motion event = true
09-13 14:45:05.643 1489-1489/omgandroid D/test: is key event = false
09-13 14:45:05.643 1489-1489/omgandroid D/test: xaxis = 0.0 yaxis = 0.0
09-13 14:45:05.643 1489-1489/omgandroid D/test: returning directionPressed as -1
Run Code Online (Sandbox Code Playgroud)

我看到它getAxisValue(MotionEvent.AXIS_HAT_X/Y)总是返回 0.0,但我不知道为什么。

这是我在MainActivity.java(内部OnCreate)中调用此函数的代码:

mContentView.setOnGenericMotionListener(new View.OnGenericMotionListener() {
    @Override
    public boolean onGenericMotion(View view, MotionEvent event) {
        Log.d("test", "this works too");
        // Check if this event if from a D-pad and process accordingly.
        boolean check = Dpad.isDpadDevice(event);
        String str_check = String.valueOf(check);
        Log.d("test", "is dpad device? " + str_check);
        if (check) {

            int press = mDpad.getDirectionPressed(event);
            Log.d("test", String.valueOf(press));
            switch (press) {
                case LEFT:
                    // Do something for LEFT direction press
                    Log.d("test", "LEFT");
                    String uri = source + image;
                    ImageView img = (ImageView) findViewById(R.id.fullscreen_content);
                    img.setImageResource(R.drawable.a00_d01_01);
                    return true;
                case RIGHT:
                    // Do something for RIGHT direction press
                    Log.d("test", "RIGHT");
                    return true;
                case UP:
                    // Do something for UP direction press
                    Log.d("test", "UP");
                    return true;
                case DOWN:
                    // Do something for DOWN direction press
                    Log.d("test", "DOWN");
                    return true;
                case CENTER:
                    // DO something for CENTER direction press
                    Log.d("test", "CENTER");
                    return true;
                default:
                    return false;
            }
        }
        return false;
    }
});
Run Code Online (Sandbox Code Playgroud)

Kyl*_*enn 6

如果您不使用 Leanback 并且想要 an 中的功能Activity,那么您可以覆盖该Activity方法onKeyDown()

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    Log.d("debug", "we are here");
    switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_UP:
        case KeyEvent.KEYCODE_DPAD_DOWN:
        case KeyEvent.KEYCODE_DPAD_RIGHT:
        case KeyEvent.KEYCODE_DPAD_LEFT:
        case KeyEvent.KEYCODE_BACK:
        case KeyEvent.KEYCODE_ESCAPE:
            Log.d("OnKey", "key pressed!");
            Toast.makeText(MainActivity.this, "key pressed!", Toast.LENGTH_SHORT).show();
            return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

然后使用switch语句像下面(上键代码)来触发你想赶上(的条件case KeyEvent.KEYCODE_DPAD_UPcase KeyEvent.KEYCODE_DPAD_DOWN等等)。

正如您在代码共享中所做的那样,您还可以设置OnKeyListeneron 视图,但在这种情况下,您只需要覆盖该Activity方法。


如果您使用的是leanback(擅长列表管理和媒体播放):

Leanback是 Google 创建的用于简化 Android TV 应用程序编写的库,它在本机处理此问题,因为它与内容列表和媒体播放相关。我建议查看我上面链接的他们的示例项目。

如果你想自己实现点击处理,你可以查看他们的源代码,看看他们是如何在PlaybackControlGluePlaybackOverlayFragment类中解决它的。

他们在这里处理onKey(...)方法中的事件:

@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_UP:
        case KeyEvent.KEYCODE_DPAD_DOWN:
        case KeyEvent.KEYCODE_DPAD_RIGHT:
        case KeyEvent.KEYCODE_DPAD_LEFT:
        case KeyEvent.KEYCODE_BACK:
        case KeyEvent.KEYCODE_ESCAPE:
Run Code Online (Sandbox Code Playgroud)

以及dispatchAction(...)它正下方的方法中的一些其他事件:

boolean canPlay = keyEvent == null ||
                keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
                keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY;
Run Code Online (Sandbox Code Playgroud)

他们通过输入处理程序设置键处理程序:

private final PlaybackOverlayFragment.InputEventHandler mOnInputEventHandler =
        new PlaybackOverlayFragment.InputEventHandler() {
    @Override
    public boolean handleInputEvent(InputEvent event) {
        if (event instanceof KeyEvent) {
            KeyEvent keyEvent = (KeyEvent) event;
            return onKey(null, keyEvent.getKeyCode(), keyEvent);
        }
        return false;
    }
};
Run Code Online (Sandbox Code Playgroud)

这是通过设置: mFragment.setInputEventHandler(mOnInputEventHandler);


另一个很好的例子是在这里找到PlaybackOverlayFragmentonInterceptInputEvent(...)方法:

private boolean onInterceptInputEvent(InputEvent event) {
    final boolean controlsHidden = areControlsHidden();
    if (DEBUG) Log.v(TAG, "onInterceptInputEvent hidden " + controlsHidden + " " + event);
    boolean consumeEvent = false;
    int keyCode = KeyEvent.KEYCODE_UNKNOWN;

    if (mInputEventHandler != null) {
        consumeEvent = mInputEventHandler.handleInputEvent(event);
    }
    if (event instanceof KeyEvent) {
        keyCode = ((KeyEvent) event).getKeyCode();
    }

    switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_CENTER:
        case KeyEvent.KEYCODE_DPAD_DOWN:
        case KeyEvent.KEYCODE_DPAD_UP:
        case KeyEvent.KEYCODE_DPAD_LEFT:
        case KeyEvent.KEYCODE_DPAD_RIGHT:
Run Code Online (Sandbox Code Playgroud)

他们通过以下方式附加拦截器: getVerticalGridView().setOnKeyInterceptListener(mOnKeyInterceptListener);

如果这能解决您的问题,请告诉我。