zoukankan      html  css  js  c++  java
  • Android 小米盒子游戏手柄按键捕获

    Android 小米盒子游戏手柄按键捕获

    太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es)

    本文遵循“署名-非商业用途-保持一致”创作公用协议

    转载请保留此句:太阳火神的漂亮人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino否则,出自本博客的文章拒绝转载或再转载。谢谢合作。



    最终又告一段落,能够好好歇息一下了。

    曾经。提及身体,总是再坚持一下。就这样坚持了 15 年。

    如今。提及生命。不敢再坚持一下,还是休养一段,再整装前行。也来得及。


    记得高中老师教导过我们,歇息是学习的重要组成部分。

    那么,休养是工作、生活的重要组成部分,就合情合理了。


    我是一个闲不住的人。时刻都感到危机的存在。不敢稍停脚步。狠怕被后面的穷鬼追上,或是前面的曙光遗忘。

    不知从何时開始。还有一种危机感由然而生,

    总是预见到自已无力去做到眼前的小事。倍感心凉。渐而被生命遗忘。


    趁此良机。边休养。边捣腾一下家里的小米套装。

    以下就晒晒我这个非米粉所拥有的米装备。能够解读为显摆,只是很多其他要吐槽或者是期待吧:

    1、红米 Note 手机一部;

    2、小米盒子增强版一块(像个圆圆的河流石,所以论块了。只是配的是三星的电视,最初并不太信任小米。故没直购电视)

    3、小米路由器(内置 1T 硬盘,家里台式机。IBM笔记本和MacBookAir以及联想、红米、苹果等手机的照片自己主动备份上来。真是太帅了。之前买过一个 BT3 的开发版套了个小盒子,只是做起来确实有困难,最难只是电源管理)

    4、小蚁摄像头(不论什么有 WIFI 的地方,用手机都能看到家里。并用手机实时对讲)

    5、小米插座(用来控制三星电视的电源,这样不论什么一款电视,都被纳入到小米家族了,只是尚缺一个带学习功能的红外,或许仅仅有 Arduino 能搞定了)

    6、小米游戏手柄一对儿(玩儿了近两周了。游戏虽少,但确都非常耐玩)

    7、小米灯泡、小米体重称,一直在观注,多次立即要付款了。突然又放弃了,在我的思维中并没有答案,但我知道我的潜意识肯定有她的道理。


    今儿个把小米盒子用手机数据线连接到 MacBookAir 上。稍加设置,就能够调试了:

    一是打开电视中设置里的调试开关项;

    二是直接运行时,电视上会提示,点同意就能够了;


    想做点小东西,即能让小孩拿游戏手柄玩,又能以算术做为工具来玩,这个小东西,不知道叫啥,不知道咋分类,但我知道,首先得能识别到游戏手柄的各个按键才行,小米官方有按键码说明《电视/盒子应用开发指南》,只是对于我这非常少用和记这些键码的人来说,这个确有用处不大,我还是直接获取到键码值,反馈出来让我自个儿知道即可了。这样能推断哪个键能识别到。哪个不能识别到。基本当下的任务就完毕了。


    先来看一下 Activity 响应按键按下事件的重载方法:

    	@Override
    	public boolean onKeyDown(int keyCode, KeyEvent event) {
    		
        	return super.onKeyDown(keyCode, event);
    	}

    super.onKeyDown(keyCode, event); 方法的实现 Anroid 源代码例如以下节选:

        public boolean onKeyDown(int keyCode, KeyEvent event)  {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (getApplicationInfo().targetSdkVersion
                        >= Build.VERSION_CODES.ECLAIR) {
                    event.startTracking();
                } else {
                    onBackPressed();
                }
                return true;
            }

    当按下返回键时,目标版本号大于 ECLAIR 即 SDK 2.1,就会运行 

        event.startTracking();

    翻译:在 Callback.onKeyDown 运行期间调用该方法。使系统跟踪当前键按下事件,直到结束(可能包括一个长按事件)。

    注意,同一时候仅仅能有一个键被跟踪 -- 假设在前一个键被跟踪的时侯收到了还有一个键按下事件,前一个事件跟踪行为停止。


    通过查看 Android 源代码,你会发现 

        return super.onKeyDown(keyCode, event);

        return super.onKeyUp(keyCode, event);
    有一个配合点,以下贴 onKeyUp 源代码就非常easy看出来了:

        public boolean onKeyUp(int keyCode, KeyEvent event) {
            if (getApplicationInfo().targetSdkVersion
                    >= Build.VERSION_CODES.ECLAIR) {
                if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
                        && !event.isCanceled()) {
                    onBackPressed();
                    return true;
                }
            }
            return false;
        }
    当中这一句

        keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
                        && !event.isCanceled()
    先推断是返回按键,然后推断该事件是否处于跟踪状态,即在 onKeyDown 中 

        event.startTracking();
    开启的跟踪状态,而且推断该事件对象未处于取消状态,那么符合这三个条件,就正好与 onKeyDown 配合上了。

    当按键按下时。跟踪状态开启。一直没有其他按键按下的情况下,按键松开,通过系统跟踪的该按键事件状态,确定返回按键完毕了一次完整的

    按下松开,即运行 onBackPressed() ,源代码例如以下 :

        public void onBackPressed() {
            if (!mFragments.popBackStackImmediate()) {
                finish();
            }
        }
    该方法和 onKeyDown 方法中版本号小于 SDK 2.1 时调用的是同一个,当中调用了 finish() 方法,即结束当前 Activity 。


    由以上分析能够掌握最终返回按键的处理过程,怎样结束当前 Activity 的,接下来要实现二次按返回键再关闭当前 Activity ,


    先声明当前主线程下的 Handler:

    	Handler handler=new Handler();


    接下来重载 onKeyDown 方法

    	@Override
    	public boolean onKeyDown(int keyCode, KeyEvent event) {
    		switch (keyCode) {
    		case 3:
    			dealResult = dealWithHomeKey();
    			break;
    		case 4:
    			dealResult = dealWithBackKey();
    			break;
    		default:
    			break;
    		}
        	
        	if (!dealResult) {
        		finish();
        	}
        	
        	return true;
        	//return super.onKeyDown(keyCode, event);
    	}
    

    方法 dealWithBackKey() 处理返回按键,先声明类成员变量,用于记录状态

    	boolean ifBack = false;
    	boolean ifHome = false;
    	boolean dealResult = false;
    	long delayCancelInterval = 3000;

    然后声明 dealWithBackKey() 方法进行处理

        boolean dealWithBackKey() {
        	
        	if (!ifBack) {
        		
        		// 响应按键设置取消标识,在被延迟取消前再次按返回键。则退出
        		ifBack = true;
        		
        		// 延迟几秒取消返回标识
        		handler.postDelayed(new Runnable() {
    				
    				@Override
    				public void run() {
    					
    					ifBack = false;
    				}
    			}, delayCancelInterval);
        		
        		Toast.makeText(this, "再按一下返回键。退出应用", Toast.LENGTH_SHORT).show();
        		
        		// 返回 true ,事件不再继续向上传递
        		return true;
        	}
        	
        	return false;
        }
    或者单独声明 Runnable ,能够留出取消 Runnable 的余地。只是感觉用处不大,此处仅供技术參考

    	Runnable delayCancelBack = new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			ifBack = false;
    		}
    	};

    再看看 dealWithBackKey() 方法

        boolean dealWithBackKey() {
        	
        	if (!ifBack) {
        		
        		// 响应按键设置取消标识,在被延迟取消前再次按返回键,则退出
        		ifBack = true;
        		
        		// 延迟几秒取消返回标识
        		handler.postDelayed(delayCancelBack, delayCancelInterval);
        		
        		Toast.makeText(this, "再按一下返回键,退出应用", Toast.LENGTH_SHORT).show();
        		
        		// 返回 true ,事件不再继续向上传递
        		return true;
        	}
        	
        	return false;
        }

    对照一下,感觉后者能更好一些,相对清晰,且功能分离,随时可替换。

    话说回来,不管是 Java 的匿名内部类还是 OC 的 Block 。作为一种先进的编程语言元素,并非随处使用的。有节有度才干达到预期效果。

    针对于上面的代码,感觉直接内嵌内部类要好些。毕竟逻辑不非常复杂。假设逻辑非常复杂,不能作为当前被嵌入代码的简单扩展。那么。还是声明并用变量索引,然后再使用。相对能把两个复杂的逻辑范畴隔离开,引用的范畴内代码逻辑清晰,但凝视一定要配合得当。才干非常好地掩盖内部实现。


    以上代码在小米盒子增强版运行通过,Android SDK 4.4.2。 Mac Book Air 开发环境
    以上隐匿了一段代码,用于提示所按键的键码值,在 onKeyDown 重载方法开头部位:

        	String logText = "onKeyDown - keyCode:"+keyCode;
        	Log.d("Mi", logText);
    		Toast.makeText(this, logText, Toast.LENGTH_SHORT).show();
        	pressKeyTextView.setText(logText);


    Home 键通过注冊广播监听也是能够接收到了。但怎样能拦截,让系统响应不到,这样在我的应用中按 Home 键,不回到桌面,还是没有解决。

    下载了一些其他小米应用商店中的应用。有些确实是无法通过按 Home 回到桌面,尚不知是怎样实现的,须要时能够考虑反编译一下,看看实现方式,当然了。仅是学习的目的。


    待续......



  • 相关阅读:
    时间使用
    关于Dubbo说明及备注
    jQuery 的function简单备注
    Eclipse插件
    存储过程和视图的区别
    easyUi jqgrid search
    Python3内置函数——reversed() = 翻转我的世界
    你追求的目标正确吗
    Python3正则表示式(3)
    英语口语学习笔记(13)
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7083481.html
Copyright © 2011-2022 走看看