美文网首页Android程序员Android系统开发
关于Android系统无用户操作相关处理

关于Android系统无用户操作相关处理

作者: J_Coder | 来源:发表于2016-05-13 19:04 被阅读915次

最近开发产品遇到一个需求:当Android系统若干时间内无用户操作响应时启动多媒体轮播应用。

思路1:监听输入事件并对其处理

接到需求想到的一个土办法就是在android系统input事件响应端对相关输入事件进行处理,可以追溯到android系统输入事件的framework层处理,相关代码目录在frameworks/base/core/java/android/view下,
我起初的处理在在ViewRootImpl.java,读者如果对Android输入系统不熟悉的话,最好可以去了解下,这里我就不进行拓展。

 final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }    

        @Override
        public void onInputEvent(InputEvent event) {
            //这里获取到各种输入的事件,在此进行相关逻辑处理
            //对产生输入事件的时间进行统计和运算并通知上层应用,如利用广播机制
            Log.d(TAG ,"onInputEvent:"+event.toString());
            enqueueInputEvent(event, this, 0, true);
        }    

        @Override
        public void onBatchedInputEventPending() {
            scheduleConsumeBatchedInput();
        }    

        @Override
        public void dispose() {
            unscheduleConsumeBatchedInput();
            super.dispose();
        }    
    }    

在WindowInputEventReceiver这个类里面会接收到输入系统输入的各种事件,包括用户的触摸,遥控 ,鼠标操作,当有输入时候,WindowInputEventReceiver的onInputEvent()就会响应,这时候就知道系统有用户在操作了,那么你可以在这个函数里对产生输入事件的时间进行统计和运算,用户多久操作多久没操作你都清楚啦,你可以在这里通过广播或者其他途径告诉上层应用去做响应的处理,到此可以完成需求了。

思路2:利用Android系统原有的休眠机制

Android系统本身是有无操作若干时间后自动休眠的功能,一般在设置程序中的显示这项中找到休眠一项,这里就直接给出相关的代码,实际上这里只是设置了一个SCREEN_OFF_TIMEOUT关键字的数据库字段,相关代码在设置程序的DisplaySettings中。

    @Override
    public boolean onPreferenceChange(Preference preference, Object objValue) {
        final String key = preference.getKey();
        if (KEY_SCREEN_TIMEOUT.equals(key)) {
            int value = Integer.parseInt((String) objValue);
            try {
              //设置
                Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value);
                updateTimeoutPreferenceDescription(value);
            } catch (NumberFormatException e) {
                Log.e(TAG, "could not persist screen timeout setting", e); 
            }   
        }   
        if (KEY_FONT_SIZE.equals(key)) {
            writeFontSizePreference(objValue);
        }   

        return true;
    }   

那么实际上的操作处理在哪里呢,经过一段搜索后(搜索SCREEN_OFF_TIMEOUT关键字),我们发现是在PowerManagerService中查找到相关的处理,因为休眠部分涉及到电源管理,读者对这部分有疑问,建议去读下关于PowerManagerService的相关分析,在这里介绍调用到PowerManagerService里关键的方法updateUserActivitySummaryLocked()。

    /**
     * Updates the value of mUserActivitySummary to summarize the user requested
     * state of the system such as whether the screen should be bright or dim.
     * Note that user activity is ignored when the system is asleep.
     *
     * This function must have no other side-effects.
     */
     private long mLastUserActivityTimeRecord =0;
    private void updateUserActivitySummaryLocked(long now, int dirty) {
     Slog.d(TAG, "updateUserActivitySummaryLocked:"+now
        +"mLastUserActivityTime:"+mLastUserActivityTime
        +"mLastWakeTime:"+mLastWakeTime);
        // Update the status of the user activity timeout timer.
        if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
            mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);

            long nextTimeout = 0;
            if (mWakefulness != WAKEFULNESS_ASLEEP) {
                final int screenOffTimeout = getScreenOffTimeoutLocked();
                final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);

                mUserActivitySummary = 0;
                if (mLastUserActivityTime >= mLastWakeTime) {
                    nextTimeout = mLastUserActivityTime
                            + screenOffTimeout - screenDimDuration;
                    if (now < nextTimeout) {
                        mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
                    } else {
                        nextTimeout = mLastUserActivityTime + screenOffTimeout;
                        if (now < nextTimeout) {
                            mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }
                if (mUserActivitySummary == 0
                        && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                    nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
                    if (now < nextTimeout
                            && mDisplayPowerRequest.screenState
                                    != DisplayPowerRequest.SCREEN_STATE_OFF) {
                        mUserActivitySummary = mDisplayPowerRequest.screenState
                                == DisplayPowerRequest.SCREEN_STATE_BRIGHT ?
                                USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;
                    }
                }
                if (mUserActivitySummary != 0) {
                    Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtTime(msg, nextTimeout);
                }
            } else {
                mUserActivitySummary = 0;
            }

            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
                        + wakefulnessToString(mWakefulness)
                        + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
                        + ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
            }
        }
    }

