IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Androird TV 全局窗口 -> 正文阅读

[移动开发]Androird TV 全局窗口

Android TV 全局窗口


需求场景

?最近应广告机项目需求开发定时开关功能,关机的倒计时需要一个倒计时提示。开始使用的是跳转到一个专门用来计时的Activity,开始测试时都没有问题。后来发现第三方的广告应用会强制跳转,而我们计时的Activity就看不到了,这显然是不行的。所以后来通过查阅资料了解到了全局窗口,也是本文主要讲述的内容。


实现

?先上代码:

	private boolean isCountDown;
    private final Handler mHandler = new Handler();
    private WindowManager wm;
    private WindowManager.LayoutParams params;
    private View countDownView;
    private TextView tv_time;
    private static Timer countDown = null;
    private int mValue = 60;
    
    ......
    public void show() {
        wm = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
		......
        params = new WindowManager.LayoutParams();
        // 系统级别的窗口
        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
                | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
        // 居中显示
        params.gravity = Gravity.CENTER;
        // 设置背景透明
        params.format = PixelFormat.TRANSPARENT;
        //拦截特殊按键,eg:power,volume
        int keyFeatures = params.keyFeatures;
        keyFeatures |= WindowManager.LayoutParams.KEY_FEATURE_POWER_PASS_TO_USER;
        keyFeatures |= WindowManager.LayoutParams.KEY_FEATURE_HOME_PASS_TO_USER;
        keyFeatures |= WindowManager.LayoutParams.KEY_FEATURE_VOLUME_PASS_TO_USER;
        keyFeatures |= WindowManager.LayoutParams.KEY_FEATURE_APP_LAUNCHER_PASS_TO_USER;
        keyFeatures |= WindowManager.LayoutParams.KEY_FEATURE_INPUT_SOURCE_PASS_TO_USER;
        if (keyFeatures != params.keyFeatures) {
            params.keyFeatures = keyFeatures;
        }
        countDownView = new View(getApplicationContext()); // 不依赖activity的生命周期
        //加载自定义的倒计时页面
        countDownView = View.inflate(getApplicationContext(),
                R.layout.countdown_weight, null);
        //设置触摸可以获得焦点
        countDownView.setFocusableInTouchMode(true);
        tv_time = (TextView) countDownView.findViewById(R.id.countdown_text);
        tv_time.setText(getStyledText(60));
        wm.addView(countDownView, params);
        //设置按键监听
        countDownView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
                Log.d(TAG, "onKey: " + keyEvent.getKeyCode());
                if (keyEvent.getAction() == KeyEvent.ACTION_UP) {
                	//按下任意按键后,移除当前的倒计时窗口及定时任务
                    if (countDownView != null) {
                        wm.removeView(countDownView);
                        countDownView = null;
                        countDown.cancel();
                        mValue = 60;
                    }
                }
                return true;
            }
        });
        // 添加倒计时功能
        countDown = new Timer();
        countDown.schedule(new TimerTask() {
            @Override
            public void run() {
                mValue--;
                mHandler.post(drawCount);
                if (mValue == 0) {
                    // 执行关机操作(这里可以使任意其他操作,根据自己的需求)
                    if (countDownView != null) {
                        wm.removeView(countDownView);
                        countDownView = null;
                        // 取消定时
                        countDown.cancel();
                        goToShutdown();
                    }
                }
            }
        }, 0, 1000);
    }
	
	//更新倒计时
	Runnable drawCount = new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "Count Down Value: " + mValue);
            tv_time.setText(getStyledText(mValue));
        }
    };

	//这里可以替换为其他内容,如果你需要用到这种类似倒计时执行指定方法的需求。
    private void goToShutdown() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
  				//关机
            }
        }, 200);
    }

在上面代码中,主要有以下几点需要注意:
?①窗口需要设置setFocusableInTouchMode为true,允许触摸获得焦点。因为遥控器响应需要这个属性,同时添加的view不可以设置layoutParams.flags=LayoutParams.FLAG_NOT_FOCUSABLE,否则就完全屏蔽了按键了。满足这两个条件后,为添加的VIew设置的按键监听才可以接收到按键信息,具体怎么处理就是看需求了,我这里的需求就是移除窗口及取消定时任务。
?②这个倒计时窗口肯定是允许取消的,那我们这里就设置了按下任意键就需要取消这个计时,同时移除窗口。但是在电视上面有些按键是在PhoneWindowManager做过处理的,我们的窗口无法响应,所以才有了上面特殊按键拦截的部分代码。这样即使按下关机键也仅仅只是做为一个取消的按键,而不是真的去关机。


总结

?本文以关机倒计时的窗口举例阐述Android TV上面的全局窗口实现,通过这种方式启动的窗口,在所有的应用页面都能看的到,不会因为Activity的生命周期而受到影响。这里需要注意,高版本下Android对服务管理还是很严格的,跳转应用后有可能服务无法正常工作,而我们的窗口也会受到影响,这里需要参考自家项目如何添加白名单去实现这种全局保活窗口的效果。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-06 09:57:05  更:2021-08-06 09:58:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 13:51:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码