安卓TV开发(九) Android模拟事件 遥控器变身成鼠标来操作TV
本文出处:http://blog.csdn.net/sk719887916/article/details/40348853,作者:skay
一 自定义鼠标视图
public MouseView(Context context) {super(context);}public MouseView(Context context, MouseManager mMouseMrg) {super(context);init( mMouseMrg);}public OnMouseListener getOnMouseListener() {return mOnMouseListener;}public void setOnMouseListener(OnMouseListener mOnMouseListener) {this.mOnMouseListener = mOnMouseListener;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (mMouseView != null && mMouseBitmap != null) {mMouseView.measure(MeasureSpec.makeMeasureSpec(mMouseBitmap.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mMouseBitmap.getHeight(), MeasureSpec.EXACTLY));}}private void init(MouseManager manager) {mMouseManager = manager;Drawable drawable = getResources().getDrawable(R.drawable.shubiao);mMouseBitmap = drawableToBitamp(drawable);mMouseView = new ImageView(getContext());mMouseView.setImageBitmap(mMouseBitmap);addView(mMouseView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));mOffsetX = (int)((mMouseBitmap.getWidth()));mOffsetY = (int)((mMouseBitmap.getHeight()));}@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {if(mMouseView != null) {mMouseView.layout(mMouseX, mMouseY, mMouseX + mMouseView.getMeasuredWidth(), mMouseY + mMouseView.getMeasuredHeight());}}
二 鼠标控制器
/*** @param parent* @param type*/public void init(ViewGroup parentView, int type) {mParentView = parentView;mContext = parentView.getContext();mMouseView = new MouseView(mContext, this);mMouseView.setOnMouseListener(this);mCurrentType = type;}/*** @return*/public boolean getMouseType() {return isMouseType;}/*** @return*/public int getCurrentActivityType() {return mCurrentType;}/*** showmouse*/public void showMouseView() {ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);if(mMouseView != null) {mParentView.addView(mMouseView, lp);}}public boolean onDpadClicked(KeyEvent event) {if(!isMouseType) {return false;}if(event.getKeyCode() == KEYCODE_CENTER) {dispatchKeyEventToMouse(event);} else {if(event.getAction() == KeyEvent.ACTION_DOWN) {if(!isKeyEventCousumed) {if(event.getDownTime() - mLastEventTime < defTimes) {if(mSpeed < defMaxSpeed) {mSpeed ++;}} else {mSpeed = 1;}}mLastEventTime = event.getDownTime();dispatchKeyEventToMouse(event);isKeyEventCousumed = true;} else if(event.getAction() == KeyEvent.ACTION_UP) {if(!isKeyEventCousumed){dispatchKeyEventToMouse(event);}isKeyEventCousumed = false;}}return true;}public void sendCenterClickEvent(int x, int y, int action) {sendMotionEvent(x, y, action);}@SuppressLint("InlinedApi")public void sendMouseHoverEvent(int downx, int downy) {sendMotionEvent(downx, downy, MotionEvent.ACTION_HOVER_MOVE);}@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)@SuppressLint("NewApi")private void sendMotionEvent(int x, int y, int action) {MotionEvent motionEvent = getMotionEvent( x, y ,action) ;if(action == MotionEvent.ACTION_HOVER_MOVE) {motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);mMouseView.dispatchGenericMotionEvent(motionEvent);//mParentView.dispatchGenericMotionEvent(motionEvent);} else {//mParentView.dispatchTouchEvent(motionEvent);mMouseView.dispatchTouchEvent(motionEvent);}}private MotionEvent getMotionEvent(int downx, int downy, int action) {// TODO Auto-generated method stublong downTime = SystemClock.uptimeMillis();long eventTime = SystemClock.uptimeMillis();int metaState = 0;return MotionEvent.obtain(downTime, eventTime, action, downx, downy, metaState);}@Overridepublic boolean onclick(View v, KeyEvent et) {if (getMouseType()) {return onDpadClicked(et);}return mParentView.dispatchKeyEvent(et);}
三 当前页面加入鼠标
public class MainActivity extends Activity {WindowManager wm;WindowManager.LayoutParams params;private MouseManager mMouseManager;public static ViewGroup contentView;private WebView webView;private View mLoginStatusView;private TextView mLoaddingMessageView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);LayoutInflater inflater = getLayoutInflater();contentView = (ViewGroup) inflater.inflate(R.layout.test, null);setContentView(contentView);init();initMouse();showMouse();}private void init() {webView = (WebView) contentView.findViewById(R.id.web);mLoginStatusView = this.findViewById(R.id.login_status);mLoaddingMessageView = (TextView) this.findViewById(R.id.login_status_message);Button button = (Button) contentView.findViewById(R.id.btn_onclick);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "onclicked ", 1).show();showProgress(true);webView.setVisibility(View.VISIBLE);webView.loadUrl("https://www.baidu.com/");WebSettings settings = webView.getSettings();settings.setJavaScriptEnabled(true);webView.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view,String url) {view.loadUrl(url);return true;}@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);}@Overridepublic void onReceivedError(WebView view, int errorCode,String description, String failingUrl) {Toast.makeText(MainActivity.this, "加载失败 ",Toast.LENGTH_LONG).show();super.onReceivedError(view, errorCode, description,failingUrl);}});webView.setWebChromeClient(new WebChromeClient() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {// TODO Auto-generated method stubif (newProgress == 100) {showProgress(false);} else {}}});}});}@SuppressLint("NewApi")private void showProgress(final boolean show) {// On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow// for very easy animations. If available, use these APIs to fade-in// the progress spinner.if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);mLoginStatusView.setVisibility(View.VISIBLE);mLoginStatusView.animate().setDuration(shortAnimTime).alpha(show ? 1 : 0).setListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {webView.setVisibility(show ? View.VISIBLE: View.GONE);}});webView.setVisibility(View.VISIBLE);webView.animate().setDuration(shortAnimTime).alpha(show ? 0 : 1).setListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {webView.setVisibility(show ? View.GONE: View.VISIBLE);}});} else {// The ViewPropertyAnimator APIs are not available, so simply show// and hide the relevant UI components.mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);webView.setVisibility(show ? View.GONE : View.VISIBLE);}}private void showMouse() {mMouseManager.showMouseView();}public void initMouse() {initMouseMrg();}public void initMouseMrg() {mMouseManager = new MouseManager();mMouseManager.init(contentView, MouseManager.MOUSE_TYPE);mMouseManager.setshowMouse(true);}}
简单三步,代码就可以实现简单的用于遥控器操作的TV的浏览器,本次demo只是用户手动模拟点击,至于实现自动化模拟点击,以上方式显得极为笨拙,
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));
具体逻辑是当我的app启动时 。就可以用全局的Instrumentation来监控到底当前在哪个界面,提前将点击的入口定义OK后,接下来的点击事件就如同用户主动点击一样,包括跳转逻辑不再需要考虑。
安卓TV开发(九) Android模拟事件 遥控器变身成鼠标来操作TV相关推荐
- STC8H开发(九): STC8H8K64U模拟USB HID外设
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- 【安卓开发 】Android初级开发(九)Android中封装View提供接口供点击事件回调的方法及使用
自古一楼先上图 package com.example.mydialog;import android.app.Dialog; import android.content.Context; impo ...
- 安卓多媒体开发!Android高级工程师面试实战,系列篇
开头 最近,程序员这个圈子可谓热闹非凡,前不久,一个神奇的开源项目996.ICU诞生,几天时间就有超过10w+ star 和 1w+ fork ,可谓是Github上star增长最快的项目.996.i ...
- java安卓app开发教程,Android app开发入门 —— your 'Hello, World'
从这篇可以掌握到 Android app开发环境的搭建 开发工具介绍及安装 创建你的"Hello, World" 工程结构的介绍 工程gradle配置 简单布局 代码sample ...
- android+tv+开发+icon,Android TV+HTML5的架构设计和应用开发经验.pdf
Android TV + HTML5 : 架構設計與App開發經驗 高煥堂 亞太地區Android 技術大會主席 中國電子視像行業協會高級顧問 ★ 講題簡介 HTML5天生麗質,具有天賦的跨端.跨雲. ...
- 安卓原生开发!Android面试题集2021版,附答案
正文 Android行业主要问题是初级Android太多了,会写xml和Activity的程序员太多了,初中级程序员面临很大的竞争,现状也就偏于高级开发者.越来越多的初中级Android程序员找不到满 ...
- android tv 开发布局,Android TV开发总结(七)构建一个TV app中的剧集列表控件
前言:剧集类控件,在TV app中非常常见,今天将介绍构建一个TV app中的剧集列表控件,此控件上传到我的Github:https://github.com/hejunlin2013/Episode ...
- Android模拟事件keycode对照表
1.例子: //这条命令相当于按了设备的Backkey键 adb shell input keyevent 4 //可以解锁屏幕 adb shell input keyevent 82 //在屏幕上 ...
- android 模拟crash_Android 收集Crash信息及用户操作步骤
对于android开发者来说,Crash 可谓是司空见惯的事了,没有一个程序员敢保证自己的程序绝对不会发生crash.开发的时候发生crash还好,可以Logcat来查看log分析出原因,但是在线上, ...
最新文章
- Coursera台大机器学习技法课程笔记04-Soft-Margin Support Vector Machine
- 机器学习导论(张志华):基本概念
- 分布式内存数据库---Redis数据库之(键)key
- [Vue源码分析] Virtual DOM
- c#精彩编程200例百度云_邂逅百度云智学院:福州理工学院AIOT实训营火热开营!...
- P4248-[AHOI2013]差异【SAM or SA】
- C#中采用OLEDB方式来读取EXCEL文件
- Linux 压缩与解压
- sklearn炼丹术之——交叉验证Cross-validation: evaluating estimator performance
- ATM系统之问题描述与词汇表
- Web移动端常见问题-摘抄
- PIM DM技术原理与实验
- 服务器配置文档模板,服务器配置模板
- 用Java实现24点游戏
- 从0写USB摄像头驱动程序
- 表格进阶03——简历制作(用表格布局)
- 如何开发微信小程序?微信小程序有哪些特点?
- 编译型语言和解释型语言的区别总结
- 19年6月仔细阅读A篇:游戏界声优
- 如何旋转图片方法#ps教程#ps学习#ps修图抠图