读者可以仔细读下这个部分的注释,大概意思是通过这个办法统计更新用户请求的一些信息和状态,通过打印发现这个方法在若干毫秒被系统调用的(具体的回调过程我还没仔细研究);需要注意的是这里有声明该方法内不能有其他副作用的操作,言下之意不能过多的操作不然系统会崩溃重启。这里我吃过苦头了,反复发一个intent也会导致系统重启,各位看官如果要操作之记得慎重操作。
需要注意的变量now,mLastUserActivityTime,now是通过SystemClock.uptimeMillis()获取,表示当前时间,mLastUserActivityTime表示用户上一次操作的时间,now和mLastUserActivityTime的对比可以知道距离用户上一次多久没有操作了。通过大家可以研读其中逻辑打印体会下。只要搞定了这个地方,可以满足目前的需求,而且不用单独去输入系统去做处理,这里的需求推荐思路2去实现。

在处理一些问题,在思路上,我建议优雅地方式去处理,而不是简单粗暴地把功能实现了。何为优雅地处理,我认为是要建立在对系统的理解上,利用和结合系统原有的机制,不做低效重复地开发,所以要不断地去认识学习系统的一些机制。

欢迎关注我的个人主页,谢谢大家!

相关文章

  • 关于Android系统无用户操作相关处理

    最近开发产品遇到一个需求:当Android系统若干时间内无用户操作响应时启动多媒体轮播应用。 思路1:监听输入事件...

  • centos 7 常用操作命令

    用户操作 文件操作 系统相关操作 linux系统服务管理命令 防火墙操作相关 压缩、解压 相关操作 快捷键操作

  • 安卓多用户学习笔记

    一.背景 多用户是Android4.2被引入的 二.用户相关操作(创建,切换,删除) 相关类(基于Android...

  • Android应用基础知识

    应用基础知识 Android操作系统是一种多用户Linux系统,其中的每个Android 操作系统是一种多用户 L...

  • 操作系统学习笔记(八)

    操作系统用户界面(SHD) 用户界面的定义 用户界面的分类 操作界面典型的操作界面图形界面命令界面批处理 系统调用...

  • 系统日历提醒事件获取与添加

    针对系统日历相关提醒/事件的处理,iOS提供了两个库EventKit:该框架提供了对用户日历数据库相关操作的API...

  • (二)操作系统的分类

    传统操作系统的分类: 1.批处理操作系统 工作方式 用户将作业交给系统操作员 系统操作员将许多用户的作业组成一批作...

  • 《疯狂Android讲义》学习笔记一

    疯狂Android讲义 Android系统的底层建立在Linux系统之上,该平台由操作系统、中间件、用户界面和应用...

  • Android系统联系人相关介绍以及具体的用法

    概述 本文主要解读Android系统联系人相关的知识,以及展示联系人相关的操作实例。参考Android官方API。...

  • Auth关于用户相关操作

    用户验证 可以使用controller类的validate方法验证用户数据,例如: 用户登录 Laravel 提供...

网友评论

  • Ucoon:怎么去判断设备是否休眠了
  • b2d1c736a99d:你好,请问第二个方法是怎么去实现的呢?
    我是判断时间差然后进行相应的操作,但是这样很容易死机
  • 呃哈哈:有demo楼主,会更好,谢谢
    J_Coder:@我是不是你大爷 这里主要讲处理的思路,更多的需要动动手尝试和实验,这样可以获得更多 :smile:

本文标题:关于Android系统无用户操作相关处理

本文链接:https://www.haomeiwen.com/subject/vylmrttx.html