原文:http://blog.csdn.net/sk719887916/article/details/44781475 skay

前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验上有很大的区别,本系列博文主要用移动智能电视(TV)上实现视频播放器的去了解下在智能设备上的开发的相关技术。本系列将实现遥控器焦点控制,模拟鼠标点击,视频在线直播,和手机当遥控器等功能,带给你不一样的开发体验。

上篇文章中说道了触控事件,(安卓Tv开发(一)焦点控制(触控事件))但是只对MotionEvent做了细说,很多东西还是不懂怎么用触控事件,现在就做对上篇的补充吧   本文出处:http://blog.csdn.net/sk719887916

; i < events.length; i++)

  • {
  • if(events[i] == event.getAction())
  • {
  • if(oldevent != event.getAction())
  • {
  • DisplayEventType(szEvents[i]);
  • oldevent = event.getAction();
  • }
  • break;
  • }
  • }
  • return super.onTouchEvent(event);
  • }
  • 好了 ,今天言归正传,接着说键盘事件:keyevent.

    KeyEvent事件


    一  keyEvent:

       

    源码位于android.view下,包装管理所有按键有关输入的事件体系,KeyEvent和MotionEvent的分发流程一样,都是InputEvent的子类,都是从Activity开始的,KeyEvent主要有以下事件类型:

       KeyEvent.KEYCODE_DPAD_UP; 上
       KeyEvent.KEYCODE_DPAD_DOWN; 下
       KeyEvent.KEYCODE_DPAD_LEFT;左
       KeyEvent.KEYCODE_DPAD_RIGHT;右
       KeyEvent.KEYCODE_DPAD_CENTER;确定键
       KeyEvent.KEYCODE_DPAD_RIGHT; 右
       KeyEvent.KEYCODE_XXX:数字键 (xx表示你按了数字几)
       KeyEvent.KEYCODE_BACK; 返回键
       KeyEvent.KEYCODE_HOME;房子键

       KeyEvent.KEYCODE_A: A-Z,26个字母

       KeyEvent.KEYCODE_MENU菜单键。

       谷歌提供了260种keyEvent,其他类型可以去源码查看,一个最基本的构造函数:

           

    public KeyEvent(long downTime, long eventTime, int action,
        int code, int repeat, int metaState,
        int deviceId, int scancode, int flags, int source) {
        mDownTime = downTime;
        mEventTime = eventTime;
        mAction = action;
        mKeyCode = code;
        mRepeatCount = repeat;
        mMetaState = metaState;
        mDeviceId = deviceId;
        mScanCode = scancode;
        mFlags = flags;
        mSource = source;
        }

    仔细观察,发现一个按键事件,会包含以上很多属性, 按键Id,设备ID, 按键坐标,按键资源,按键标记位,按键action(Up,down),响应次数,按下的时间等。

       一般我们处理按键事件可以这样做:

           public boolean onKeyDown(int keyCode, KeyEvent event) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_CENTER:
                    Toast("你按下中间键");
                    break;
    
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    Toast("你按下下方向键");
                break;
    
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    Toast("你按下左方向键");
                    break;
    
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    Toast("你按下右方向键");
                    break;
    
                case KeyEvent.KEYCODE_DPAD_UP:
                    Toast("你按下上方向键");
                    break;
            }
            return super.onKeyDown(keyCode, event);
        }

    复写onKeyDown()或者onKeyUp();

       不管是触控和按键事件,我们在Java代码中凭空创建,API提供了obtain()函数,来让开发者模拟事件,让系统处理。

    KeyEvent事件分发

       上一篇文中介绍了触控事件的机制,其实按键事件和他很相似,基本也传递和分发(拦截不存在,你无法阻止实际物理键的按下去),主要有dispatchKeyEvent(KeyEvent event),onKeyUp和onKeyDown,

    **dispatchKeyEvent()**

      主要处理按键的分发。avtivity和view都拥有此方法,两种有所区别的,实际都是交给DecorView来处理。

      

      public boolean dispatchKeyEvent(KeyEvent event) {
            onUserInteraction();
    
            // Let action bars open menus in response to the menu key prioritized over
            // the window handling it
            if (event.getKeyCode() == KeyEvent.KEYCODE_MENU &&
                    mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
                return true;
            }
    
            Window win = getWindow();
            if (win.superDispatchKeyEvent(event)) {
                return true;
            }
            View decor = mDecor;
            if (decor == null) decor = win.getDecorView();
            return event.dispatch(this, decor != null
                    ? decor.getKeyDispatcherState() : null, this);
        }

    上层拦截可以复写就可以了,

       

     @Override
         public boolean dispatchKeyEvent(KeyEvent event) {
                Log.i("dispatchKeyEvent",
                        "dispatchKeyEvent(), action=" + event.getAction() + " keycode="
                                + event.getKeyCode());
    
                return super.dispatchKeyEvent(event);
    
            }

    如果我们想消费某个按键事件我们可以复写onKeyDown()或者onKeyUp();

        

    @Override
        public boolean onKeyUp(int keyCode, KeyEvent event) {
            return super.onKeyUp(keyCode, event);
    
            // // TODO: 2014-10-30
        }

    **总结下整个流程:**

    首先触发dispatchKeyEvent()
    再次onKeyDown 如果按下紧接着松开,则是俩步

    紧跟着触发dispatchKeyEvent 
    然后触发onUserInteraction 
    再次onKeyUp


    本文出http://blog.csdn.net/sk719887916处:

    Focus

    - requestFocus():强制设置一个焦点到指定的view或它的一个子类,(前提是android:focusable为true能够获得焦点)
     
    -    android:focusable:设置一个控件能否获得焦点
    -    android:background:设置在作为背景的drawable
    -    android:nextFocusDown:定义下一个获得焦点的控件当按下键时
    -    android:nextFocusUp:定义下一个获得焦点的控件当按上键时
    -    android:nextFocusLeft:定义下一个获得焦点的控件当按左键时
    -    android:nextFocusRight:定义下一个获得焦点的控件当按右键时

    可以通过焦点事件变化操作view,    View.setFocusable(true);   设置控件是否可以获得焦点,同时会触发 setOnFocusChangeListener()

     view.setOnFocusChangeListener(){
              public void onFocus(boolean Focus){
                       if( Focus ){
                        //获得焦点
                        } else{
                           //失去焦点
                        }     

    三 instrumentation

    Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的,我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。Instrumentation,开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义。有了这样的功能,开发者就可以实现更为灵活的运行时虚拟机监控和 Java 类操作,代替认为操作,主要用于自动测试框架。

    instrumentation发送键盘鼠标事件:Instrumentation提供了丰富的以send开头的函数接口来实现模拟键盘和鼠标,如下所述:

    sendCharacterSync(int keyCode)            //用于发送指定KeyCode的按键

    sendKeyDownUpSync(int key)                //用于发送指定KeyCode的按键

    sendPointerSync(MotionEvent event)     //用于模拟Touch

    sendStringSync(String text)                   //用于发送字符串

                         Instrumentation inst=new Instrumentation();
                         inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 10, 10, 0));
                         inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 10, 10, 0));

    本文出处:http://blog.csdn.net/sk719887916/article/details/44781475

    但是TV的遥控器模拟鼠标并非需要此类,也没这么复杂,具体可以拦截事件,发送模拟事件即可,欢迎阅读。

    安卓实现遥控器模拟鼠标请阅读:《安卓TV开发(九) Android之模拟事件点击并实现遥控器模模拟鼠标操作

    04-16 06:32