【android系统】限制儿童观看视频时长,做了个播放限时方案

背景

随着时代的发展、科技的进步,电子产品的拥有日趋低龄化。电子产品的不当使用可能造成很多问题,过度使用容易上瘾,影响孩子的社交生活。据资料显示看电视绝不仅仅只会影响孩子的视力,更严重的会影响到孩子的身体和智力发育!只要在电视荧光幕前坐上半个小时,人的新陈代谢与活动力都会下降,智商减少五十。
合理的管理孩子对电视的接触时间是不可或缺的。作为开发者的我们,更应该注意这个问题。下面我们就说说在机顶盒平台上怎么实现这么样的一个功能。

方案流程

Android亮屏、熄屏的时候会发出广播,思路是监听这些广播来达到限时播放的效果。

1、设置锁屏时间

1.1、设置锁屏接口

Settings.System.putIntForUser(mContext.getContentResolver(),
                                Settings.System.SCREEN_OFF_TIMEOUT, timeout,
                                UserHandle.USER_CURRENT);

1.2、获取锁屏时间接口

int timeout = Settings.System.getInt(mContext.getContentResolver(),
                                       Settings.System.SCREEN_OFF_TIMEOUT);
Log.i(TAG, "getTimeOutToPMS timeout = " + timeout);

2、监听锁屏广播

// 屏幕灭屏广播  Intent.ACTION_SCREEN_OFF
// 屏幕亮屏广播  Intent.ACTION_SCREEN_ON
// 屏幕解锁广播  Intent.ACTION_USER_PRESENT

3、收到灭屏广播后弹出提示窗口来关闭播放

讲道理这个方案到这里就应该已经结束了,但是你会发现在某些应用中限时播放功能是ok的,然而在某些应用中播放视频时这个限时播放功能却不行了。到底是个什么情况?

方案优化

原来很多应用自带了常亮功能,导致你在该应用下一直处于不超时退出状态。

1、常见的应用常亮功能三种实现方式

1.1、持有WakeLock

权限:

 <uses-permission android:name="android.permission.WAKE_LOCK" />

代码实现:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
    if (powerManager != null) {
        mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "WakeLock");
    }
}
 
@Override
protected void onResume() {
    super.onResume();
    if (mWakeLock != null) {
        mWakeLock.acquire();
    }
}
 
@Override
protected void onPause() {
    super.onPause();
    if (mWakeLock != null) {
        mWakeLock.release();
    }
}

1.2、设置window的flag

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

1.3、需要常亮的activity的xml布局文件添加属性(TextView)

android:keepScreenOn="true"

通过以上三种就能设置常亮,系统就不会进入灭屏状态,发送灭屏广播上来,基于灭屏广播实现的应用就不会成功。是否就没有办法了呢?有,这时我们作为系统开发者的优势就体现出来了。

2、方案优化

设置常亮的三种方式最后都是通过PowerManager.WakeLock提供的接口,修改PowerManagerService.mFlags(感兴趣的关注我们的公众号回复PowerManager,如果人多的话我们会出一个分析PowerManager流程的文章,欢迎留言。ps:还可以回复各种你们想要知道的模块或者问题)。然后在PowerManagerService.java文件中的updateWakeLockSummaryLocked函数中检测PowerManagerService.mFlags来设置是否常亮。

在这个函数中看到看到熟悉的(FULL_WAKE_LOCK )。没错这就是常亮设置的flag,具体实现就在这里:

private void updateWakeLockSummaryLocked(int dirty) {
   if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
        mWakeLockSummary = 0;

        final int numWakeLocks = mWakeLocks.size();
        for (int i = 0; i < numWakeLocks; i++) {
            final WakeLock wakeLock = mWakeLocks.get(i);
            switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
                case PowerManager.PARTIAL_WAKE_LOCK:
                    ... ...
                case PowerManager.SUSPEND_WAKE_LOCK:
                    ... ...
                case PowerManager.FULL_WAKE_LOCK:
                    ... ...
                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                    ... ...
                case PowerManager.SCREEN_DIM_WAKE_LOCK:
                ......
            }
        }
    }
    ......
}

说明:
PARTIAL_WAKE_LOCK :保持CPU 运转,屏幕和键盘灯有可能是关闭的。
SCREEN_DIM_WAKE_LOCK :保持CPU运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK :保持CPU运转,允许保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK :保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度

这个时候你要做的就很简单了,直接屏蔽FULL_WAKE_LOCK 和SCREEN_BRIGHT_WAKE_LOCK这两个分支的代码,应用就没法设置常亮了,或者说设置了也没用。

结束语

孩子是祖国的花朵,对孩子的呵护就是对我们未来的呵护。没事多陪陪孩子,到处走走,多接触下现实生活,而不是为了减少麻烦让他们整天对着冷冰冰的电视或者手机。

陪着孩子去看看花花世界,体验生活,这才是我们的最佳方案。如果不知道去哪玩,或者如何跟孩子交流可以关注公众号【呱呱喳幼儿园】。

附上他们的优秀文章:趁着阳光正好,我们一起去赏花!

小编目前也是粗略学习了其中的皮毛,如果大家有更好的方案,欢迎大家扫描关注下方二维码和我们多多交流吧,欢迎不吝赐教!
【android系统】限制儿童观看视频时长,做了个播放限时方案

  • END -